Files
Cagire/docs/forth/oddities.md

214 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Cagire's Forth VS Classic Forth
Cagire's Forth is not a classic Forth. It borrows the core ideas (stack-based evaluation, postfix notation, word definitions) but adds modern features and domain-specific extensions. If you know traditional Forth, here are the differences.
## Comments
Classic Forth uses parentheses for comments:
```forth
( this is a comment )
```
In Cagire, parentheses create quotations, so comments use double semicolons instead:
```forth
;; this is a comment
```
Everything after `;;` until the end of the line is ignored.
## Conditionals
Classic Forth uses `IF ... ELSE ... THEN`:
```forth
x 0 > IF 1 ELSE -1 THEN
```
Cagire supports this syntax but also provides quotation-based conditionals:
```forth
( 1 ) ( -1 ) x 0 > ifelse
```
The words `?` and `!?` execute a quotation based on a condition:
```forth
( "kick" snd . ) coin ? ;; execute if coin is 1
( "snare" snd . ) coin !? ;; execute if coin is 0
```
## Strings
Classic Forth has limited string support. You print strings with `."`:
```forth
." Hello World"
```
Cagire has first-class strings:
```forth
"hello"
```
This pushes a string value onto the stack. Strings are used for sound names, sample names, and variable keys. You often do not need quotes at all. Any unrecognized word becomes a string automatically:
```forth
kick snd . ;; "kick" is not a word, so it becomes the string "kick"
myweirdname ;; pushes "myweirdname" onto the stack
```
This makes scripts cleaner. You only need quotes when the string contains spaces or conflicts with a real word.
## Variables
Classic Forth declares variables explicitly:
```forth
VARIABLE x
10 x !
x @
```
Cagire uses prefix syntax:
```forth
10 !x ;; store 10 in x
@x ;; fetch x (returns 0 if undefined)
10 ,x ;; store 10 in x, keep on stack
```
No declaration needed. Variables spring into existence when you store to them. `,x` stores and keeps the value on the stack.
## Floating Point
Classic Forth (in its original form) has no floating point. Numbers are integers. Floating point was added later as an optional extension with separate words. Cagire has native floating point:
```forth
3.14159
0.5 0.3 + ;; 0.8
```
Integers and floats mix freely. Division always produces a float.
## Loops
Classic Forth has `DO ... LOOP`:
```forth
10 0 DO I . LOOP
```
Cagire uses a quotation-based loop with `times`:
```forth
4 ( @i . ) times ;; prints 0 1 2 3
```
The loop counter is stored in the variable `i`, accessed with `@i`. This fits Cagire's style where control flow uses quotations.
```forth
4 ( @i 4 / at hat snd . ) times ;; hat at 0, 0.25, 0.5, 0.75
4 ( c4 @i + note sine snd . ) times ;; ascending notes
```
For generating sequences without side effects, use `..` or `gen`:
```forth
1 5 .. ;; pushes 1 2 3 4 5
( dup * ) 4 gen ;; pushes 0 1 4 9 (squares)
```
## The Command Register
This is completely unique to Cagire. Traditional Forth programs print text. Cagire programs build sound commands.
The command register accumulates a sound name and parameters:
```forth
"sine" sound ;; set sound
440 freq ;; add parameter
0.5 gain ;; add parameter
. ;; emit and clear
```
Nothing is sent to the audio engine until you emit with `.`. This is unlike any classic Forth.
## Context Words
Cagire provides words that read the current sequencer state:
```forth
step ;; current step index (0-127)
beat ;; current beat position
iter ;; pattern iteration count
tempo ;; current BPM
phase ;; position in bar (0-1)
```
These have no equivalent in classic Forth. They connect your script to the sequencer's timeline.
## Probability
Classic Forth is deterministic. Cagire has built-in randomness:
```forth
( "snare" snd . ) 50 prob ;; 50% chance
( "clap" snd . ) 0.25 chance ;; 25% chance
( "hat" snd . ) often ;; 75% chance
( "rim" snd . ) sometimes ;; 50% chance
( "tom" snd . ) rarely ;; 25% chance
```
These words take a quotation and execute it probabilistically.
## Periodic Execution
Execute a quotation on specific iterations:
```forth
( "snare" snd . ) 4 every ;; every 4th pattern iteration
( "hat" snd . ) 3 8 bjork ;; Euclidean: 3 hits across 8 step runs
( "hat" snd . ) 5 8 pbjork ;; Euclidean: 5 hits across 8 pattern iterations
```
`every` checks the pattern iteration count. On iteration 0, 4, 8, 12... the quotation runs. On all other iterations it is skipped.
`bjork` and `pbjork` use Bjorklund's algorithm to distribute k hits as evenly as possible across n positions. `bjork` counts by step runs, `pbjork` counts by pattern iterations. Classic Euclidean rhythms: tresillo (3,8), cinquillo (5,8), son clave (5,16).
## Polyphonic Parameters
Parameter words like `note`, `freq`, and `gain` consume the entire stack. If you push multiple values before a param word, you get polyphony:
```forth
60 64 67 note sine snd . ;; emits 3 voices with notes 60, 64, 67
```
This works for any param and for the sound word itself:
```forth
440 880 freq sine tri snd . ;; 2 voices: sine at 440, tri at 880
```
When params have different lengths, shorter lists cycle:
```forth
60 64 67 note ;; 3 notes
0.5 1.0 gain ;; 2 gains (cycles: 0.5, 1.0, 0.5)
sine snd . ;; emits 3 voices
```
Polyphony multiplies with `at` deltas:
```forth
0 0.5 at ;; 2 time points
60 64 note ;; 2 notes
sine snd . ;; emits 4 voices (2 notes × 2 times)
```
## Summary
Cagire's Forth is a domain-specific language for music. It keeps Forth's elegance (stack, postfix, definitions) but adapts it for live coding.