Feat: UI / UX

This commit is contained in:
2026-02-16 01:22:40 +01:00
parent b23dd85d0f
commit af6732db1c
37 changed files with 1045 additions and 64 deletions

View File

@@ -60,3 +60,6 @@ mod chords;
#[path = "forth/euclidean.rs"]
mod euclidean;
#[path = "forth/case_statement.rs"]
mod case_statement;

View File

@@ -0,0 +1,108 @@
use super::harness::*;
#[test]
fn single_clause_match() {
expect_int("1 case 1 of 42 endof endcase", 42);
}
#[test]
fn single_clause_no_match() {
let f = run("1 case 2 of 42 endof endcase");
assert!(f.stack().is_empty());
}
#[test]
fn multi_clause_first() {
expect_int("0 case 0 of 10 endof 1 of 20 endof 2 of 30 endof endcase", 10);
}
#[test]
fn multi_clause_middle() {
expect_int("1 case 0 of 10 endof 1 of 20 endof 2 of 30 endof endcase", 20);
}
#[test]
fn multi_clause_last() {
expect_int("2 case 0 of 10 endof 1 of 20 endof 2 of 30 endof endcase", 30);
}
#[test]
fn no_match_stack_clean() {
let f = run("99 case 0 of 10 endof 1 of 20 endof endcase");
assert!(f.stack().is_empty());
}
#[test]
fn expression_test_value() {
expect_int("3 case 1 2 + of 42 endof endcase", 42);
}
#[test]
fn expression_case_value() {
expect_int("1 2 + case 3 of 42 endof endcase", 42);
}
#[test]
fn body_with_computation() {
expect_int("1 case 1 of 10 20 + endof endcase", 30);
}
#[test]
fn default_clause() {
// Default drops case value and pushes replacement twice (endcase drops one)
expect_int("99 case 0 of 10 endof 1 of 20 endof drop 42 42 endcase", 42);
}
#[test]
fn default_clause_uses_case_value() {
// dup preserves case value through endcase's drop
expect_int("99 case 0 of 10 endof dup endcase", 99);
}
#[test]
fn default_clause_not_reached_on_match() {
expect_int("0 case 0 of 10 endof 999 endcase", 10);
}
#[test]
fn nested_case_in_case() {
// outer matches 1, inner matches 2
expect_int("1 case 1 of 2 case 2 of 42 endof endcase endof endcase", 42);
}
#[test]
fn if_inside_case_body() {
expect_int("1 case 1 of 1 if 42 else 99 then endof endcase", 42);
}
#[test]
fn case_inside_if_body() {
expect_int("1 if 2 case 2 of 42 endof endcase then", 42);
}
#[test]
fn preserves_stack_below() {
let f = run("100 1 case 1 of 42 endof endcase");
let stack = f.stack();
assert_eq!(stack.len(), 2);
}
#[test]
fn missing_endcase() {
expect_error("1 case 0 of 10 endof", "missing 'endcase'");
}
#[test]
fn stray_of() {
expect_error("1 of", "unexpected 'of'");
}
#[test]
fn stray_endof() {
expect_error("1 endof", "unexpected 'endof'");
}
#[test]
fn stray_endcase() {
expect_error("1 endcase", "unexpected 'endcase'");
}

View File

@@ -42,3 +42,28 @@ fn float_var() {
fn increment_pattern() {
expect_int(r#"0 !n @n 1 + !n @n 1 + !n @n"#, 2);
}
#[test]
fn set_keep() {
expect_int(r#"42 ,x"#, 42);
}
#[test]
fn set_keep_stores() {
let f = forth();
let ctx = default_ctx();
f.evaluate(r#"42 ,x"#, &ctx).unwrap();
f.clear_stack();
f.evaluate(r#"@x"#, &ctx).unwrap();
assert_eq!(stack_int(&f), 42);
}
#[test]
fn set_keep_chain() {
let f = forth();
let ctx = default_ctx();
f.evaluate(r#"10 ,a ,b"#, &ctx).unwrap();
f.clear_stack();
f.evaluate(r#"@a @b +"#, &ctx).unwrap();
assert_eq!(stack_int(&f), 20);
}