Clisp
A lightweight (~550 lines of code) Lisp interpreter with Scheme dialect. I was inspired to make this after watching all the SICP lectures.
Features:
- file inclusion e.g. (include test.scm), can be nested inside files
- optimized tail recursion
- first class procedures and by extension higher order procedures
- lexical scoping so you don't have to worry about local variables clashing in called procedures
- free typed arguments, e.g. (define (add x) ...) x is expected by the semantics to be a list, but not enforced
- local binding (essentially giving code blocks) with keyword let
- ; comments
I originally intended to include the boost parts required, but as you can see from include_list,
you're better off getting the proper boost distribution.
To compensate, this repository contains
a binary built on Ubuntu 14.04 which should work on most Unix based machines.
Example:
(include funcs.scm) ; don't do this! recursive inclusion is bad D:
(define (if test a b) (cond ((test) a) (else b)))
(define compose (lambda (f g) ; fundamental higher order procedure
(lambda (x)
(f (g x)))))
(define expt (lambda (x n) ; exponential
(cond ((= n 1) x)
(else (* x
(expt x (- n 1)))))))
(define nth-power (lambda (n)
(lambda (x)
(expt x n))))
(define square (nth-power 2))
(define cube (nth-power 3))
(define square_and_cube (compose square cube))
(define (add x)
(cond ((empty? x) 0)
(else (+ (car x) (add (cdr x))))))
(begin (do something) (do somethingelse) result) ; basic sequencing
(define (add4 n)
(let ((x 4)) (+ x n))) ; basic local binding
(cat 'something 'somethingelse)
(square 5)
(add (1 2 3 4))
Tips:
- build by typing "make" in the same directory
- build benchmark version by replacing main.cpp with timing.cpp in makefile
- list parameters (such as x for add above) treated same as 'normal' parameters
- interpret files with
./clisp [filename] [-p]
, add -p or -print option to force printing of file evaluation, silent by default (assumes a lot of definitions)- include files with (include filename), which can be nested
- build debug information (with step by step info) by changing build target and source in makefile to "testing" and "testing.cpp" respectively
- requires a compiler supporting C++11
- uses boost::variant (link above)
- keywords (so far): define, lambda, cond, cons, cdr, list, else, and, or, not, empty?, include, begin
- use 'quote to signify string
string
will raise an error if it's not defined, but'string
will return string
- use cat primitive instead of + to concatenate strings
- expressions can extend over different lines, terminated by appropriate )!