Feat: add slicing words

This commit is contained in:
2026-02-28 02:37:09 +01:00
parent 511726b65b
commit 7ae3f255b0
6 changed files with 46 additions and 13 deletions

View File

@@ -58,7 +58,7 @@ pub(super) fn simple_op(name: &str) -> Option<Op> {
"nand" => Op::Nand, "nand" => Op::Nand,
"nor" => Op::Nor, "nor" => Op::Nor,
"ifelse" => Op::IfElse, "ifelse" => Op::IfElse,
"pick" => Op::Pick, "select" => Op::Pick,
"sound" => Op::NewCmd, "sound" => Op::NewCmd,
"." => Op::Emit, "." => Op::Emit,
"rand" => Op::Rand(None), "rand" => Op::Rand(None),

View File

@@ -507,12 +507,12 @@ pub(super) const WORDS: &[Word] = &[
varargs: false, varargs: false,
}, },
Word { Word {
name: "pick", name: "select",
aliases: &[], aliases: &[],
category: "Logic", category: "Logic",
stack: "(..quots n --)", stack: "(..quots n --)",
desc: "Execute nth quotation (0-indexed)", desc: "Execute nth quotation (0-indexed)",
example: "{ 1 } { 2 } { 3 } 2 pick => 3", example: "{ 1 } { 2 } { 3 } 2 select => 3",
compile: Simple, compile: Simple,
varargs: true, varargs: true,
}, },

View File

@@ -186,6 +186,26 @@ pub(super) const WORDS: &[Word] = &[
compile: Param, compile: Param,
varargs: true, varargs: true,
}, },
Word {
name: "slice",
aliases: &[],
category: "Sample",
stack: "(v.. --)",
desc: "Divide sample into N equal slices",
example: r#""break" s 8 slice 3 pick ."#,
compile: Param,
varargs: true,
},
Word {
name: "pick",
aliases: &[],
category: "Sample",
stack: "(v.. --)",
desc: "Select which slice to play (0-indexed, wraps)",
example: r#""break" s 8 slice 3 pick ."#,
compile: Param,
varargs: true,
},
Word { Word {
name: "voice", name: "voice",
aliases: &[], aliases: &[],

View File

@@ -63,12 +63,12 @@ Reads naturally: "c3 or c4, depending on the coin."
tri s c4 note 0.2 decay . ;; loud during fills, quiet otherwise tri s c4 note 0.2 decay . ;; loud during fills, quiet otherwise
``` ```
## pick ## select
Choose the nth option from a list of quotations: Choose the nth option from a list of quotations:
```forth ```forth
{ c4 } { e4 } { g4 } { b4 } iter 4 mod pick { c4 } { e4 } { g4 } { b4 } iter 4 mod select
note sine s 0.5 decay . note sine s 0.5 decay .
``` ```

View File

@@ -196,21 +196,21 @@ fn ifelse_false() {
} }
#[test] #[test]
fn pick_first() { fn select_first() {
expect_int("{ 10 } { 20 } { 30 } 0 pick", 10); expect_int("{ 10 } { 20 } { 30 } 0 select", 10);
} }
#[test] #[test]
fn pick_second() { fn select_second() {
expect_int("{ 10 } { 20 } { 30 } 1 pick", 20); expect_int("{ 10 } { 20 } { 30 } 1 select", 20);
} }
#[test] #[test]
fn pick_third() { fn select_third() {
expect_int("{ 10 } { 20 } { 30 } 2 pick", 30); expect_int("{ 10 } { 20 } { 30 } 2 select", 30);
} }
#[test] #[test]
fn pick_preserves_stack() { fn select_preserves_stack() {
expect_int("5 { 10 } { 20 } 0 pick +", 15); expect_int("5 { 10 } { 20 } 0 select +", 15);
} }

View File

@@ -255,3 +255,16 @@ fn all_replaces_previous_global() {
assert_eq!(outputs.len(), 1); assert_eq!(outputs.len(), 1);
assert!(outputs[0].contains("lpf/2000"), "latest lpf should be 2000: {}", outputs[0]); assert!(outputs[0].contains("lpf/2000"), "latest lpf should be 2000: {}", outputs[0]);
} }
#[test]
fn slice_param() {
let outputs = expect_outputs(r#""break" s 8 slice ."#, 1);
assert!(outputs[0].contains("slice/8"));
}
#[test]
fn pick_param() {
let outputs = expect_outputs(r#""break" s 8 slice 3 pick ."#, 1);
assert!(outputs[0].contains("slice/8"));
assert!(outputs[0].contains("pick/3"));
}