Files
Cagire/crates/forth/src/words.rs
2026-01-29 11:53:47 +01:00

2486 lines
59 KiB
Rust

use super::ops::Op;
use super::theory;
use super::types::{Dictionary, SourceSpan};
pub enum WordCompile {
Simple,
Context(&'static str),
Param,
Probability(f64),
}
pub struct Word {
pub name: &'static str,
pub aliases: &'static [&'static str],
pub category: &'static str,
pub stack: &'static str,
pub desc: &'static str,
pub example: &'static str,
pub compile: WordCompile,
pub varargs: bool,
}
use WordCompile::*;
pub const WORDS: &[Word] = &[
// Stack manipulation
Word {
name: "dup",
aliases: &[],
category: "Stack",
stack: "(a -- a a)",
desc: "Duplicate top of stack",
example: "3 dup => 3 3",
compile: Simple,
varargs: false,
},
Word {
name: "dupn",
aliases: &["!"],
category: "Stack",
stack: "(a n -- a a ... a)",
desc: "Duplicate a onto stack n times",
example: "2 4 dupn => 2 2 2 2",
compile: Simple,
varargs: true,
},
Word {
name: "drop",
aliases: &[],
category: "Stack",
stack: "(a --)",
desc: "Remove top of stack",
example: "1 2 drop => 1",
compile: Simple,
varargs: false,
},
Word {
name: "swap",
aliases: &[],
category: "Stack",
stack: "(a b -- b a)",
desc: "Exchange top two items",
example: "1 2 swap => 2 1",
compile: Simple,
varargs: false,
},
Word {
name: "over",
aliases: &[],
category: "Stack",
stack: "(a b -- a b a)",
desc: "Copy second to top",
example: "1 2 over => 1 2 1",
compile: Simple,
varargs: false,
},
Word {
name: "rot",
aliases: &[],
category: "Stack",
stack: "(a b c -- b c a)",
desc: "Rotate top three",
example: "1 2 3 rot => 2 3 1",
compile: Simple,
varargs: false,
},
Word {
name: "nip",
aliases: &[],
category: "Stack",
stack: "(a b -- b)",
desc: "Remove second item",
example: "1 2 nip => 2",
compile: Simple,
varargs: false,
},
Word {
name: "tuck",
aliases: &[],
category: "Stack",
stack: "(a b -- b a b)",
desc: "Copy top under second",
example: "1 2 tuck => 2 1 2",
compile: Simple,
varargs: false,
},
// Arithmetic
Word {
name: "+",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a+b)",
desc: "Add",
example: "2 3 + => 5",
compile: Simple,
varargs: false,
},
Word {
name: "-",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a-b)",
desc: "Subtract",
example: "5 3 - => 2",
compile: Simple,
varargs: false,
},
Word {
name: "*",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a*b)",
desc: "Multiply",
example: "3 4 * => 12",
compile: Simple,
varargs: false,
},
Word {
name: "/",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a/b)",
desc: "Divide",
example: "10 2 / => 5",
compile: Simple,
varargs: false,
},
Word {
name: "mod",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a%b)",
desc: "Modulo",
example: "7 3 mod => 1",
compile: Simple,
varargs: false,
},
Word {
name: "neg",
aliases: &[],
category: "Arithmetic",
stack: "(a -- -a)",
desc: "Negate",
example: "5 neg => -5",
compile: Simple,
varargs: false,
},
Word {
name: "abs",
aliases: &[],
category: "Arithmetic",
stack: "(a -- |a|)",
desc: "Absolute value",
example: "-5 abs => 5",
compile: Simple,
varargs: false,
},
Word {
name: "floor",
aliases: &[],
category: "Arithmetic",
stack: "(f -- n)",
desc: "Round down to integer",
example: "3.7 floor => 3",
compile: Simple,
varargs: false,
},
Word {
name: "ceil",
aliases: &[],
category: "Arithmetic",
stack: "(f -- n)",
desc: "Round up to integer",
example: "3.2 ceil => 4",
compile: Simple,
varargs: false,
},
Word {
name: "round",
aliases: &[],
category: "Arithmetic",
stack: "(f -- n)",
desc: "Round to nearest integer",
example: "3.5 round => 4",
compile: Simple,
varargs: false,
},
Word {
name: "min",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- min)",
desc: "Minimum of two values",
example: "3 5 min => 3",
compile: Simple,
varargs: false,
},
Word {
name: "max",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- max)",
desc: "Maximum of two values",
example: "3 5 max => 5",
compile: Simple,
varargs: false,
},
Word {
name: "pow",
aliases: &[],
category: "Arithmetic",
stack: "(a b -- a^b)",
desc: "Exponentiation",
example: "2 3 pow => 8",
compile: Simple,
varargs: false,
},
Word {
name: "sqrt",
aliases: &[],
category: "Arithmetic",
stack: "(a -- √a)",
desc: "Square root",
example: "16 sqrt => 4",
compile: Simple,
varargs: false,
},
Word {
name: "sin",
aliases: &[],
category: "Arithmetic",
stack: "(a -- sin(a))",
desc: "Sine (radians)",
example: "3.14159 2 / sin => 1.0",
compile: Simple,
varargs: false,
},
Word {
name: "cos",
aliases: &[],
category: "Arithmetic",
stack: "(a -- cos(a))",
desc: "Cosine (radians)",
example: "0 cos => 1.0",
compile: Simple,
varargs: false,
},
Word {
name: "log",
aliases: &[],
category: "Arithmetic",
stack: "(a -- ln(a))",
desc: "Natural logarithm",
example: "2.718 log => 1.0",
compile: Simple,
varargs: false,
},
// Comparison
Word {
name: "=",
aliases: &[],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Equal",
example: "3 3 = => 1",
compile: Simple,
varargs: false,
},
Word {
name: "!=",
aliases: &["<>"],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Not equal",
example: "3 4 != => 1",
compile: Simple,
varargs: false,
},
Word {
name: "lt",
aliases: &[],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Less than",
example: "2 3 lt => 1",
compile: Simple,
varargs: false,
},
Word {
name: "gt",
aliases: &[],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Greater than",
example: "3 2 gt => 1",
compile: Simple,
varargs: false,
},
Word {
name: "<=",
aliases: &[],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Less or equal",
example: "3 3 <= => 1",
compile: Simple,
varargs: false,
},
Word {
name: ">=",
aliases: &[],
category: "Comparison",
stack: "(a b -- bool)",
desc: "Greater or equal",
example: "3 3 >= => 1",
compile: Simple,
varargs: false,
},
// Logic
Word {
name: "and",
aliases: &[],
category: "Logic",
stack: "(a b -- bool)",
desc: "Logical and",
example: "1 1 and => 1",
compile: Simple,
varargs: false,
},
Word {
name: "or",
aliases: &[],
category: "Logic",
stack: "(a b -- bool)",
desc: "Logical or",
example: "0 1 or => 1",
compile: Simple,
varargs: false,
},
Word {
name: "not",
aliases: &[],
category: "Logic",
stack: "(a -- bool)",
desc: "Logical not",
example: "0 not => 1",
compile: Simple,
varargs: false,
},
Word {
name: "xor",
aliases: &[],
category: "Logic",
stack: "(a b -- bool)",
desc: "Exclusive or",
example: "1 0 xor => 1",
compile: Simple,
varargs: false,
},
Word {
name: "nand",
aliases: &[],
category: "Logic",
stack: "(a b -- bool)",
desc: "Not and",
example: "1 1 nand => 0",
compile: Simple,
varargs: false,
},
Word {
name: "nor",
aliases: &[],
category: "Logic",
stack: "(a b -- bool)",
desc: "Not or",
example: "0 0 nor => 1",
compile: Simple,
varargs: false,
},
Word {
name: "ifelse",
aliases: &[],
category: "Logic",
stack: "(true-quot false-quot bool --)",
desc: "Execute true-quot if true, else false-quot",
example: "{ 1 } { 2 } coin ifelse",
compile: Simple,
varargs: false,
},
Word {
name: "pick",
aliases: &[],
category: "Logic",
stack: "(..quots n --)",
desc: "Execute nth quotation (0-indexed)",
example: "{ 1 } { 2 } { 3 } 2 pick => 3",
compile: Simple,
varargs: true,
},
// Sound
Word {
name: "sound",
aliases: &["s"],
category: "Sound",
stack: "(name --)",
desc: "Begin sound command",
example: "\"kick\" sound",
compile: Simple,
varargs: false,
},
Word {
name: ".",
aliases: &[],
category: "Sound",
stack: "(--)",
desc: "Emit current sound",
example: "\"kick\" s . . . .",
compile: Simple,
varargs: false,
},
Word {
name: ".!",
aliases: &[],
category: "Sound",
stack: "(n --)",
desc: "Emit current sound n times",
example: "\"kick\" s 4 .!",
compile: Simple,
varargs: true,
},
// Variables (prefix syntax: @name to fetch, !name to store)
Word {
name: "@<var>",
aliases: &[],
category: "Variables",
stack: "( -- val)",
desc: "Fetch variable value",
example: "@freq => 440",
compile: Simple,
varargs: false,
},
Word {
name: "!<var>",
aliases: &[],
category: "Variables",
stack: "(val --)",
desc: "Store value in variable",
example: "440 !freq",
compile: Simple,
varargs: false,
},
// Randomness
Word {
name: "rand",
aliases: &[],
category: "Randomness",
stack: "(min max -- n|f)",
desc: "Random in range. Int if both args are int, float otherwise",
example: "1 6 rand => 4 | 0.0 1.0 rand => 0.42",
compile: Simple,
varargs: false,
},
Word {
name: "seed",
aliases: &[],
category: "Randomness",
stack: "(n --)",
desc: "Set random seed",
example: "12345 seed",
compile: Simple,
varargs: false,
},
Word {
name: "coin",
aliases: &[],
category: "Randomness",
stack: "(-- bool)",
desc: "50/50 random boolean",
example: "coin => 0 or 1",
compile: Simple,
varargs: false,
},
Word {
name: "chance",
aliases: &[],
category: "Probability",
stack: "(quot prob --)",
desc: "Execute quotation with probability (0.0-1.0)",
example: "{ 2 distort } 0.75 chance",
compile: Simple,
varargs: false,
},
Word {
name: "prob",
aliases: &[],
category: "Probability",
stack: "(quot pct --)",
desc: "Execute quotation with probability (0-100)",
example: "{ 2 distort } 75 prob",
compile: Simple,
varargs: false,
},
Word {
name: "choose",
aliases: &[],
category: "Randomness",
stack: "(..n n -- val)",
desc: "Random pick from n items",
example: "1 2 3 3 choose",
compile: Simple,
varargs: true,
},
Word {
name: "cycle",
aliases: &[],
category: "Selection",
stack: "(v1..vn n -- selected)",
desc: "Cycle through n items by step runs",
example: "60 64 67 3 cycle",
compile: Simple,
varargs: true,
},
Word {
name: "pcycle",
aliases: &[],
category: "Selection",
stack: "(v1..vn n -- selected)",
desc: "Cycle through n items by pattern iteration",
example: "60 64 67 3 pcycle",
compile: Simple,
varargs: true,
},
Word {
name: "tcycle",
aliases: &[],
category: "Selection",
stack: "(v1..vn n -- CycleList)",
desc: "Create cycle list for emit-time resolution",
example: "60 64 67 3 tcycle note",
compile: Simple,
varargs: true,
},
Word {
name: "every",
aliases: &[],
category: "Time",
stack: "(n -- bool)",
desc: "True every nth iteration",
example: "4 every",
compile: Simple,
varargs: false,
},
// Probability shortcuts
Word {
name: "always",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Always execute quotation",
example: "{ 2 distort } always",
compile: Probability(1.0),
varargs: false,
},
Word {
name: "never",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Never execute quotation",
example: "{ 2 distort } never",
compile: Probability(0.0),
varargs: false,
},
Word {
name: "often",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Execute quotation 75% of the time",
example: "{ 2 distort } often",
compile: Probability(0.75),
varargs: false,
},
Word {
name: "sometimes",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Execute quotation 50% of the time",
example: "{ 2 distort } sometimes",
compile: Probability(0.5),
varargs: false,
},
Word {
name: "rarely",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Execute quotation 25% of the time",
example: "{ 2 distort } rarely",
compile: Probability(0.25),
varargs: false,
},
Word {
name: "almostNever",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Execute quotation 10% of the time",
example: "{ 2 distort } almostNever",
compile: Probability(0.1),
varargs: false,
},
Word {
name: "almostAlways",
aliases: &[],
category: "Probability",
stack: "(quot --)",
desc: "Execute quotation 90% of the time",
example: "{ 2 distort } almostAlways",
compile: Probability(0.9),
varargs: false,
},
// Context
Word {
name: "step",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Current step index",
example: "step => 0",
compile: Context("step"),
varargs: false,
},
Word {
name: "beat",
aliases: &[],
category: "Context",
stack: "(-- f)",
desc: "Current beat position",
example: "beat => 4.5",
compile: Context("beat"),
varargs: false,
},
Word {
name: "bank",
aliases: &[],
category: "Sample",
stack: "(str --)",
desc: "Set sample bank suffix",
example: "\"a\" bank",
compile: Param,
varargs: false,
},
Word {
name: "pattern",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Current pattern index",
example: "pattern => 0",
compile: Context("pattern"),
varargs: false,
},
Word {
name: "pbank",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Current pattern's bank index",
example: "pbank => 0",
compile: Context("bank"),
varargs: false,
},
Word {
name: "tempo",
aliases: &[],
category: "Context",
stack: "(-- f)",
desc: "Current BPM",
example: "tempo => 120.0",
compile: Context("tempo"),
varargs: false,
},
Word {
name: "phase",
aliases: &[],
category: "Context",
stack: "(-- f)",
desc: "Phase in bar (0-1)",
example: "phase => 0.25",
compile: Context("phase"),
varargs: false,
},
Word {
name: "slot",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Current slot number",
example: "slot => 0",
compile: Context("slot"),
varargs: false,
},
Word {
name: "runs",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Times this step ran",
example: "runs => 3",
compile: Context("runs"),
varargs: false,
},
Word {
name: "iter",
aliases: &[],
category: "Context",
stack: "(-- n)",
desc: "Pattern iteration count",
example: "iter => 2",
compile: Context("iter"),
varargs: false,
},
Word {
name: "stepdur",
aliases: &[],
category: "Context",
stack: "(-- f)",
desc: "Step duration in seconds",
example: "stepdur => 0.125",
compile: Context("stepdur"),
varargs: false,
},
// Live keys
Word {
name: "fill",
aliases: &[],
category: "Context",
stack: "(-- bool)",
desc: "True when fill is on (f key)",
example: "\"snare\" s . fill ?",
compile: Context("fill"),
varargs: false,
},
// Music
Word {
name: "mtof",
aliases: &[],
category: "Music",
stack: "(midi -- hz)",
desc: "MIDI note to frequency",
example: "69 mtof => 440.0",
compile: Simple,
varargs: false,
},
Word {
name: "ftom",
aliases: &[],
category: "Music",
stack: "(hz -- midi)",
desc: "Frequency to MIDI note",
example: "440 ftom => 69.0",
compile: Simple,
varargs: false,
},
// LFO
Word {
name: "ramp",
aliases: &[],
category: "LFO",
stack: "(freq curve -- val)",
desc: "Ramp [0,1]: fract(freq*beat)^curve",
example: "0.25 2.0 ramp",
compile: Simple,
varargs: false,
},
Word {
name: "range",
aliases: &[],
category: "LFO",
stack: "(val min max -- scaled)",
desc: "Scale [0,1] to [min,max]",
example: "0.5 200 800 range => 500",
compile: Simple,
varargs: false,
},
Word {
name: "linramp",
aliases: &[],
category: "LFO",
stack: "(freq -- val)",
desc: "Linear ramp (curve=1)",
example: "1.0 linramp",
compile: Simple,
varargs: false,
},
Word {
name: "expramp",
aliases: &[],
category: "LFO",
stack: "(freq -- val)",
desc: "Exponential ramp (curve=3)",
example: "0.25 expramp",
compile: Simple,
varargs: false,
},
Word {
name: "logramp",
aliases: &[],
category: "LFO",
stack: "(freq -- val)",
desc: "Logarithmic ramp (curve=0.3)",
example: "2.0 logramp",
compile: Simple,
varargs: false,
},
Word {
name: "tri",
aliases: &[],
category: "LFO",
stack: "(freq -- val)",
desc: "Triangle wave [0,1]: 0→1→0",
example: "0.5 tri",
compile: Simple,
varargs: false,
},
Word {
name: "perlin",
aliases: &[],
category: "LFO",
stack: "(freq -- val)",
desc: "Perlin noise [0,1] sampled at freq*beat",
example: "0.25 perlin",
compile: Simple,
varargs: false,
},
Word {
name: "loop",
aliases: &[],
category: "Time",
stack: "(n --)",
desc: "Fit sample to n beats",
example: "\"break\" s 4 loop @",
compile: Simple,
varargs: false,
},
Word {
name: "tempo!",
aliases: &[],
category: "Time",
stack: "(bpm --)",
desc: "Set global tempo",
example: "140 tempo!",
compile: Simple,
varargs: false,
},
Word {
name: "speed!",
aliases: &[],
category: "Time",
stack: "(multiplier --)",
desc: "Set pattern speed multiplier",
example: "2.0 speed!",
compile: Simple,
varargs: false,
},
Word {
name: "chain",
aliases: &[],
category: "Time",
stack: "(bank pattern --)",
desc: "Chain to bank/pattern (1-indexed) when current pattern ends",
example: "1 4 chain",
compile: Simple,
varargs: false,
},
Word {
name: "at",
aliases: &[],
category: "Time",
stack: "(v1..vn n --)",
desc: "Set delta context for emit timing",
example: "0 0.5 2 at kick s . => emits at 0 and 0.5 of step",
compile: Simple,
varargs: true,
},
// Quotations
Word {
name: "?",
aliases: &[],
category: "Logic",
stack: "(quot bool --)",
desc: "Execute quotation if true",
example: "{ 2 distort } 0.5 chance ?",
compile: Simple,
varargs: false,
},
Word {
name: "!?",
aliases: &[],
category: "Logic",
stack: "(quot bool --)",
desc: "Execute quotation if false",
example: "{ 1 distort } 0.5 chance !?",
compile: Simple,
varargs: false,
},
// Sample playback
Word {
name: "time",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set time offset",
example: "0.1 time",
compile: Param,
varargs: false,
},
Word {
name: "repeat",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Set repeat count",
example: "4 repeat",
compile: Param,
varargs: false,
},
Word {
name: "dur",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set duration",
example: "0.5 dur",
compile: Param,
varargs: false,
},
Word {
name: "gate",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set gate time",
example: "0.8 gate",
compile: Param,
varargs: false,
},
Word {
name: "freq",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set frequency (Hz)",
example: "440 freq",
compile: Param,
varargs: false,
},
Word {
name: "detune",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set detune amount",
example: "0.01 detune",
compile: Param,
varargs: false,
},
Word {
name: "speed",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set playback speed",
example: "1.5 speed",
compile: Param,
varargs: false,
},
Word {
name: "glide",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set glide/portamento",
example: "0.1 glide",
compile: Param,
varargs: false,
},
Word {
name: "pw",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set pulse width",
example: "0.5 pw",
compile: Param,
varargs: false,
},
Word {
name: "spread",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set stereo spread",
example: "0.5 spread",
compile: Param,
varargs: false,
},
Word {
name: "mult",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set multiplier",
example: "2 mult",
compile: Param,
varargs: false,
},
Word {
name: "warp",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set warp amount",
example: "0.5 warp",
compile: Param,
varargs: false,
},
Word {
name: "mirror",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set mirror",
example: "1 mirror",
compile: Param,
varargs: false,
},
Word {
name: "harmonics",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set harmonics (mutable only)",
example: "4 harmonics",
compile: Param,
varargs: false,
},
Word {
name: "timbre",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set timbre (mutable only)",
example: "0.5 timbre",
compile: Param,
varargs: false,
},
Word {
name: "morph",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set morph (mutable only)",
example: "0.5 morph",
compile: Param,
varargs: false,
},
Word {
name: "begin",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set sample start (0-1)",
example: "0.25 begin",
compile: Param,
varargs: false,
},
Word {
name: "end",
aliases: &[],
category: "Sample",
stack: "(f --)",
desc: "Set sample end (0-1)",
example: "0.75 end",
compile: Param,
varargs: false,
},
Word {
name: "gain",
aliases: &[],
category: "Gain",
stack: "(f --)",
desc: "Set volume (0-1)",
example: "0.8 gain",
compile: Param,
varargs: false,
},
Word {
name: "postgain",
aliases: &[],
category: "Gain",
stack: "(f --)",
desc: "Set post gain",
example: "1.2 postgain",
compile: Param,
varargs: false,
},
Word {
name: "velocity",
aliases: &[],
category: "Gain",
stack: "(f --)",
desc: "Set velocity",
example: "100 velocity",
compile: Param,
varargs: false,
},
Word {
name: "pan",
aliases: &[],
category: "Gain",
stack: "(f --)",
desc: "Set pan (-1 to 1)",
example: "0.5 pan",
compile: Param,
varargs: false,
},
Word {
name: "attack",
aliases: &["att"],
category: "Envelope",
stack: "(f --)",
desc: "Set attack time",
example: "0.01 attack",
compile: Param,
varargs: false,
},
Word {
name: "decay",
aliases: &["dec"],
category: "Envelope",
stack: "(f --)",
desc: "Set decay time",
example: "0.1 decay",
compile: Param,
varargs: false,
},
Word {
name: "sustain",
aliases: &["sus"],
category: "Envelope",
stack: "(f --)",
desc: "Set sustain level",
example: "0.5 sustain",
compile: Param,
varargs: false,
},
Word {
name: "release",
aliases: &["rel"],
category: "Envelope",
stack: "(f --)",
desc: "Set release time",
example: "0.3 release",
compile: Param,
varargs: false,
},
Word {
name: "adsr",
aliases: &[],
category: "Envelope",
stack: "(a d s r --)",
desc: "Set attack, decay, sustain, release",
example: "0.01 0.1 0.5 0.3 adsr",
compile: Simple,
varargs: false,
},
Word {
name: "ad",
aliases: &[],
category: "Envelope",
stack: "(a d --)",
desc: "Set attack, decay (sustain=0)",
example: "0.01 0.1 ad",
compile: Simple,
varargs: false,
},
Word {
name: "lpf",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass frequency",
example: "2000 lpf",
compile: Param,
varargs: false,
},
Word {
name: "lpq",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass resonance",
example: "0.5 lpq",
compile: Param,
varargs: false,
},
Word {
name: "lpe",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass envelope",
example: "0.5 lpe",
compile: Param,
varargs: false,
},
Word {
name: "lpa",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass attack",
example: "0.01 lpa",
compile: Param,
varargs: false,
},
Word {
name: "lpd",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass decay",
example: "0.1 lpd",
compile: Param,
varargs: false,
},
Word {
name: "lps",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass sustain",
example: "0.5 lps",
compile: Param,
varargs: false,
},
Word {
name: "lpr",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set lowpass release",
example: "0.3 lpr",
compile: Param,
varargs: false,
},
Word {
name: "hpf",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass frequency",
example: "100 hpf",
compile: Param,
varargs: false,
},
Word {
name: "hpq",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass resonance",
example: "0.5 hpq",
compile: Param,
varargs: false,
},
Word {
name: "hpe",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass envelope",
example: "0.5 hpe",
compile: Param,
varargs: false,
},
Word {
name: "hpa",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass attack",
example: "0.01 hpa",
compile: Param,
varargs: false,
},
Word {
name: "hpd",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass decay",
example: "0.1 hpd",
compile: Param,
varargs: false,
},
Word {
name: "hps",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass sustain",
example: "0.5 hps",
compile: Param,
varargs: false,
},
Word {
name: "hpr",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set highpass release",
example: "0.3 hpr",
compile: Param,
varargs: false,
},
Word {
name: "bpf",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass frequency",
example: "1000 bpf",
compile: Param,
varargs: false,
},
Word {
name: "bpq",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass resonance",
example: "0.5 bpq",
compile: Param,
varargs: false,
},
Word {
name: "bpe",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass envelope",
example: "0.5 bpe",
compile: Param,
varargs: false,
},
Word {
name: "bpa",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass attack",
example: "0.01 bpa",
compile: Param,
varargs: false,
},
Word {
name: "bpd",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass decay",
example: "0.1 bpd",
compile: Param,
varargs: false,
},
Word {
name: "bps",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass sustain",
example: "0.5 bps",
compile: Param,
varargs: false,
},
Word {
name: "bpr",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set bandpass release",
example: "0.3 bpr",
compile: Param,
varargs: false,
},
Word {
name: "llpf",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder lowpass frequency",
example: "2000 llpf",
compile: Param,
varargs: false,
},
Word {
name: "llpq",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder lowpass resonance",
example: "0.5 llpq",
compile: Param,
varargs: false,
},
Word {
name: "lhpf",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder highpass frequency",
example: "100 lhpf",
compile: Param,
varargs: false,
},
Word {
name: "lhpq",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder highpass resonance",
example: "0.5 lhpq",
compile: Param,
varargs: false,
},
Word {
name: "lbpf",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder bandpass frequency",
example: "1000 lbpf",
compile: Param,
varargs: false,
},
Word {
name: "lbpq",
aliases: &[],
category: "Ladder Filter",
stack: "(f --)",
desc: "Set ladder bandpass resonance",
example: "0.5 lbpq",
compile: Param,
varargs: false,
},
Word {
name: "ftype",
aliases: &[],
category: "Filter",
stack: "(n --)",
desc: "Set filter type",
example: "1 ftype",
compile: Param,
varargs: false,
},
Word {
name: "penv",
aliases: &[],
category: "Pitch Env",
stack: "(f --)",
desc: "Set pitch envelope",
example: "0.5 penv",
compile: Param,
varargs: false,
},
Word {
name: "patt",
aliases: &[],
category: "Pitch Env",
stack: "(f --)",
desc: "Set pitch attack",
example: "0.01 patt",
compile: Param,
varargs: false,
},
Word {
name: "pdec",
aliases: &[],
category: "Pitch Env",
stack: "(f --)",
desc: "Set pitch decay",
example: "0.1 pdec",
compile: Param,
varargs: false,
},
Word {
name: "psus",
aliases: &[],
category: "Pitch Env",
stack: "(f --)",
desc: "Set pitch sustain",
example: "0 psus",
compile: Param,
varargs: false,
},
Word {
name: "prel",
aliases: &[],
category: "Pitch Env",
stack: "(f --)",
desc: "Set pitch release",
example: "0.1 prel",
compile: Param,
varargs: false,
},
Word {
name: "vib",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set vibrato rate",
example: "5 vib",
compile: Param,
varargs: false,
},
Word {
name: "vibmod",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set vibrato depth",
example: "0.5 vibmod",
compile: Param,
varargs: false,
},
Word {
name: "vibshape",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set vibrato shape",
example: "0 vibshape",
compile: Param,
varargs: false,
},
Word {
name: "fm",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM frequency",
example: "200 fm",
compile: Param,
varargs: false,
},
Word {
name: "fmh",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM harmonic ratio",
example: "2 fmh",
compile: Param,
varargs: false,
},
Word {
name: "fmshape",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM shape",
example: "0 fmshape",
compile: Param,
varargs: false,
},
Word {
name: "fme",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM envelope",
example: "0.5 fme",
compile: Param,
varargs: false,
},
Word {
name: "fma",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM attack",
example: "0.01 fma",
compile: Param,
varargs: false,
},
Word {
name: "fmd",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM decay",
example: "0.1 fmd",
compile: Param,
varargs: false,
},
Word {
name: "fms",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM sustain",
example: "0.5 fms",
compile: Param,
varargs: false,
},
Word {
name: "fmr",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set FM release",
example: "0.1 fmr",
compile: Param,
varargs: false,
},
Word {
name: "am",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set AM frequency",
example: "10 am",
compile: Param,
varargs: false,
},
Word {
name: "amdepth",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set AM depth",
example: "0.5 amdepth",
compile: Param,
varargs: false,
},
Word {
name: "amshape",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set AM shape",
example: "0 amshape",
compile: Param,
varargs: false,
},
Word {
name: "rm",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set RM frequency",
example: "100 rm",
compile: Param,
varargs: false,
},
Word {
name: "rmdepth",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set RM depth",
example: "0.5 rmdepth",
compile: Param,
varargs: false,
},
Word {
name: "rmshape",
aliases: &[],
category: "Modulation",
stack: "(f --)",
desc: "Set RM shape",
example: "0 rmshape",
compile: Param,
varargs: false,
},
Word {
name: "phaser",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set phaser rate",
example: "1 phaser",
compile: Param,
varargs: false,
},
Word {
name: "phaserdepth",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set phaser depth",
example: "0.5 phaserdepth",
compile: Param,
varargs: false,
},
Word {
name: "phasersweep",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set phaser sweep",
example: "0.5 phasersweep",
compile: Param,
varargs: false,
},
Word {
name: "phasercenter",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set phaser center",
example: "1000 phasercenter",
compile: Param,
varargs: false,
},
Word {
name: "flanger",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set flanger rate",
example: "0.5 flanger",
compile: Param,
varargs: false,
},
Word {
name: "flangerdepth",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set flanger depth",
example: "0.5 flangerdepth",
compile: Param,
varargs: false,
},
Word {
name: "flangerfeedback",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set flanger feedback",
example: "0.5 flangerfeedback",
compile: Param,
varargs: false,
},
Word {
name: "chorus",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set chorus rate",
example: "1 chorus",
compile: Param,
varargs: false,
},
Word {
name: "chorusdepth",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set chorus depth",
example: "0.5 chorusdepth",
compile: Param,
varargs: false,
},
Word {
name: "chorusdelay",
aliases: &[],
category: "Mod FX",
stack: "(f --)",
desc: "Set chorus delay",
example: "0.02 chorusdelay",
compile: Param,
varargs: false,
},
Word {
name: "eqlo",
aliases: &[],
category: "EQ",
stack: "(f --)",
desc: "Set low shelf gain (dB)",
example: "3 eqlo",
compile: Param,
varargs: false,
},
Word {
name: "eqmid",
aliases: &[],
category: "EQ",
stack: "(f --)",
desc: "Set mid peak gain (dB)",
example: "-2 eqmid",
compile: Param,
varargs: false,
},
Word {
name: "eqhi",
aliases: &[],
category: "EQ",
stack: "(f --)",
desc: "Set high shelf gain (dB)",
example: "1 eqhi",
compile: Param,
varargs: false,
},
Word {
name: "tilt",
aliases: &[],
category: "EQ",
stack: "(f --)",
desc: "Set tilt EQ (-1 dark, 1 bright)",
example: "-0.5 tilt",
compile: Param,
varargs: false,
},
Word {
name: "width",
aliases: &[],
category: "Stereo",
stack: "(f --)",
desc: "Set stereo width (0 mono, 1 normal, 2 wide)",
example: "0 width",
compile: Param,
varargs: false,
},
Word {
name: "haas",
aliases: &[],
category: "Stereo",
stack: "(f --)",
desc: "Set Haas delay in ms (spatial placement)",
example: "8 haas",
compile: Param,
varargs: false,
},
Word {
name: "comb",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set comb filter mix",
example: "0.5 comb",
compile: Param,
varargs: false,
},
Word {
name: "combfreq",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set comb frequency",
example: "200 combfreq",
compile: Param,
varargs: false,
},
Word {
name: "combfeedback",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set comb feedback",
example: "0.5 combfeedback",
compile: Param,
varargs: false,
},
Word {
name: "combdamp",
aliases: &[],
category: "Filter",
stack: "(f --)",
desc: "Set comb damping",
example: "0.5 combdamp",
compile: Param,
varargs: false,
},
Word {
name: "coarse",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set coarse tune",
example: "12 coarse",
compile: Param,
varargs: false,
},
Word {
name: "crush",
aliases: &[],
category: "Lo-fi",
stack: "(f --)",
desc: "Set bit crush",
example: "8 crush",
compile: Param,
varargs: false,
},
Word {
name: "sub",
aliases: &[],
category: "Oscillator",
stack: "(f --)",
desc: "Set sub oscillator level",
example: "0.5 sub",
compile: Param,
varargs: false,
},
Word {
name: "suboct",
aliases: &[],
category: "Oscillator",
stack: "(n --)",
desc: "Set sub oscillator octave",
example: "2 suboct",
compile: Param,
varargs: false,
},
Word {
name: "subwave",
aliases: &[],
category: "Oscillator",
stack: "(n --)",
desc: "Set sub oscillator waveform",
example: "1 subwave",
compile: Param,
varargs: false,
},
Word {
name: "fold",
aliases: &[],
category: "Lo-fi",
stack: "(f --)",
desc: "Set wave fold",
example: "2 fold",
compile: Param,
varargs: false,
},
Word {
name: "wrap",
aliases: &[],
category: "Lo-fi",
stack: "(f --)",
desc: "Set wave wrap",
example: "0.5 wrap",
compile: Param,
varargs: false,
},
Word {
name: "distort",
aliases: &[],
category: "Lo-fi",
stack: "(f --)",
desc: "Set distortion",
example: "0.5 distort",
compile: Param,
varargs: false,
},
Word {
name: "distortvol",
aliases: &[],
category: "Lo-fi",
stack: "(f --)",
desc: "Set distortion volume",
example: "0.8 distortvol",
compile: Param,
varargs: false,
},
Word {
name: "delay",
aliases: &[],
category: "Delay",
stack: "(f --)",
desc: "Set delay mix",
example: "0.3 delay",
compile: Param,
varargs: false,
},
Word {
name: "delaytime",
aliases: &[],
category: "Delay",
stack: "(f --)",
desc: "Set delay time",
example: "0.25 delaytime",
compile: Param,
varargs: false,
},
Word {
name: "delayfeedback",
aliases: &[],
category: "Delay",
stack: "(f --)",
desc: "Set delay feedback",
example: "0.5 delayfeedback",
compile: Param,
varargs: false,
},
Word {
name: "delaytype",
aliases: &[],
category: "Delay",
stack: "(n --)",
desc: "Set delay type",
example: "1 delaytype",
compile: Param,
varargs: false,
},
Word {
name: "verb",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set reverb mix",
example: "0.3 verb",
compile: Param,
varargs: false,
},
Word {
name: "verbdecay",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set reverb decay",
example: "2 verbdecay",
compile: Param,
varargs: false,
},
Word {
name: "verbdamp",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set reverb damping",
example: "0.5 verbdamp",
compile: Param,
varargs: false,
},
Word {
name: "verbpredelay",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set reverb predelay",
example: "0.02 verbpredelay",
compile: Param,
varargs: false,
},
Word {
name: "verbdiff",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set reverb diffusion",
example: "0.7 verbdiff",
compile: Param,
varargs: false,
},
Word {
name: "voice",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Set voice number",
example: "1 voice",
compile: Param,
varargs: false,
},
Word {
name: "orbit",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Set orbit/bus",
example: "0 orbit",
compile: Param,
varargs: false,
},
Word {
name: "note",
aliases: &[],
category: "Oscillator",
stack: "(n --)",
desc: "Set MIDI note",
example: "60 note",
compile: Param,
varargs: false,
},
Word {
name: "size",
aliases: &[],
category: "Reverb",
stack: "(f --)",
desc: "Set size",
example: "1 size",
compile: Param,
varargs: false,
},
Word {
name: "n",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Set sample number",
example: "0 n",
compile: Param,
varargs: false,
},
Word {
name: "cut",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Set cut group",
example: "1 cut",
compile: Param,
varargs: false,
},
Word {
name: "reset",
aliases: &[],
category: "Sample",
stack: "(n --)",
desc: "Reset parameter",
example: "1 reset",
compile: Param,
varargs: false,
},
Word {
name: "clear",
aliases: &[],
category: "Sound",
stack: "(--)",
desc: "Clear sound register (sound and all params)",
example: "\"kick\" s 0.5 gain . clear \"hat\" s .",
compile: Simple,
varargs: false,
},
// Quotation execution
Word {
name: "apply",
aliases: &[],
category: "Logic",
stack: "(quot --)",
desc: "Execute quotation unconditionally",
example: "{ 2 * } apply",
compile: Simple,
varargs: false,
},
// Word definitions
Word {
name: ":",
aliases: &[],
category: "Definitions",
stack: "( -- )",
desc: "Begin word definition",
example: ": kick \"kick\" s emit ;",
compile: Simple,
varargs: false,
},
Word {
name: ";",
aliases: &[],
category: "Definitions",
stack: "( -- )",
desc: "End word definition",
example: ": kick \"kick\" s emit ;",
compile: Simple,
varargs: false,
},
// Generator
Word {
name: "..",
aliases: &[],
category: "Generator",
stack: "(start end -- start start+1 ... end)",
desc: "Push arithmetic sequence from start to end",
example: "1 4 .. => 1 2 3 4",
compile: Simple,
varargs: false,
},
Word {
name: "gen",
aliases: &[],
category: "Generator",
stack: "(quot n -- results...)",
desc: "Execute quotation n times, push all results",
example: "{ 1 6 rand } 4 gen => 4 random values",
compile: Simple,
varargs: true,
},
Word {
name: "geom..",
aliases: &[],
category: "Generator",
stack: "(start ratio count -- start start*r start*r^2 ...)",
desc: "Push geometric sequence",
example: "1 2 4 geom.. => 1 2 4 8",
compile: Simple,
varargs: false,
},
];
pub(super) fn simple_op(name: &str) -> Option<Op> {
Some(match name {
"dup" => Op::Dup,
"dupn" => Op::Dupn,
"drop" => Op::Drop,
"swap" => Op::Swap,
"over" => Op::Over,
"rot" => Op::Rot,
"nip" => Op::Nip,
"tuck" => Op::Tuck,
"+" => Op::Add,
"-" => Op::Sub,
"*" => Op::Mul,
"/" => Op::Div,
"mod" => Op::Mod,
"neg" => Op::Neg,
"abs" => Op::Abs,
"floor" => Op::Floor,
"ceil" => Op::Ceil,
"round" => Op::Round,
"min" => Op::Min,
"max" => Op::Max,
"pow" => Op::Pow,
"sqrt" => Op::Sqrt,
"sin" => Op::Sin,
"cos" => Op::Cos,
"log" => Op::Log,
"=" => Op::Eq,
"!=" => Op::Ne,
"lt" => Op::Lt,
"gt" => Op::Gt,
"<=" => Op::Le,
">=" => Op::Ge,
"and" => Op::And,
"or" => Op::Or,
"not" => Op::Not,
"xor" => Op::Xor,
"nand" => Op::Nand,
"nor" => Op::Nor,
"ifelse" => Op::IfElse,
"pick" => Op::Pick,
"sound" => Op::NewCmd,
"." => Op::Emit,
"rand" => Op::Rand,
"seed" => Op::Seed,
"cycle" => Op::Cycle,
"pcycle" => Op::PCycle,
"tcycle" => Op::TCycle,
"choose" => Op::Choose,
"every" => Op::Every,
"chance" => Op::ChanceExec,
"prob" => Op::ProbExec,
"coin" => Op::Coin,
"mtof" => Op::Mtof,
"ftom" => Op::Ftom,
"?" => Op::When,
"!?" => Op::Unless,
"tempo!" => Op::SetTempo,
"speed!" => Op::SetSpeed,
"at" => Op::At,
"adsr" => Op::Adsr,
"ad" => Op::Ad,
"apply" => Op::Apply,
"ramp" => Op::Ramp,
"tri" => Op::Tri,
"range" => Op::Range,
"perlin" => Op::Perlin,
"chain" => Op::Chain,
"loop" => Op::Loop,
"oct" => Op::Oct,
".!" => Op::EmitN,
"clear" => Op::ClearCmd,
".." => Op::IntRange,
"gen" => Op::Generate,
"geom.." => Op::GeomRange,
_ => return None,
})
}
/// Parse note names like c4, c#4, cs4, eb4 into MIDI numbers.
/// C4 = 60 (middle C), A4 = 69 (440 Hz reference).
fn parse_note_name(name: &str) -> Option<i64> {
let name = name.to_lowercase();
let bytes = name.as_bytes();
if bytes.len() < 2 {
return None;
}
let base = match bytes[0] {
b'c' => 0,
b'd' => 2,
b'e' => 4,
b'f' => 5,
b'g' => 7,
b'a' => 9,
b'b' => 11,
_ => return None,
};
let (modifier, octave_start) = match bytes[1] {
b'#' | b's' => (1, 2),
b'b' if bytes.len() > 2 && bytes[2].is_ascii_digit() => (-1, 2), // flat: eb4, bb4
b'0'..=b'9' => (0, 1),
_ => return None,
};
let octave_str = &name[octave_start..];
let octave: i64 = octave_str.parse().ok()?;
if !(-1..=9).contains(&octave) {
return None;
}
// MIDI: C4 = 60, so C-1 = 0
Some((octave + 1) * 12 + base + modifier)
}
/// Parse interval names like m3, M3, P5 into semitone counts.
/// Supports simple intervals (1-8) and compound intervals (9-15).
fn parse_interval(name: &str) -> Option<i64> {
// Simple intervals: unison through octave
let simple = match name {
"P1" | "unison" => 0,
"m2" => 1,
"M2" => 2,
"m3" => 3,
"M3" => 4,
"P4" => 5,
"aug4" | "dim5" | "tritone" => 6,
"P5" => 7,
"m6" => 8,
"M6" => 9,
"m7" => 10,
"M7" => 11,
"P8" => 12,
// Compound intervals (octave + simple)
"m9" => 13,
"M9" => 14,
"m10" => 15,
"M10" => 16,
"P11" => 17,
"aug11" => 18,
"P12" => 19,
"m13" => 20,
"M13" => 21,
"m14" => 22,
"M14" => 23,
"P15" => 24,
_ => return None,
};
Some(simple)
}
pub(super) fn compile_word(
name: &str,
span: Option<SourceSpan>,
ops: &mut Vec<Op>,
dict: &Dictionary,
) -> bool {
match name {
"linramp" => {
ops.push(Op::PushFloat(1.0, span));
ops.push(Op::Ramp);
return true;
}
"expramp" => {
ops.push(Op::PushFloat(3.0, span));
ops.push(Op::Ramp);
return true;
}
"logramp" => {
ops.push(Op::PushFloat(0.3, span));
ops.push(Op::Ramp);
return true;
}
_ => {}
}
if let Some(pattern) = theory::lookup(name) {
ops.push(Op::Degree(pattern));
return true;
}
for word in WORDS {
if word.name == name || word.aliases.contains(&name) {
match &word.compile {
Simple => {
if let Some(op) = simple_op(word.name) {
ops.push(op);
}
}
Context(ctx) => ops.push(Op::GetContext((*ctx).into())),
Param => ops.push(Op::SetParam(word.name.into())),
Probability(p) => {
ops.push(Op::PushFloat(*p, None));
ops.push(Op::ChanceExec);
}
}
return true;
}
}
// @varname - fetch variable
if let Some(var_name) = name.strip_prefix('@') {
if !var_name.is_empty() {
ops.push(Op::PushStr(var_name.to_string(), span));
ops.push(Op::Get);
return true;
}
}
// !varname - store into variable
if let Some(var_name) = name.strip_prefix('!') {
if !var_name.is_empty() {
ops.push(Op::PushStr(var_name.to_string(), span));
ops.push(Op::Set);
return true;
}
}
// Note names: c4, c#4, cs4, eb4, etc. -> MIDI number
if let Some(midi) = parse_note_name(name) {
ops.push(Op::PushInt(midi, span));
return true;
}
// Intervals: m3, M3, P5, etc. -> dup top, add semitones (for chord building)
if let Some(semitones) = parse_interval(name) {
ops.push(Op::Dup);
ops.push(Op::PushInt(semitones, span));
ops.push(Op::Add);
return true;
}
// Internal ops not exposed in WORDS
if let Some(op) = simple_op(name) {
ops.push(op);
return true;
}
// User-defined words from dictionary
if let Some(body) = dict.lock().unwrap().get(name) {
ops.extend(body.iter().cloned());
return true;
}
// Unrecognized token becomes a string
ops.push(Op::PushStr(name.to_string(), span));
true
}