Skip to content

Latest commit

 

History

History
125 lines (93 loc) · 3.45 KB

README.md

File metadata and controls

125 lines (93 loc) · 3.45 KB

sparrow-lisp

sparrow is a scheme-like lisp interpreter implemented in C. the name comes from the idiom:

the sparrow may be small but all its vital organs are there.

I have been always wanted to write a LISP interpreter, especially when I was a college student.
recently, I reread the book Structure and Interpretation of Computer Programs and I find that it's time to get my hands dirty.

quick start

to get the read-eval-print-loop:

$make

to run sicp's meta-circular evaluator on sparrow:

$make mceval

to run the test code:

$make test

and you'll get something like this:

    ************************
    (assert (max 23 1 90 2 3) 90)
    ==> "pass"
    ************************

    ************************
    (assert (filter odd? (list 1 2 3 4 5 6)) (quote (1 3 5)))
    ==> "pass"
    ************************

    ************************
    (assert (map square (list 1 2 3 4 5)) (quote (1 4 9 16 25)))
    ==> "pass"
    ************************

    ************************
    (assert (sort (list 7 6 9 1 0 19 21)) (quote (0 1 6 7 9 19 21)))
    ==> "pass"
    ************************

    ************************
    (assert (fact 5) 120)
    ==> "pass"
    ************************

    ************************
    (assert (fib 8) 34)
    ==> "pass"
    ************************

    ************************
    (assert (eval (quote (sum 1 2 3))) 6)
    ==> "pass"
    ************************

    ************************
    (assert (apply * 1 2 3 (quote (4 5))) 120)
    ==> "pass"
    ************************

supported forms

;; define
(define <name> <val>)
(define (<name> <formal-paramerters>) <body>)
;; block structure and internal definition is also supported

;; lambda
(lambda (<formal-parameters>) <body>) ;; (lambda (x) (* x x))

;; variadic arguments
(define (<name> . <arglist>) <body>)  ;; (define (sum . l ) (apply + l))
(lambda <arglist> <body>)  ;; (lambda args (apply func (cons x args)))

;; if
(if <predicate> <consequent> <alternative>)

;; cond
(cond (<p1> <e1>)
      (<p2> <e2>)
      ...
      (<pn> <en>))


;; let
(let ((<var1> <exp1>)
      (<var2> <exp2>)
      (<var3> <exp3>)
      ...
      (<varn> <expn>))
  <body>)

;; set!
(set! <name> <new-value>)

;; begin
(begin
        <exp1>
        <exp2>
        ...
        <expn>)

;; etc.

not supported

  1. macro system
  2. continuation

p.s. gc is not implemented on purpose, you can do it yourself, mark-and-sweep is easy.check here.

useful materials

  • lis.py and lispy.py are written in Python by Peter Norvig. both are very easy to understand.
  • this is the SICP's metacircular evaluator.
  • the implementation of microlisp takes the homoiconic approach outlined in SICP's metacircular evaluator.
  • micro-lisp tries to implement a small Lisp/Scheme language in as little C code as possible.
  • some test code comes from yoctolisp.
  • minilang.rkt is written in Racket.