Lisp interpreter in C++
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
README.md
clisp
environment.cpp
environment.h
error.cpp
error.h
forward.h
funcs.scm
include_list
lexer.cpp
lexer.h
main.cpp
makefile
parser.cpp
parser.h
parser_impl.h
testing.cpp
timing.cpp
webbinding.cpp

README.md

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

Get boost
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 )!