107 lines
2.6 KiB
Rust
107 lines
2.6 KiB
Rust
use super::harness::*;
|
|
|
|
#[test]
|
|
fn choose_from_stack() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
f.evaluate("1 2 3 3 choose", &ctx).unwrap();
|
|
let val = stack_int(&f);
|
|
assert!(val >= 1 && val <= 3, "expected 1, 2, or 3, got {}", val);
|
|
}
|
|
|
|
#[test]
|
|
fn cycle_by_runs() {
|
|
let ctx = ctx_with(|c| c.runs = 0);
|
|
let f = run_ctx("10 20 30 3 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 10);
|
|
|
|
let ctx = ctx_with(|c| c.runs = 1);
|
|
let f = run_ctx("10 20 30 3 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 20);
|
|
|
|
let ctx = ctx_with(|c| c.runs = 2);
|
|
let f = run_ctx("10 20 30 3 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 30);
|
|
|
|
let ctx = ctx_with(|c| c.runs = 3);
|
|
let f = run_ctx("10 20 30 3 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 10);
|
|
}
|
|
|
|
#[test]
|
|
fn pcycle_by_iter() {
|
|
let ctx = ctx_with(|c| c.iter = 0);
|
|
let f = run_ctx("10 20 30 3 pcycle", &ctx);
|
|
assert_eq!(stack_int(&f), 10);
|
|
|
|
let ctx = ctx_with(|c| c.iter = 1);
|
|
let f = run_ctx("10 20 30 3 pcycle", &ctx);
|
|
assert_eq!(stack_int(&f), 20);
|
|
|
|
let ctx = ctx_with(|c| c.iter = 2);
|
|
let f = run_ctx("10 20 30 3 pcycle", &ctx);
|
|
assert_eq!(stack_int(&f), 30);
|
|
}
|
|
|
|
#[test]
|
|
fn cycle_with_quotations() {
|
|
let ctx = ctx_with(|c| c.runs = 0);
|
|
let f = run_ctx("5 { dup } { 2 * } 2 cycle", &ctx);
|
|
let stack = f.stack();
|
|
assert_eq!(stack.len(), 2);
|
|
assert_eq!(stack_int(&f), 5);
|
|
|
|
let ctx = ctx_with(|c| c.runs = 1);
|
|
let f = run_ctx("5 { dup } { 2 * } 2 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 10);
|
|
}
|
|
|
|
#[test]
|
|
fn cycle_executes_quotation() {
|
|
let ctx = ctx_with(|c| c.runs = 0);
|
|
let f = run_ctx("10 { 3 + } { 5 + } 2 cycle", &ctx);
|
|
assert_eq!(stack_int(&f), 13);
|
|
}
|
|
|
|
#[test]
|
|
fn dupn_basic() {
|
|
// 5 3 dupn -> 5 5 5, then + + -> 15
|
|
expect_int("5 3 dupn + +", 15);
|
|
}
|
|
|
|
#[test]
|
|
fn dupn_alias() {
|
|
expect_int("5 3 ! + +", 15);
|
|
}
|
|
|
|
#[test]
|
|
fn tcycle_creates_cycle_list() {
|
|
let outputs = expect_outputs(r#"0.0 at 60 64 67 3 tcycle note sine s ."#, 1);
|
|
assert!(outputs[0].contains("note/60"));
|
|
}
|
|
|
|
#[test]
|
|
fn tcycle_with_multiple_emits() {
|
|
let f = forth();
|
|
let ctx = default_ctx();
|
|
let outputs = f.evaluate(r#"0 0.5 2 at 60 64 2 tcycle note sine s ."#, &ctx).unwrap();
|
|
assert_eq!(outputs.len(), 2);
|
|
assert!(outputs[0].contains("note/60"));
|
|
assert!(outputs[1].contains("note/64"));
|
|
}
|
|
|
|
#[test]
|
|
fn cycle_zero_count_error() {
|
|
expect_error("1 2 3 0 cycle", "cycle count must be > 0");
|
|
}
|
|
|
|
#[test]
|
|
fn choose_zero_count_error() {
|
|
expect_error("1 2 3 0 choose", "choose count must be > 0");
|
|
}
|
|
|
|
#[test]
|
|
fn tcycle_zero_count_error() {
|
|
expect_error("1 2 3 0 tcycle", "tcycle count must be > 0");
|
|
}
|