CyCy¶
CyCy is a small C interpreter built during a 48 hour hackathon at Magnetic.
It certainly does not interpret an appreciable amount of C, nor does it run particularly quickly, but it’s a small step beyond the example interpreter (which we’ll also see soon).
It is highly recommended to resist temptation on directly copying its layout (or the layout of the example interpreter) line for line. Reading it briefly and using it as a reference when stuck will allow you to proceed without (much) frustration while still taking time to play with RPython enough to experience it.
Installing CyCy¶
Clone the CyCy repo which can be found at https://github.com/Magnetic/CyCy:
$ git clone https://github.com/Magnetic/cycy
$ cd cycy
Optional: Create a Virtualenv¶
Create a virtualenv which you will install CyCy into. If you have no other preference on location, create one within the CyCy repo checkout:
$ python -m pip install -U virtualenv
$ virtualenv -p pypy venv
which will create a virtualenv (a directory) named venv
in the checkout,
and will use the PyPy interpreter you’ve installed inside it.
Install CyCy as you would a normal Python package:
$ venv/bin/pip install -e .
which should fetch all of the necessary dependencies.
Run venv/bin/rpython --help
to confirm that the toolchain was successfully
installed, and you’re on your way.
Alternate: Without a Virtualenv¶
If you do not wish to use a virtualenv, you can install CyCy and its dependencies globally:
$ pip install --user -e .
Follow along with the rest of the document by removing venv/bin/
from the
beginning of commands, since your binaries will be available globally.
Note
If after running the above command you cannot run rpython --help
,
you likely do not have ~/.local/bin
on your shell’s $PATH
.
Follow the instructions of your shell on adding it (typically either
to .bash_profile
or .zshenv
if you’re using bash or zsh
respectively).
Running & Translating CyCy¶
Take a quick look at the contents of the directories in front of you. We will cover the types of components in them as we develop our own interpreter, but it will be useful (and perhaps somewhat irresistible) to peek at what reasonably small amount of code is there.
At a high level, the translation process will take the code you have and translate it into an executable you can run standalone.
Before we do so, let’s prove that the interpreter can simply be run as a normal program on top of Python. Running:
$ venv/bin/pypy -m cycy
should present you with a CyCy REPL. Here you certainly will notice things amiss (bonus points if you simply crash the interpreter).
But! If you run something simple, like:
CC-> int main (void) { return 2 + 23; }
you should see:
25
outputted below. There are various slightly more complicated things for which CyCy manages to implement support for so far.
Note
For both CyCy and the interpreter we will attempt to build, you may
find it helpful to install the rlwrap
*nix utility and to use
it as a wrapper around the REPL:
$ rlwrap venv/bin/pypy -m cycy
will give you a REPL with readline support provided via rlwrap.
You can find it in homebrew or via your Linux package manager.
Now that we can run CyCy on top of Python, let’s use the RPython toolchain to create an executable that is independent of the Python runtime.
From the same directory (the root of the checkout)::
$ venv/bin/rpython --output=cycy-nojit cycy/target.py
will produce a long stream of output that you might find interesting to stare out.
After around 2 minutes of churning, out should pop an executable in the current directory which you can run via:
$ ./cycy-nojit
which should produce a REPL with (roughly) the same behavior as before.
This executable depends neither on Python nor the RPython toolchain:
$ file ./cycy-nojit
$ otool -L ./cycy-nojit
which should show you some basic information on the executable (and
specifically that it does not in fact try to link against Python). On
Linux, use ldd
in place of otool -L
.