Minimal scheme: a toy scheme interpreter written in Python
This is a from-scratch Scheme implementation written for pleasure and education purposes only. It is targetting R5RS (HTML copy of spec), or at least an interesting subset of it. I'd also like it to run the code in SICP.
All functionality is implemented with corresponding tests. Functions are generally thorough with their error messages, and we strive to give informative error messages.
$ virtualenv ~/.py_envs/scheme -p python3
$ . ~/.py_envs/scheme/bin/activate
(scheme)$ pip install -r requirements.pip
(scheme)$ ./repl
Welcome to Minimal Scheme 0.1 alpha.
scheme> (+ 1 1)
2
(scheme)$ python interpreter/main.py examples/hello-world.scm
hello world
(scheme)$ nosetests interpreter/tests.py
The terms primitive
, built-in
and standard function
are used to
refer to different things in minimal scheme.
A primitive
is written in Python and controls whether or not it
evaluates its arguments.
A built-in
is written in Python but has all its arguments evaluated
automatically.
A standard function
is written in Scheme.
define
, lambda
, if
, begin
, quote
, eqv?
, eq?
,
quasiquote
, unquote
, unquote-splicing
let
cond
, not
, and
(binary only), or
(binary only)
number?
, complex?
, rational?
, real?
, exact?
, inexact?
,
+
, -
, *
, /
, <
, <=
, >
, >=
, =
, zero?
, positive?
,
negative?
, odd?
, even?
, abs
, quotient
, modulo
,
remainder
, exp
, log
No support for exact fractions or complex numbers.
char?
, char=?
, char<?
, char>?
, char<=?
, char>=?
car
, cdr
, caar
, cadr
, cdar
, cddr
, cons
, null?
,
pair?
, list
, length
, set-car!
, set-cdr!
map
(unary only), for-each
(unary only), procedure?
, apply
make-vector
, vector?
, vector-ref
, vector-set!
,
vector-length
, vector
, vector->list
, list->vector
,
vector-fill!
No distinction between constant vectors and normal vectors.
string?
, make-string
, string-length
, string-ref
, string-set!
defmacro
display
, newline
(both stdout only)
Comments work too!
(eq? 1 1.0)
exact
and inexact
/
doesn't check type of argumentscar
crashes on non-listscond
doesn't allow multiple statements after a conditionaleval_program
-- it's justmap(eval_s_expression, s_expressions)
internal_result
to actual_result
in tests.pyexp
, log
etc) to library.scm(+ 1 2.0)
)There's also a skeleton compiler here, this is based on the paper An Incremental Approach to Compiler Construction.