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"); }