Feat: documentation, UI/UX

This commit is contained in:
2026-03-01 19:09:52 +01:00
parent ecb559e556
commit db44f9b98e
57 changed files with 1531 additions and 615 deletions

View File

@@ -328,6 +328,16 @@ impl Forth {
Op::Drop => {
pop(stack)?;
}
Op::Print => {
let val = pop(stack)?;
let text = match &val {
Value::Int(n, _) => n.to_string(),
Value::Float(f, _) => format!("{f}"),
Value::Str(s, _) => s.to_string(),
_ => format!("{val:?}"),
};
outputs.push(format!("print:{text}"));
}
Op::Swap => {
ensure(stack, 2)?;
let len = stack.len();
@@ -558,9 +568,12 @@ impl Forth {
Op::NewCmd => {
ensure(stack, 1)?;
let values = std::mem::take(stack);
let values = drain_skip_quotations(stack);
if values.is_empty() {
return Err("expected sound name".into());
}
let val = if values.len() == 1 {
values.into_iter().next().expect("single value after len check")
values.into_iter().next().unwrap()
} else {
Value::CycleList(Arc::from(values))
};
@@ -568,9 +581,12 @@ impl Forth {
}
Op::SetParam(param) => {
ensure(stack, 1)?;
let values = std::mem::take(stack);
let values = drain_skip_quotations(stack);
if values.is_empty() {
return Err("expected parameter value".into());
}
let val = if values.len() == 1 {
values.into_iter().next().expect("single value after len check")
values.into_iter().next().unwrap()
} else {
Value::CycleList(Arc::from(values))
};
@@ -1866,6 +1882,21 @@ fn pop_bool(stack: &mut Vec<Value>) -> Result<bool, String> {
Ok(pop(stack)?.is_truthy())
}
/// Drain the stack, returning non-quotation values.
/// Quotations are pushed back onto the stack (transparent).
fn drain_skip_quotations(stack: &mut Vec<Value>) -> Vec<Value> {
let values = std::mem::take(stack);
let mut result = Vec::new();
for v in values {
if matches!(v, Value::Quotation(..)) {
stack.push(v);
} else {
result.push(v);
}
}
result
}
fn ensure(stack: &[Value], n: usize) -> Result<(), String> {
if stack.len() < n {
return Err("stack underflow".into());