Add support for recursive let binding codegen
[scheme.git] / abi.md
1 # heap
2
3 a heap is allocated at the start, and the address to the next free
4 space on it is stored in `heap_start`. it needs to be
5 updated/decremented whenever you put anything on the heap
6
7 ## todo
8 - how should allocation be managed?
9 make free blocks a doubly linked list. (how big is a block?)
10 when allocating, use first free block, move up free pointer
11 when freeing, do ???
12
13
14 # closures
15
16 * lambda: actual function containing the code
17 * closure: reference to the lambda containing captives
18
19 closures are stored on the heap. They contain the address to the
20 lambda along with any "captives", i.e. captured variables. They have
21 the following layout:
22
23 ```
24 0            8          16        24        32
25 lambda code  1st        2nd       3rd
26 address      captive    captive   captive   ...
27 ```
28
29 ## note on recursive closures
30
31 The following example shows a recursive lambda, that results in a
32 closure that captures itself.
33 ```
34 (let ([f (closure lambda0 (f))])
35   (f 42))
36 ```
37 When this happens, `codegen-let` will insert `(f . 'self-captive)`
38 into the environment when codegen'ing the closure. `codegen-closure`
39 will then pick this up, and use it to insert its own heap address into
40 its inner environment.
41
42 # lambdas
43
44 lambdas use the system v amd64 calling convention.
45
46 * param 0: the start address of the **1st** captive
47 * param 1...n: the remaining, regular args.
48
49 e.g.
50 ```
51 (let [(x 42)] (lambda (y) (+ x y)))
52 ```
53
54 * param 0: pointer to the value of `x`
55 * param 1: the value of`y`