├── .gitignore ├── .travis.yml ├── Makefile ├── README.rst ├── builtin-functions └── index.rst ├── builtin-types ├── boolean-operations.rst ├── comparisons.rst ├── file.rst ├── index.rst ├── iterator.rst ├── mapping.rst ├── numeric.rst ├── primitive-type-cheat-sheet.rst ├── sequence.rst ├── set.rst └── truth-value-testing.rst ├── classes └── index.rst ├── code ├── Makefile ├── annotator_error.py ├── benchmarks │ ├── Makefile │ ├── binary-tree.py │ ├── binary-tree_rpy.py │ ├── buffer.py │ ├── buffer_rpy.py │ ├── fannkuch.py │ ├── fannkuch_rpy.py │ ├── fib.py │ ├── fib_rpy.py │ ├── float.py │ ├── float_rpy.py │ ├── spectral-norm.py │ └── spectral-norm_rpy.py ├── bf.py ├── boolean_operations.py ├── builtin.py ├── classes.py ├── classes_mixin.py ├── comparisons.py ├── dict.py ├── dict_unsupported.py ├── errors_exceptions.py ├── file.py ├── flow_control_variables.py ├── flowing2_error.py ├── flowing_error.py ├── handle_exceptions.py ├── hello_world.py ├── hello_world_python.py ├── iterator.py ├── iterator_generator.py ├── lists.py ├── lists_unsupported.py ├── listsort.py ├── numeric.py ├── numeric_bitwise.py ├── numeric_constfold.py ├── numeric_math.py ├── numeric_unsupported.py ├── rarithmetic.py ├── rbigint.py ├── rbisect.py ├── rffi_abs.py ├── rffi_liststr.py ├── rffi_more.py ├── rffi_separate_module_sources.py ├── rffi_str.py ├── rmd5.py ├── rpath.py ├── rrandom.py ├── rsha.py ├── rsre.py ├── rsre_more.py ├── rtime.py ├── rtimer.py ├── rurandom.py ├── sequence.py ├── sequence_unsupported.py ├── sets.py ├── sets_unsupported.py ├── strings.py ├── strings_unsupported.py ├── truth_value_testing.py ├── truth_value_testing_inconsistency.py ├── tuples.py ├── union_error.py └── xrange.py ├── conf.py ├── error └── index.rst ├── examples └── index.rst ├── flow-control └── index.rst ├── getting-started └── index.rst ├── images └── union_error.png ├── index.rst ├── jit └── index.rst ├── overview └── index.rst ├── references └── index.rst ├── rewrite-benchmarks └── index.rst ├── rffi └── index.rst └── rlib ├── index.rst ├── listsort.rst ├── rarithmetic.rst ├── rbigint.rst ├── rbisect.rst ├── rmd5.rst ├── rpath.rst ├── rrandom.rst ├── rsha.rst ├── rsre.rst ├── rtime.rst ├── rtimer.rst └── rurandom.rst /.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | __pycache__ 3 | code/**/*-c 4 | *.pyc -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "2.7" 4 | env: 5 | - PYPY_VERSION=pypy2.7-v7.1.0 6 | - PYPY_VERSION=pypy2-v6.0.0 7 | install: 8 | - sudo apt-get install pypy libgc-dev 9 | - pip install sphinx sphinx_rtd_theme 10 | script: 11 | - make html 12 | - wget https://bitbucket.org/pypy/pypy/downloads/$PYPY_VERSION-src.tar.bz2 13 | - tar jxf $PYPY_VERSION-src.tar.bz2 14 | - export RPY=$(pwd)/$PYPY_VERSION-src/rpython/bin/rpython 15 | - make -C code 16 | - make -C code/benchmarks 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SOURCEDIR = . 8 | BUILDDIR = _build 9 | 10 | # Put it first so that "make" without argument is like "make help". 11 | help: 12 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 13 | 14 | .PHONY: help Makefile 15 | 16 | # Catch-all target: route all unknown targets to Sphinx using the new 17 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 18 | %: Makefile 19 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | RPython By Example 2 | ================== 3 | 4 | RPython by Example (RPyBE) is a collection of runnable examples that illustrate 5 | various RPython concepts and libraries. 6 | 7 | Please use following commands to install dependencies, build RPyBE in HTML/PDF, and run example code. 8 | 9 | .. code-block:: shell 10 | 11 | $ pip install sphinx sphinx_rtd_theme # install Sphinx and theme 12 | $ make html # generate webpages in _build/html 13 | 14 | $ sudo apt-get install texlive-full # install TeX Live for generating PDF 15 | $ make latexpdf # generate a PDF in _build/latex 16 | 17 | $ cd code # change to the directory of code examples 18 | $ export RPY=$(PATH_TO_PYPY)/rpython/bin/rpython # setup the RPython compiler path 19 | 20 | $ make # compile all RPython code 21 | $ make hello_world # compile a specific example 22 | $ ./hello_world-c # run the example 23 | 24 | Rendered: 25 | * HTML: ``_ 26 | -------------------------------------------------------------------------------- /builtin-functions/index.rst: -------------------------------------------------------------------------------- 1 | Built-in Functions 2 | ================== 3 | 4 | The Python interpreter has a number of 5 | `built-in functions `_, 6 | but only few of them are supported by RPython. 7 | 8 | .. literalinclude:: ../code/builtin.py 9 | 10 | .. attention:: 11 | Built-in functions are very limited in RPython. For instance, ``sum()`` is 12 | not supported in RPython. Moreover, supported functions like ``min()`` do not 13 | provide the same functionalities in Python. The ``min()`` function in RPython 14 | can only compare two values, but in Python, it can be used to find the 15 | minimum value in a list. 16 | -------------------------------------------------------------------------------- /builtin-types/boolean-operations.rst: -------------------------------------------------------------------------------- 1 | Boolean Operations 2 | ================== 3 | 4 | The boolean operations in RPython are exactly *same* as Python. You can use ``and``, 5 | ``or``, and ``not`` to operate on two truth values (e.g., ``True``, ``False``, ``''``, ``{}``). 6 | 7 | .. literalinclude:: ../code/boolean_operations.py 8 | -------------------------------------------------------------------------------- /builtin-types/comparisons.rst: -------------------------------------------------------------------------------- 1 | Comparisons 2 | =========== 3 | 4 | Comparison operations in RPython are similar with Python, which contain: 5 | ``<``, ``<=``, ``>``, ``>=``, ``==``, ``!=``, ``is``, ``is not``. Note that 6 | ``is`` and ``is not`` are operations to compare object identity. 7 | 8 | Non-identical instances of a class normally compare as non-equal unless the 9 | class defines the ``__eq__()`` method. 10 | 11 | .. attention:: 12 | One exception should be noted is that the comparisons of instances of same class 13 | or other types of object by defining ``__lt__()``, ``__le__()``, ``__gt__()``, 14 | ``__ge__()``, and ``__cmp__()`` method was not supported in RPython. 15 | 16 | The following example shows the comparisons between integers and instances. 17 | 18 | .. literalinclude:: ../code/comparisons.py 19 | -------------------------------------------------------------------------------- /builtin-types/file.rst: -------------------------------------------------------------------------------- 1 | File Objects 2 | ============ 3 | 4 | File operations in RPython are very similar with Python. The following example 5 | shows some simple use cases. 6 | 7 | .. literalinclude:: ../code/file.py 8 | 9 | .. attention:: 10 | In addition to these operations and methods of the built-in file objects, 11 | RPython's libraries (``rpython.rlib.rfile``)also provides some advanced 12 | operations such as ``create_stdio()`` and ``create_temp_rfile()``. 13 | -------------------------------------------------------------------------------- /builtin-types/index.rst: -------------------------------------------------------------------------------- 1 | Built-in Types 2 | ============== 3 | 4 | Python provides various `built-in types `_ 5 | such as numerics, sequences, mappings, files, classes, instance and exceptions. 6 | Let's see how do these types behave in RPython. Note that, in this document, we 7 | only focus on Python 2.7. The built-in types in Python 3 may be a little 8 | different, but most of the types are same. 9 | 10 | .. toctree:: 11 | :maxdepth: 1 12 | 13 | truth-value-testing 14 | boolean-operations 15 | comparisons 16 | numeric 17 | iterator 18 | sequence 19 | set 20 | mapping 21 | file 22 | primitive-type-cheat-sheet 23 | -------------------------------------------------------------------------------- /builtin-types/iterator.rst: -------------------------------------------------------------------------------- 1 | Iterator Types 2 | ============== 3 | 4 | The iterator type in RPython is similar with Python, it can help to iterator 5 | over containers. The iterator objects should support ``__iter__()`` and 6 | ``next()`` methods. These two methods form the *iterator protocol*. 7 | 8 | .. literalinclude:: ../code/iterator.py 9 | 10 | .. attention:: 11 | You cannot get an iterator object of a list using the ``__iter__()`` method 12 | in RPython. 13 | 14 | If a container object's ``__iter__()`` method is implemented as a generator, it 15 | will automatically return an iterator object with the ``__iter__()`` and 16 | ``next()`` method. Here is an example of a customized container object 17 | implemented the *iterator protocol* using generator. 18 | 19 | .. literalinclude:: ../code/iterator_generator.py 20 | -------------------------------------------------------------------------------- /builtin-types/mapping.rst: -------------------------------------------------------------------------------- 1 | Mapping Types 2 | ============= 3 | 4 | There is currently only one standard mapping type in Python, the dictionary. 5 | Operations and methods of the dict type in RPython are similar with Python. 6 | 7 | .. literalinclude:: ../code/dict.py 8 | 9 | As you can see, most methods of dictionary are supported in RPython. However, 10 | there are some exceptions. 11 | 12 | .. attention:: 13 | * dicts with a unique key type only, provided it is hashable 14 | * custom hash functions and custom equality will not be honored. Use 15 | ``rpython.rlib.objectmodel.r_dict`` for custom hash functions. 16 | * the dictionary view object is not supported in RPython. 17 | 18 | .. literalinclude:: ../code/dict_unsupported.py 19 | -------------------------------------------------------------------------------- /builtin-types/numeric.rst: -------------------------------------------------------------------------------- 1 | Numeric Types 2 | ============= 3 | 4 | Built-in numeric types 5 | ---------------------- 6 | 7 | There are three numeric types: plain integers (also called integers), long 8 | integers, floating point numbers. 9 | 10 | .. attention:: 11 | Complex numbers are not supported as built-in types in RPython. However, you can 12 | use RPython libraries to handle complex numbers. 13 | 14 | This table describes the details of RPython's built-in types: low-level (LL) 15 | types, corresponding C types and sizes in memory (64-bit). 16 | 17 | +-----------+---------+--------+---------------+---------------+ 18 | | Type | LL Type | C Type | Size (32-bit) | Size (64-bit) | 19 | +===========+=========+========+===============+===============+ 20 | | ``int`` | Signed | long | 32 | 64 | 21 | +-----------+---------+--------+---------------+---------------+ 22 | | ``long`` | Signed | long | 32 | 64 | 23 | +-----------+---------+--------+---------------+---------------+ 24 | | ``float`` | Float | double | 64 | 64 | 25 | +-----------+---------+--------+---------------+---------------+ 26 | 27 | For more primitive types, you can find them in the 28 | :doc:`primitive type cheat sheet ` section. 29 | 30 | Note that the ``int`` type and ``long`` type are same type in RPython, which 31 | have same low level representation and size. 32 | 33 | All built-in numeric types support the following operations. 34 | 35 | .. literalinclude:: ../code/numeric.py 36 | 37 | .. attention:: 38 | Some operations or built-in functions can be used in Python but currently not 39 | supported in RPython such as ``long()``, ``complex()``, ``conjugate()``, 40 | ``x ** y``, ``divmode(x, y)``, ``pow(x, y)`` and ``float(nan)``. However, 41 | RPython's math library provided some mathematical functions. 42 | 43 | Also, it's worth noting that RPython do constant folding at the compilation 44 | time. Therefore, you may found that some built-in functions work with 45 | RPython's code in some scenarios. For example, you can write ``pow(123, 456)`` 46 | in RPython code and the compiler will calculate the value at the compilation 47 | time. 48 | 49 | The code snippet shows that although RPython does not support above mentioned 50 | built-in functions, it still can do constant folding. For instance, ``divmod(x, y)`` 51 | will not yield any compilation error if x and y are constants. 52 | 53 | .. literalinclude:: ../code/numeric_constfold.py 54 | 55 | In addition to above functions, the following code illustrated some other 56 | unsupported operations in RPython but supported in CPython. 57 | 58 | .. literalinclude:: ../code/numeric_unsupported.py 59 | 60 | .. attention:: 61 | Besides these three built-in numeric types, RPython provides more types such as 62 | ``r_uint``, ``r_int32``, ``r_longlong``, etc in the arithmetic module. For more 63 | information, please refer to :doc:`/rlib/rarithmetic` in the rlib section 64 | 65 | Not like Python, RPython will not automatically use big integer when 66 | appropriate. The big integer type and corresponding operations are provided 67 | in the ``rbigint`` library, please refer to :doc:`/rlib/rbigint` in the rlib 68 | section. 69 | 70 | Bitwise operations 71 | ------------------ 72 | 73 | Bitwise operations on integer types in RPython are same as Python. 74 | 75 | .. literalinclude:: ../code/numeric_bitwise.py 76 | 77 | Additional methods 78 | ------------------ 79 | 80 | In Python, there are several `additional methods 81 | `_ 82 | on integer and float types. 83 | However, *all* these methods are not supported in RPython. For example, 84 | ``int.bit_length()`` and ``long.bit_length()`` can be used to get the number 85 | of bits to present an integer. Others like ``float.as_integer_ratio()``, 86 | ``float.is_integer()``, ``float.hex()``, and ``float.fronhex(S)`` are also 87 | not supported. 88 | 89 | .. attention:: 90 | *All* additional methods such as ``int.bit_length()`` and 91 | ``float.float.as_integer_ratio()`` on numeric types are not supported in 92 | RPython. 93 | 94 | Math functions 95 | -------------- 96 | 97 | In Python, the ``math`` module provides access to the mathematical functions 98 | defined by the C standard. For RPython, you can call math functions in the 99 | similar way. 100 | 101 | The math functions contain 102 | ``fabs``, ``log``, ``log10``, ``log1p``, ``copysign``, ``atan2``, ``frexp``, 103 | ``modf``, ``ldexp``, ``pow``, ``fmod``, ``hypot``, ``floor``, ``sqrt``, ``sin``, 104 | ``cos``, ``acos``, ``asin``, ``atan``, ``ceil``, ``cosh``, ``exp``, ``fabs``, 105 | ``sinh``, ``tan``, ``tanh``, ``acosh``, ``asinh``, ``atanh``, ``expm1``. 106 | These math functions will call corresponding C functions in libc. 107 | 108 | .. literalinclude:: ../code/numeric_math.py 109 | -------------------------------------------------------------------------------- /builtin-types/primitive-type-cheat-sheet.rst: -------------------------------------------------------------------------------- 1 | Primitive Type Cheat Sheet 2 | ========================== 3 | 4 | The following table summarizes RPython's primitive types and corresponding 5 | low-level types, FFI types, and C types. 6 | 7 | +-------------------------+----------------------+--------------+----------------------+ 8 | |RPython Type (Primitive) |LL Type |FFI Type |C Type (64-bit Linux) | 9 | +=========================+======================+==============+======================+ 10 | |``int`` |``Signed`` |``SIGNED`` |``long`` | 11 | +-------------------------+----------------------+--------------+----------------------+ 12 | |``long`` |``Signed`` |``LONG`` |``long`` | 13 | +-------------------------+----------------------+--------------+----------------------+ 14 | |``r_uint`` |``Unsigned`` |``UINT`` |``unsigned long`` | 15 | +-------------------------+----------------------+--------------+----------------------+ 16 | |``r_ulonglong`` |``UnsignedLongLong`` |``ULONGLONG`` |``unsigned long`` | 17 | +-------------------------+----------------------+--------------+----------------------+ 18 | |``r_longlong`` |``SignedLongLong`` |``LONGLONG`` |``long long`` | 19 | +-------------------------+----------------------+--------------+----------------------+ 20 | |``r_longlonglong`` |``SignedLongLongLong``|``__INT128_T``|``__int128_t`` | 21 | +-------------------------+----------------------+--------------+----------------------+ 22 | |``r_singlefloat`` |``SingleFloat`` |``FLOAT`` |``float`` | 23 | +-------------------------+----------------------+--------------+----------------------+ 24 | |``float`` |``Float`` |``DOUBLE`` |``double`` | 25 | +-------------------------+----------------------+--------------+----------------------+ 26 | |``r_longfloat`` |``LongFloat`` |``LONGDOUBLE``|``long double`` | 27 | +-------------------------+----------------------+--------------+----------------------+ 28 | |``char`` |``Char`` |``CHAR`` |``char`` | 29 | +-------------------------+----------------------+--------------+----------------------+ 30 | |``bool`` |``Bool`` | N/A |``boot_t`` | 31 | +-------------------------+----------------------+--------------+----------------------+ 32 | |``NoneType`` |``Void`` |``VOID`` |``void`` | 33 | +-------------------------+----------------------+--------------+----------------------+ 34 | |``unicode`` |``UniChar`` |``WCHAR_T`` |``wchar_t`` | 35 | +-------------------------+----------------------+--------------+----------------------+ 36 | 37 | * RPython types start with ``r_`` can be imported from the ``rpython.rlib.rarithmetic`` module. 38 | * Low-level types can be imported from the ``rpython.rtyper.lltypesystem.lltype`` module. 39 | * FFI types can be imported from the ``rpython.rtyper.lltypesystem.rffi`` module. 40 | 41 | The definitions of these types can be found in the following source code. 42 | 43 | * Arithmetic type (``r_*``): `rpython/rlib/rarithmetic.py `_ 44 | * LL type: `rpython/rtyper/lltypesystem/lltype.py `_ 45 | * FFI type: `rpython/rtyper/lltypesystem/rffi.py `_ 46 | * C type: `rpython/translator/c/primitive.py `_ 47 | 48 | In addition to these primitive types, there are other types like pointer types for FFI. 49 | 50 | .. dump some data structures of lltype, ffi, c types 51 | .. {'AroundFnPtr': <* Func ( ) -> Void>, 52 | 'CConstant': , 53 | 'CallbackHolder': , 54 | 'CompilationError': , 55 | 'ExtRegistryEntry': , 56 | 'ExternalCompilationInfo': , 57 | 'INT': , 58 | 'INTMAX_T': , 59 | 'INTMAX_TP': <* Array of Signed >, 60 | 'INTP': <* Array of INT >, 61 | 'INTPTR_T': , 62 | 'INTPTR_TP': <* Array of Signed >, 63 | 'INT_FAST16_T': , 64 | 'INT_FAST16_TP': <* Array of Signed >, 65 | 'INT_FAST32_T': , 66 | 'INT_FAST32_TP': <* Array of Signed >, 67 | 'INT_FAST64_T': , 68 | 'INT_FAST64_TP': <* Array of Signed >, 69 | 'INT_FAST8_T': , 70 | 'INT_FAST8_TP': <* Array of SIGNEDCHAR >, 71 | 'INT_LEAST16_T': , 72 | 'INT_LEAST16_TP': <* Array of SHORT >, 73 | 'INT_LEAST32_T': , 74 | 'INT_LEAST32_TP': <* Array of INT >, 75 | 'INT_LEAST64_T': , 76 | 'INT_LEAST64_TP': <* Array of Signed >, 77 | 'INT_LEAST8_T': , 78 | 'INT_LEAST8_TP': <* Array of SIGNEDCHAR >, 79 | 'INT_real': , 80 | 'LONG': , 81 | 'LONGLONG': , 82 | 'LONGLONGP': <* Array of Signed >, 83 | 'LONGP': <* Array of Signed >, 84 | 'LONG_BIT': 64, 85 | 'MODE_T': , 86 | 'MODE_TP': <* Array of INT >, 87 | 'NUMBER_TYPES': [, 88 | , 89 | , 90 | , 91 | , 92 | , 93 | , 94 | , 95 | , 96 | , 97 | , 98 | , 99 | , 100 | , 101 | , 102 | , 103 | , 104 | , 105 | , 106 | , 107 | , 108 | , 109 | , 110 | , 111 | , 112 | , 113 | , 114 | , 115 | , 116 | , 117 | , 118 | , 119 | , 120 | , 121 | , 122 | , 123 | , 124 | , 125 | , 126 | ], 127 | 'PID_T': , 128 | 'PID_TP': <* Array of INT >, 129 | 'PTRDIFF_T': , 130 | 'PTRDIFF_TP': <* Array of Signed >, 131 | 'RFFI_ALT_ERRNO': 64, 132 | 'RFFI_ERR_ALL': 27, 133 | 'RFFI_ERR_NONE': 0, 134 | 'RFFI_FULL_ERRNO': 3, 135 | 'RFFI_FULL_ERRNO_ZERO': 5, 136 | 'RFFI_FULL_LASTERROR': 24, 137 | 'RFFI_READSAVED_ERRNO': 2, 138 | 'RFFI_READSAVED_LASTERROR': 16, 139 | 'RFFI_SAVE_ERRNO': 1, 140 | 'RFFI_SAVE_LASTERROR': 8, 141 | 'RFFI_SAVE_WSALASTERROR': 32, 142 | 'RFFI_ZERO_ERRNO_BEFORE': 4, 143 | 'SHORT': , 144 | 'SHORTP': <* Array of SHORT >, 145 | 'SIGNEDCHAR': , 146 | 'SIGNEDCHARP': <* Array of SIGNEDCHAR >, 147 | 'SIZE_T': , 148 | 'SIZE_TP': <* Array of Unsigned >, 149 | 'SSIZE_T': , 150 | 'SSIZE_TP': <* Array of Signed >, 151 | 'SomePtr': , 152 | 'StackCounter': , 153 | 'StringBuilder': , 154 | 'Symbolic': , 155 | 'TIME_T': , 156 | 'TIME_TP': <* Array of Signed >, 157 | 'TYPES': ['short', 158 | 'unsigned short', 159 | 'int', 160 | 'unsigned int', 161 | 'long', 162 | 'unsigned long', 163 | 'signed char', 164 | 'unsigned char', 165 | 'long long', 166 | 'unsigned long long', 167 | 'size_t', 168 | 'time_t', 169 | 'wchar_t', 170 | 'uintptr_t', 171 | 'intptr_t', 172 | 'void*', 173 | '__int128_t', 174 | 'mode_t', 175 | 'pid_t', 176 | 'ssize_t', 177 | 'ptrdiff_t', 178 | 'int_least8_t', 179 | 'uint_least8_t', 180 | 'int_least16_t', 181 | 'uint_least16_t', 182 | 'int_least32_t', 183 | 'uint_least32_t', 184 | 'int_least64_t', 185 | 'uint_least64_t', 186 | 'int_fast8_t', 187 | 'uint_fast8_t', 188 | 'int_fast16_t', 189 | 'uint_fast16_t', 190 | 'int_fast32_t', 191 | 'uint_fast32_t', 192 | 'int_fast64_t', 193 | 'uint_fast64_t', 194 | 'intmax_t', 195 | 'uintmax_t'], 196 | 'UCHAR': , 197 | 'UCHARP': <* Array of UCHAR >, 198 | 'UINT': , 199 | 'UINTMAX_T': , 200 | 'UINTMAX_TP': <* Array of Unsigned >, 201 | 'UINTP': <* Array of UINT >, 202 | 'UINTPTR_T': , 203 | 'UINTPTR_TP': <* Array of Unsigned >, 204 | 'UINT_FAST16_T': , 205 | 'UINT_FAST16_TP': <* Array of Unsigned >, 206 | 'UINT_FAST32_T': , 207 | 'UINT_FAST32_TP': <* Array of Unsigned >, 208 | 'UINT_FAST64_T': , 209 | 'UINT_FAST64_TP': <* Array of Unsigned >, 210 | 'UINT_FAST8_T': , 211 | 'UINT_FAST8_TP': <* Array of UCHAR >, 212 | 'UINT_LEAST16_T': , 213 | 'UINT_LEAST16_TP': <* Array of USHORT >, 214 | 'UINT_LEAST32_T': , 215 | 'UINT_LEAST32_TP': <* Array of UINT >, 216 | 'UINT_LEAST64_T': , 217 | 'UINT_LEAST64_TP': <* Array of Unsigned >, 218 | 'UINT_LEAST8_T': , 219 | 'UINT_LEAST8_TP': <* Array of UCHAR >, 220 | 'ULONG': , 221 | 'ULONGLONG': , 222 | 'ULONGLONGP': <* Array of Unsigned >, 223 | 'ULONGP': <* Array of Unsigned >, 224 | 'USHORT': , 225 | 'USHORTP': <* Array of USHORT >, 226 | 'UnicodeBuilder': , 227 | 'VOID*': , 228 | 'VOID*P': <* Array of Signed >, 229 | 'WCHAR_T': , 230 | 'WCHAR_TP': <* Array of INT >, 231 | '_IsLLPtrEntry': , 232 | '_KEEPER_CACHE': {}, 233 | '__INT128_T': , 234 | '__INT128_TP': <* Array of SignedLongLongLong >, 235 | '__builtins__': , 236 | '__cached__': '/home/mssun/rpython/pypy/rpython/rtyper/lltypesystem/__pycache__/rffi.pypy-41.pyc', 237 | '__doc__': None, 238 | '__file__': '/home/mssun/rpython/pypy/rpython/rtyper/lltypesystem/rffi.py', 239 | '__name__': 'rpython.rtyper.lltypesystem.rffi', 240 | '__package__': 'rpython.rtyper.lltypesystem', 241 | '_isfunctype': , 242 | '_isllptr': , 243 | '_keeper_for_type': , 244 | '_make_wrapper_for': , 245 | '_name': 'long', 246 | 'annmodel': , 247 | 'assert_str0': , 248 | 'cast_ptr_to_adr': , 249 | 'enforceargs': , 250 | 'func_with_new_name': , 251 | 'generate_macro_wrapper': , 252 | 'get_keepalive_object': , 253 | 'itemoffsetof': , 254 | 'jit': , 255 | 'keepalive_until_here': , 256 | 'll2ctypes': , 257 | 'llexternal': , 258 | 'llexternal_use_eci': , 259 | 'llhelper': , 260 | 'llmemory': , 261 | 'lltype': , 262 | 'lltype_to_annotation': , 263 | 'maxint': 9223372036854775807, 264 | 'name': 'unsigned long', 265 | 'os': , 266 | 'platform': , 267 | 'populate_inttypes': , 268 | 'pprint': , 269 | 'py': , 270 | 'r___int128_t': , 271 | 'r_int': , 272 | 'r_int_fast16_t': , 273 | 'r_int_fast32_t': , 274 | 'r_int_fast64_t': , 275 | 'r_int_fast8_t': , 276 | 'r_int_least16_t': , 277 | 'r_int_least32_t': , 278 | 'r_int_least64_t': , 279 | 'r_int_least8_t': , 280 | 'r_int_real': , 281 | 'r_intmax_t': , 282 | 'r_intptr_t': , 283 | 'r_long': , 284 | 'r_longlong': , 285 | 'r_mode_t': , 286 | 'r_pid_t': , 287 | 'r_ptrdiff_t': , 288 | 'r_short': , 289 | 'r_signedchar': , 290 | 'r_size_t': , 291 | 'r_ssize_t': , 292 | 'r_time_t': , 293 | 'r_uchar': , 294 | 'r_uint': , 295 | 'r_uint_fast16_t': , 296 | 'r_uint_fast32_t': , 297 | 'r_uint_fast64_t': , 298 | 'r_uint_fast8_t': , 299 | 'r_uint_least16_t': , 300 | 'r_uint_least32_t': , 301 | 'r_uint_least64_t': , 302 | 'r_uint_least8_t': , 303 | 'r_uintmax_t': , 304 | 'r_uintptr_t': , 305 | 'r_ulong': , 306 | 'r_ulonglong': , 307 | 'r_ushort': , 308 | 'r_void*': , 309 | 'r_wchar_t': , 310 | 'rarithmetic': , 311 | 'register_keepalive': , 312 | 'rgc': , 313 | 'setup': , 314 | 'sizeof_c_type': , 315 | 'specialize': , 316 | 'stackcounter': , 317 | 'sys': , 318 | 'unregister_keepalive': , 319 | 'unrolling_iterable': , 320 | 'we_are_translated': , 321 | 'we_are_translated_to_c': } 322 | 323 | .. ['AroundFnPtr', 324 | 'CArray', 325 | 'CArrayPtr', 326 | 'CCHARP', 327 | 'CCHARPP', 328 | 'CCallback', 329 | 'CConstant', 330 | 'CExternVariable', 331 | 'CFixedArray', 332 | 'CHAR', 333 | 'CONST_CCHARP', 334 | 'COpaque', 335 | 'COpaquePtr', 336 | 'CStruct', 337 | 'CStructPtr', 338 | 'CWCHARP', 339 | 'CWCHARPP', 340 | 'CallbackHolder', 341 | 'CompilationError', 342 | 'DOUBLE', 343 | 'DOUBLEP', 344 | 'ExtRegistryEntry', 345 | 'ExternalCompilationInfo', 346 | 'FLOAT', 347 | 'FLOATP', 348 | 'INT', 349 | 'INTMAX_T', 350 | 'INTMAX_TP', 351 | 'INTP', 352 | 'INTPTR_T', 353 | 'INTPTR_TP', 354 | 'INT_FAST16_T', 355 | 'INT_FAST16_TP', 356 | 'INT_FAST32_T', 357 | 'INT_FAST32_TP', 358 | 'INT_FAST64_T', 359 | 'INT_FAST64_TP', 360 | 'INT_FAST8_T', 361 | 'INT_FAST8_TP', 362 | 'INT_LEAST16_T', 363 | 'INT_LEAST16_TP', 364 | 'INT_LEAST32_T', 365 | 'INT_LEAST32_TP', 366 | 'INT_LEAST64_T', 367 | 'INT_LEAST64_TP', 368 | 'INT_LEAST8_T', 369 | 'INT_LEAST8_TP', 370 | 'INT_real', 371 | 'LONG', 372 | 'LONGDOUBLE', 373 | 'LONGDOUBLEP', 374 | 'LONGLONG', 375 | 'LONGLONGP', 376 | 'LONGP', 377 | 'LONG_BIT', 378 | 'MODE_T', 379 | 'MODE_TP', 380 | 'MakeEntry', 381 | 'NULL', 382 | 'NUMBER_TYPES', 383 | 'PID_T', 384 | 'PID_TP', 385 | 'PTRDIFF_T', 386 | 'PTRDIFF_TP', 387 | 'RFFI_ALT_ERRNO', 388 | 'RFFI_ERR_ALL', 389 | 'RFFI_ERR_NONE', 390 | 'RFFI_FULL_ERRNO', 391 | 'RFFI_FULL_ERRNO_ZERO', 392 | 'RFFI_FULL_LASTERROR', 393 | 'RFFI_READSAVED_ERRNO', 394 | 'RFFI_READSAVED_LASTERROR', 395 | 'RFFI_SAVE_ERRNO', 396 | 'RFFI_SAVE_LASTERROR', 397 | 'RFFI_SAVE_WSALASTERROR', 398 | 'RFFI_ZERO_ERRNO_BEFORE', 399 | 'RawBytes', 400 | 'SHORT', 401 | 'SHORTP', 402 | 'SIGNED', 403 | 'SIGNEDCHAR', 404 | 'SIGNEDCHARP', 405 | 'SIGNEDP', 406 | 'SIGNEDPP', 407 | 'SIZE_T', 408 | 'SIZE_TP', 409 | 'SSIZE_T', 410 | 'SSIZE_TP', 411 | 'SomePtr', 412 | 'StackCounter', 413 | 'StringBuilder', 414 | 'Symbolic', 415 | 'TEST_RAW_ADDR_KEEP_ALIVE', 416 | 'TIME_T', 417 | 'TIME_TP', 418 | 'TYPES', 419 | 'UCHAR', 420 | 'UCHARP', 421 | 'UINT', 422 | 'UINTMAX_T', 423 | 'UINTMAX_TP', 424 | 'UINTP', 425 | 'UINTPTR_T', 426 | 'UINTPTR_TP', 427 | 'UINT_FAST16_T', 428 | 'UINT_FAST16_TP', 429 | 'UINT_FAST32_T', 430 | 'UINT_FAST32_TP', 431 | 'UINT_FAST64_T', 432 | 'UINT_FAST64_TP', 433 | 'UINT_FAST8_T', 434 | 'UINT_FAST8_TP', 435 | 'UINT_LEAST16_T', 436 | 'UINT_LEAST16_TP', 437 | 'UINT_LEAST32_T', 438 | 'UINT_LEAST32_TP', 439 | 'UINT_LEAST64_T', 440 | 'UINT_LEAST64_TP', 441 | 'UINT_LEAST8_T', 442 | 'UINT_LEAST8_TP', 443 | 'ULONG', 444 | 'ULONGLONG', 445 | 'ULONGLONGP', 446 | 'ULONGP', 447 | 'USHORT', 448 | 'USHORTP', 449 | 'UnicodeBuilder', 450 | 'VOID*', 451 | 'VOID*P', 452 | 'VOIDP', 453 | 'VOIDPP', 454 | 'WCHAR_T', 455 | 'WCHAR_TP', 456 | '_IsLLPtrEntry', 457 | '_KEEPER_CACHE', 458 | '__INT128_T', 459 | '__INT128_TP', 460 | '__builtins__', 461 | '__cached__', 462 | '__doc__', 463 | '__file__', 464 | '__name__', 465 | '__not_usable', 466 | '__package__', 467 | '_get_structcopy_fn', 468 | '_isfunctype', 469 | '_isllptr', 470 | '_keeper_for_type', 471 | '_make_wrapper_for', 472 | '_name', 473 | 'alloc_buffer', 474 | 'alloc_unicodebuffer', 475 | 'annmodel', 476 | 'assert_str0', 477 | 'c_memcpy', 478 | 'c_memset', 479 | 'cast', 480 | 'cast_ptr_to_adr', 481 | 'charp2str', 482 | 'charp2strn', 483 | 'charpp2liststr', 484 | 'charpsize2str', 485 | 'enforceargs', 486 | 'free_charp', 487 | 'free_charpp', 488 | 'free_nonmoving_unicodebuffer', 489 | 'free_nonmovingbuffer', 490 | 'free_wcharp', 491 | 'func_with_new_name', 492 | 'generate_macro_wrapper', 493 | 'get_keepalive_object', 494 | 'get_nonmoving_unicodebuffer', 495 | 'get_nonmovingbuffer', 496 | 'get_nonmovingbuffer_final_null', 497 | 'get_raw_address_of_string', 498 | 'getintfield', 499 | 'itemoffsetof', 500 | 'jit', 501 | 'keep_buffer_alive_until_here', 502 | 'keep_unicodebuffer_alive_until_here', 503 | 'keepalive_until_here', 504 | 'liststr2charpp', 505 | 'll2ctypes', 506 | 'll_liststr2charpp', 507 | 'llexternal', 508 | 'llexternal_use_eci', 509 | 'llhelper', 510 | 'llmemory', 511 | 'lltype', 512 | 'lltype_to_annotation', 513 | 'make', 514 | 'make_string_mappings', 515 | 'maxint', 516 | 'name', 517 | 'offsetof', 518 | 'os', 519 | 'platform', 520 | 'populate_inttypes', 521 | 'pprint', 522 | 'ptradd', 523 | 'py', 524 | 'r___int128_t', 525 | 'r_int', 526 | 'r_int_fast16_t', 527 | 'r_int_fast32_t', 528 | 'r_int_fast64_t', 529 | 'r_int_fast8_t', 530 | 'r_int_least16_t', 531 | 'r_int_least32_t', 532 | 'r_int_least64_t', 533 | 'r_int_least8_t', 534 | 'r_int_real', 535 | 'r_intmax_t', 536 | 'r_intptr_t', 537 | 'r_long', 538 | 'r_longlong', 539 | 'r_mode_t', 540 | 'r_pid_t', 541 | 'r_ptrdiff_t', 542 | 'r_short', 543 | 'r_signedchar', 544 | 'r_singlefloat', 545 | 'r_size_t', 546 | 'r_ssize_t', 547 | 'r_time_t', 548 | 'r_uchar', 549 | 'r_uint', 550 | 'r_uint_fast16_t', 551 | 'r_uint_fast32_t', 552 | 'r_uint_fast64_t', 553 | 'r_uint_fast8_t', 554 | 'r_uint_least16_t', 555 | 'r_uint_least32_t', 556 | 'r_uint_least64_t', 557 | 'r_uint_least8_t', 558 | 'r_uintmax_t', 559 | 'r_uintptr_t', 560 | 'r_ulong', 561 | 'r_ulonglong', 562 | 'r_ushort', 563 | 'r_void*', 564 | 'r_wchar_t', 565 | 'rarithmetic', 566 | 'register_keepalive', 567 | 'rgc', 568 | 'scoped_alloc_buffer', 569 | 'scoped_alloc_unicodebuffer', 570 | 'scoped_nonmoving_unicodebuffer', 571 | 'scoped_nonmovingbuffer', 572 | 'scoped_str2charp', 573 | 'scoped_unicode2wcharp', 574 | 'scoped_view_charp', 575 | 'setintfield', 576 | 'setup', 577 | 'size_and_sign', 578 | 'sizeof', 579 | 'sizeof_c_type', 580 | 'specialize', 581 | 'stackcounter', 582 | 'str2chararray', 583 | 'str2charp', 584 | 'str2rawmem', 585 | 'str_from_buffer', 586 | 'structcopy', 587 | 'sys', 588 | 'unicode2rawmem', 589 | 'unicode2wchararray', 590 | 'unicode2wcharp', 591 | 'unicode_from_buffer', 592 | 'unregister_keepalive', 593 | 'unrolling_iterable', 594 | 'wcharp2unicode', 595 | 'wcharp2unicoden', 596 | 'wcharpsize2unicode', 597 | 'we_are_translated', 598 | 'we_are_translated_to_c'] 599 | 600 | .. ['BaseIntTypeEntry', 601 | 'BaseIntValueEntry', 602 | 'Constant', 603 | 'For_r_singlefloat_type_Entry', 604 | 'For_r_singlefloat_values_Entry', 605 | 'INT_MAX', 606 | 'INT_MIN', 607 | 'LONGLONGLONG_BIT', 608 | 'LONGLONGLONG_MASK', 609 | 'LONGLONGLONG_TEST', 610 | 'LONGLONG_BIT', 611 | 'LONGLONG_MASK', 612 | 'LONGLONG_TEST', 613 | 'LONG_BIT', 614 | 'LONG_BIT_SHIFT', 615 | 'LONG_MASK', 616 | 'LONG_TEST', 617 | 'SHRT_MAX', 618 | 'SHRT_MIN', 619 | 'UINT_MAX', 620 | 'USHRT_MAX', 621 | '__builtins__', 622 | '__cached__', 623 | '__doc__', 624 | '__file__', 625 | '__name__', 626 | '__package__', 627 | '_get_bitsize', 628 | '_get_long_bit', 629 | '_inttypes', 630 | '_long_typecode', 631 | '_should_widen_type', 632 | 'base_int', 633 | 'build_int', 634 | 'byteswap', 635 | 'compute_restype', 636 | 'const', 637 | 'extregistry', 638 | 'get_long_pattern', 639 | 'highest_bit', 640 | 'int_between', 641 | 'int_c_div', 642 | 'int_c_mod', 643 | 'int_force_ge_zero', 644 | 'intmask', 645 | 'is_emulated_long', 646 | 'is_signed_integer_type', 647 | 'is_valid_int', 648 | 'longlonglongmask', 649 | 'longlongmask', 650 | 'longlongmax', 651 | 'math', 652 | 'maxint', 653 | 'most_neg_value_of', 654 | 'most_neg_value_of_same_type', 655 | 'most_pos_value_of', 656 | 'most_pos_value_of_same_type', 657 | 'normalizedinttype', 658 | 'not_rpython', 659 | 'objectmodel', 660 | 'ovfcheck', 661 | 'ovfcheck_float_to_int', 662 | 'ovfcheck_float_to_longlong', 663 | 'ovfcheck_int32_add', 664 | 'ovfcheck_int32_mul', 665 | 'ovfcheck_int32_sub', 666 | 'r_int', 667 | 'r_int32', 668 | 'r_int64', 669 | 'r_longfloat', 670 | 'r_longlong', 671 | 'r_longlonglong', 672 | 'r_singlefloat', 673 | 'r_uint', 674 | 'r_uint32', 675 | 'r_uint64', 676 | 'r_ulonglong', 677 | 'register_flow_sc', 678 | 'sc_r_uint', 679 | 'signed_int', 680 | 'signedtype', 681 | 'specialize', 682 | 'string_to_int', 683 | 'struct', 684 | 'sys', 685 | 'unsigned_int', 686 | 'widen'] 687 | 688 | .. {: 'Signed @', 689 | : 'Unsigned @', 690 | : '__int128_t @', 691 | : 'int @', 692 | : 'unsigned short @', 693 | : 'unsigned char @', 694 | : 'unsigned int @', 695 | : 'signed char @', 696 | : 'short @', 697 | : 'int @', 698 |
: 'void* @', 699 | : 'float @', 700 | : 'double @', 701 | : 'long double @', 702 | : 'char @', 703 | : 'bool_t @', 704 | : 'void @', 705 | : 'wchar_t @', 706 | <* GCREF (gcopaque)>: 'void* @'} 707 | -------------------------------------------------------------------------------- /builtin-types/sequence.rst: -------------------------------------------------------------------------------- 1 | Sequence Types 2 | ============== 3 | 4 | There are seven sequence types: strings, Unicode strings, lists, tuples, 5 | bytearrays, buffers, and xrange objects. For other containers see the 6 | built in dict and set classes. These types can be used in RPython same 7 | as in Python. 8 | 9 | .. literalinclude:: ../code/sequence.py 10 | 11 | Most operations for sequence types are supported in RPython, but some have 12 | restrictions. Such as slicing with negative indexes and min/max builtin methods. 13 | 14 | .. literalinclude:: ../code/sequence_unsupported.py 15 | 16 | string 17 | ------ 18 | 19 | Only a few string methods are supported in RPython. Besides the limited methods 20 | in RPython, there are also some restrictions of indexing, slicing, and string 21 | formating. Also, note that the type of items in a list should be same, and you 22 | cannot mix types in a RPython list. 23 | The following examples show some supported methods and usages in RPython. 24 | 25 | .. literalinclude:: ../code/strings.py 26 | 27 | .. attention:: 28 | * Not all string methods are supported and those that are supported, not 29 | necesarilly accept all arguments. 30 | * Indexes can be negative. In case they are not, then you get slightly more 31 | efficient code if the translator can prove that they are non-negative. When 32 | slicing a string it is necessary to prove that the slice start and stop 33 | indexes are non-negative. 34 | * No implicit str-to-unicode cast. 35 | * Simple string formatting using the ``%`` operator works, as long as the 36 | format string is known at translation time; the only supported formatting 37 | specifiers are ``%s``, ``%d``, ``%x``, ``%o``, ``%f``, plus ``%r`` but only 38 | for user-defined instances 39 | * Modifiers such as conversion flags, precision, length etc. are not 40 | supported. 41 | * It is forbidden to mix unicode and strings when formatting. 42 | 43 | The following examples show some unsupported methods and usages in RPython, but 44 | can be used in a normal Python implementation. 45 | 46 | .. literalinclude:: ../code/strings_unsupported.py 47 | 48 | list 49 | ---- 50 | 51 | Most list operations and methods are supported in RPython. However, methods 52 | may have some restrictions. The following examples illustrate usages of the list 53 | in RPython and some unsupported operations as well. 54 | 55 | .. literalinclude:: ../code/lists.py 56 | 57 | .. attention:: 58 | lists are used as an allocated array. Lists are over-allocated, so list.append() 59 | is reasonably fast. However, if you use a fixed-size list, the code 60 | is more efficient. Annotator can figure out most of the time that your 61 | list is fixed-size, even when you use list comprehension. 62 | Negative or out-of-bound indexes are only allowed for the 63 | most common operations, as follows: 64 | 65 | - *indexing*: 66 | positive and negative indexes are allowed. Indexes are checked when requested 67 | by an IndexError exception clause. 68 | 69 | - *slicing*: 70 | the slice start must be within bounds. The stop doesn't need to, but it must 71 | not be smaller than the start. All negative indexes are disallowed, except for 72 | the [:-1] special case. No step. Slice deletion follows the same rules. 73 | 74 | - *slice assignment*: 75 | only supports ``lst[x:y] = sublist``, if ``len(sublist) == y - x``. 76 | In other words, slice assignment cannot change the total length of the list, 77 | but just replace items. 78 | 79 | - *other operators*: 80 | ``+``, ``+=``, ``in``, ``*``, ``*=``, ``==``, ``!=`` work as expected. 81 | 82 | - *methods*: 83 | append, index, insert, extend, reverse, pop. The index used in pop() follows 84 | the same rules as for *indexing* above. The index used in insert() must be within 85 | bounds and not negative. 86 | 87 | .. literalinclude:: ../code/lists_unsupported.py 88 | 89 | tuple 90 | ----- 91 | 92 | Tuples in RPython are very different. There are many restrictions to use tuples. 93 | 94 | .. literalinclude:: ../code/tuples.py 95 | 96 | The restrictions can be summarized as follows. 97 | 98 | .. attention:: 99 | * no variable-length tuples; use them to store or return pairs or n-tuples of 100 | values. Each combination of types for elements and length constitute a 101 | separate and not mixable type. 102 | * There is no general way to convert a list into a tuple, because the length 103 | of the result would not be known statically. (You can of course do 104 | ``t = (lst[0], lst[1], lst[2])`` if you know that lst has got 3 items.) 105 | 106 | xrange 107 | ------ 108 | 109 | The following examples illustrate the usage of ``range`` and ``xrange`` in 110 | RPython. ``range`` and ``xrange`` are identical. ``range`` does not necessarily 111 | create an array, only if the result is modified. 112 | 113 | .. literalinclude:: ../code/xrange.py 114 | -------------------------------------------------------------------------------- /builtin-types/set.rst: -------------------------------------------------------------------------------- 1 | Set Types 2 | ========= 3 | 4 | A set object is an unordered collection of distinct hashable objects. Common 5 | uses include membership testing, removing duplicates from a sequence, and 6 | computing mathematical operations such as intersection, union, difference, and 7 | symmetric difference. There are two built-in types in Python: ``set`` and 8 | ``frozenset``. *However, both types are not supported in RPython*. 9 | 10 | .. attention:: 11 | sets are not directly supported in RPython. Instead you should use a plain 12 | dict and fill the values with None. Values in that dict will not consume 13 | space. 14 | 15 | Right now, we can use dict to simulate a set. 16 | 17 | .. literalinclude:: ../code/sets.py 18 | 19 | All set operations and methods in the following code are *not supported* in 20 | RPython. 21 | 22 | .. literalinclude:: ../code/sets_unsupported.py 23 | -------------------------------------------------------------------------------- /builtin-types/truth-value-testing.rst: -------------------------------------------------------------------------------- 1 | Truth Value Testing 2 | =================== 3 | 4 | The truth value testing of RPython is similar with Python. 5 | 6 | Any object can be tested for truth value, for use in an if or while condition or 7 | as operand of the Boolean operations below. The following values are considered 8 | false: 9 | 10 | 11 | * ``None`` 12 | * ``False`` 13 | * zero of any numeric type, for example, ``0``, ``0L``, ``0.0``. 14 | * any empty sequence, for example, ``''``, ``()``, ``[]``. 15 | * any empty mapping, for example, ``{}``. 16 | 17 | All other values are considered true — so objects of many types are always true. 18 | 19 | Operations and built-in functions that have a Boolean result always return ``0`` or 20 | ``False`` for false and 1 or ``True`` for true, unless otherwise stated. (Important 21 | exception: the Boolean operations ``or`` and ``and`` always return one of their 22 | operands.) 23 | 24 | .. literalinclude:: ../code/truth_value_testing.py 25 | 26 | .. attention:: 27 | However, there is one inconsistency. In Python, the following values are 28 | considered *false*: 29 | 30 | * instances of user-defined classes, if the class defines a ``__nonzero__()`` or 31 | ``__len__()`` method, when that method returns the integer zero or ``bool`` value 32 | ``False``. 33 | 34 | In RPython, the above values are considered *true*. 35 | 36 | For example, we have two classes: ``ZeroLen`` and ``NonZero``. They define 37 | ``__len__()`` and ``__nonzero__()`` methods respectively. Truth value testing of 38 | instances of ``ZeroLen`` and ``NonZero`` are *different* in RPython and Python. 39 | 40 | .. literalinclude:: ../code/truth_value_testing_inconsistency.py 41 | 42 | However, the execution results are inconsistent using RPython and Python 43 | 44 | .. code-block:: shell 45 | 46 | $ rpython truth_value_testing_inconsistency.py # compile with RPython 47 | $ ./truth_value_testing_inconsistency-c 48 | zero_len is True in RPython. 49 | non_zero is True in RPython. 50 | 51 | $ python truth_value_testing_inconsistency.py # interpret with Python 52 | zero_len is False in Python. 53 | non_zero is False in Python. 54 | -------------------------------------------------------------------------------- /classes/index.rst: -------------------------------------------------------------------------------- 1 | Classes 2 | ======= 3 | 4 | Classes in RPython are very similar with Python. You can inherit a class 5 | and override methods. 6 | 7 | .. attention:: 8 | There are some restrictions in RPython: 1) methods and other class attributes 9 | do not change after startup, 2) only single inheritance is supported. 10 | 11 | .. literalinclude:: ../code/classes.py 12 | 13 | Multiple inheritance only supported with *mixin*. 14 | 15 | .. attention:: 16 | use ``rpython.rlib.objectmodel.import_from_mixin(M)`` in a class body to copy 17 | the whole content of a class M. This can be used to implement mixins: 18 | functions and staticmethods are duplicated (the other class attributes are 19 | just copied unmodified). 20 | 21 | .. literalinclude:: ../code/classes_mixin.py 22 | -------------------------------------------------------------------------------- /code/Makefile: -------------------------------------------------------------------------------- 1 | src = $(filter-out $(wildcard *_unsupported.py) $(wildcard *_error.py), $(wildcard *.py)) 2 | obj = $(src:.py=) 3 | 4 | RPYFLAGS = -O0 5 | RPY ?= rpython 6 | 7 | all: $(obj) 8 | 9 | %: %.py 10 | $(RPY) $(RPYFLAGS) $^ 11 | 12 | clean: 13 | @rm -f *-c 14 | @rm -rf __pycache__ 15 | -------------------------------------------------------------------------------- /code/annotator_error.py: -------------------------------------------------------------------------------- 1 | def func(): return 0 2 | def compiler_error(arg): 3 | func(1) 4 | 5 | def entry_point(argv): compiler_error(argv[1]); return 0 6 | def target(*args): return entry_point 7 | -------------------------------------------------------------------------------- /code/benchmarks/Makefile: -------------------------------------------------------------------------------- 1 | src = $(wildcard *_rpy.py) 2 | obj = $(src:.py=) 3 | 4 | RPYFLAGS = -O0 5 | 6 | all: $(obj) 7 | 8 | %: %.py 9 | $(RPY) $(RPYFLAGS) $^ 10 | 11 | clean: 12 | @rm -f *-c 13 | @rm -rf __pycache__ 14 | -------------------------------------------------------------------------------- /code/benchmarks/binary-tree.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # 5 | # contributed by Antoine Pitrou 6 | # modified by Dominique Wahli and Daniel Nanz 7 | 8 | def make_tree(i, d): 9 | 10 | if d > 0: 11 | i2 = i + i 12 | d -= 1 13 | return (i, make_tree(i2 - 1, d), make_tree(i2, d)) 14 | return (i, None, None) 15 | 16 | 17 | def check_tree(node): 18 | 19 | (i, l, r) = node 20 | if l is None: 21 | return i 22 | else: 23 | return i + check_tree(l) - check_tree(r) 24 | 25 | 26 | def make_check(itde, make=make_tree, check=check_tree): 27 | 28 | i, d = itde 29 | return check(make(i, d)) 30 | 31 | 32 | def get_argchunks(i, d, chunksize=5000): 33 | 34 | assert chunksize % 2 == 0 35 | chunk = [] 36 | for k in range(1, i + 1): 37 | chunk.extend([(k, d), (-k, d)]) 38 | if len(chunk) == chunksize: 39 | yield chunk 40 | chunk = [] 41 | if len(chunk) > 0: 42 | yield chunk 43 | 44 | 45 | def main(n, min_depth=4): 46 | 47 | max_depth = max(min_depth + 2, n) 48 | stretch_depth = max_depth + 1 49 | 50 | print 'stretch tree of depth %d\t check: %d' % ( 51 | stretch_depth, make_check((0, stretch_depth))) 52 | 53 | long_lived_tree = make_tree(0, max_depth) 54 | 55 | mmd = max_depth + min_depth 56 | for d in range(min_depth, stretch_depth, 2): 57 | i = 2 ** (mmd - d) 58 | cs = 0 59 | for argchunk in get_argchunks(i,d): 60 | cs += sum(map(make_check, argchunk)) 61 | print '%d\t trees of depth %d\t check: %d' % (i * 2, d, cs) 62 | 63 | print 'long lived tree of depth %d\t check: %d' % ( 64 | max_depth, check_tree(long_lived_tree)) 65 | 66 | 67 | if __name__ == '__main__': 68 | main(17) 69 | -------------------------------------------------------------------------------- /code/benchmarks/binary-tree_rpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # 5 | # contributed by Antoine Pitrou 6 | # modified by Dominique Wahli and Daniel Nanz 7 | 8 | import math 9 | 10 | class Node(object): 11 | """ 12 | Represent nodes in a binary tree. 13 | """ 14 | def __init__(self, value, left, right): 15 | self.value = value 16 | self.left = left # left node 17 | self.right = right # right node 18 | 19 | def make_tree(i, d): 20 | 21 | if d > 0: 22 | i2 = i + i 23 | d -= 1 24 | return Node(i, make_tree(i2 - 1, d), make_tree(i2, d)) 25 | return Node(i, None, None) # use Node instead of tuple 26 | 27 | 28 | def check_tree(node): 29 | 30 | (i, l, r) = (node.value, node.left, node.right) 31 | if l is None: 32 | return i 33 | else: 34 | return i + check_tree(l) - check_tree(r) 35 | 36 | 37 | def make_check(itde, make=make_tree, check=check_tree): 38 | 39 | i, d = itde 40 | return check(make(i, d)) 41 | 42 | 43 | def get_argchunks(i, d, chunksize=5000): 44 | 45 | assert chunksize % 2 == 0 46 | chunk = [] 47 | for k in range(1, i + 1): 48 | chunk.extend([(k, d), (-k, d)]) 49 | if len(chunk) == chunksize: 50 | yield chunk 51 | chunk = [] 52 | if len(chunk) > 0: 53 | yield chunk 54 | 55 | 56 | def main(n, min_depth=4): 57 | 58 | max_depth = max(min_depth + 2, n) 59 | stretch_depth = max_depth + 1 60 | 61 | print 'stretch tree of depth %d\t check: %d' % ( 62 | stretch_depth, make_check((0, stretch_depth))) 63 | 64 | long_lived_tree = make_tree(0, max_depth) 65 | 66 | mmd = max_depth + min_depth 67 | for d in range(min_depth, stretch_depth, 2): 68 | i = int(math.pow(2, (mmd - d))) # use math.pow instead of built-in pow 69 | cs = 0 70 | for argchunk in get_argchunks(i,d): # write the sum built-in function 71 | s = 0 72 | for a in argchunk: 73 | s += make_check(a) 74 | cs += s 75 | print '%d\t trees of depth %d\t check: %d' % (i*2, d, cs) 76 | 77 | print 'long lived tree of depth %d\t check: %d' % ( 78 | max_depth, check_tree(long_lived_tree)) 79 | 80 | if __name__ == '__main__': 81 | main(17) 82 | 83 | def entry_point(argv): 84 | main(int(argv[1])) # get argument from input to avoid optimization 85 | return 0 86 | 87 | # add a target 88 | def target(*args): return entry_point, None 89 | -------------------------------------------------------------------------------- /code/benchmarks/buffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | table = [range(1000) for i in range(1000)] 5 | 6 | class a(object): 7 | def main(self, table): 8 | _buffer = [] 9 | _buffer_write = _buffer.append 10 | _buffer_write(u'') 11 | _buffer_write(u'\n') 12 | for row in table: 13 | _buffer_write(u'') 14 | _buffer_write(u'\n') 15 | for column in row: 16 | _buffer_write(u'') 19 | _buffer_write(u'\n') 20 | _buffer_write(u'') 21 | _buffer_write(u'\n') 22 | _buffer_write(u'
') 17 | _buffer_write('%s' % column) 18 | _buffer_write(u'
') 23 | _buffer_write(u'\n') 24 | return ''.join(_buffer) 25 | 26 | 27 | if __name__ == '__main__': 28 | a().main(table) 29 | -------------------------------------------------------------------------------- /code/benchmarks/buffer_rpy.py: -------------------------------------------------------------------------------- 1 | class a(object): 2 | def main(self, table): 3 | _buffer = [] 4 | _buffer_write = _buffer.append 5 | _buffer_write(u'') 6 | _buffer_write(u'\n') 7 | for row in table: 8 | _buffer_write(u'') 9 | _buffer_write(u'\n') 10 | for column in row: 11 | _buffer_write(u'') 14 | _buffer_write(u'\n') 15 | _buffer_write(u'') 16 | _buffer_write(u'\n') 17 | _buffer_write(u'
') 12 | _buffer_write(u'%d' % column) 13 | _buffer_write(u'
') 18 | _buffer_write(u'\n') 19 | return u''.join(_buffer) 20 | 21 | if __name__ == '__main__': 22 | import sys 23 | table = [range(int(sys.argv[1])) for i in range(int(sys.argv[1]))] 24 | a().main(table) 25 | 26 | def entry_point(argv): 27 | table = [range(int(argv[1])) for i in range(int(argv[1]))] 28 | a().main(table) 29 | return 0 30 | 31 | def target(*args): 32 | return entry_point, None 33 | -------------------------------------------------------------------------------- /code/benchmarks/fannkuch.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # 5 | # contributed by Sokolov Yura 6 | # modified by Tupteq 7 | 8 | def fannkuch(n): 9 | count = range(1, n+1) 10 | max_flips = 0 11 | m = n-1 12 | r = n 13 | check = 0 14 | perm1 = range(n) 15 | perm = range(n) 16 | perm1_ins = perm1.insert 17 | perm1_pop = perm1.pop 18 | 19 | while 1: 20 | if check < 30: 21 | #print "".join(str(i+1) for i in perm1) 22 | check += 1 23 | 24 | while r != 1: 25 | count[r-1] = r 26 | r -= 1 27 | 28 | if perm1[0] != 0 and perm1[m] != m: 29 | perm = perm1[:] 30 | flips_count = 0 31 | k = perm[0] 32 | while k: 33 | perm[:k+1] = perm[k::-1] 34 | flips_count += 1 35 | k = perm[0] 36 | 37 | if flips_count > max_flips: 38 | max_flips = flips_count 39 | 40 | while r != n: 41 | perm1_ins(r, perm1_pop(0)) 42 | count[r] -= 1 43 | if count[r] > 0: 44 | break 45 | r += 1 46 | else: 47 | return max_flips 48 | 49 | DEFAULT_ARG = 9 50 | 51 | def main(n): 52 | for i in range(n): 53 | fannkuch(DEFAULT_ARG) 54 | 55 | if __name__ == "__main__": 56 | print main(10) 57 | -------------------------------------------------------------------------------- /code/benchmarks/fannkuch_rpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # 5 | # contributed by Sokolov Yura 6 | # modified by Tupteq 7 | 8 | def fannkuch(n): 9 | count = range(1, n+1) 10 | max_flips = 0 11 | m = n-1 12 | r = n 13 | check = 0 14 | perm1 = range(n) 15 | perm = range(n) 16 | perm1_ins = perm1.insert 17 | perm1_pop = perm1.pop 18 | 19 | while 1: 20 | if check < 30: 21 | #print "".join(str(i+1) for i in perm1) 22 | check += 1 23 | 24 | while r != 1: 25 | count[r-1] = r 26 | r -= 1 27 | 28 | if perm1[0] != 0 and perm1[m] != m: 29 | perm = perm1[:] 30 | flips_count = 0 31 | k = perm[0] 32 | while k: 33 | tmp = perm[:k+1] 34 | tmp.reverse() 35 | perm[:k+1] = tmp 36 | flips_count += 1 37 | k = perm[0] 38 | 39 | if flips_count > max_flips: 40 | max_flips = flips_count 41 | 42 | while r != n: 43 | perm1_ins(r, perm1_pop(0)) 44 | count[r] -= 1 45 | if count[r] > 0: 46 | break 47 | r += 1 48 | else: 49 | return max_flips 50 | 51 | def main(n1, n2=9): 52 | for i in range(n1): 53 | fannkuch(n2) 54 | 55 | if __name__ == "__main__": 56 | main(10) 57 | 58 | def entry_point(argv): 59 | main(int(argv[1]), int(argv[2])) 60 | return 0 61 | 62 | def target(*args): 63 | return entry_point, None 64 | -------------------------------------------------------------------------------- /code/benchmarks/fib.py: -------------------------------------------------------------------------------- 1 | def fib(n): 2 | if n == 0 or n == 1: 3 | return 1 4 | return fib(n - 1) + fib(n - 2) 5 | 6 | def main(): 7 | fib(40) 8 | 9 | if __name__ == '__main__': 10 | main() 11 | -------------------------------------------------------------------------------- /code/benchmarks/fib_rpy.py: -------------------------------------------------------------------------------- 1 | def fib(n): 2 | if n == 0 or n == 1: 3 | return 1 4 | return fib(n - 1) + fib(n - 2) 5 | 6 | # n should not be a constant, otherwise RPython will optimize it 7 | def main(n): 8 | ret = fib(n) 9 | # output the result, otherwise RPython will optimize out the above call 10 | # (the `transform_dead_op_vars` pass) 11 | print ret 12 | 13 | def target(*args): # we need a target function 14 | return entry_point, None 15 | 16 | def entry_point(argv): 17 | main(int(argv[1])) # get n from the arguments 18 | return 0 19 | -------------------------------------------------------------------------------- /code/benchmarks/float.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from math import sin, cos, sqrt 4 | 5 | class Point(object): 6 | 7 | def __init__(self, i): 8 | self.x = x = sin(i) 9 | self.y = cos(i) * 3 10 | self.z = (x * x) / 2 11 | 12 | def __repr__(self): 13 | return "" % (self.x, self.y, self.z) 14 | 15 | def normalize(self): 16 | x = self.x 17 | y = self.y 18 | z = self.z 19 | norm = sqrt(x * x + y * y + z * z) 20 | self.x /= norm 21 | self.y /= norm 22 | self.z /= norm 23 | 24 | def maximize(self, other): 25 | self.x = self.x if self.x > other.x else other.x 26 | self.y = self.y if self.y > other.y else other.y 27 | self.z = self.z if self.z > other.z else other.z 28 | return self 29 | 30 | 31 | def maximize(points): 32 | next = points[0] 33 | for p in points[1:]: 34 | next = next.maximize(p) 35 | return next 36 | 37 | def benchmark(n): 38 | points = [None] * n 39 | for i in xrange(n): 40 | points[i] = Point(i) 41 | for p in points: 42 | p.normalize() 43 | return maximize(points) 44 | 45 | def main(arg, POINTS = 100000): 46 | for i in xrange(arg): 47 | o = benchmark(POINTS) 48 | 49 | if __name__ == "__main__": 50 | main(100) 51 | 52 | def entry_point(argv): 53 | main(int(argv[1])) 54 | return 0 55 | 56 | def target(*args): 57 | return entry_point, None 58 | -------------------------------------------------------------------------------- /code/benchmarks/float_rpy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | from math import sin, cos, sqrt 4 | 5 | class Point(object): 6 | 7 | def __init__(self, i): 8 | self.x = x = sin(i) 9 | self.y = cos(i) * 3 10 | self.z = (x * x) / 2 11 | 12 | def __repr__(self): 13 | return "" % (self.x, self.y, self.z) 14 | 15 | def normalize(self): 16 | x = self.x 17 | y = self.y 18 | z = self.z 19 | norm = sqrt(x * x + y * y + z * z) 20 | self.x /= norm 21 | self.y /= norm 22 | self.z /= norm 23 | 24 | def maximize(self, other): 25 | self.x = self.x if self.x > other.x else other.x 26 | self.y = self.y if self.y > other.y else other.y 27 | self.z = self.z if self.z > other.z else other.z 28 | return self 29 | 30 | 31 | def maximize(points): 32 | next = points[0] 33 | for p in points[1:]: 34 | next = next.maximize(p) 35 | return next 36 | 37 | def benchmark(n): 38 | points = [None] * n 39 | for i in xrange(n): 40 | points[i] = Point(i) 41 | for p in points: 42 | p.normalize() 43 | return maximize(points) 44 | 45 | def main(arg, POINTS = 100000): 46 | for i in xrange(arg): 47 | o = benchmark(POINTS) 48 | 49 | if __name__ == "__main__": 50 | main(100) 51 | 52 | def entry_point(argv): 53 | main(int(argv[1])) 54 | return 0 55 | 56 | def target(*args): 57 | return entry_point, None 58 | -------------------------------------------------------------------------------- /code/benchmarks/spectral-norm.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # Contributed by Sebastien Loisel 5 | # Fixed by Isaac Gouy 6 | # Sped up by Josh Goldfoot 7 | # Dirtily sped up by Simon Descarpentries 8 | # Concurrency by Jason Stitt 9 | 10 | from itertools import izip 11 | 12 | def eval_A (i, j): 13 | return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1) 14 | 15 | def eval_A_times_u (u): 16 | args = ((i,u) for i in xrange(len(u))) 17 | return map(part_A_times_u, args) 18 | 19 | def eval_At_times_u (u): 20 | args = ((i,u) for i in xrange(len(u))) 21 | return map(part_At_times_u, args) 22 | 23 | def eval_AtA_times_u (u): 24 | return eval_At_times_u (eval_A_times_u (u)) 25 | 26 | def part_A_times_u((i,u)): 27 | partial_sum = 0 28 | for j, u_j in enumerate(u): 29 | partial_sum += eval_A (i, j) * u_j 30 | return partial_sum 31 | 32 | def part_At_times_u((i,u)): 33 | partial_sum = 0 34 | for j, u_j in enumerate(u): 35 | partial_sum += eval_A (j, i) * u_j 36 | return partial_sum 37 | 38 | DEFAULT_N = 130 39 | 40 | def main(n): 41 | for i in range(n): 42 | u = [1] * DEFAULT_N 43 | 44 | for dummy in xrange (10): 45 | v = eval_AtA_times_u (u) 46 | u = eval_AtA_times_u (v) 47 | 48 | vBv = vv = 0 49 | 50 | for ue, ve in izip (u, v): 51 | vBv += ue * ve 52 | vv += ve * ve 53 | 54 | if __name__ == "__main__": 55 | main(400) 56 | -------------------------------------------------------------------------------- /code/benchmarks/spectral-norm_rpy.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # The Computer Language Benchmarks Game 3 | # http://shootout.alioth.debian.org/ 4 | # Contributed by Sebastien Loisel 5 | # Fixed by Isaac Gouy 6 | # Sped up by Josh Goldfoot 7 | # Dirtily sped up by Simon Descarpentries 8 | # Concurrency by Jason Stitt 9 | 10 | def eval_A (i, j): 11 | return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1) 12 | 13 | def eval_A_times_u (u): 14 | args = [] 15 | for i in range(len(u)): 16 | args.append((i, u)) 17 | ret = [] 18 | for i in args: 19 | ret.append(part_A_times_u(i)) 20 | return ret 21 | 22 | def eval_At_times_u (u): 23 | args = [] 24 | for i in range(len(u)): 25 | args.append((i, u)) 26 | ret = [] 27 | for i in args: 28 | tmp = part_At_times_u(i) 29 | ret.append(tmp) 30 | return ret 31 | 32 | def eval_AtA_times_u (u): 33 | return eval_At_times_u (eval_A_times_u (u)) 34 | 35 | def part_A_times_u((i,u)): 36 | partial_sum = 0 37 | for j, u_j in enumerate(u): 38 | partial_sum += eval_A (i, j) * u_j 39 | return partial_sum 40 | 41 | def part_At_times_u((i,u)): 42 | partial_sum = 0 43 | for j, u_j in enumerate(u): 44 | partial_sum += eval_A (j, i) * u_j 45 | return partial_sum 46 | 47 | DEFAULT_N = 130 48 | 49 | def main(n): 50 | for i in range(n): 51 | v = [] 52 | u = [1] * DEFAULT_N 53 | 54 | for dummy in xrange (10): 55 | v = eval_AtA_times_u (u) 56 | u = eval_AtA_times_u (v) 57 | 58 | vBv = vv = 0 59 | 60 | l = 0 61 | if len(u) > len(v): l = len(u) 62 | else: l = len(v) 63 | for i in range(l): 64 | vBv += u[i] * v[i] 65 | vv += v[i] * v[i] 66 | print vBv, vv 67 | 68 | if __name__ == "__main__": 69 | main(400) 70 | 71 | def entry_point(argv): 72 | main(int(argv[1])) 73 | return 0 74 | 75 | def target(*args): 76 | return entry_point, None 77 | -------------------------------------------------------------------------------- /code/bf.py: -------------------------------------------------------------------------------- 1 | import os 2 | from rpython.rlib.jit import JitDriver, elidable 3 | 4 | def get_location(pc, program, bracket_map): 5 | return "%s_%s_%s" % (program[:pc], program[pc], program[pc+1:]) 6 | 7 | jitdriver = JitDriver(greens=['pc', 'program', 'bracket_map'], 8 | reds=['tape'], 9 | get_printable_location=get_location) 10 | 11 | @elidable 12 | def get_matching_bracket(bracket_map, pc): 13 | return bracket_map[pc] 14 | 15 | def mainloop(program, bracket_map): 16 | pc = 0 17 | tape = Tape() 18 | 19 | while pc < len(program): 20 | jitdriver.jit_merge_point(pc=pc, 21 | tape=tape, 22 | program=program, 23 | bracket_map=bracket_map) 24 | 25 | code = program[pc] 26 | 27 | if code == ">": tape.advance() 28 | elif code == "<": tape.devance() 29 | elif code == "+": tape.inc() 30 | elif code == "-": tape.dec() 31 | elif code == ".": os.write(1, chr(tape.get())) # write 32 | elif code == ",": tape.set(ord(os.read(0, 1)[0])) # read from stdin 33 | elif code == "[" and tape.get() == 0: 34 | # Skip forward to the matching ] 35 | pc = get_matching_bracket(bracket_map, pc) 36 | elif code == "]" and tape.get() != 0: 37 | # Skip back to the matching [ 38 | pc = get_matching_bracket(bracket_map, pc) 39 | 40 | pc += 1 41 | 42 | class Tape(object): 43 | def __init__(self): 44 | self.thetape = [0] 45 | self.position = 0 46 | 47 | def get(self): return self.thetape[self.position] 48 | def set(self, val): self.thetape[self.position] = val 49 | def inc(self): self.thetape[self.position] += 1 50 | def dec(self): self.thetape[self.position] -= 1 51 | def advance(self): 52 | self.position += 1 53 | if len(self.thetape) <= self.position: 54 | self.thetape.append(0) 55 | def devance(self): self.position -= 1 56 | 57 | def parse(program): 58 | parsed = [] 59 | bracket_map = {} 60 | leftstack = [] 61 | 62 | pc = 0 63 | for char in program: 64 | if char in ('[', ']', '<', '>', '+', '-', ',', '.'): 65 | parsed.append(char) 66 | 67 | if char == '[': 68 | leftstack.append(pc) 69 | elif char == ']': 70 | left = leftstack.pop() 71 | right = pc 72 | bracket_map[left] = right 73 | bracket_map[right] = left 74 | pc += 1 75 | 76 | return "".join(parsed), bracket_map 77 | 78 | def run(filename): 79 | with open(filename) as f: 80 | program_contents = f.read() 81 | program, bm = parse(program_contents) 82 | mainloop(program, bm) 83 | 84 | def entry_point(argv): 85 | try: 86 | filename = argv[1] 87 | except IndexError: 88 | print "You must supply a filename" 89 | return 1 90 | 91 | run(filename) 92 | return 0 93 | 94 | def target(*args): return entry_point, None 95 | -------------------------------------------------------------------------------- /code/boolean_operations.py: -------------------------------------------------------------------------------- 1 | def boolean_operations(): 2 | t = True 3 | f = False 4 | empty_dict = {} 5 | 6 | if t or f: print("True or False is True") 7 | 8 | if t and f: pass 9 | else: print("True and False is False") 10 | 11 | if not empty_dict: print("not {} is True") 12 | 13 | def entry_point(argv): 14 | boolean_operations() 15 | return 0 16 | 17 | def target(*args): 18 | return entry_point 19 | -------------------------------------------------------------------------------- /code/builtin.py: -------------------------------------------------------------------------------- 1 | def builtin_functions(): 2 | print bool(1) # return a boolean value 3 | print int(1.0) # return an integer value 4 | print float(1) # return a float value 5 | print chr(65) # return a string of one character whose ASCII code is the input 6 | print str(53) # return a string containing a nicely printable representation of an object 7 | print unichr(97) # return the Unicode string of one character whose Unicode code is the integer input 8 | print unicode('abc') # return the Unicode string version of object 9 | print bytearray('abc') # return a new array of bytes 10 | print list('abc') # return a list whose items are the same and in the same order as iterable’s items 11 | for i in range(3): # create a list containing arithmetic progressions 12 | print i 13 | for i in xrange(3): 14 | print i 15 | seasons = ['Spring', 'Summer', 'Fall', 'Winter'] 16 | for i in enumerate(seasons): # return an enumerate object 17 | print i 18 | print min(1, 2) # return the smallest of two arguments 19 | print max(1, 2) # return the largest of two arguments 20 | for i in reversed([1, 2, 3]): # return a reverse iterator 21 | print i 22 | 23 | def entry_point(argv): 24 | builtin_functions() 25 | return 0 26 | 27 | def target(*args): return entry_point 28 | if __name__ == "__main__": import sys; entry_point(sys.argv) 29 | -------------------------------------------------------------------------------- /code/classes.py: -------------------------------------------------------------------------------- 1 | class Animal(object): 2 | def __init__(self, name): 3 | self.name = name 4 | 5 | def greet(self): 6 | self.say("I'm " + self.name + ".") 7 | 8 | def say(self, msg): pass 9 | 10 | class Cat(Animal): 11 | def say(self, msg): 12 | print "Meow, " + msg 13 | 14 | class Dog(Animal): 15 | def say(self, msg): 16 | print "Wuff, " + msg 17 | 18 | class Playground(object): 19 | def __init__(self, size): 20 | self._item = [None] * size 21 | 22 | def __setitem__(self, index, animal): 23 | self._item[index] = animal 24 | 25 | def __getitem__(self, index): 26 | return self._item[index] 27 | 28 | def classes(): 29 | c = Cat("Kitty") 30 | c.greet() # Meow, I'm Kitty. 31 | 32 | d = Dog("Buddy") 33 | d.greet() # Wuff, I'm Buddy. 34 | 35 | p = Playground(3) # create a playground with size of 3 36 | p[0] = c 37 | p[1] = d 38 | 39 | p[0].greet() # Meow, I'm Kitty. 40 | p[1].greet() # Wuff, I'm Buddy. 41 | 42 | def entry_point(argv): 43 | classes() 44 | return 0 45 | 46 | def target(*args): return entry_point 47 | if __name__ == "__main__": import sys; entry_point(sys.argv) 48 | -------------------------------------------------------------------------------- /code/classes_mixin.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.objectmodel import import_from_mixin 2 | 3 | class ActivityMixin(object): 4 | def eat(self, food): 5 | print "Eating " + food 6 | 7 | class Animal(object): 8 | import_from_mixin(ActivityMixin) # import ActivityMixin 9 | 10 | def __init__(self, name): 11 | self.name = name 12 | 13 | def greet(self): 14 | self.say("I'm " + self.name + ".") 15 | 16 | def say(self, msg): pass 17 | 18 | class Cat(Animal): 19 | def say(self, msg): 20 | print "Meow, " + msg 21 | 22 | # class Cat2(Animal, ActivityMixin): # multiple inheritance only supported with mixin 23 | # pass 24 | 25 | class Dog(Animal): 26 | def say(self, msg): 27 | print "Wuff, " + msg 28 | 29 | def classes(): 30 | c = Cat("Kitty") 31 | c.greet() # Meow, I'm Kitty. 32 | c.eat("cat food") 33 | 34 | def entry_point(argv): 35 | classes() 36 | return 0 37 | 38 | def target(*args): return entry_point 39 | if __name__ == "__main__": import sys; entry_point(sys.argv) 40 | -------------------------------------------------------------------------------- /code/comparisons.py: -------------------------------------------------------------------------------- 1 | class Cat: 2 | def __init__(self, name, height): 3 | self.name = name 4 | self.height = height 5 | 6 | def __eq__(self, other): 7 | return self.name == other.name and self.height == other.height 8 | 9 | def __cmp__(self, other): 10 | return self.height - other.height 11 | 12 | def __gt__(self, other): 13 | return self.height > other.height 14 | 15 | def comparisons(): 16 | if 1 < 2: print("<: 1 is strictly less than 2") 17 | if 1 <= 2: print("<=: 1 is less than or equal to 2") 18 | if 2 > 1: print(">: 2 is strictly greater than 1") 19 | if 2 >= 1: print(">=: 2 is greater than or equal 1") 20 | if 1 == 1: print ("==: 1 is equal to 1") 21 | if 1 != 2: print("!=: 1 is not equal to 2") 22 | 23 | tiger = Cat("Tiger", 9.1) 24 | kitty = Cat("Kitty", 9.8) 25 | puss = tiger 26 | 27 | if tiger is puss: print("is: Tiger and Puss are same cat") 28 | if tiger is not kitty: print("is not: Tiger and Kitty are different cats") 29 | 30 | # Even though __cmp__() and __gt__() are defined in the Cat class, we still 31 | # cannot compare two Cat instances in RPython. Uncomment the following line 32 | # to compile with RPython and you will get an unimplemented operation: 'gt' 33 | # error. 34 | 35 | # if kitty > tiger: print(">: Kitty is taller than Kitty") 36 | # if tiger != kitty: print("==: Tiger and Kitty are same cats") 37 | 38 | def entry_point(argv): 39 | comparisons() 40 | return 0 41 | 42 | def target(*args): 43 | return entry_point 44 | 45 | if __name__ == "__main__": 46 | import sys 47 | entry_point(sys.argv) 48 | -------------------------------------------------------------------------------- /code/dict.py: -------------------------------------------------------------------------------- 1 | def rdict(): 2 | def print_dict(d): 3 | for k, v in d.iteritems(): print k, v 4 | 5 | d = {'one': 1, 'two': 2, 'three': 3, 'four': 4, 'five': 5} 6 | print_dict(d) 7 | 8 | print "len: ", len(d) 9 | print "d[key]: ", d['one'] 10 | 11 | d['one'] = 3 12 | print "d[key] = value: ", d['one'] 13 | 14 | del d['one'] 15 | try: 16 | print "d[key] = value: ", d['one'] 17 | except KeyError: 18 | print "KeyError: not found." 19 | 20 | if 'one' not in d: 21 | print "'one' is not in d" 22 | 23 | # iterator over a dictionary 24 | for i in iter(d): print i 25 | for i in d.iterkeys(): print i 26 | for i in d.itervalues(): print i 27 | for i in d.keys(): print i 28 | for i in d.values(): print i 29 | 30 | d.pop('five') 31 | k, v = d.popitem() 32 | print k, v 33 | 34 | d.update({'five': 55}) 35 | 36 | def entry_point(argv): 37 | rdict() 38 | return 0 39 | 40 | def target(*args): return entry_point 41 | if __name__ == "__main__": import sys; entry_point(sys.argv) 42 | -------------------------------------------------------------------------------- /code/dict_unsupported.py: -------------------------------------------------------------------------------- 1 | ################### UNSUPPORTED IN RPYTHON ###################### 2 | 3 | def dict_unsupported(): 4 | d1 = dict(one=1, two=2, three=3) 5 | d2 = dict({'one': 1, 'two': 2, 'three': 3}) 6 | d3 = dict([('two', 2), ('one', 1), ('three', 3)]) 7 | d4 = dict(zip(['one', 'two', 'three'], [1, 2, 3])) 8 | print d1 9 | print d2 10 | print d3 11 | print d4 12 | 13 | # There is no dictionary view objects in RPython 14 | d5 = dict({'three': 3, 'four': 4, 'five': 5}) 15 | v1 = d1.viewkeys() 16 | v5 = d5.viewkeys() 17 | print v1 & v5 18 | print v1 | v5 19 | print v1 - v5 20 | print v1 ^ v5 21 | 22 | # keys in different types are note supported in RPython 23 | d6 = dict({1: 1, 'two': 2}) 24 | print d6[1], d6['two'] 25 | 26 | def entry_point(argv): 27 | dict_unsupported() 28 | return 0 29 | 30 | def target(*args): return entry_point 31 | if __name__ == "__main__": import sys; entry_point(sys.argv) 32 | -------------------------------------------------------------------------------- /code/errors_exceptions.py: -------------------------------------------------------------------------------- 1 | def exceptions(x, y): 2 | try: 3 | n = x / y 4 | except ZeroDivisionError: 5 | print "division by zero" 6 | 7 | def entry_point(argv): 8 | exceptions(int(argv[1]), int(argv[2])) 9 | return 0 10 | 11 | def target(*args): return entry_point 12 | if __name__ == "__main__": import sys; entry_point(sys.argv) 13 | -------------------------------------------------------------------------------- /code/file.py: -------------------------------------------------------------------------------- 1 | def rfile(): 2 | with open ("file.py", "r") as f: 3 | c = f.read(10) 4 | for line in c.split("\n"): 5 | print line 6 | 7 | f = open("file.py", "r") # open a file 8 | c = f.readline() # read one entire line from the file 9 | print f.tell() # return the file's current position 10 | print f.fileno() # return the integer "file descriptor" 11 | print f.isatty() # return True if the file is connected to a tty(-like) device 12 | f.close() # close a file 13 | 14 | def entry_point(argv): 15 | rfile() 16 | return 0 17 | 18 | def target(*args): return entry_point 19 | if __name__ == "__main__": import sys; entry_point(sys.argv) 20 | -------------------------------------------------------------------------------- /code/flow_control_variables.py: -------------------------------------------------------------------------------- 1 | class Obj(): 2 | pass 3 | 4 | def flow_control_variables_unsupported(arg): 5 | """ 6 | int, floats or tuples cannot be mixed with None. 7 | """ 8 | i = None # integer 9 | f = None # float 10 | t = None # tuple 11 | 12 | if arg: 13 | i = None 14 | f = None 15 | t = None 16 | else: 17 | i = 0 18 | f = 0.0 19 | t = (1, 2, 3) 20 | 21 | return i, f, t 22 | 23 | def flow_control_variables(arg): 24 | """ 25 | It is allowed to mix None with many other types: wrapped objects, class 26 | instances, lists, dicts, strings, etc. 27 | """ 28 | o = None # object instance 29 | l = None # list 30 | d = None # dict 31 | s = None # string 32 | 33 | if arg: 34 | o = None 35 | l = None 36 | d = None 37 | s = None 38 | else: 39 | o = Obj() 40 | l = [1, 2, 3] 41 | d = {1: "123"} 42 | s = "hello" 43 | 44 | if o and l and d and s: 45 | print o, l, d[1], s 46 | 47 | return o, l, d, s 48 | 49 | def entry_point(argv): flow_control_variables(int(argv[1])); return 0 50 | def target(*args): return entry_point 51 | -------------------------------------------------------------------------------- /code/flowing2_error.py: -------------------------------------------------------------------------------- 1 | def compiler_error(arg): 2 | n = 10 * (1/0) 3 | return n 4 | 5 | def entry_point(argv): compiler_error(argv[1]); return 0 6 | def target(*args): return entry_point 7 | -------------------------------------------------------------------------------- /code/flowing_error.py: -------------------------------------------------------------------------------- 1 | def compiler_error(arg): 2 | return v 3 | 4 | def entry_point(argv): compiler_error(argv[1]); return 0 5 | def target(*args): return entry_point 6 | -------------------------------------------------------------------------------- /code/handle_exceptions.py: -------------------------------------------------------------------------------- 1 | class B(Exception): 2 | pass 3 | 4 | class C(B): 5 | pass 6 | 7 | class D(C): 8 | pass 9 | 10 | def exceptions(): 11 | for cls in [B, C, D]: 12 | try: 13 | raise cls() 14 | except D: 15 | print("exception D") 16 | except C: 17 | print("exception C") 18 | except B: 19 | print("exception B") 20 | finally: 21 | print("put clean-up actions here") 22 | 23 | def entry_point(argv): 24 | exceptions() 25 | return 0 26 | 27 | def target(*args): return entry_point 28 | if __name__ == "__main__": import sys; entry_point(sys.argv) 29 | -------------------------------------------------------------------------------- /code/hello_world.py: -------------------------------------------------------------------------------- 1 | def entry_point(argv): 2 | print "Hello, World!" 3 | return 0 4 | 5 | # The target function is the main function of a RPython program. It takes 6 | # command line arguments as inputs and return an entry point function. 7 | def target(*args): 8 | return entry_point 9 | -------------------------------------------------------------------------------- /code/hello_world_python.py: -------------------------------------------------------------------------------- 1 | def entry_point(argv): 2 | print "Hello, World!" 3 | return 0 4 | 5 | # The target function is the main function of a RPython program. It takes 6 | # command line arguments as inputs and return an entry point function. 7 | def target(*args): 8 | return entry_point 9 | 10 | # This is the entry point for interpreting a script with Python. 11 | if __name__ == "__main__": 12 | import sys 13 | entry_point(sys.argv) 14 | -------------------------------------------------------------------------------- /code/iterator.py: -------------------------------------------------------------------------------- 1 | class Counter(): 2 | c = 100 3 | 4 | def __iter__(self): 5 | return self 6 | 7 | def next(self): 8 | t = self.c 9 | self.c += 1 10 | return t 11 | 12 | def iterator(): 13 | l = [1, 2, 3, 4, 5] 14 | 15 | it = iter(l) # return an iterator object on the list l 16 | print it.next() # get next item from the list 17 | 18 | c = Counter() 19 | 20 | it = c.__iter__() 21 | print it.next() 22 | print next(it) 23 | 24 | def iterator_unsupported(): 25 | l = [1, 2, 3, 4, 5] 26 | 27 | # __iter__() method for list is not supported in RPython 28 | it = l.__iter__() 29 | print it.next() 30 | 31 | def entry_point(argv): 32 | iterator() 33 | return 0 34 | 35 | def target(*args): return entry_point 36 | 37 | if __name__ == "__main__": 38 | import sys 39 | entry_point(sys.argv) 40 | iterator_unsupported() 41 | -------------------------------------------------------------------------------- /code/iterator_generator.py: -------------------------------------------------------------------------------- 1 | class Box(): 2 | content = [] 3 | 4 | def add(self, cat): 5 | self.content.append(cat) 6 | 7 | def __iter__(self): 8 | for i in self.content: 9 | yield i 10 | 11 | def iterator_generator(): 12 | b = Box() 13 | b.add("Tiger") 14 | b.add("Kitty") 15 | 16 | it = b.__iter__() 17 | print it.next() 18 | 19 | for i in b: 20 | print i 21 | 22 | def entry_point(argv): 23 | iterator_generator() 24 | return 0 25 | 26 | def target(*args): return entry_point 27 | if __name__ == "__main__": import sys; entry_point(sys.argv) 28 | -------------------------------------------------------------------------------- /code/lists.py: -------------------------------------------------------------------------------- 1 | def lists(): 2 | l = [0, 1, 2, 3, 4] 3 | print l[3] 4 | print l[-1] 5 | 6 | # Indexes are checked when requested by an IndexError exception clause. 7 | try: 8 | print l[100] 9 | except IndexError: 10 | print "IndexError" 11 | 12 | print l[3:5] 13 | print l[0:-1] 14 | 15 | l[0:2] = [100, 101, 102] 16 | print l 17 | 18 | # other operators: +, +=, in, *, *=, ==, != work as expected. 19 | 20 | l = [0] + [1] # [0, 1] 21 | l *= 2 # [0, 1, 0, 1] 22 | 23 | # append, index, insert, extend, reverse, pop. The index used in pop() 24 | # follows the same rules as for indexing above. The index used in insert() 25 | # must be within bounds and not negative. 26 | l = [] 27 | l.append(0) # [0] 28 | print l.index(0) 29 | l.insert(1, 1) # [0, 1] 30 | l.extend([2, 3, 4]) # [0, 1, 2, 3, 4] 31 | l.reverse() # [4, 3, 2, 1, 0] 32 | l.pop() # [4, 3, 2, 1] 33 | del l[0:1] # [3, 2, 1] 34 | l.remove(1) # [3, 2] 35 | print l 36 | 37 | def entry_point(argv): 38 | lists() 39 | return 0 40 | 41 | def target(*args): return entry_point 42 | if __name__ == "__main__": 43 | import sys; entry_point(sys.argv) 44 | -------------------------------------------------------------------------------- /code/lists_unsupported.py: -------------------------------------------------------------------------------- 1 | ################### UNSUPPORTED IN RPYTHON ###################### 2 | 3 | def lists_unsupported(): 4 | l = [0, 1, 2, 3, 4] 5 | 6 | # In RPython, stop doesn't need to within bounds, but it must not be 7 | # smaller than the start 8 | print l[3:2] 9 | 10 | # In RPython, all negative indexes are disallowed, except for the [:-1] 11 | # special case. 12 | print l[0:-2] 13 | 14 | # No step in RPython 15 | print l[0:-1:2] 16 | 17 | # Slice assignment cannot change the total length of the list, but just 18 | # replace items 19 | l[0:2] = [100, 101, 102, 103] 20 | print l 21 | 22 | # The sort() and count() methods are not supported 23 | l.sort() 24 | print l.count(103) 25 | 26 | # Mixing types in a list is not supported in RPython 27 | l.append("mix integer with string types in a list") 28 | print l 29 | 30 | def entry_point(argv): 31 | lists_unsupported() 32 | return 0 33 | 34 | def target(*args): return entry_point 35 | if __name__ == "__main__": 36 | import sys; entry_point(sys.argv) 37 | lists_unsupported() 38 | -------------------------------------------------------------------------------- /code/listsort.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.listsort import TimSort 2 | 3 | def listsort(): 4 | lst = [10, 1, 9, 2, 8, 3, 7, 4, 5, 6] 5 | TimSort(lst).sort() 6 | print lst 7 | 8 | def entry_point(argv): 9 | listsort() 10 | return 0 11 | 12 | def target(*args): return entry_point 13 | -------------------------------------------------------------------------------- /code/numeric.py: -------------------------------------------------------------------------------- 1 | def numeric(x, y, f, l): 2 | print "int: -1024 =", x 3 | print "float: 3.14 =", f 4 | print "long: 1L =", l 5 | 6 | print "x + y =", x + y # sum of x and y 7 | print "x - y =", x - y # difference of x and y 8 | print "x * y =", x * y # product of x and y 9 | print "x / y =", x / y # quotient of x and y 10 | print "x // y =", x // y # (floored) quotient of x and y 11 | print "x % y =", x % y # remainder of x / y 12 | print "-x =", -x # x negated 13 | print "+x =", +x # x unchanged 14 | 15 | print "abs(x) =", abs(x) # absolute value or magnitude of x 16 | print "int(x) =", int(f) # x converted to integer 17 | print "float(x) =", float(y) # x converted to floating point 18 | # print "divmod(x, y) =", divmod(x, y) # the pair (x // y, x % y) 19 | # print "pow(x, y) =", pow(x, y) # x to the power y 20 | 21 | def entry_point(argv): 22 | x = -1024 # plain integer 23 | y = 42 24 | f = 3.14 # float 25 | l = 1L # a long integer 26 | numeric(x, y, f, l) 27 | return 0 28 | 29 | def target(*args): return entry_point 30 | if __name__ == "__main__": import sys; entry_point(sys.argv) 31 | -------------------------------------------------------------------------------- /code/numeric_bitwise.py: -------------------------------------------------------------------------------- 1 | def numeric_bitwise(): 2 | x = 2 3 | y = 4 4 | n = 1 5 | 6 | print "x = ", x, ", y = ", y 7 | # the bitwise operations sorted in ascending priority 8 | print "x | y =", x | y # bitwise or of x and y 9 | print "x ^ y =", x ^ y # bitwise exclusive or of x and y 10 | print "x & y =", x & y # bitwise and of x and y 11 | print "x << n =", x << n # x shifted left by n bits 12 | print "x >> n =", x >> n # x shifted right by n bits 13 | print "~x =", ~x # the bits of x inverted 14 | 15 | 16 | def entry_point(argv): 17 | numeric_bitwise() 18 | return 0 19 | 20 | def target(*args): return entry_point 21 | if __name__ == "__main__": import sys; entry_point(sys.argv) 22 | -------------------------------------------------------------------------------- /code/numeric_constfold.py: -------------------------------------------------------------------------------- 1 | def numeric_constfold(): 2 | """Constant folding on numeric.""" 3 | x = -1024 4 | y = 42 5 | 6 | j = 1j # yield an imaginary number (complex number with zero real part) 7 | print "complex: 1j =", j 8 | print "divmod(x, y) =", divmod(x, y) # the pair (x // y, x % y) 9 | print "pow(x, y) =", pow(x, y) # x to the power y 10 | 11 | def numeric_no_constfold(x, y): 12 | """RPython cannot do constant folding on x and y""" 13 | print "divmod(x, y) =", divmod(x, y) # the pair (x // y, x % y) 14 | print "pow(x, y) =", pow(x, y) # x to the power y 15 | 16 | def entry_point(argv): 17 | numeric_constfold() 18 | # numeric_no_constfold(int(argv[1]), int(argv[2])) # compilation error, comment this function to try constant folding 19 | return 0 20 | 21 | def target(*args): return entry_point 22 | if __name__ == "__main__": import sys; entry_point(sys.argv) 23 | -------------------------------------------------------------------------------- /code/numeric_math.py: -------------------------------------------------------------------------------- 1 | import math 2 | 3 | def numeric_math(): 4 | print math.exp(1e-5) - 1 5 | print math.pi 6 | print math.log(10) 7 | print math.floor(1.5) 8 | print math.sqrt(2) 9 | 10 | def entry_point(argv): 11 | numeric_math() 12 | return 0 13 | 14 | def target(*args): return entry_point 15 | if __name__ == "__main__": import sys; entry_point(sys.argv) 16 | -------------------------------------------------------------------------------- /code/numeric_unsupported.py: -------------------------------------------------------------------------------- 1 | ################### UNSUPPORTED IN RPYTHON ###################### 2 | 3 | def numeric_unsupported(): 4 | """Operations and functions supported in Python but not supported in RPython.""" 5 | x = -1024 6 | y = 42 7 | 8 | print "long(x) =", long(x) # x converted to long integer 9 | 10 | re = 1 11 | im = 2 12 | # a complex number with real part re, imaginary part im. im defaults to zero. 13 | print "complex(x) =", complex(re, im) 14 | 15 | c = 0 16 | # conjugate of the complex number c. (Identity on real numbers) 17 | print "c.conjugate() =", c.conjugate() 18 | 19 | print "x ** y =", x ** y # x to the power y 20 | 21 | # float also accepts the strings "nan" and "inf" with an optional prefix 22 | # "+" or "-" for Not a Number (NaN) and positive or negative infinity. 23 | print "float(inf) =", float("inf") 24 | print "float(+inf) =", float("+inf") 25 | print "float(-inf) =", float("-inf") 26 | 27 | print "float(nan) =", float("nan") 28 | print "float(+nan) =", float("+nan") 29 | print "float(-nan) =", float("-nan") 30 | 31 | def entry_point(argv): 32 | numeric_unsupported() 33 | return 0 34 | 35 | def target(*args): return entry_point 36 | if __name__ == "__main__": import sys; entry_point(sys.argv) 37 | -------------------------------------------------------------------------------- /code/rarithmetic.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rarithmetic import * 2 | 3 | def rarithmetic_example(): 4 | # integer types in C 5 | i = r_int(0) # 32 6 | u = r_uint(0) # 32 7 | i32 = r_int32(0) # 32 8 | u32 = r_uint32(0) # 32 9 | i64 = r_int64(0) # 64 10 | u64 = r_uint64(0) # 64 11 | ll = r_longlong(0) # 64 12 | ull = r_ulonglong(0) # 64 13 | lll = r_longlonglong(0) # 128 14 | 15 | print intmask(longlongmax) 16 | 17 | # convert little endian to big endian and vice versa 18 | print byteswap(1) 19 | 20 | # perform an add/sub/mul between two regular integers, but assumes that 21 | # they fit inside signed 32-bit ints and raises OverflowError if the result 22 | # no longer does 23 | print ovfcheck_int32_add(10000, 1000) 24 | print ovfcheck_int32_sub(10000, 1000) 25 | print ovfcheck_int32_mul(10000, 1000) 26 | 27 | # convert to an integer or raise OverflowError 28 | try: 29 | print ovfcheck_float_to_int(9223372036854775296.0 + 1) 30 | except OverflowError: 31 | print "Exception ovfcheck_float_to_int(): OverflowError" 32 | # convert to a longlong or raise OverflowError 33 | try: 34 | print ovfcheck_float_to_longlong(9223372036854775296.0 + 1) 35 | except OverflowError: 36 | print "Exception ovfcheck_float_to_longlong(): OverflowError" 37 | 38 | # utility to converts a string to an integer 39 | print string_to_int("10", base=10) 40 | print string_to_int("A", base=16) 41 | print string_to_int("1010", base=2) 42 | print string_to_int("1_000", base=10, allow_underscores=True) 43 | 44 | 45 | def entry_point(argv): rarithmetic_example(); return 0 46 | def target(*args): return entry_point 47 | -------------------------------------------------------------------------------- /code/rbigint.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rbigint import rbigint 2 | 3 | def rbigint_example(): 4 | r1 = rbigint.fromint((1 << 63 - 1)) 5 | r2 = rbigint.fromint(1 << 32) 6 | print r1.add(r2).str() 7 | print r1.sub(r2).str() 8 | print r1.mul(r2).str() 9 | print r1.div(r2).str() 10 | print r1.digit(1) # Return the x'th digit, as an int 11 | r2.setdigit(1, 5) 12 | r3 = rbigint.fromstr("1234567890000") 13 | print r3.str() 14 | r4 = rbigint.fromstr("1234567890000", base=16) 15 | print r4.str() 16 | 17 | print r3.lt(r4) # less than 18 | 19 | def entry_point(argv): rbigint_example(); return 0 20 | def target(*args): return entry_point 21 | -------------------------------------------------------------------------------- /code/rbisect.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rbisect import bisect_left, bisect_right 2 | 3 | def rbisect_example(): 4 | l = [1, 1, 2, 2, 3] 5 | 6 | # Locate the leftmost value exactly equal to 1 7 | i = bisect_left(l, 1, len(l)) 8 | if i != len(l) and l[i] == 1: 9 | print "The index of leftmost value exactly equal to 1: ", i 10 | 11 | # Find leftmost value greater than 1 12 | i = bisect_right(l, 1, len(l)) 13 | if i != len(l): 14 | print "The index of leftmost value greater than 1: ", i 15 | 16 | def entry_point(argv): 17 | rbisect_example() 18 | return 0 19 | 20 | def target(*args): return entry_point 21 | if __name__ == "__main__": import sys; entry_point(sys.argv) 22 | -------------------------------------------------------------------------------- /code/rffi_abs.py: -------------------------------------------------------------------------------- 1 | from rpython.rtyper.lltypesystem import rffi 2 | from rpython.translator.tool.cbuild import ExternalCompilationInfo 3 | from rpython.rlib.rarithmetic import r_int32, r_int64, r_longlong 4 | 5 | eci = ExternalCompilationInfo( 6 | includes=['stdlib.h'], 7 | ) 8 | 9 | # int abs(int j); 10 | c_abs = rffi.llexternal('abs', # function name 11 | [rffi.INT], # argument types 12 | rffi.INT, # return type 13 | compilation_info=eci) 14 | 15 | # long int labs(long int j); 16 | c_labs = rffi.llexternal('labs', # function name 17 | [rffi.LONG], # argument types 18 | rffi.LONG, # return type 19 | compilation_info=eci) 20 | 21 | # long long int llabs(long long int j); 22 | c_llabs = rffi.llexternal('llabs', # function name 23 | [rffi.LONGLONG], # argument types 24 | rffi.LONGLONG, # return type 25 | compilation_info=eci) 26 | 27 | def rffi_example(): 28 | int_number = r_int32(-10) 29 | print c_abs(int_number) 30 | 31 | long_number = r_int64(-10) 32 | print c_labs(long_number) 33 | 34 | longlong_number = r_longlong(-10) 35 | print c_llabs(longlong_number) 36 | 37 | def entry_point(argv): rffi_example(); return 0 38 | def target(*args): return entry_point 39 | -------------------------------------------------------------------------------- /code/rffi_liststr.py: -------------------------------------------------------------------------------- 1 | from rpython.rtyper.lltypesystem import rffi 2 | from rpython.translator.tool.cbuild import ExternalCompilationInfo 3 | 4 | # Calculate the total length of strings in the list 5 | c_source = """ 6 | #include 7 | 8 | int strlen_list(char *args[]) { 9 | char **p = args; // CHARPP in RPython 10 | int l = 0; 11 | while (*p) { 12 | l += strlen(*p); 13 | p++; 14 | } 15 | return l; 16 | } 17 | """ 18 | eci = ExternalCompilationInfo(separate_module_sources=[c_source]) 19 | c_strlen_list = rffi.llexternal('strlen_list', # function name 20 | [rffi.CCHARPP], # parameters 21 | rffi.SIGNED, # return value 22 | compilation_info=eci) 23 | 24 | def rffi_list_example(): 25 | l = ["Hello", ",", "World", "!"] 26 | l_charpp = rffi.liststr2charpp(l) 27 | r = c_strlen_list(l_charpp) 28 | rffi.free_charpp(l_charpp) 29 | print r 30 | 31 | def entry_point(argv): rffi_list_example(); return 0 32 | def target(*args): return entry_point 33 | -------------------------------------------------------------------------------- /code/rffi_more.py: -------------------------------------------------------------------------------- 1 | from rpython.rtyper.lltypesystem import rffi 2 | from rpython.rtyper.lltypesystem import lltype 3 | from rpython.translator import cdir 4 | from rpython.tool.udir import udir 5 | from rpython.translator.tool.cbuild import ExternalCompilationInfo 6 | 7 | ########################### callback ################################# 8 | 9 | h_source_callback = """ 10 | #ifndef _CALLBACK_H 11 | #define _CALLBACK_H 12 | RPY_EXTERN Signed compute(Signed arg, Signed(*callback)(Signed)); 13 | #endif /* _CALLBACK_H */ 14 | """ 15 | h_include_callback = udir.join("callback.h") 16 | h_include_callback.write(h_source_callback) 17 | 18 | c_source_callback = """ 19 | #include "src/precommondefs.h" 20 | 21 | RPY_EXTERN Signed compute(Signed arg, Signed(*callback)(Signed)) 22 | { 23 | Signed res = callback(arg); 24 | if (res == -1) 25 | return -1; 26 | return res; 27 | } 28 | """ 29 | 30 | eci = ExternalCompilationInfo(includes=['callback.h'], 31 | include_dirs=[str(udir), cdir], 32 | separate_module_sources=[c_source_callback]) 33 | 34 | args = [rffi.SIGNED, rffi.CCallback([rffi.SIGNED], rffi.SIGNED)] 35 | compute = rffi.llexternal('compute', args, rffi.SIGNED, 36 | compilation_info=eci) 37 | 38 | ########################### callback end ############################# 39 | 40 | def rffi_callback(): 41 | def g(i): return i + 3 42 | print compute(1, g) 43 | 44 | def rffi_more_examples(): 45 | rffi_callback() 46 | 47 | def entry_point(argv): rffi_more_examples(); return 0 48 | def target(*args): return entry_point 49 | -------------------------------------------------------------------------------- /code/rffi_separate_module_sources.py: -------------------------------------------------------------------------------- 1 | from rpython.rtyper.lltypesystem import rffi 2 | from rpython.rtyper.lltypesystem.lltype import Signed 3 | from rpython.translator.tool.cbuild import ExternalCompilationInfo 4 | 5 | c_source = """ 6 | int someexternalfunction(int x) 7 | { 8 | return (x + 3); 9 | } 10 | """ 11 | 12 | eci = ExternalCompilationInfo(separate_module_sources=[c_source]) 13 | c_someexternalfunction = rffi.llexternal('someexternalfunction', 14 | [Signed], 15 | Signed, 16 | compilation_info=eci) 17 | 18 | def rffi_example(): 19 | print c_someexternalfunction(1) 20 | 21 | def entry_point(argv): rffi_example(); return 0 22 | def target(*args): return entry_point 23 | -------------------------------------------------------------------------------- /code/rffi_str.py: -------------------------------------------------------------------------------- 1 | from rpython.rtyper.lltypesystem import rffi 2 | from rpython.rtyper.lltypesystem import lltype 3 | from rpython.translator import cdir 4 | from rpython.tool.udir import udir 5 | from rpython.translator.tool.cbuild import ExternalCompilationInfo 6 | 7 | ########################### str2charp ################################ 8 | 9 | eci1 = ExternalCompilationInfo(includes=['string.h']) 10 | c_strlen = rffi.llexternal('strlen', 11 | [rffi.CCHARP], 12 | rffi.SIGNED, 13 | compilation_info=eci1) 14 | 15 | def rffi_strlen(): 16 | s = rffi.str2charp("Hello, World!") # alloc a string buffer 17 | res = c_strlen(s) 18 | print res 19 | rffi.free_charp(s) # free the string buffer 20 | 21 | ########################### charp2str ################################ 22 | 23 | c_source_2 = """ 24 | #include 25 | #include 26 | 27 | void my_strcpy(char *target, char* arg) 28 | { 29 | strcpy(target, arg); 30 | } 31 | """ 32 | eci2 = ExternalCompilationInfo(separate_module_sources=[c_source_2], 33 | post_include_bits=['void my_strcpy(char*,char*);']) 34 | c_my_strcpy = rffi.llexternal('my_strcpy', 35 | [rffi.CCHARP, rffi.CCHARP], 36 | lltype.Void, 37 | compilation_info=eci2) 38 | 39 | def rffi_strcpy(): 40 | s = rffi.str2charp("Hello, World!") # alloc a string buffer 41 | l_res = lltype.malloc(rffi.CCHARP.TO, 32, flavor='raw') # alloc a raw buffer 42 | c_my_strcpy(l_res, s) 43 | res = rffi.charp2str(l_res) # convert C string (char*) to RPython string 44 | print res 45 | lltype.free(l_res, flavor='raw') # free the raw buffer 46 | rffi.free_charp(s) # free the string buffer 47 | 48 | def rffi_str(): 49 | rffi_strlen() 50 | rffi_strcpy() 51 | 52 | def entry_point(argv): rffi_str(); return 0 53 | def target(*args): return entry_point 54 | -------------------------------------------------------------------------------- /code/rmd5.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rmd5 2 | 3 | def rmd5_example(): 4 | print "digest_size:", rmd5.digest_size 5 | 6 | d1 = rmd5.RMD5() # or rmd5.new() 7 | d1.update("123") 8 | 9 | # Terminate and return digest in HEX form. 10 | print d1.hexdigest() 11 | 12 | # Terminate the message-digest computation and return digest. 13 | print d1.digest() 14 | 15 | d2 = rmd5.RMD5("123") # or rmd5.new("123") 16 | 17 | # Return a copy ('clone') of the md5 object. This can be used to 18 | # efficiently compute the digests of strings that shared a common initial 19 | # substring. 20 | d3 = d2.copy() 21 | 22 | print d3.hexdigest() 23 | print d3.digest() 24 | 25 | def entry_point(argv): rmd5_example(); return 0 26 | def target(*args): return entry_point 27 | 28 | -------------------------------------------------------------------------------- /code/rpath.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rpath 2 | 3 | def rpath_example(): 4 | # normalize a pathname by collapsing redundant separators and up-level 5 | # references so that A//B, A/B/, A/./B and A/foo/../B all become A/B 6 | print rpath.rnormpath("///..//./foo/.//bar") # "/foo/bar" 7 | 8 | # return a normalized absolutized version of the pathname path 9 | print rpath.rabspath('foo') # $(pwd)/foo 10 | 11 | # join two pathname components, inserting '/' as needed 12 | print rpath.rjoin("/foo", "bar" + rpath.sep + "foo") 13 | 14 | # return True if path is an absolute pathname 15 | print rpath.risabs('C:\\foo\\bar') # 0 16 | 17 | # return True if path is an existing directory 18 | print rpath.risdir('_some_non_existant_file_') # 0 19 | 20 | def entry_point(argv): rpath_example(); return 0 21 | def target(*args): return entry_point 22 | -------------------------------------------------------------------------------- /code/rrandom.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rrandom import Random 2 | 3 | def rrandom_example(): 4 | rnd1 = Random() 5 | 6 | print rnd1.genrand32() # get a 32-bit random number 7 | print rnd1.random() # get a float random number x, 0.0 <= x < 1.0 8 | 9 | seed = 1546979228 10 | rnd2 = Random(seed) # set a seed 11 | print rnd2.random() 12 | 13 | print rnd1.state # you can access the internal state of the generator 14 | 15 | # change the internal state to one different from and likely far away from 16 | # the current state, n is a non-negative integer which is used to scramble 17 | # the current state vector. 18 | n = 10 19 | rnd1.jumpahead(n) 20 | rnd1.random() 21 | 22 | def entry_point(argv): 23 | rrandom_example() 24 | return 0 25 | 26 | def target(*args): return entry_point 27 | -------------------------------------------------------------------------------- /code/rsha.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rsha 2 | 3 | def rsha_example(): 4 | print "digest_size:", rsha.digest_size 5 | print "blocksize:", rsha.blocksize 6 | 7 | d1 = rsha.RSHA() # or rsha.new() 8 | d1.update("123") 9 | 10 | # Terminate and return digest in HEX form. 11 | print d1.hexdigest() 12 | 13 | # Terminate the message-digest computation and return digest. 14 | print d1.digest() 15 | 16 | d2 = rsha.RSHA("123") # or rsha.new("123") 17 | 18 | # Return a copy ('clone') of the md5 object. This can be used to 19 | # efficiently compute the digests of strings that rshared a common initial 20 | # substring. 21 | d3 = d2.copy() 22 | 23 | print d3.hexdigest() 24 | print d3.digest() 25 | 26 | def entry_point(argv): rsha_example(); return 0 27 | def target(*args): return entry_point 28 | 29 | -------------------------------------------------------------------------------- /code/rsre.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rsre import rsre_re as re 2 | 3 | def rsre_example(): 4 | # scan through string looking for the first location where the regular 5 | # expression pattern produces a match 6 | print re.search('x*', 'axx').span(0) 7 | 8 | # if zero or more characters at the beginning of string match the regular 9 | # expression pattern 10 | print re.match('a+', 'xxx') 11 | 12 | # split string by the occurrences of pattern 13 | print re.split(":", ":a:b::c") 14 | 15 | # return all non-overlapping matches of pattern in string, as a list of 16 | # strings 17 | print re.findall(":+", "a:b::c:::d") 18 | 19 | def entry_point(argv): rsre_example(); return 0 20 | def target(*args): return entry_point 21 | -------------------------------------------------------------------------------- /code/rsre_more.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib.rsre import rsre_re as re 2 | 3 | def rsre_example(): 4 | # simulate scanf, %s - %d errors, %d warnings 5 | print re.search(r"(\S+) - (\d+) errors, (\d+) warnings", 6 | "/usr/sbin/sendmail - 0 errors, 4 warnings").groups() 7 | 8 | # making a phone book 9 | text = """Ross McFluff: 834.345.1254 155 Elm Street 10 | Ronald Heathmore: 892.345.3428 436 Finley Avenue 11 | Frank Burger: 925.541.7625 662 South Dogwood Way 12 | Heather Albrecht: 548.326.4584 919 Park Place""" 13 | entries = re.split("\n+", text) 14 | print [re.split(":? ", entry, 4) for entry in entries] 15 | 16 | # finding all adverbs 17 | text = "He was carefully disguised but captured quickly by police." 18 | print re.findall(r"\w+ly", text) 19 | 20 | def entry_point(argv): rsre_example(); return 0 21 | def target(*args): return entry_point 22 | -------------------------------------------------------------------------------- /code/rtime.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rtime 2 | 3 | def rtime_example(): 4 | # Return the time in seconds since the epoch as a floating point number. 5 | print rtime.time() 6 | 7 | # Suspend execution of the calling thread for the given number of seconds. 8 | rtime.sleep(3) 9 | 10 | # On Unix, return the current processor time as a floating point number 11 | # expressed in seconds. 12 | print rtime.clock() 13 | 14 | def entry_point(argv): rtime_example(); return 0 15 | def target(*args): return entry_point 16 | -------------------------------------------------------------------------------- /code/rtimer.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rtimer 2 | 3 | def rtimer_example(): 4 | t1 = rtimer.read_timestamp() 5 | print rtimer.get_timestamp_unit() 6 | t2 = rtimer.read_timestamp() 7 | print t2 - t1 8 | 9 | def entry_point(argv): rtimer_example(); return 0 10 | def target(*args): return entry_point 11 | -------------------------------------------------------------------------------- /code/rurandom.py: -------------------------------------------------------------------------------- 1 | from rpython.rlib import rurandom 2 | 3 | def rurandom_example(): 4 | r = rurandom.urandom(None, 100) 5 | print r 6 | 7 | # The call can be interrupted by a signal, you can define a callback 8 | # function for status checking 9 | r = rurandom.urandom(None, 100, signal_checker) 10 | 11 | def signal_checker(): 12 | print "Checking signal" 13 | 14 | def entry_point(argv): 15 | rurandom_example() 16 | return 0 17 | 18 | def target(*args): return entry_point 19 | -------------------------------------------------------------------------------- /code/sequence.py: -------------------------------------------------------------------------------- 1 | def sequence(): 2 | s = "this is a string" 3 | u = u"this is a unicode string" 4 | l = ["this", "is", "a", "list", "of", "strings"] 5 | t = ("first", "second") 6 | ba = bytearray(b"\x44\x45\x41\x44\x42\x45\x45\x46") 7 | buf = buffer(s, 10, 6) 8 | r = xrange(0, 5, 2) 9 | 10 | print s; print u; print l; print t; print ba; print buf 11 | for i in r: print i 12 | 13 | # x in s: True if an item of s is equal to x, else False 14 | if 't' in s: 15 | print "t is in string", s 16 | 17 | # x not in s: False if an item of s is equal to x, else True 18 | if 'b' not in u: 19 | print "b is not in unicode string", u 20 | 21 | # s + t: the concatenation of s and t 22 | print l + [":)"] 23 | 24 | # s * n, n * s: equivalent to adding s to itself n times 25 | print t * 2 26 | 27 | # s[i]: ith item of s, origin 0 28 | print "3rd item of l is:", l[2] 29 | 30 | # s[i:j]: slice of s from i to j 31 | print "slice of s:", s[2:-1] 32 | 33 | # len(s): length of s 34 | print "length of ba is", len(ba) 35 | 36 | # s.index(x): index of the first occurrence of x in s 37 | print l.index("of") 38 | 39 | # s.count(x): total number of occurrences of x in s 40 | print s.count("is") 41 | 42 | def entry_point(argv): 43 | sequence() 44 | return 0 45 | 46 | def target(*args): return entry_point 47 | if __name__ == "__main__": import sys; entry_point(sys.argv) 48 | -------------------------------------------------------------------------------- /code/sequence_unsupported.py: -------------------------------------------------------------------------------- 1 | ################### UNSUPPORTED IN RPYTHON ###################### 2 | 3 | def sequence_unsupported(): 4 | l = ["this", "is", "a", "list", "of", "strings"] 5 | 6 | print "slice of l from 3rd to end:", l[2:-1] 7 | # s[i:j:k]: slice of s from i to j with step k 8 | print "slice of l from 1st to 4th with 2 steps:", l[0:5:2] 9 | 10 | # min(s): smallest item of s 11 | list_number = [1, 2, 3] 12 | print "smallest item of s", min(list_number) 13 | 14 | # max(s): largest item of s 15 | print "largest item of s", max(list_number) 16 | 17 | def entry_point(argv): 18 | sequence_unsupported() 19 | return 0 20 | 21 | def target(*args): return entry_point 22 | if __name__ == "__main__": import sys; entry_point(sys.argv) 23 | -------------------------------------------------------------------------------- /code/sets.py: -------------------------------------------------------------------------------- 1 | def sets(): 2 | # Since set is not supported in RPython, we use dict with None as values to 3 | # simulate a set. 4 | s1 = {'foo': None, 'bar': None, 'baz': None, 'foo': None, 'baz': None} 5 | if 'fooo' not in s1: print 'fooo is not in the set s1' 6 | if 'foo' in s1: print 'foo is in the set s1' 7 | for i in s1: print i 8 | 9 | s2 = {'foo': None, 'hello': None, 'world': None, 'foo': None} 10 | 11 | # union 12 | def set_union(s1, s2): 13 | s3 = s1.copy() 14 | s3.update(s2) 15 | return s3 16 | 17 | print 'union:' 18 | s3 = set_union(s1, s2) 19 | for i in s3: print i 20 | 21 | # intersection: 22 | def set_intersection(s1, s2): 23 | s3 = {} 24 | for i in s1: 25 | if i in s2: 26 | s3.update({i: None}) 27 | 28 | for i in s2: 29 | if i in s1: 30 | s3.update({i: None}) 31 | return s3 32 | 33 | print 'intersection:' 34 | s3 = set_intersection(s1, s2) 35 | for i in s3: print i 36 | 37 | def entry_point(argv): 38 | sets() 39 | return 0 40 | 41 | def target(*args): return entry_point 42 | if __name__ == "__main__": 43 | import sys 44 | entry_point(sys.argv) 45 | -------------------------------------------------------------------------------- /code/sets_unsupported.py: -------------------------------------------------------------------------------- 1 | ################### UNSUPPORTED IN RPYTHON ###################### 2 | 3 | def sets_unsupported(): 4 | s1 = set(['foo', 'bar', 'baz', 'foo']) 5 | s2 = set(['foo', 'hello', 'world', 'foo']) 6 | if 'fooo' not in s1: print 'fooo is not in the set s1' 7 | if 'foo' in s1: print 'foo is in the set s1' 8 | print s1 9 | 10 | # union 11 | print s1.union(s2) 12 | print s1 | s2 13 | 14 | # intersection 15 | print s1.intersection(s2) 16 | print s1 & s2 17 | 18 | # difference 19 | print s1.difference(s2) 20 | print s1 - s2 21 | 22 | # symmetric difference 23 | print s1.symmetric_difference(s2) 24 | print s1 ^ s2 25 | 26 | # whether or not two sets have any elements in common 27 | print s1.isdisjoint(s2) 28 | 29 | # whether one set is a subset/superset of the other 30 | print s1.issubset(s2) 31 | print s1 <= s2 32 | print s1.issubset(s2) 33 | print s1 >= s2 34 | 35 | # whether on set is a proper subset/superset of the other 36 | print s1 < s2 37 | print s1 > s2 38 | 39 | # modifying a set 40 | s1 |= s2 41 | s1.update(['fob', 'bah']) 42 | s1.add('boz') 43 | s1.remove('boz') 44 | s1.pop() 45 | s2.clear() 46 | print s1 47 | 48 | fs = frozenset(['foo', 'bar', 'baz']) # frozenset is immutable 49 | print fs 50 | 51 | def entry_point(argv): 52 | sets_unsupported() 53 | return 0 54 | 55 | def target(*args): return entry_point 56 | if __name__ == "__main__": 57 | import sys 58 | entry_point(sys.argv) 59 | -------------------------------------------------------------------------------- /code/strings.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | def strings(): 3 | s = "this is a string" 4 | 5 | print s.count("this", 0, len(s)) 6 | 7 | if s.endswith("ing"): print "s ends with string" 8 | 9 | if s.find("is"): print "found is in s" 10 | 11 | s2 = "thisisastring2" 12 | if s2.isalnum(): print "s2 is alnum" 13 | 14 | s3 = "thisisastringthree" 15 | if s3.isalpha(): print "s3 is alpha" 16 | 17 | s4 = "12345" 18 | if s4.isdigit(): print "s4 is digit" 19 | 20 | l = ["this", "is", "a", "string"] 21 | print " ".join(l) 22 | 23 | print "THI IS A STRING".lower() 24 | print ' spacious '.lstrip() 25 | print s.rfind("is") 26 | print s.rsplit(" ") 27 | print s.split(" ") 28 | 29 | s_lines = "This is a string.\nAnd another string." 30 | print s_lines.splitlines() 31 | 32 | if s.startswith("this"): print "s starts with this" 33 | 34 | print ' spacious '.strip() 35 | print s.upper() 36 | 37 | print "%s, %d, %x, %o, %f" % ("string", 1, 16, 9, 3.14) 38 | 39 | def entry_point(argv): 40 | strings() 41 | return 0 42 | 43 | def target(*args): return entry_point 44 | if __name__ == "__main__": 45 | import sys; entry_point(sys.argv) 46 | -------------------------------------------------------------------------------- /code/strings_unsupported.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | ################### UNSUPPORTED IN RPYTHON ###################### 4 | def strings_unsupported(): 5 | s = "this is a string" 6 | 7 | print s.capitalize() 8 | print s.center(30) 9 | 10 | s_utf8 = "你好".decode("utf-8") 11 | print s_utf8 12 | 13 | print '01\t012\t0123\t01234'.expandtabs() 14 | 15 | print "The sum of 1 + 2 is {0}".format(1+2) 16 | print s.index("is") 17 | 18 | s5 = "this is lowercased string" 19 | if s5.islower(): print "s5 is lowercased" 20 | 21 | s6 = " " 22 | if s6.isspace(): print "s6 contains only whitespaces" 23 | 24 | s7 = "This Is A Title String" 25 | if s7.istitle(): print "s7 is a title cased string" 26 | 27 | s8 = "THIS IS A SUPPER STRING" 28 | if s8.isupper(): print "s8 is all cased characters" 29 | 30 | print s.ljust(10) 31 | print s.partition(" ") 32 | print s.replace("this", "that") 33 | print s.rindex("is") 34 | print s.rjust(10) 35 | print s.rpartition(" ") 36 | print s.swapcase() 37 | print "they're bill's friends from the UK".title() 38 | print s.zfill(20) 39 | print "Hello, %(name)s" % {"name": "world"} 40 | 41 | def entry_point(argv): 42 | strings_unsupported() 43 | return 0 44 | 45 | def target(*args): return entry_point 46 | if __name__ == "__main__": 47 | import sys; entry_point(sys.argv) 48 | strings_unsupported() 49 | -------------------------------------------------------------------------------- /code/truth_value_testing.py: -------------------------------------------------------------------------------- 1 | def truth_value_testing(): 2 | if None or \ 3 | False or \ 4 | 0 or \ 5 | 0L or \ 6 | 0.0 or \ 7 | '' or \ 8 | () or \ 9 | [] or \ 10 | {}: 11 | print("Some values are True.") 12 | else: 13 | print("None, False, 0, 0L, 0.0, '', (), [], {} are considered False.") 14 | 15 | def entry_point(argv): 16 | truth_value_testing() 17 | return 0 18 | 19 | def target(*args): 20 | return entry_point 21 | 22 | if __name__ == "__main__": 23 | import sys 24 | entry_point(sys.argv) 25 | -------------------------------------------------------------------------------- /code/truth_value_testing_inconsistency.py: -------------------------------------------------------------------------------- 1 | class ZeroLen(): 2 | def __len__(self): 3 | return 0 4 | 5 | class NonZero(): 6 | def __nonzero__(self): 7 | return False 8 | 9 | def truth_value_testing_inconsistency(): 10 | zero_len = ZeroLen() 11 | non_zero = NonZero() 12 | 13 | if zero_len: 14 | print("zero_len is True in RPython.") # RPython 15 | else: 16 | print("zero_len is False in Python.") # Python 17 | 18 | if non_zero: 19 | print("non_zero is True in RPython.") # RPtyhon 20 | else: 21 | print("non_zero is False in Python.") # Python 22 | 23 | def entry_point(argv): 24 | truth_value_testing_inconsistency() 25 | return 0 26 | 27 | def target(*args): 28 | return entry_point 29 | 30 | if __name__ == "__main__": 31 | import sys 32 | entry_point(sys.argv) 33 | -------------------------------------------------------------------------------- /code/tuples.py: -------------------------------------------------------------------------------- 1 | def tuples(): 2 | t = (1, 2) 3 | i, j = t # "unpack" a tuple 4 | print t, i, j 5 | t = (1, "123") # mixing types in a tuple 6 | print t 7 | 8 | l = [1, 2] 9 | t = (l[0], l[1]) # manually convert from a list to a tuple 10 | print t 11 | 12 | 13 | def tuples_unsupported(): 14 | l = [1, "123"] # mixing types in lists is not supported in RPython 15 | t = tuple(l) # converting from list to tuple is unsupported 16 | print t 17 | 18 | def entry_point(argv): 19 | tuples() 20 | return 0 21 | 22 | def target(*args): return entry_point 23 | if __name__ == "__main__": 24 | import sys; entry_point(sys.argv) 25 | tuples_unsupported() 26 | -------------------------------------------------------------------------------- /code/union_error.py: -------------------------------------------------------------------------------- 1 | def compiler_error(arg): 2 | v = 0 # v is an integer 3 | if arg: 4 | v = 1 # assign integer 1 to v 5 | else: 6 | v = "" # assign string "" to v 7 | return v 8 | 9 | def entry_point(argv): compiler_error(argv[1]); return 0 10 | def target(*args): return entry_point 11 | -------------------------------------------------------------------------------- /code/xrange.py: -------------------------------------------------------------------------------- 1 | def rrange(): 2 | # range and xrange are same in RPython 3 | for i in range(0, 10, 2): 4 | print i 5 | for i in xrange(0, 10, 3): 6 | print i 7 | 8 | def entry_point(argv): 9 | rrange() 10 | return 0 11 | 12 | def target(*args): return entry_point 13 | if __name__ == "__main__": import sys; entry_point(sys.argv) 14 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Configuration file for the Sphinx documentation builder. 4 | # 5 | # This file does only contain a selection of the most common options. For a 6 | # full list see the documentation: 7 | # http://www.sphinx-doc.org/en/master/config 8 | 9 | # -- Path setup -------------------------------------------------------------- 10 | 11 | # If extensions (or modules to document with autodoc) are in another directory, 12 | # add these directories to sys.path here. If the directory is relative to the 13 | # documentation root, use os.path.abspath to make it absolute, like shown here. 14 | # 15 | # import os 16 | # import sys 17 | # sys.path.insert(0, os.path.abspath('.')) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = u'RPython By Example' 23 | copyright = u'Mingshen Sun' 24 | author = u'Mingshen Sun' 25 | 26 | # The short X.Y version 27 | version = u'' 28 | # The full version, including alpha/beta/rc tags 29 | release = u'' 30 | 31 | 32 | # -- General configuration --------------------------------------------------- 33 | 34 | # If your documentation needs a minimal Sphinx version, state it here. 35 | # 36 | # needs_sphinx = '1.0' 37 | 38 | # Add any Sphinx extension module names here, as strings. They can be 39 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 40 | # ones. 41 | extensions = [ 42 | 'sphinx.ext.todo', 43 | 'sphinx.ext.viewcode', 44 | ] 45 | 46 | # Add any paths that contain templates here, relative to this directory. 47 | # templates_path = ['_templates'] 48 | 49 | # The suffix(es) of source filenames. 50 | # You can specify multiple suffix as a list of string: 51 | # 52 | # source_suffix = ['.rst', '.md'] 53 | source_suffix = '.rst' 54 | 55 | # The master toctree document. 56 | master_doc = 'index' 57 | 58 | # The language for content autogenerated by Sphinx. Refer to documentation 59 | # for a list of supported languages. 60 | # 61 | # This is also used if you do content translation via gettext catalogs. 62 | # Usually you set "language" from the command line for these cases. 63 | language = None 64 | 65 | # List of patterns, relative to source directory, that match files and 66 | # directories to ignore when looking for source files. 67 | # This pattern also affects html_static_path and html_extra_path. 68 | exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store', 'README.rst'] 69 | 70 | # The name of the Pygments (syntax highlighting) style to use. 71 | pygments_style = 'sphinx' 72 | 73 | # If true, `todo` and `todoList` produce output, else they produce nothing. 74 | todo_include_todos = True 75 | 76 | 77 | # -- Options for HTML output ------------------------------------------------- 78 | 79 | # The theme to use for HTML and HTML Help pages. See the documentation for 80 | # a list of builtin themes. 81 | # 82 | html_theme = 'sphinx_rtd_theme' 83 | 84 | # Theme options are theme-specific and customize the look and feel of a theme 85 | # further. For a list of options available for each theme, see the 86 | # documentation. 87 | # 88 | html_theme_options = { 89 | } 90 | html_context = { 91 | 'display_github': True, 92 | 'github_user': 'mesalock-linux', 93 | 'github_repo': 'rpython-by-example', 94 | 'github_version': 'master/' 95 | } 96 | 97 | html_show_sourcelink = False 98 | 99 | # Add any paths that contain custom static files (such as style sheets) here, 100 | # relative to this directory. They are copied after the builtin static files, 101 | # so a file named "default.css" will overwrite the builtin "default.css". 102 | # html_static_path = ['_static'] 103 | 104 | # Custom sidebar templates, must be a dictionary that maps document names 105 | # to template names. 106 | # 107 | # The default sidebars (for documents that don't match any pattern) are 108 | # defined by theme itself. Builtin themes are using these templates by 109 | # default: ``['localtoc.html', 'relations.html', 'sourcelink.html', 110 | # 'searchbox.html']``. 111 | # 112 | # html_sidebars = {} 113 | 114 | 115 | # -- Options for HTMLHelp output --------------------------------------------- 116 | 117 | # Output file base name for HTML help builder. 118 | htmlhelp_basename = 'RPythonByExampledoc' 119 | 120 | 121 | # -- Options for LaTeX output ------------------------------------------------ 122 | 123 | latex_elements = { 124 | 'sphinxsetup': 'hmargin={1.5in,1.5in}, vmargin={1.2in,1.2in}, marginpar=1in', 125 | # The paper size ('letterpaper' or 'a4paper'). 126 | # 127 | # 'papersize': 'letterpaper', 128 | 129 | # The font size ('10pt', '11pt' or '12pt'). 130 | # 131 | 'pointsize': '11pt', 132 | 133 | # Additional stuff for the LaTeX preamble. 134 | # 135 | 'preamble': r''' 136 | \usepackage{xeCJK} 137 | \fvset{fontsize=\footnotesize} 138 | ''', 139 | 140 | # Latex figure (float) alignment 141 | # 142 | # 'figure_align': 'htbp', 143 | } 144 | 145 | # Grouping the document tree into LaTeX files. List of tuples 146 | # (source start file, target name, title, 147 | # author, documentclass [howto, manual, or own class]). 148 | latex_documents = [ 149 | (master_doc, 'RPythonByExample.tex', u'RPython By Example', 150 | u'Mingshen Sun', 'manual'), 151 | ] 152 | 153 | latex_engine = 'xelatex' 154 | 155 | # -- Options for manual page output ------------------------------------------ 156 | 157 | # One entry per manual page. List of tuples 158 | # (source start file, name, description, authors, manual section). 159 | man_pages = [ 160 | (master_doc, 'rpythonbyexample', u'RPython By Example', 161 | [author], 1) 162 | ] 163 | 164 | 165 | # -- Options for Texinfo output ---------------------------------------------- 166 | 167 | # Grouping the document tree into Texinfo files. List of tuples 168 | # (source start file, target name, title, author, 169 | # dir menu entry, description, category) 170 | texinfo_documents = [ 171 | (master_doc, 'RPythonByExample', u'RPython By Example', 172 | author, 'RPythonByExample', 'RPython By Example (RPyBE) is a collection of \ 173 | runnable examples that illustrate various RPython concepts and RPython \ 174 | libraries.', 175 | 'Programming Language'), 176 | ] 177 | 178 | 179 | # -- Options for Epub output ------------------------------------------------- 180 | 181 | # Bibliographic Dublin Core info. 182 | epub_title = project 183 | 184 | # The unique identifier of the text. This can be a ISBN number 185 | # or the project homepage. 186 | # 187 | # epub_identifier = '' 188 | 189 | # A unique identification for the text. 190 | # 191 | # epub_uid = '' 192 | 193 | # A list of files that should not be packed into the epub file. 194 | epub_exclude_files = ['search.html'] 195 | -------------------------------------------------------------------------------- /error/index.rst: -------------------------------------------------------------------------------- 1 | Compilation Errors 2 | ================== 3 | 4 | Since RPython is only designed for PyPy at the first place, the compilation error 5 | messages are a bit confusing. Sometime, you need some knowledge of compiler 6 | design to understand what's going on. In this section, we show some common 7 | error messages you will see when compiler fails to compile the RPython sources. 8 | 9 | This is a very common error message caused by mixing different types. 10 | 11 | .. literalinclude:: ../code/union_error.py 12 | 13 | The following is a very verbose and confusing error message (which can be 14 | greatly improved). The RPython compiler will print out the stack trace like 15 | other exceptions in Python. You can find out types, error description, and other 16 | useful information of the error in the highlighted part below. In addition, 17 | the RPython compiler will give you a Pdb for debugging. 18 | 19 | .. code-block:: text 20 | :emphasize-lines: 34-46 21 | 22 | [translation:info] Error: 23 | File "/pypy/rpython/translator/goal/translate.py", line 318, in main 24 | drv.proceed(goals) 25 | File "/pypy/rpython/translator/driver.py", line 554, in proceed 26 | result = self._execute(goals, task_skip = self._maybe_skip()) 27 | File "/pypy/rpython/translator/tool/taskengine.py", line 114, in _execute 28 | res = self._do(goal, taskcallable, *args, **kwds) 29 | File "/pypy/rpython/translator/driver.py", line 278, in _do 30 | res = func() 31 | File "/pypy/rpython/translator/driver.py", line 315, in task_annotate 32 | s = annotator.build_types(self.entry_point, self.inputtypes) 33 | File "/pypy/rpython/annotator/annrpython.py", line 92, in build_types 34 | return self.build_graph_types(flowgraph, inputs_s, complete_now=complete_now) 35 | File "/pypy/rpython/annotator/annrpython.py", line 140, in build_graph_types 36 | self.complete() 37 | File "/pypy/rpython/annotator/annrpython.py", line 229, in complete 38 | self.complete_pending_blocks() 39 | File "/pypy/rpython/annotator/annrpython.py", line 224, in complete_pending_blocks 40 | self.processblock(graph, block) 41 | File "/pypy/rpython/annotator/annrpython.py", line 398, in processblock 42 | self.flowin(graph, block) 43 | File "/pypy/rpython/annotator/annrpython.py", line 572, in flowin 44 | self.follow_link(graph, link, constraints) 45 | File "/pypy/rpython/annotator/annrpython.py", line 603, in follow_link 46 | self.addpendingblock(graph, link.target, inputs_s) 47 | File "/pypy/rpython/annotator/annrpython.py", line 189, in addpendingblock 48 | self.mergeinputargs(graph, block, cells) 49 | File "/pypy/rpython/annotator/annrpython.py", line 435, in mergeinputargs 50 | unions = [annmodel.unionof(c1,c2) for c1, c2 in zip(oldcells,inputcells)] 51 | File "/pypy/rpython/annotator/model.py", line 775, in unionof 52 | s1 = pair(s1, s2).union() 53 | File "/pypy/rpython/annotator/binaryop.py", line 93, in union 54 | raise UnionError(obj1, obj2) 55 | [translation:ERROR] UnionError: 56 | 57 | Offending annotations: 58 | SomeString(const='', no_nul=True) 59 | SomeInteger(const=1, knowntype=int, nonneg=True, unsigned=False) 60 | 61 | In : 62 | 63 | Processing block: 64 | block@9[arg_0] is a 65 | in (error:1)compiler_error 66 | containing the following operations: 67 | v0 = bool(arg_0) 68 | --end-- 69 | [translation] start debugger... 70 | > /pypy/rpython/annotator/binaryop.py(93)union() 71 | -> raise UnionError(obj1, obj2) 72 | (Pdb+) 73 | 74 | Basically, there are two common errors (i.e., compiler exceptions) 75 | ``AnnotatorError``, ``FlowingError``. 76 | 77 | 78 | ``AnnotatorError`` 79 | ------------------ 80 | 81 | ``AnnotatorError`` is a class of compiler errors happens in annotating a RPython 82 | program. There are several specific errors in this class: 83 | 84 | * ``UnionError`` (``annotator/module.py``): annotator complains on type conflicts 85 | * ``TooLateForChange`` (``annotator/listdef.py``): not documented 86 | * ``ListChangeUnallowed`` (``annotator/listdef.py``): not documented 87 | * ``NoSuchAttrError`` (``annotator/classdesc.py``): attributes not found in a class 88 | * ``SignatureError`` (``annotator/signature.py``): function declaration signature difference 89 | 90 | In addition to above specific errors, there are many common annotator errors 91 | which are not raised by above error classes. 92 | 93 | For instance, this is a common annotator error: 94 | 95 | .. literalinclude:: ../code/annotator_error.py 96 | 97 | Here is the error message, which is very informative. In line 3, there is a 98 | signature mismatch. Specifically, the function takes no argument but 1 argument 99 | given in line 3. 100 | 101 | .. code-block:: text 102 | 103 | [translation:ERROR] AnnotatorError: 104 | 105 | signature mismatch: func() takes no arguments (1 given) 106 | 107 | 108 | Occurred processing the following simple_call: 109 | function func returning 110 | 111 | v0 = simple_call((function func), (1)) 112 | 113 | In : 114 | Happened at file signature_error.py line 3 115 | 116 | ==> func(1) 117 | 118 | Known variable annotations: 119 | 120 | Processing block: 121 | block@6[arg_0] is a 122 | in (signature_error:2)compiler_error 123 | containing the following operations: 124 | v0 = simple_call((function func), (1)) 125 | --end-- 126 | 127 | ``UnionError`` 128 | ~~~~~~~~~~~~~~ 129 | 130 | ``UnionError`` represents there is a type conflict when annotating types. In the 131 | above example, the variable ``v`` can be an integer type and a string type 132 | depends on the ``arg`` function parameter. Let us look at the error message again. 133 | 134 | .. code-block:: text 135 | :emphasize-lines: 4,5,7 136 | 137 | [translation:ERROR] UnionError: 138 | 139 | Offending annotations: 140 | SomeString(const='', no_nul=True) 141 | SomeInteger(const=1, knowntype=int, nonneg=True, unsigned=False) 142 | 143 | In : 144 | 145 | Processing block: 146 | block@9[arg_0] is a 147 | in (error:1)compiler_error 148 | containing the following operations: 149 | v0 = bool(arg_0) 150 | 151 | It tells you that there is a type conflict. The RPython annotator gives you the 152 | offending annotations, the ``SomeString`` type and the ``SomeInteger`` 153 | type, which cannot be unified. And this conflict is in the ``compiler_error`` 154 | function. 155 | 156 | ``FlowingError`` 157 | ---------------- 158 | 159 | ``FlowingError`` is all about errors when RPython compiler building control flow 160 | graphs. Here are some common causes for ``FlowingError``. 161 | 162 | * unsupported operations 163 | * invalid exception class 164 | * cannot import modules 165 | * local variable referenced before assignment 166 | * global name is not defined 167 | * etc. 168 | 169 | The flowing gives a simple example to illustrate ``FlowingError``. 170 | 171 | .. literalinclude:: ../code/flowing_error.py 172 | 173 | In addition to report ``FlowingError``, the compiler will give you some detailed 174 | explanation. 175 | 176 | .. code-block:: text 177 | :emphasize-lines: 3 178 | 179 | [translation:ERROR] FlowingError: 180 | 181 | global name 'v' is not defined 182 | 183 | In : 184 | Happened at file flowing_error.py line 2 185 | 186 | return v 187 | 188 | Processing block: 189 | block@9[argv_0] is a 190 | in (flowing_error:4)entry_point 191 | containing the following operations: 192 | v0 = getitem(argv_0, (1)) 193 | v1 = simple_call((function compiler_error), v0) 194 | --end-- 195 | 196 | When RPython detected a control flow which always raise an exception, it will 197 | report ``FlowingError``. 198 | 199 | .. literalinclude:: ../code/flowing2_error.py 200 | 201 | In the above example, ``1/0`` always raises a ``ZeroDivisionError`` exception. 202 | 203 | .. code-block:: text 204 | :emphasize-lines: 3 205 | 206 | [translation:ERROR] FlowingError: 207 | 208 | div(1, 0) always raises : integer division by zero 209 | 210 | In : 211 | Happened at file flowing2_error.py line 2 212 | 213 | n = 10 * (1/0) 214 | 215 | Processing block: 216 | block@9[argv_0] is a 217 | in (flowing2_error:5)entry_point 218 | containing the following operations: 219 | v0 = getitem(argv_0, (1)) 220 | v1 = simple_call((function compiler_error), v0) 221 | --end-- 222 | -------------------------------------------------------------------------------- /examples/index.rst: -------------------------------------------------------------------------------- 1 | Examples with RPython 2 | ===================== 3 | 4 | Here are some examples implemented with RPython: 5 | 6 | References: 7 | * `Tutorial: Writing an Interpreter with PyPy, Part 1 `_ 8 | * `Tutorial Part 2: Adding a JIT `_ (`code `__) 9 | * `Kermit - an example interpreter `_ 10 | * `Implementing a Calculator REPL in RPython `_ (`code `__) 11 | -------------------------------------------------------------------------------- /flow-control/index.rst: -------------------------------------------------------------------------------- 1 | Flow Control 2 | ============ 3 | 4 | .. todo:: This section is not finished yet. Provides more examples and 5 | explanations. 6 | 7 | Variables 8 | --------- 9 | 10 | Variables should contain values of at most *one type* at each control flow 11 | point. For example, this means that joining control paths using the same 12 | variable to contain both a string and a int must be avoided. 13 | 14 | Let's look at this example code. 15 | 16 | .. literalinclude:: ../code/union_error.py 17 | 18 | The control flow graph of the ``compiler_error`` function is shown in the 19 | following figure. 20 | 21 | .. figure:: ../images/union_error.png 22 | :width: 60% 23 | :align: center 24 | 25 | Merge point of a control flow with different types. 26 | 27 | As you can see, at the merge point (highlighted in green), ``v2`` can be 28 | either integer ``1`` or an empty string ``''``. this violate the RPython's 29 | restriction. 30 | 31 | It is allowed to mix ``None`` with many other types: wrapped objects, class 32 | instances, lists, dicts, strings, etc., but not with int, floats or tuples. 33 | 34 | .. literalinclude:: ../code/flow_control_variables.py 35 | 36 | Constants 37 | --------- 38 | 39 | .. note:: 40 | All module globals are considered constants. Their binding must not be 41 | changed at run-time. Moreover, global (i.e. prebuilt) lists and dictionaries 42 | are supposed to be immutable: modifying e.g. a global list will give 43 | inconsistent results. However, global instances don’t have this restriction, 44 | so if you need mutable global state, store it in the attributes of some 45 | prebuilt singleton instance. 46 | 47 | Control structures 48 | ------------------ 49 | 50 | .. note:: 51 | All allowed, for loops restricted to builtin types, generators very restricted. 52 | 53 | Range 54 | ----- 55 | 56 | .. note:: 57 | Range and xrange are identical. range does not necessarily create an array, 58 | only if the result is modified. It is allowed everywhere and completely 59 | implemented. The only visible difference to CPython is the inaccessibility 60 | of the xrange fields start, stop and step. 61 | 62 | Definitions 63 | ----------- 64 | 65 | .. note:: 66 | Run-time definition of classes or functions is not allowed. 67 | 68 | Generators 69 | ---------- 70 | 71 | .. note:: 72 | Generators are supported, but their exact scope is very limited. you can’t 73 | merge two different generator in one control point. 74 | 75 | Exceptions 76 | ---------- 77 | 78 | Python exceptions are fully supported. For example, you can catch exceptions by 79 | the ``except`` keyword following a specific exception class. 80 | 81 | .. literalinclude:: ../code/errors_exceptions.py 82 | 83 | You can also use the ``raise`` keyword to raise exceptions. The ``finally`` keyword 84 | is used to do some cleanup actions. 85 | 86 | .. literalinclude:: ../code/handle_exceptions.py 87 | 88 | .. attention:: 89 | There is one special difference in the exception handling on "simple cases". 90 | In `RPython document 91 | `_, it 92 | says by default, **code with no exception handlers does 93 | not raise exceptions**. By supplying an exception handler, you ask for error 94 | checking. Without, you assure the system that the operation cannot fail. This 95 | rule does not apply to function calls: any called function is assumed to be 96 | allowed to raise any exception. 97 | 98 | .. todo:: 99 | MesaPy added mandatory ``IndexError`` checks. Give some details here. 100 | -------------------------------------------------------------------------------- /getting-started/index.rst: -------------------------------------------------------------------------------- 1 | Getting Started 2 | =============== 3 | 4 | Hello, World! 5 | ------------- 6 | 7 | This is the source code of a traditional Hello World program written in 8 | RPython. 9 | 10 | .. literalinclude:: ../code/hello_world.py 11 | 12 | To compile it, we should first install Python (both CPython and PyPy are OK). 13 | In addition, we need to obtain the RPython compiler from 14 | `PyPy's repository `_. The RPython compiler 15 | is located at ``pypy/rpython/bin/rpython``. 16 | 17 | .. note:: 18 | All examples in this doc are tested with the RPython compiler in PyPy's 19 | codebase (tag: ``release-pypy2.7-v6.0.0`` and ``release-pypy2.7-v7.1.0``), 20 | and with CPython 2.7 (aka. Python 2.7) or PyPy 2.7 installed. 21 | 22 | .. code-block:: shell 23 | 24 | $ sudo apt-get install python2 libgc-dev 25 | $ sudo apt-get install libgc-dev # if you want to use Boehm GC 26 | $ wget https://bitbucket.org/pypy/pypy/downloads/pypy2.7-v7.1.0-src.tar.bz2 27 | $ tar jxf pypy2.7-v7.1.0-src.tar.bz2 28 | $ export RPY=$(pwd)/pypy2.7-v7.1.0-src/rpython/bin/rpython 29 | $ export PATH=$PATH:$(pwd)/pypy2.7-v7.1.0-src/rpython/bin 30 | $ cd code && make hello_world 31 | 32 | Now, we can compile our first hello world example by running: 33 | 34 | .. code-block:: shell 35 | 36 | $ rpython hello_world.py 37 | 38 | An executable named ``hello_world-c`` is generated by the compiler. When 39 | launching the executable, a "Hello, World!" message will be printed out. 40 | 41 | .. code-block:: shell 42 | 43 | $ ./hello_world-c 44 | Hello, World! 45 | 46 | Since RPython syntax is a restricted version of Python, therefore you can 47 | use any Python interpreter to run the hello world example just like before. 48 | In this example, we should add an entry point in the script. 49 | 50 | .. literalinclude:: ../code/hello_world_python.py 51 | 52 | Then, you can run the script as normal with Python. 53 | 54 | .. code-block:: shell 55 | 56 | $ python hello_world_python.py 57 | Hello, World! 58 | 59 | This implies that you can test your RPython code with any Python interpreter and 60 | then compile to native code. 61 | -------------------------------------------------------------------------------- /images/union_error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mssun/rpython-by-example/2d5f7450f8188dd10fca330bf81c55641a9748fd/images/union_error.png -------------------------------------------------------------------------------- /index.rst: -------------------------------------------------------------------------------- 1 | RPython By Example 2 | ================== 3 | 4 | RPython is a language designed for producing implementations of dynamic 5 | languages. The most notable one is PyPy, which is a fast alternative 6 | implementation of the Python language. However, we thought the value of RPython 7 | is far beyond that. In this doc, we will meet RPython language by several 8 | examples, and compare the syntax with Python. At last, we wish you can have 9 | a better understanding of the language, and hopefully, adopt it in many other 10 | scenarios. 11 | 12 | RPython by Example (RPyBE) is a collection of runnable examples that illustrate 13 | various RPython concepts and libraries. RPyBE starts with a hello world example 14 | and built-in types in RPython, then dives into RPython libraries, and build a 15 | simple application at last. 16 | 17 | .. toctree:: 18 | :maxdepth: 1 19 | :caption: Contents: 20 | 21 | overview/index 22 | getting-started/index 23 | builtin-types/index 24 | builtin-functions/index 25 | classes/index 26 | flow-control/index 27 | rlib/index 28 | jit/index 29 | rffi/index 30 | error/index 31 | rewrite-benchmarks/index 32 | examples/index 33 | references/index 34 | -------------------------------------------------------------------------------- /jit/index.rst: -------------------------------------------------------------------------------- 1 | JIT 2 | === 3 | 4 | Simple Example 5 | -------------- 6 | 7 | The following example is a interpreter of `brainfuck 8 | `_ language with JIT. 9 | There is a detailed tutorial (`part1 10 | `_, 11 | `part2 `_) on 12 | how to write a simple interpreter with RPython. 13 | Here, we briefly introduce some JIT-related data structures, functions, and decorators. 14 | 15 | .. literalinclude:: ../code/bf.py 16 | :linenos: 17 | 18 | JitDriver 19 | ------------- 20 | 21 | An interpreter wishing to use the RPython JIT generator must define a list of 22 | green variables and a list of red variables. The green variables are loop 23 | constants. They are used to identify the current loop. Red variables are for 24 | everything else used in the execution loop. 25 | 26 | JIT Decorators and Functions 27 | ---------------------------- 28 | 29 | * elidable 30 | * hint 31 | * promote 32 | * promote_string 33 | * dont_look_inside 34 | * look_inside 35 | * look_inside_iff 36 | * unroll_safe 37 | * loop_invariant 38 | * elidable_promote 39 | * oopspec 40 | * not_in_trace 41 | * isconstant 42 | * isvirtual 43 | * loop_unroll_heuristic 44 | * we_are_jitted 45 | 46 | JIT Parameters 47 | -------------- 48 | 49 | * ``threshold``: number of times a loop has to run for it to become hot 50 | * ``function_threshold``: number of times a function must run for it to become traced from start 51 | * ``trace_eagerness``: number of times a guard has to fail before we start compiling a bridge 52 | * ``decay``: amount to regularly decay counters by (0=none, 1000=max) 53 | * ``trace_limit``: number of recorded operations before we abort tracing with ABORT_TOO_LONG 54 | * ``inlining``: inline python functions or not (1/0) 55 | * ``loop_longevity``: a parameter controlling how long loops will be kept before being freed, an estimate 56 | * ``retrace_limit``: how many times we can try retracing before giving up 57 | * ``max_retrace_guards``: number of extra guards a retrace can cause 58 | * ``max_unroll_loops``: number of extra unrollings a loop can cause 59 | * ``disable_unrolling``: after how many operations we should not unroll 60 | * ``enable_opts``: internal use only (may not work or lead to crashes): optimizations 61 | to enable, or all = intbounds:rewrite:virtualize:string:pure:earlyforce:heap:unroll 62 | * ``max_unroll_recursion``: how many levels deep to unroll a recursive function 63 | * ``vec``: turn on the vectorization optimization (vecopt). Supports x86 (SSE 4.1), powerpc (SVX), s390x SIMD 64 | * ``vec_cost``: threshold for which traces to bail. Unpacking increases the counter, vector operation decrease the cost, 65 | * ``vec_all``: try to vectorize trace loops that occur outside of the numpypy library 66 | 67 | The default parameters are: 68 | 69 | .. code-block:: python 70 | 71 | PARAMETERS = {'threshold': 1039, # just above 1024, prime 72 | 'function_threshold': 1619, # slightly more than one above, also prime 73 | 'trace_eagerness': 200, 74 | 'decay': 40, 75 | 'trace_limit': 6000, 76 | 'inlining': 1, 77 | 'loop_longevity': 1000, 78 | 'retrace_limit': 0, 79 | 'max_retrace_guards': 15, 80 | 'max_unroll_loops': 0, 81 | 'disable_unrolling': 200, 82 | 'enable_opts': 'all', 83 | 'max_unroll_recursion': 7, 84 | 'vec': 0, 85 | 'vec_all': 0, 86 | 'vec_cost': 0, 87 | } 88 | -------------------------------------------------------------------------------- /overview/index.rst: -------------------------------------------------------------------------------- 1 | Overview 2 | ======== 3 | 4 | RPython by Example (RPyBE) is a collection of runnable examples that illustrate 5 | various RPython concepts and libraries. RPyBE starts with a hello world example 6 | and built-in types in RPython, then dives into RPython libraries, and build a 7 | simple application at last. 8 | 9 | Since RPython is based on the Python syntax, most concepts in RPython are 10 | similar with Python. However, there are still some notable differences in 11 | built-in types. Firstly, RPython is strong typed. This imposes some restrictions 12 | on using built-in types such as list and dict. In addition, some implementation 13 | differences also bring us restrictions to a certain degree. For instance, the 14 | set type is not implemented in RPython, and we have to use dict to simulate the 15 | set type. Since there are many differences scattered here and there, we 16 | highlight the differences, inconsistencies, and usage suggestions in admonition 17 | boxes within the paragraphs. 18 | 19 | In RPyBE, we give plentiful examples on RPython's builtin types, RPython 20 | modules, and FFI. Also, to demonstrate the capabilities of RPython, we use it to 21 | design and implement a toy language with JIT. In a nutshell, RPyBE will help you 22 | to understand RPython's restrictions and quickly get started with it. 23 | 24 | .. note:: 25 | All example source code in the book can be found in the RPyBE repository 26 | under the ``code`` directory. Note that file names with the ``unsupported`` 27 | suffix are code which supported by CPython but not RPython. And file names with 28 | the ``error`` suffix are code to illustrate RPython compiler errors. You can 29 | use the ``make`` to compile a specific RPython source. For instance, to compile 30 | the hello world example, you need to setup ``$RPY`` path first, run ``make 31 | hello_world``, and execute with ``./hello_world-c``. 32 | -------------------------------------------------------------------------------- /references/index.rst: -------------------------------------------------------------------------------- 1 | References 2 | ========== 3 | 4 | * `PyPy Repository `_ 5 | * `PyPy Status Blog `_ 6 | * `RPython's documentation `_ 7 | * `Understanding RPython `_ 8 | * `The Architecture of Open Source Applications Volume II `_ 9 | -------------------------------------------------------------------------------- /rewrite-benchmarks/index.rst: -------------------------------------------------------------------------------- 1 | Rewriting Python Benchmarks 2 | =========================== 3 | 4 | To understand the performance of RPython, we are trying to rewrite some `Python 5 | benchmarks `_ with RPython. In this 6 | section, we use several examples (fibonacci number and binary tree) to 7 | illustrate tips to rewrite Python code with RPython. As you will see, rewriting 8 | Python with RPython doesn't require much effort, and we will gain a lot of 9 | performance improvements. 10 | 11 | Fibonacci Number 12 | ---------------- 13 | 14 | The following code is to calculate fibonacci number recursively. 15 | 16 | .. literalinclude:: /code/benchmarks/fib.py 17 | 18 | To run this benchmark, we should add a target function to tell RPython the entry 19 | point. Also, we change to get ``n`` from arguments instead of hard-coding a 20 | constant to avoid optimization. The following code can be compiled by RPython. 21 | 22 | .. literalinclude:: /code/benchmarks/fib_rpy.py 23 | :linenos: 24 | :emphasize-lines: 6-11,13-14,16-18 25 | 26 | .. note:: 27 | There are some passes to `simplify flow graph 28 | `_ 29 | for optimization. These passes include 30 | ``transform_dead_op_vars``, ``eliminate_empty_blocks``, ``remove_assertion_errors``, 31 | ``remove_identical_vars_SSA``, ``constfold_exitswitch``, ``remove_trivial_links``, 32 | ``SSA_to_SSI``, ``coalesce_bool``, ``transform_ovfcheck``, ``simplify_exceptions``, 33 | ``transform_xxxitem``, and ``remove_dead_exceptions``. 34 | 35 | Here, we simply use the GNU ``time`` command to measure the execution time and 36 | maximum resident set size during the process's lifetime. 37 | 38 | .. code-block:: text 39 | 40 | $ /usr/bin/time -f "%C\t%U\t%M" python fib.py > /dev/null 41 | python fib.py 18.21 5956 42 | 43 | $ /usr/bin/time -f "%C\t%U\t%M" pypy fib.py > /dev/null 44 | pypy fib.py 4.77 112960 45 | 46 | $ rpython fib_rpy.py 47 | 48 | $ /usr/bin/time -f "%C\t%U\t%M" ./fib-c 40 > /dev/null 49 | ./fib_rpy-c 40 0.40 1704 50 | 51 | Binary Tree 52 | ----------- 53 | 54 | Rewriting the binary tree benchmark needs a little more efforts. In the Python 55 | version, it uses a tuple of tuples to represent nodes the the tree. Since 56 | RPython doesn't allow variable length tuples and mixed types tuples, we write a 57 | new ``Node`` class to represent nodes in binary trees. In addition, we 58 | rewrite the ``sum`` built-in function. The following code only shows ``diff`` of 59 | original Python code and modified RPython version. 60 | 61 | .. literalinclude:: ../code/benchmarks/binary-tree_rpy.py 62 | :diff: ../code/benchmarks/binary-tree.py 63 | 64 | Let us measure execution times of the binary tree benchmark with Python and 65 | PyPy, and RPython rewrite as well. 66 | 67 | .. code-block:: text 68 | 69 | $ /usr/bin/time -f "%C\t%U\t%M" python binary-tree.py > /dev/null 70 | python binary-tree.py 10.45 60432 71 | 72 | $ /usr/bin/time -f "%C\t%U\t%M" pypy binary-tree.py > /dev/null 73 | pypy binary-tree.py 1.60 187256 74 | 75 | $ /usr/bin/time -f "%C\t%U\t%M" ./binary-tree_rpy-c 17 > /dev/null 76 | ./binary-tree_rpy-c 17 0.38 68312 77 | 78 | Spectral Norm 79 | ------------- 80 | 81 | For the spectral norm benchmark, we made the following changes: 82 | 83 | * rewrite map function 84 | * rewrite generators 85 | * use list instead of tuple 86 | * use loop to rewrite izip function 87 | 88 | .. literalinclude:: ../code/benchmarks/spectral-norm_rpy.py 89 | :diff: ../code/benchmarks/spectral-norm.py 90 | 91 | .. code-block:: text 92 | 93 | $ /usr/bin/time -f "%C\t%U\t%M" python spectral-norm.py > /dev/null 94 | python spectral-norm.py 34.83 6140 95 | 96 | $ /usr/bin/time -f "%C\t%U\t%M" pypy spectral-norm.py > /dev/null 97 | pypy spectral-norm.py 1.20 81016 98 | 99 | $ /usr/bin/time -f "%C\t%U\t%M" ./spectral-norm_rpy-c 17 > /dev/null 100 | ./spectral-norm_rpy-c 400 0.26 7892 101 | 102 | Benchmark Results 103 | ----------------- 104 | 105 | In addition to "fibonacci number" and "binary tree", we also rewrite some other 106 | benchmarks (`source code 107 | `_). 108 | The following table summarize the benchmark results. 109 | 110 | +-----------------+-----------------+----------+-------------+----------+----------+----------+----------+ 111 | | | Python 2.7.15 | PyPy2 v6.0.0 | RPython (PyPy2 v6.0.0) | 112 | +=================+=================+==========+=============+==========+=====================+==========+ 113 | | |Time (s) |Time (s) |Speedup |Time (s) |Speedup | | 114 | | | | | | | |Size (KB) | 115 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 116 | |fib.py |18.21 |4.77 |3.82 |0.40 |45.53 |282 | 117 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 118 | |binary-tree.py |10.45 |1.60 |6.53 |0.38 |27.50 |301 | 119 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 120 | |float.py |11.47 |1.51 |7.60 |0.57 |20.12 |277 | 121 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 122 | |fannkuch.py |3.91 |0.54 |7.24 |0.32 |12.22 |282 | 123 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 124 | |buffer.py |1.23 |0.64 |1.92 |0.52 |2.37 |284 | 125 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 126 | |spectral-norm.py |34.83 |1.20 |29.03 |0.26 |133.96 |307 | 127 | +-----------------+-----------------+----------+-------------+----------+---------------------+----------+ 128 | 129 | As you can see, the average speedup of RPython compared to Python 2.7.15 is 130 | about 21. Moreover, compared to the very large Python interpreter, the size of 131 | RPython binary is pretty small. 132 | -------------------------------------------------------------------------------- /rffi/index.rst: -------------------------------------------------------------------------------- 1 | Foreign Function Interface (rffi) 2 | ================================= 3 | 4 | The foreign function interface of RPython is called rffi. With rffi, you can 5 | declaring low-level external C function, registering function as external, 6 | defining C types, etc. 7 | 8 | Call Functions in libc 9 | ---------------------- 10 | 11 | The following example shows how to use rffi to call math function in libc. 12 | 13 | .. literalinclude:: ../code/rffi_abs.py 14 | 15 | Separate Module Source 16 | ---------------------- 17 | 18 | You can also write C function directly. The C build tool of RPython translator 19 | will automatically compile and link with the C functions. 20 | 21 | .. literalinclude:: ../code/rffi_separate_module_sources.py 22 | 23 | String Operations 24 | ----------------- 25 | 26 | There are several functions to handle string conversion including ASCII and 27 | unicode encodings: 28 | 29 | .. code-block:: text 30 | 31 | * str2charp, free_charp, charp2str, 32 | get_nonmovingbuffer, free_nonmovingbuffer, get_nonmovingbuffer_final_null, 33 | alloc_buffer, str_from_buffer, keep_buffer_alive_until_here, 34 | charp2strn, charpsize2str, str2chararray, str2rawmem, 35 | 36 | * unicode2wcharp, free_wcharp, wcharp2unicode, 37 | get_nonmoving_unicodebuffer, free_nonmoving_unicodebuffer, 38 | alloc_unicodebuffer, unicode_from_buffer, keep_unicodebuffer_alive_until_here, 39 | wcharp2unicoden, wcharpsize2unicode, unicode2wchararray, unicode2rawmem, 40 | 41 | Here are two examples illustrate the usage of ``str2charp`` and ``charp2str``. 42 | 43 | .. literalinclude:: ../code/rffi_str.py 44 | 45 | List Conversion 46 | --------------- 47 | 48 | List of strings is commonly used in some cases, there are two pair of functions: 49 | ``liststr2charpp`` and ``charpp2liststr``. Remember to free the list using 50 | ``free_charpp``. 51 | 52 | .. code-block:: text 53 | 54 | * liststr2charpp: list[str] -> char**, NULL terminated 55 | * free_charpp: frees list of char**, NULL terminated 56 | * charpp2liststr: char** NULL terminated -> list[str]. No freeing is done. 57 | 58 | Here is an example of calculating the total length of a list of strings. 59 | 60 | .. literalinclude:: ../code/rffi_liststr.py 61 | 62 | Other Functions 63 | --------------- 64 | 65 | There are other useful functions like scoped str conversion and buffer allocation. 66 | 67 | .. todo:: Need more detailed examples and explanation. 68 | 69 | .. code-block:: text 70 | 71 | * size_and_sign, sizeof, offsetof 72 | * structcopy 73 | * setintfiled, getintfield 74 | * scoped_str2charp, scoped_unicode2wcharp, scoped_nonmovingbuffer, 75 | scoped_view_charp, schoped_nonmoving_unicodebuffer, scoped_alloc_buffer, 76 | scoped_alloc_unicodebuffer 77 | * c_memcpy, c_memset 78 | * get_raw_address_of_string 79 | 80 | More Examples 81 | ------------- 82 | 83 | Here are three more examples on handling string and callback functions. 84 | 85 | .. literalinclude:: ../code/rffi_more.py 86 | 87 | .. note:: 88 | More examples of handling built-in types, string, unicode, opaque type, 89 | struct, pre-built constant, callback, and buffer can be found in 90 | `rffi's tests `_. 91 | 92 | 93 | Usage of ExternalCompilationInfo 94 | -------------------------------- 95 | 96 | As you can see ``rpython.translator.tool.cbuild.ExternalCompilationInfo`` is a 97 | pretty useful utility to interacting with external function through C ffi. 98 | Let us read the detailed explanation on the attributes of 99 | ``ExternalCompilationInfo`` in the source code 100 | (``rpython/translator/tool/cbuild.py``). 101 | 102 | * ``pre_include_bits``: list of pieces of text that should be put at the top of the 103 | generated .c files, before any #include. They shouldn't contain an #include 104 | themselves. (Duplicate pieces are removed.) 105 | * ``includes``: list of .h file names to be #include'd from the generated .c files. 106 | * ``include_dirs``: list of dir names that is passed to the C compiler 107 | * ``post_include_bits``: list of pieces of text that should be put at the top of the 108 | generated .c files, after the #includes. (Duplicate pieces are removed.) 109 | * ``libraries``: list of library names that is passed to the linker 110 | * ``library_dirs``: list of dir names that is passed to the linker 111 | * ``separate_module_sources``: list of multiline strings that are each written to a 112 | .c file and compiled separately and linked later on. (If function prototypes 113 | are needed for other .c files to access this, they can be put in 114 | post_include_bits.) 115 | * ``separate_module_files``: list of .c file names that are compiled separately and 116 | linked later on. (If an .h file is needed for other .c files to access this, 117 | it can be put in includes.) 118 | * ``compile_extra``: list of parameters which will be directly passed to the 119 | compiler 120 | * ``link_extra``: list of parameters which will be directly passed to the linker 121 | * ``frameworks``: list of Mac OS X frameworks which should passed to the linker. Use 122 | this instead of the 'libraries' parameter if you want to link to a framework 123 | bundle. Not suitable for unix-like .dylib installations. 124 | * ``link_files``: list of file names which will be directly passed to the linker 125 | * ``testonly_libraries``: list of libraries that are searched for during testing 126 | only, by ll2ctypes. Useful to search for a name in a dynamic library during 127 | testing but use the static library for compilation. 128 | * ``use_cpp_linker``: a flag to tell if g++ should be used instead of gcc when 129 | linking (a bit custom so far) 130 | * ``platform``: an object that can identify the platform 131 | 132 | FFI Types 133 | --------- 134 | 135 | Since there is no formal definitions of FFI types in docs and source code (some 136 | definitions are dynamically generated), here is a dump of all definitions in 137 | RPython FFI types. It is quit easy to understand the types based on the names. 138 | 139 | .. todo:: Need more detailed examples and explanation. 140 | 141 | .. code-block:: text 142 | 143 | # type definitions 144 | AroundFnPtr 145 | CCHARP 146 | CCHARPP 147 | CHAR 148 | CONST_CCHARP 149 | CWCHARP 150 | CWCHARPP 151 | DOUBLE 152 | DOUBLEP 153 | FLOAT 154 | FLOATP 155 | INT 156 | INTMAX_T 157 | INTMAX_TP 158 | INTP 159 | INTPTR_T 160 | INTPTR_TP 161 | INT_FAST16_T 162 | INT_FAST16_TP 163 | INT_FAST32_T 164 | INT_FAST32_TP 165 | INT_FAST64_T 166 | INT_FAST64_TP 167 | INT_FAST8_T 168 | INT_FAST8_TP 169 | INT_LEAST16_T 170 | INT_LEAST16_TP 171 | INT_LEAST32_T 172 | INT_LEAST32_TP 173 | INT_LEAST64_T 174 | INT_LEAST64_TP 175 | INT_LEAST8_T 176 | INT_LEAST8_TP 177 | INT_real 178 | LONG 179 | LONGDOUBLE 180 | LONGDOUBLEP 181 | LONGLONG 182 | LONGLONGP 183 | LONGP 184 | LONG_BIT 185 | MODE_T 186 | MODE_TP 187 | NULL 188 | PID_T 189 | PID_TP 190 | PTRDIFF_T 191 | PTRDIFF_TP 192 | SHORT 193 | SHORTP 194 | SIGNED 195 | SIGNEDCHAR 196 | SIGNEDCHARP 197 | SIGNEDP 198 | SIGNEDPP 199 | SIZE_T 200 | SIZE_TP 201 | SSIZE_T 202 | SSIZE_TP 203 | TIME_T 204 | TIME_TP 205 | UCHAR 206 | UCHARP 207 | UINT 208 | UINTMAX_T 209 | UINTMAX_TP 210 | UINTP 211 | UINTPTR_T 212 | UINTPTR_TP 213 | UINT_FAST16_T 214 | UINT_FAST16_TP 215 | UINT_FAST32_T 216 | UINT_FAST32_TP 217 | UINT_FAST64_T 218 | UINT_FAST64_TP 219 | UINT_FAST8_T 220 | UINT_FAST8_TP 221 | UINT_LEAST16_T 222 | UINT_LEAST16_TP 223 | UINT_LEAST32_T 224 | UINT_LEAST32_TP 225 | UINT_LEAST64_T 226 | UINT_LEAST64_TP 227 | UINT_LEAST8_T 228 | UINT_LEAST8_TP 229 | ULONG 230 | ULONGLONG 231 | ULONGLONGP 232 | ULONGP 233 | USHORT 234 | USHORTP 235 | VOID* 236 | VOID*P 237 | VOIDP 238 | VOIDPP 239 | WCHAR_T 240 | WCHAR_TP 241 | __INT128_T 242 | __INT128_TP 243 | 244 | # functions/classes to create a type 245 | CArray 246 | CArrayPtr 247 | CCallback 248 | CConstant 249 | CExternVariable 250 | CFixedArray 251 | COpaque 252 | COpaquePtr 253 | CStruct 254 | CStructPtr 255 | -------------------------------------------------------------------------------- /rlib/index.rst: -------------------------------------------------------------------------------- 1 | Modules (rlib) 2 | ============== 3 | 4 | There are many general useful modules in RPython's standard library (also called 5 | rlib). For example, ``rmd5`` and ``rsha`` are libraries for hashing. ``rsre`` is a 6 | regular expression library. In this section, we will use some examples to show 7 | commonly used libraries. 8 | 9 | Here is a full list of rlib. 10 | 11 | * buffer 12 | * cache 13 | * clibffi 14 | * compilerinfo 15 | * constant 16 | * copyright 17 | * debug 18 | * entrypoint 19 | * exports 20 | * jit_hooks 21 | * jit_libffi 22 | * jit 23 | * libffi 24 | * :doc:`listsort`: stable sorting algorithm (i.e., Timsort) 25 | * longlong2float 26 | * mutbuffer 27 | * nonconst 28 | * objectmodel 29 | * parsing 30 | * :doc:`rarithmetic`: classes and operations to express integer arithmetic 31 | * rawrefcount 32 | * rawstorage 33 | * :doc:`rbigint`: functions handle big integer 34 | * :doc:`rbisect`: a basic bisection algorithm 35 | * rcomplex 36 | * rdtoa 37 | * rdynload 38 | * rerased 39 | * rfile 40 | * rfloat 41 | * rgc 42 | * rgil 43 | * rjitlog 44 | * rlocale 45 | * rmarshal 46 | * :doc:`rmd5`: calculate MD5 digest 47 | * rmmap 48 | * ropenssl 49 | * rope 50 | * :doc:`rpath`: minimal (and limited) RPython version of some functions contained in os.path 51 | * rpoll 52 | * rposix_environ 53 | * rposix 54 | * rposix_scandir 55 | * rposix_stat 56 | * :doc:`rrandom`: pseudo-random number generators 57 | * rrawarray 58 | * :doc:`rsha`: calculate SHA digest 59 | * rshrinklist 60 | * rsignal 61 | * rsiphash 62 | * rsocket 63 | * :doc:`rsre`: regular expression matching operations same as the Python ``re`` module 64 | * rstacklet 65 | * rstackovf 66 | * rstack 67 | * rstrategies 68 | * rStringIO 69 | * rstring 70 | * rstruct 71 | * rtermios 72 | * rthread 73 | * :doc:`rtime`: time-related functions 74 | * :doc:`rtimer`: basic functions of timer 75 | * runicode 76 | * :doc:`rurandom`: random number generator depends on OS implementation 77 | * rvmprof 78 | * rweaklist 79 | * rweakref 80 | * rwin32file 81 | * rwin32 82 | * rwinreg 83 | * rzipfile 84 | * rzlib 85 | * signature 86 | * special_value 87 | * streamio 88 | * types 89 | * unicodedata 90 | * unroll 91 | 92 | 93 | .. toctree:: 94 | :hidden: 95 | :maxdepth: 2 96 | 97 | listsort 98 | rarithmetic 99 | rbigint 100 | rbisect 101 | rmd5 102 | rpath 103 | rrandom 104 | rsha 105 | rsre 106 | rtime 107 | rtimer 108 | rurandom 109 | -------------------------------------------------------------------------------- /rlib/listsort.rst: -------------------------------------------------------------------------------- 1 | listsort 2 | ======== 3 | 4 | To sort a list in RPython, you can use the `rpython.rlib.listsort` module which 5 | provides a Timsort sorting algorithm. `Timsort 6 | `_ is a hybrid stable sorting algorithm, 7 | derived from merge sort and insertion sort, designed to perform well on many 8 | kinds of real-world data. Many programming languages' standard libraries use 9 | Timsort to sort arrays of non-primitive type. 10 | 11 | .. literalinclude:: ../code/listsort.py 12 | -------------------------------------------------------------------------------- /rlib/rarithmetic.rst: -------------------------------------------------------------------------------- 1 | rarithmetic 2 | =========== 3 | 4 | rarithmetic provides lasses and operations to express integer arithmetic, such 5 | as C type integer and overflow checked methods. 6 | 7 | .. literalinclude:: ../code/rarithmetic.py 8 | -------------------------------------------------------------------------------- /rlib/rbigint.rst: -------------------------------------------------------------------------------- 1 | rbigint 2 | ======= 3 | 4 | rbigint contains functions of big integers such as math functions, converting 5 | between types, comparison, etc. 6 | 7 | .. literalinclude:: ../code/rbigint.py 8 | -------------------------------------------------------------------------------- /rlib/rbisect.rst: -------------------------------------------------------------------------------- 1 | rbisect 2 | ======= 3 | 4 | rbisect provides binary search algorithm to find an item in a sorted list. 5 | 6 | .. literalinclude:: ../code/rbisect.py 7 | -------------------------------------------------------------------------------- /rlib/rmd5.rst: -------------------------------------------------------------------------------- 1 | rrmd5 2 | ===== 3 | 4 | There are four function provided in rmd5: ``new``, ``update``, ``digest``, and ``hexdigest``. 5 | 6 | .. literalinclude:: ../code/rmd5.py 7 | -------------------------------------------------------------------------------- /rlib/rpath.rst: -------------------------------------------------------------------------------- 1 | rpath 2 | ===== 3 | 4 | rpath is a minimal (and limited) version of some functions contained in Python's 5 | `os.path`. Currently, there are four functions: ``risabs``, ``rnormpath``, 6 | ``rabspath``, ``rjoin``. 7 | 8 | .. literalinclude:: ../code/rpath.py 9 | -------------------------------------------------------------------------------- /rlib/rrandom.rst: -------------------------------------------------------------------------------- 1 | rrandom 2 | ======= 3 | 4 | .. literalinclude:: ../code/rrandom.py 5 | -------------------------------------------------------------------------------- /rlib/rsha.rst: -------------------------------------------------------------------------------- 1 | rsha 2 | ==== 3 | 4 | There are four function provided in rsha: ``new``, ``update``, ``digest``, and ``hexdigest``. 5 | 6 | .. literalinclude:: ../code/rsha.py 7 | -------------------------------------------------------------------------------- /rlib/rsre.rst: -------------------------------------------------------------------------------- 1 | rsre 2 | ==== 3 | 4 | ``rsre`` provides regular expression matching operations same as the Python 5 | ``re`` module. You can do ``match()``, ``search()``, ``findall()``, ``finditer()``, 6 | ``split()``. 7 | 8 | .. literalinclude:: ../code/rsre.py 9 | 10 | More examples. 11 | 12 | .. literalinclude:: ../code/rsre_more.py 13 | -------------------------------------------------------------------------------- /rlib/rtime.rst: -------------------------------------------------------------------------------- 1 | rtime 2 | ===== 3 | 4 | There are three function provided in rtime: ``time``, ``clock``, and ``sleep``. 5 | 6 | .. literalinclude:: ../code/rtime.py 7 | -------------------------------------------------------------------------------- /rlib/rtimer.rst: -------------------------------------------------------------------------------- 1 | rtimer 2 | ====== 3 | 4 | rtimer provides basic function of timer. 5 | 6 | .. literalinclude:: ../code/rtimer.py 7 | -------------------------------------------------------------------------------- /rlib/rurandom.rst: -------------------------------------------------------------------------------- 1 | rurandom 2 | ======== 3 | 4 | ``rurandom`` uses system random number generator, which is suitable for 5 | cryptographic use. In UNIX system, it read bytes from ``/dev/urandom``. 6 | 7 | .. literalinclude:: ../code/rurandom.py 8 | --------------------------------------------------------------------------------