LISP on browser¶

This is small implementation of LISP, which written in JavaScript and run on browsers.

I think it helps you to understand what going on in programming languages by using it and reading its source codes.

Demo¶ ;; A few examples. Click 'Load source' to load them. ; Closures (let (count 0) (define (counter) (set! count (+ 1 count)))) ; You can also define variables (define x 2) (set! x 3) ; Let (let (x 2 y 3) (+ x y)) ; Lambda (set! x (lambda () 'bla)) (x) ; Factorial example (define (fact n) (if (= n 0) 1 (* n (fact (- n 1))))) (fact 5) ; Length example (define (length list) (if (empty? list) 0 (+ 1 (length (cdr list))))) (length '(1 2 3)) ; Map example (define (map func list) (if (empty? list) nil (cons (func (car list)) (map func (cdr list))))) (map (lambda (x) (+ x 1)) '(1 2 3)) ; And macro example (defmacro (and x . xs) (if (empty? xs) x `(when ,x (and . ,xs)))) (expand-code '(and a b c d)) ; and to demonstrate the short-circuit mechanism: ; ((unknown) should crash when run) (and (= 2 2) (= 2 3) (unknown)) ;; Hygiene in macros ; Consider a simple macro: (defmacro (bad-swap a b) `(let (tmp ,a) (set! ,a ,b) (set! ,b tmp))) ; Usage example: (let (x 1 y 2) (bad-swap x y) (list x y)) ; (2 1) ; Unfortunately, this fails if we have a variable called tmp! (let (x 1 tmp 2) (bad-swap x tmp) (list x tmp)) ; (1 2) ; We solve that by using the gensym function to generate a new name ; that will not conflict with anything else: (defmacro (swap a b) (let (tmp (gensym 'tmp)) `(let (,tmp ,a) (set! ,a ,b) (set! ,b ,tmp)))) ; Now try: (expand-code '(swap x tmp)) ; (let (#tmp-0 x) (set! x tmp) (set! tmp #tmp-0))

Design¶ Readability counts. My goal is not to make complete features of Lisp. It makes source codes huge and makes difficult to read.

TODO¶ Refactor commit history so that readers can learn how to implement LISP step by step. ‘feature/M1-S-Expression-Parser’ branch is nice but ‘feature/M2’ has actually 4 milestone.

Connect with https://github.com/nishio/AST-Visualization-on-browser

Make a site in English and Japanese (for my book’s readers)

History¶ This list corresponds to current commit history. We need refactor it. Milestone1: S-expression Parser given string such like “(* 1 (+ 2 3))” and return syntax trees in this point forget about reader macros such as “’(1 2 3)”

‘feature/M2’ Milestone2: Some Built-in function arithmetic functions: +, -, *, / other functions: eval, cons, list (done) Milestone3: A REPL interpreter(when user input (* 1 (+ 2 3)), it prints 5) Now we can (* 1 (+ 2 3)) (done) Milestone4: Special forms: quote and if (done) Milestone5: Reader syntax with apostrophe: ‘(+ 2 2) = (quote (+ 2 2))

‘feature/factorial_and_counter’ Milestone6: equality and comparison: =, /=, <, etc. Milestone7: comments in the code Milestone8: a textbox for loading examples into interpreter Milestone9: lexical scope (let and variables) Milestone10: defining your own functions (defun) Now we can make factorial and counter

‘feature/macro’ variable-length argument lists (func arg1 arg2 . rest) defmacro and macro-expansion stage macroexpand function quasiquote and unquote (` ,) for easier building of macros a ‘gensym’ function and example illustrating the problem of hygiene in macros.



License¶ GPLv3 (c) NISHIO Hirokazu 2012