thp /

Filename Size Date modified Message
751 B
2.9 KB
60 B
3.0 KB

thp - a tiny Lisp interpretor

thp is a Tiny Hypertext Processo-^w^w^w“Weekend Lisp” interpretor.

Perhaps I should have named it awl -- A Weekend Lisp, or yawl -- You Figure It Out.

For that matter, it could also be said to be a “weakened” Lisp!

It requires libsexp:

I have been running it on Plan 9, but it should work on Unix with plan9port, or natively with a bit of s/print/printf/g.


(LET (
    (f (LAMBDA (x) (CONS goats x)))
    (g (LAMBDA (x) (CDR x))))

    (f (g (QUOTE (1 2 3)))))

→ (goats 2 3)


(LET ((f (LAMBDA (x) (IF (x (f (CDR x))) recursion!))))
    (f (QUOTE (a b c d e))))

→ args: ((a b c d e))
→ args: ((b c d e))
→ args: ((c d e))
→ args: ((d e))
→ args: ((e))
→ args: (nil)
→ recursion!

Functions as arguments

(LET (
    (f (LAMBDA (x) (CAR (CDR x))))
    (g (LAMBDA (f x) (f (CDR x)))))

    (g f (QUOTE (a b c))))
→ c


  • There is no garbage collection.
  • There is no tail-call optimization.
  • It is dynamically scoped. (Lexical scope coming soon!)

    (LET ((f (LAMBDA (x) (CONS x y))))
        (LET ((y world))
        (f hello)))
    → lambda
    → args: (hello)
    → (hello . world)
    • Closures are implemented, but full lexical scope is still not here.

      (LET ((f (LAMBDA (x) (LAMBDA (y) (CONS x y))))
          (helloer (f hello)))
          (helloer world))
      → (hello . world)
  • Built-in functions and special forms: CONS, CAR, CDR, IF, LAMBDA, CLOSURE, LET, QUOTE.

  • thp is a Lisp-1.
  • There is no partial application.
  • Builtins are baked into eval, which behaves magically on special atom names. It would perhaps be saner to break them out into something like (BUILTIN "CDR"), and then prepopulate the environment: (LET ((car (LAMBDA (l) (BUILTIN (CAR l)))))). Nonetheless, it is already possible to override builtins, because they have a lower "precedence" than variables:

    (LET ((CAR CDR)) (CAR (QUOTE (a b c))))
    → (b c)
  • I think it might actually be pretty easy to allow user-defined special forms by providing a (SPECIAL-FORM ...) wrapper that disables automatic evaluation of arguments, along with an explicit (EVAL ...).

  • I sort of want to add Church numerals.

  • % wc -l thp.c ../libsexp/sexp.[ch]
        163 thp.c
        216 ../libsexp/sexp.c
         31 ../libsexp/sexp.h
        410 total
  • Goats!


I would like to thank the first couple of chapters of SICP for the discussion on special forms; the Lisp 1.5 book for the outline of how eval evals, and for reminding me that if they could do it in assembly language on a 4 kiloword machine I should darn well be able to do it in C with a gigabyte of RAM; and lastly Wikipedia.

AWK-LISP was also inspirational: