Skip to content

🖨 An optimizing compiler for a Lisp variant. Compiles and executes byte code in a VM. Can also output JavaScript.

Notifications You must be signed in to change notification settings

healeycodes/lisp-to-js

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

lisp-to-js

My blog posts:


This project is an optmizing Lisp compiler and bytecode VM.

It can compile to JavaScript, or compile to bytecode and execute in a VM.

The bytecode VM is a little faster than Node.js (TODO: benchmarks).


Bytecode VM:

./program --vm --debug < fib10.lisp
   0: PushClosure(["n"])
    ->   0: LoadVar("n")
    ->   1: PushConst(2.0)
    ->   2: LessThan
    ->   3: Jump(6) // go to 6
    ->   4: LoadVar("n")
    ->   5: Jump(17) // exit
    ->   6: LoadVar("n")
    ->   7: PushConst(1.0)
    ->   8: Sub(2)
    ->   9: LoadVar("fib")
    ->  10: CallLambda(1)
    ->  11: LoadVar("n")
    ->  12: PushConst(2.0)
    ->  13: Sub(2)
    ->  14: LoadVar("fib")
    ->  15: CallLambda(1)
    ->  16: Add(2)
   1: StoreVar("fib")
   2: PushConst(10.0)
   3: LoadVar("fib")
   4: CallLambda(1)
   5: LoadVar("print")
   6: CallLambda(1)

55

Compile to JavaScript:

./program --js < fib10.lisp
/*
(let ((fib (lambda (n)
    (if (< n 2)
        n
        (+ (fib (- n 1)) (fib (- n 2)))))))
(print (fib 10)))
*/

let print = console.log;

let fib = (n) => n < 2 ? n : (fib(n - 1) + fib(n - 2));
print(fib(10));

The implemented optimizations are constant folding and propagation, and dead code elimination:

; before optimization
(let ((b 2) (c 3))
  (print
    (+
      (+ b 4 c)
      (- b c 7)
  )))
 
; after optimization
(let () (print 1))

The Lisp variant is very similar to Little Lisp.

; atoms
1 ; f64 numbers
a ; symbols

; arithmetic expressions
(+ 1 2) ; 3
(- 1 2) ; -1

; control flow expressions
(< 1 2) ; true
(> 1 2) ; false
(if (< 1 2) (+ 10 10) (+ 10 5)) ; 20

; lambda expressions
(lambda (x) (+ x x)) ; function that doubles

; variable definition
(let ((a 1)) (print a)) ; prints 1
(let ((double (lambda (x) (+ x x)))) (double 2)) ; 4

Run

Required (one of):

  • --js output JavaScript to stdout
  • --vm compile to bytecode and execute in VM

Optional:

  • --optimize for optimization
  • --debug show annotated bytecode

Tests

cargo test

About

🖨 An optimizing compiler for a Lisp variant. Compiles and executes byte code in a VM. Can also output JavaScript.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages