Skip to content

Commit 50fc507

Browse files
committed
Add a proper README file
1 parent 84e0cf5 commit 50fc507

File tree

1 file changed

+278
-0
lines changed

1 file changed

+278
-0
lines changed

src/README.md

Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
# Register based VM
2+
3+
A Lisp interpreter with a register-based bytecode virtual machine.
4+
5+
## Features
6+
7+
- **Register-based bytecode VM** - Inspired by Lua's design
8+
- **Compile-time optimizations** - Constant folding and pure function inlining
9+
- **Tail call optimization** - Write recursive functions without stack overflow (citation needed)
10+
- **Macro system** - Compile-time code generation with `defmacro`
11+
- **Reference counting** - Predictable memory management without garbage collection pauses*
12+
- **Immutable by default** - Values are immutable, inspired by FP
13+
- **Fast startup** - Minimal overhead, just feed the VM with code
14+
15+
## Installation
16+
17+
### Building from Source
18+
19+
```bash
20+
~$ git clone https://github.com/0xhenrique/code-reg.git
21+
~$ cd reg
22+
~$ cargo build --release
23+
```
24+
25+
## How to use
26+
27+
### Running a Lisp File
28+
29+
```bash
30+
./target/release/lisp-vm your-program.lisp
31+
```
32+
33+
### REPL
34+
35+
```bash
36+
./target/release/lisp-vm
37+
```
38+
39+
Try to experiment a bit with it. Type `:q` or `:quit` to exit.
40+
41+
### CLI Options
42+
43+
```bash
44+
lisp-vm [OPTIONS] [FILE]
45+
46+
Options:
47+
--arena Enable arena allocation for cons cells (experimental)
48+
```
49+
50+
## Examples
51+
52+
### Basic Arithmetic
53+
54+
```lisp
55+
; Addition, subtraction, multiplication, division
56+
(+ 1 2 3) ; => 6
57+
(* 4 5) ; => 20
58+
(- 10 3) ; => 7
59+
(/ 20 4) ; => 5
60+
61+
; Comparisons
62+
(< 5 10) ; => true
63+
(>= 5 5) ; => true
64+
(= 2 2) ; => true
65+
```
66+
67+
### Variables and Functions
68+
69+
```lisp
70+
; Define a variable
71+
(def x 42)
72+
73+
; Define a function
74+
(def square (fn (n) (* n n)))
75+
(square 5) ; => 25
76+
77+
; Functions with multiple statements using 'do'
78+
(def greet (fn (name)
79+
(do
80+
(println "Hello")
81+
name)))
82+
(greet "World") ; prints "Hello", returns "World"
83+
```
84+
85+
### Let Bindings
86+
87+
```lisp
88+
; Create local bindings
89+
(let (x 10 y 20)
90+
(+ x y)) ; => 30
91+
92+
; Nested let bindings
93+
(let (x 5)
94+
(let (y (* x 2))
95+
(+ x y))) ; => 15
96+
```
97+
98+
### Conditionals
99+
100+
```lisp
101+
; if expressions
102+
(if (< 5 10)
103+
"yes"
104+
"no") ; => "yes"
105+
106+
; if without else returns nil
107+
(if false "won't happen") ; => nil
108+
```
109+
110+
### Recursion
111+
112+
The VM supports kinda recursion with TCO. This is not battle tested:
113+
114+
```lisp
115+
; Regular recursion
116+
(def factorial (fn (n)
117+
(if (<= n 1)
118+
1
119+
(* n (factorial (- n 1))))))
120+
(factorial 5) ; => 120
121+
(factorial 10) ; => 3628800
122+
123+
; Tail-recursive function
124+
(def sum (fn (n acc)
125+
(if (<= n 0)
126+
acc
127+
(sum (- n 1) (+ acc n)))))
128+
(sum 100 0) ; => 5050
129+
(sum 10000 0) ; => 50005000 (no stack overflow!)
130+
```
131+
132+
### Lists
133+
134+
```lisp
135+
; Create a list
136+
(list 1 2 3 4 5) ; => (1 2 3 4 5)
137+
138+
; car and cdr (first and rest)
139+
(car (list 1 2 3)) ; => 1
140+
(cdr (list 1 2 3)) ; => (2 3)
141+
142+
; cons (prepend element)
143+
(cons 0 (list 1 2 3)) ; => (0 1 2 3)
144+
145+
; length
146+
(length (list 1 2 3 4 5)) ; => 5
147+
148+
; Quoting
149+
'(1 2 3) ; => (1 2 3)
150+
```
151+
152+
### Higher-Order Functions
153+
154+
```lisp
155+
; Functions are first-class values
156+
(def apply-twice (fn (f x)
157+
(f (f x))))
158+
159+
(def add-one (fn (x) (+ x 1)))
160+
(apply-twice add-one 5) ; => 7
161+
162+
; Functions can be returned
163+
(def make-adder (fn (n)
164+
(fn (x) (+ x n))))
165+
(def add-ten (make-adder 10))
166+
(add-ten 5) ; => 15
167+
```
168+
169+
### Macros
170+
171+
Macros enable compile-time code generation:
172+
173+
```lisp
174+
; Define a macro
175+
(defmacro unless (cond body)
176+
(list 'if cond nil body))
177+
178+
; Use the macro
179+
(unless false (println "This prints!"))
180+
(unless true (println "This does not print"))
181+
182+
; Macros expand at compile time
183+
(defmacro when (cond body)
184+
(list 'if cond body nil))
185+
186+
(when (> 5 3) (println "5 is greater than 3"))
187+
```
188+
189+
### Built-in Functions
190+
191+
#### Arithmetic
192+
- `+`, `-`, `*`, `/`, `mod` - Arithmetic operations (support multiple arguments)
193+
194+
#### Comparison
195+
- `<`, `<=`, `>`, `>=`, `=`, `!=` - Comparison operations
196+
197+
#### Logic
198+
- `not` - Logical negation
199+
200+
#### List Operations
201+
- `list` - Create a list
202+
- `cons` - Prepend element to list
203+
- `car` - Get first element (`first` or `head`)
204+
- `cdr` - Get rest of list (`rest` or `tail`)
205+
- `length` - Get list length
206+
207+
#### Type Predicates
208+
- `nil?`, `int?`, `float?`, `string?`, `list?`, `fn?`, `symbol?` - Type checking
209+
210+
#### I/O
211+
- `print` - Print value without newline
212+
- `println` - Print value with newline
213+
214+
#### Special Forms
215+
- `def` - Define global variable
216+
- `fn` - Create anonymous function
217+
- `if` - Conditional expression
218+
- `let` - Create local bindings
219+
- `do` - Execute multiple expressions, return last one
220+
- `quote` (or `'`) - Quote expression without evaluation
221+
- `defmacro` - Define compile-time macro
222+
- `gensym` - Generate unique symbol (for hygienic macros)
223+
224+
## Example Programs
225+
226+
### Fibonacci (Tree Recursion)
227+
228+
```lisp
229+
(def fib (fn (n)
230+
(if (<= n 1)
231+
n
232+
(+ (fib (- n 1)) (fib (- n 2))))))
233+
234+
(println (fib 10)) ; => 55
235+
```
236+
237+
### Sum of List
238+
239+
```lisp
240+
(def sum-list (fn (lst)
241+
(if (nil? lst)
242+
0
243+
(+ (car lst) (sum-list (cdr lst))))))
244+
245+
(sum-list (list 1 2 3 4 5)) ; => 15
246+
```
247+
248+
### Map Function
249+
250+
```lisp
251+
(def map (fn (f lst)
252+
(if (nil? lst)
253+
nil
254+
(cons (f (car lst)) (map f (cdr lst))))))
255+
256+
(def double (fn (x) (* x 2)))
257+
(map double (list 1 2 3 4)) ; => (2 4 6 8)
258+
```
259+
260+
## Performance
261+
262+
The VM uses some common optimization techniques:
263+
264+
- **Compile-time constant folding**: Expressions like `(+ 1 2 3)` compile directly to `6`
265+
- **Pure function inlining**: Pure functions with constant arguments are evaluated at compile time
266+
- **Register-based bytecode**: Reduced memory traffic
267+
- **Specialized opcodes**: Direct arithmetic operations bypass function call overhead
268+
- **Tail call optimization**: Recursive tail calls reuse stack frames
269+
270+
This is a rabbit hole by itself. I'm not expecting to beat something like Lua.
271+
272+
## Acknowledgments
273+
274+
Inspired by:
275+
- **Lua** - For the register-based VM design
276+
- **Crafting Interpreters** - For VM implementation techniques
277+
- **[Tsoding - Lisp in C](https://www.youtube.com/playlist?list=PLpM-Dvs8t0VYbTFO5tBwxG4Q20BJuqXD_)** - The series of videos that inspired me into learning more about VM
278+
- **A ton of blogs posts, articles, videos and Github issues** - Thank you a lot!

0 commit comments

Comments
 (0)