========================================================
HOWTO: compile RPython code into a standalone executable
========================================================

(NOTE: you should first read the `FAQ entries`_ about Using the PyPy
translation tool chain.  This document is a quick introduction to the
interactive way to compile your own RPython code.  Keep in mind though
that if you write a larger RPython program, the best and most flexible
way to compile it is not as described below, but by writing a target
file as described in the `FAQ entries`_.)

========================================

First, see the note above.
Next, understand the restrictions on RPython_ code.
Pay close attention to the description of tuples and 
dicts. 

Take this example program::

    import os
    
    def main(argv):
        os.write(1, "Hello world!\n")
    
        return 0

To compile::

    from pypy.translator.interactive import Translation
    t = Translation(main, standalone=True, gc='ref')
    
    t.source(backend='c')
    path = t.compile()
    print path

The path is the location of the executable.

To see the translation in motion, try removing
the ``argv`` argument to main, or the ``return 0``.

Type inference happens in the Annotator_.
Keep this in mind as you write RPython code.
After annotation the low level code generation
(the implementation of the types)
happens in the RTyper_.

These steps can be spelled out explicitly::

    t.annotate()
    t.rtype()
    t.source(backend='c')
    path = t.compile()

After the ``annotate()`` or ``rtype()`` call
you can view the resulting flow graph with
a pygame/dot based graphing tool::

    t.annotate()
    t.view()
    t.rtype()
    t.view()

Here are some debugging tips:

- make sure the program runs before you try and compile it. 
  The semantics of RPython compiled code should be the same as regular python.
- try assert'ing things in your code, for example ``assert isinstance(num, int)``,
  this can provide hints to the translation process that can help pinpoint the 
  problem.

RPython is tricky! 

Take this example::

    def abs(num):
        if num < 0:
            num = -num
        return num
    
If you want to use this function with
different argument types (eg. ``int`` and ``float``)
the translation will fail. In order
to generate a different function for each argument
type we need to set an attribute::

    abs._annspecialcase_ = "specialize:argtype(0)"

As another example::

    def sum(l):
        total = 0
        for v in l:
            total += v
        return total
    
    sum._annspecialcase_ = "specialize:argtype(0)"

Now we can sum with different kinds of lists, eg.
``sum([1,2,3])`` and ``sum([1.0,2.0,3.0])``.

    
.. _`FAQ Entries`: faq.html#pypy-translation-tool-chain
.. _`RPython`: coding-guide.html#restricted-python
.. _`Annotator`: dynamic-language-translation.html#annotator
.. _`RTyper`: dynamic-language-translation.html#rtyper

