Implementation overview
Here is a brief overview of each of the Read-Eval-Print Loop components in our interpreter. Refer to this section as you work through the project as a reminder of how all the small pieces fit together!
-
Read: This step parses user input (a string of Scheme code) into our interpreter's internal Python representation of Scheme expressions (e.g. Pairs).
- Lexical analysis has already been implemented for you in the
tokenize_lines
function inscheme_tokens.py
. This function returns aBuffer
of tokens. You do not need to read or understand the code for this step. - Syntactic analysis happens in
scheme_reader
. Together, these mutually recursive functions parse Scheme tokens into our interpreter's internal Python representation of Scheme expressions. You do not need to know what happened in this step.
- Lexical analysis has already been implemented for you in the
-
Eval: This step evaluates Scheme expressions (represented in Python) to obtain values. Code for this step is in the main
scheme_eval_apply.py
file.- Eval happens in the
scheme_eval
function. If the expression is a call expression, it gets evaluated according to the rules for evaluating call expressions (you will implement this). If the expression being evaluated is a special form, the correspondingdo_?_form
function is called. You will complete several of thedo_?_form
functions. - Apply happens in the
scheme_apply
function. If the function is a built-in procedure,scheme_apply
calls theapply
method of thatBuiltInProcedure
instance. If the procedure is a user-defined procedure,scheme_apply
creates a new call frame and callseval_all
on the body of the procedure, resulting in a mutually recursive eval-apply loop.
- Eval happens in the
-
Print: This step prints the
str
representation of the obtained value. -
Loop: The logic for the loop is handled by the
read_eval_print_loop
function inscheme.py
. You do not need to understand the entire implementation.
Exceptions. As you develop your Scheme interpreter, you may find that Python raises various uncaught exceptions when evaluating Scheme expressions. As a result, your Scheme interpreter will halt. Some of these may be the results of bugs in your program, but some might just be errors in user programs. The former should be fixed by debugging your interpreter and the latter should be handled, usually by raising a SchemeError
. All SchemeError
exceptions are handled and printed as error messages by the read_eval_print_loop
function in scheme.py
. Ideally, there should never be unhandled Python exceptions for any input to your interpreter.