update docs

This commit is contained in:
Chris Wanstrath 2025-10-25 10:12:36 -07:00
parent 17d846b999
commit 8d9510e9ae
2 changed files with 92 additions and 2 deletions

View File

@ -222,6 +222,40 @@ HALT
HALT
```
### Function Definition Patterns
When defining functions, you MUST prevent the PC from falling through into function bodies. Two patterns:
**Pattern 1: JUMP over function bodies (Recommended)**
```
MAKE_FUNCTION (params) .body
STORE function_name
JUMP .end ; Skip over function body
.body:
<function code>
RETURN
.end:
<continue with program>
```
**Pattern 2: Function bodies after HALT**
```
MAKE_FUNCTION (params) .body
STORE function_name
<use the function>
HALT ; Stop before function bodies
.body:
<function code>
RETURN
```
Pattern 1 is required for:
- Defining multiple functions before using them
- REPL mode
- Any case where execution continues after defining a function
Pattern 2 only works if you HALT before reaching function bodies.
### REPL Mode (Incremental Execution)
For building REPLs (like the Shrimp REPL), use `vm.continue()` and `vm.appendBytecode()`:

View File

@ -241,6 +241,40 @@ CALL
## Compiler Patterns
### Function Definitions
When defining functions, you must prevent the PC from "falling through" into the function body during sequential execution. There are two standard patterns:
**Pattern 1: JUMP over function bodies (Recommended)**
```
MAKE_FUNCTION (params) .body
STORE function_name
JUMP .end ; Skip over function body
.body:
<function code>
RETURN
.end:
<continue with program>
```
**Pattern 2: Function bodies after HALT**
```
MAKE_FUNCTION (params) .body
STORE function_name
<use the function>
HALT ; Stop execution before function bodies
.body:
<function code>
RETURN
```
**Important**: Pattern 2 only works if you HALT before reaching function bodies. Pattern 1 is more flexible and required for:
- Defining multiple functions before using them
- REPL mode (incremental execution)
- Any case where execution continues after defining a function
**Why?** `MAKE_FUNCTION` creates a function value but doesn't jump to the body—it just stores the body's address. Without JUMP or HALT, the PC increments into the function body and executes it as top-level code.
### If-Else
```
<condition>
@ -362,7 +396,8 @@ Functions automatically capture current scope:
PUSH 0
STORE counter
MAKE_FUNCTION () .increment
RETURN
STORE increment_fn
JUMP .main
.increment:
LOAD counter ; Captured variable
@ -371,6 +406,18 @@ RETURN
STORE counter
LOAD counter
RETURN
.main:
LOAD increment_fn
PUSH 0
PUSH 0
CALL ; Returns 1
POP
LOAD increment_fn
PUSH 0
PUSH 0
CALL ; Returns 2 (counter persists!)
HALT
```
### Tail Recursion
@ -378,7 +425,7 @@ Use TAIL_CALL instead of CALL for last call:
```
MAKE_FUNCTION (n acc) .factorial
STORE factorial
<...>
JUMP .main
.factorial:
LOAD n
@ -398,6 +445,15 @@ STORE factorial
PUSH 2
PUSH 0
TAIL_CALL ; Reuses stack frame
.main:
LOAD factorial
PUSH 5
PUSH 1
PUSH 2
PUSH 0
CALL ; factorial(5, 1) = 120
HALT
```
### Optional Function Calls (TRY_CALL)