Feat: documentation, UI/UX
This commit is contained in:
@@ -65,6 +65,7 @@ pub enum Op {
|
||||
NewCmd,
|
||||
SetParam(&'static str),
|
||||
Emit,
|
||||
Print,
|
||||
Get,
|
||||
Set,
|
||||
SetKeep,
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -13,6 +13,7 @@ pub(super) fn simple_op(name: &str) -> Option<Op> {
|
||||
"dup" => Op::Dup,
|
||||
"dupn" => Op::Dupn,
|
||||
"drop" => Op::Drop,
|
||||
"print" => Op::Print,
|
||||
"swap" => Op::Swap,
|
||||
"over" => Op::Over,
|
||||
"rot" => Op::Rot,
|
||||
|
||||
@@ -33,6 +33,16 @@ pub(super) const WORDS: &[Word] = &[
|
||||
compile: Simple,
|
||||
varargs: false,
|
||||
},
|
||||
Word {
|
||||
name: "print",
|
||||
aliases: &[],
|
||||
category: "Stack",
|
||||
stack: "(x --)",
|
||||
desc: "Print top of stack to footer bar",
|
||||
example: "42 print",
|
||||
compile: Simple,
|
||||
varargs: false,
|
||||
},
|
||||
Word {
|
||||
name: "swap",
|
||||
aliases: &[],
|
||||
|
||||
Reference in New Issue
Block a user