Work on documentation
This commit is contained in:
159
docs/stack.md
159
docs/stack.md
@@ -1,118 +1,95 @@
|
||||
# The Stack
|
||||
|
||||
Forth is a stack-based language. Instead of variables and expressions, you push values onto a stack and use words that consume and produce values.
|
||||
The stack is the heart of Forth. Every value you type goes onto the stack. Every word you call takes values from the stack and puts results back. There are no variables in the traditional sense, just this pile of values that grows and shrinks as your program runs.
|
||||
|
||||
## How It Works
|
||||
## Pushing Values
|
||||
|
||||
The stack is a last-in, first-out (LIFO) structure. Values you type get pushed on top. Words pop values off and push results back.
|
||||
When you type a number or a string, it goes on top of the stack:
|
||||
|
||||
```
|
||||
3 4 +
|
||||
```
|
||||
| Input | Stack (top on right) |
|
||||
|-------|---------------------|
|
||||
| `3` | `3` |
|
||||
| `4` | `3 4` |
|
||||
| `5` | `3 4 5` |
|
||||
|
||||
Step by step:
|
||||
1. `3` → push 3 onto stack: `[3]`
|
||||
2. `4` → push 4 onto stack: `[3, 4]`
|
||||
3. `+` → pop two values, add them, push result: `[7]`
|
||||
The stack grows to the right. The rightmost value is the top.
|
||||
|
||||
## Values
|
||||
## Words Consume and Produce
|
||||
|
||||
Three types can live on the stack:
|
||||
Words take values from the top and push results back. The `+` word pops two numbers and pushes their sum:
|
||||
|
||||
- **Integers**: `42`, `-7`, `0`
|
||||
- **Floats**: `3.14`, `0.5`, `-1.0`
|
||||
- **Strings**: `"kick"`, `"hello"`
|
||||
| Input | Stack |
|
||||
|-------|-------|
|
||||
| `3` | `3` |
|
||||
| `4` | `3 4` |
|
||||
| `+` | `7` |
|
||||
|
||||
This is why Forth uses postfix notation: operands come first, then the operator.
|
||||
|
||||
## Stack Notation
|
||||
|
||||
Documentation uses stack effect notation:
|
||||
Documentation describes what words do using stack effect notation:
|
||||
|
||||
```
|
||||
( before -- after )
|
||||
```
|
||||
|
||||
For example, `+` has effect `( a b -- sum )` meaning it takes two values and leaves one.
|
||||
The word `+` has the effect `( a b -- sum )`. It takes two values and leaves one.
|
||||
The word `dup` has the effect `( a -- a a )`. It takes one value and leaves two.
|
||||
|
||||
## Core Words
|
||||
## Thinking in Stack
|
||||
|
||||
### dup
|
||||
The key to Forth is learning to visualize the stack as you write. Consider this program:
|
||||
|
||||
Duplicate the top value.
|
||||
| Input | Stack | What happens |
|
||||
|-------|-------|--------------|
|
||||
| `3` | `3` | Push 3 |
|
||||
| `4` | `3 4` | Push 4 |
|
||||
| `+` | `7` | Add them |
|
||||
| `2` | `7 2` | Push 2 |
|
||||
| `*` | `14` | Multiply |
|
||||
|
||||
```
|
||||
3 dup ( 3 3 )
|
||||
This computes `(3 + 4) * 2`. The parentheses are implicit in the order of operations. You can use line breaks and white spaces to keep organized, and the editor will also show the stack at each step for you if you ask it nicely :)
|
||||
|
||||
## Rearranging Values
|
||||
|
||||
Sometimes you need values in a different order. Stack manipulation words like `dup`, `swap`, `drop`, and `over` let you shuffle things around. You will find them in the dictionary. Here is a common pattern. You want to use a value twice:
|
||||
|
||||
| Input | Stack |
|
||||
|-------|-------|
|
||||
| `3` | `3` |
|
||||
| `dup` | `3 3` |
|
||||
| `+` | `6` |
|
||||
|
||||
The word `dup` duplicates the top, so `3 dup +` doubles the number.
|
||||
|
||||
Another pattern. You have two values but need them swapped:
|
||||
|
||||
| Input | Stack |
|
||||
|-------|-------|
|
||||
| `3` | `3` |
|
||||
| `4` | `3 4` |
|
||||
| `swap` | `4 3` |
|
||||
| `-` | `1` |
|
||||
|
||||
Without `swap`, `3 4 -` would compute `3 - 4 = -1`. With `swap`, you get `4 - 3 = 1`.
|
||||
|
||||
## Stack Errors
|
||||
|
||||
Two things can go wrong with the stack:
|
||||
|
||||
* **Stack underflow** happens when a word needs more values than the stack has. If you write `+` with only one number on the stack, there is nothing to add. The script stops with an error.
|
||||
|
||||
```forth
|
||||
3 + ;; error: stack underflow
|
||||
```
|
||||
|
||||
### drop
|
||||
The fix is simple: make sure you push enough values before calling a word. Check the stack effect in the dictionary if you are unsure.
|
||||
|
||||
Discard the top value.
|
||||
* **Stack overflow** is the opposite: too many values left on the stack. This is less critical but indicates sloppy code. If your script leaves unused values behind, you probably made a mistake somewhere.
|
||||
|
||||
```
|
||||
3 4 drop ( 3 )
|
||||
```forth
|
||||
3 4 5 + . ;; plays a sound, but 3 is still on the stack
|
||||
```
|
||||
|
||||
### swap
|
||||
|
||||
Swap the top two values.
|
||||
|
||||
```
|
||||
3 4 swap ( 4 3 )
|
||||
```
|
||||
|
||||
### over
|
||||
|
||||
Copy the second value to the top.
|
||||
|
||||
```
|
||||
3 4 over ( 3 4 3 )
|
||||
```
|
||||
|
||||
### rot
|
||||
|
||||
Rotate the top three values.
|
||||
|
||||
```
|
||||
1 2 3 rot ( 2 3 1 )
|
||||
```
|
||||
|
||||
### nip
|
||||
|
||||
Drop the second value.
|
||||
|
||||
```
|
||||
3 4 nip ( 4 )
|
||||
```
|
||||
|
||||
### tuck
|
||||
|
||||
Copy top value below second.
|
||||
|
||||
```
|
||||
3 4 tuck ( 4 3 4 )
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
Build a chord by duplicating and adding:
|
||||
|
||||
```
|
||||
60 dup 4 + swap 7 + ( 64 67 60 )
|
||||
```
|
||||
|
||||
Use `over` to keep a base value:
|
||||
|
||||
```
|
||||
c4 over M3 swap P5 ( e4 g4 c4 )
|
||||
```
|
||||
|
||||
## Words
|
||||
|
||||
| Word | Stack | Description |
|
||||
|------|-------|-------------|
|
||||
| `dup` | (a -- a a) | Duplicate top |
|
||||
| `drop` | (a --) | Discard top |
|
||||
| `swap` | (a b -- b a) | Swap top two |
|
||||
| `over` | (a b -- a b a) | Copy second to top |
|
||||
| `rot` | (a b c -- b c a) | Rotate three |
|
||||
| `nip` | (a b -- b) | Drop second |
|
||||
| `tuck` | (a b -- b a b) | Copy top below second |
|
||||
The `3` was never used. Either it should not be there, or you forgot a word that consumes it.
|
||||
|
||||
Reference in New Issue
Block a user