This project contains an AST-based interpreter for the Tiger language using the RPython meta-tracing framework for self-optimizing at runtime. Tiger is a small, imperative language designed by Dr. Andrew Appel in his Modern Compiler Implementation textbooks. This implementation follows his textbook closely, much like Hirzel and Rose's Tiger Language Specification and unlike the class extensions of EPITA's Tiger Compiler Reference Manual. RPython is a toolchain for lowering Python to C and JIT-compiling traces of repeated code at runtime; Benjamin Peterson describes RPython's architecture and how it is employed in the PyPy project in The Architecture of Open Source Applications: PyPy.
Pre-requisites: git, make, Python 2.7.
# clone the PyPy repository and verify that the RPython translator works (this project used revision 33f417d9c3f73dadb61346aa1b2579a1bf947ee9 but any recent version should do)
git clone https://github.com/mozillazg/pypy
python pypy/rpython/bin/rpython --help
# clone the tiger-rpython repository (note: currently the Makefile expects the pypy directory to be in the parent directory)
git clone https://github.com/abrown/tiger-rpython
cd tiger-rpython
# create a Python virtual environment with necessary libraries
make venv
source venv/bin/activate
# build 'tiger-parser' and 'tiger-interpreter' under the 'bin' directory
make binaries
For ease of testing, the project builds two RPython-translated binaries in the bin
directory:
tiger-parser [program.tig]
parses a Tiger program and prints its AST; it returns code40
when it cannot find the Tiger program file, code42
if the Tiger program is unparseable, and0
otherwisetiger-interpreter [program.tig]
parses a Tiger program, evaluates it to a value, and prints this value (if the program returns a value at all); it returns similar codes totiger-parser
This project contains several distinct test sets that are used to verify different parts of the interpreter; the files
live in src/test
and include:
- Python unit tests: Python
unittest
code that tests specific functions of the Tiger interpreter (e.g.src/test/tokenizing.py
) appel-tests
: These Tiger programs (some of which are purposely incorrect) are borrowed from Dr. Andrew Appel's Modern Compiler Implementation book; see published files at the book's site; currently they are used for verifying correct parsing, not evaluationexpr-tests
: These Tiger programs are simple expressions; the expression is interpreted to a value and compared against values a corresponding[test name].out.bak
fileprint-tests
: These Tiger programs are complex expressions thatprint()
values during their evaluation; the printed values are collected and compared a corresponding[test name].out.bak
file
When unit tests run, a Python interpreter executes unittest
cases that include 1) the *.py
files in src/test
, 2)
the Python-interpreted evaluation of the expr-tests
expressions, and 3) the Python-interpreted evaluation of the
print-tests
programs; to run them, execute:
make test
When integration tests run, the tiger-parser
and tiger-interpreter
binaries are built by RPython and used for 1)
comparing the Python-interpreted parsing against the RPython-compiled parsing of the appel-tests
(i.e. the parsed
AST is printed by both python src/main/tiger-parser.py
and bin/tiger-parser
and compared to ensure no discrepancies)
and 2) verifying that the RPython-compiled tiger-interpreter
correctly evaluates the print-tests
programs. To run
these, execute:
make integration-test
This list describes which Tiger language features implemented (and which not):
- Valid Tiger programs are parsed correctly; no errors are raised, however, for typing issues (e.g.
var i : int = "a string"
) - Except for
print(s : string)
, the standard library functions (e.g.concat
,exit
,substring
) are not implemented - Control flow expressions such as sequences,
if-then-else
,for
, andwhile
evaluate as expected, includingbreak
for loops - Function declarations (including nesting) and function calls (left-to-right parameter evaluation)
- Declare and assign to variables with
lets
, including nestedlets
- Allows creation of arrays and records and referencing them with lvalues
- No type-checking of values (yet)
Some helpful documents explaining RPython:
- Summary of the RPython architecture (e.g. the translation toolchain
flowspace
->annotator
->rtyper
and the meta-interpreter injit
): http://doc.pypy.org/en/latest/architecture.html - JIT compiler architecture, including off-line partial evaluation principles (translation time vs compile time vs runtime), distinction of green vs red (green are known at compile time, red are not known until runtime), and promotion (stop compilation until the runtime reaches this point): https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D08.2_JIT_Compiler_Architecture-2007-05-01.pdf
- In-depth PyPy description, including flow space, annotation model: https://bitbucket.org/pypy/extradoc/raw/tip/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf
- Using RPython interactively (e.g. displaying the flow graph): http://rpython.readthedocs.io/en/latest/getting-started.html