Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/healeycodes/lisp-to-js
🖨 A Lisp-to-JavaScript optimizing compiler written in Rust.
https://github.com/healeycodes/lisp-to-js
compiler javascript lisp optimization parser-combinators transpiler
Last synced: 14 days ago
JSON representation
🖨 A Lisp-to-JavaScript optimizing compiler written in Rust.
- Host: GitHub
- URL: https://github.com/healeycodes/lisp-to-js
- Owner: healeycodes
- Created: 2024-05-26T11:56:58.000Z (5 months ago)
- Default Branch: main
- Last Pushed: 2024-05-31T19:44:27.000Z (5 months ago)
- Last Synced: 2024-05-31T22:18:00.361Z (5 months ago)
- Topics: compiler, javascript, lisp, optimization, parser-combinators, transpiler
- Language: Rust
- Homepage:
- Size: 18.6 KB
- Stars: 10
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# lisp-to-js
> My blog posts:
>
> - [Compiling Lisp to Bytecode and Running It](https://healeycodes.com/compiling-lisp-to-bytecode-and-running-it)
> - [Lisp to JavaScript Compiler](https://healeycodes.com/lisp-to-javascript-compiler)
> - [Lisp Compiler Optimizations](https://healeycodes.com/lisp-compiler-optimizations)
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:```lisp
; before optimization
(let ((b 2) (c 3))
(+
(+ b 4 c)
(- b c 7)
)))
; after optimization
(let () (print 1))
```
The Lisp variant is very similar to
[Little Lisp](https://maryrosecook.com/blog/post/little-lisp-interpreter).```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 VMOptional:
- `--optimize` for optimization
- `--debug` show annotated bytecode
### Tests
```
cargo test
```