Add WORDS for Programming-Tools word set

Walk dictionary linked list, print all visible word names.
Uses pending_define mechanism for dictionary access.
This commit is contained in:
2026-04-13 18:33:13 +02:00
parent 38b956c7a3
commit 45de5c62fc
2 changed files with 66 additions and 0 deletions
+44
View File
@@ -2584,6 +2584,7 @@ impl<R: Runtime> ForthVM<R> {
// -- Programming-Tools word set --
self.register_n_to_r()?;
self.register_words()?;
// -- Search-Order word set --
self.register_search_order()?;
@@ -4704,6 +4705,7 @@ impl<R: Runtime> ForthVM<R> {
self.dictionary.set_current_wid(top);
}
}
40 => self.do_words(),
_ => {}
}
}
@@ -5328,6 +5330,16 @@ impl<R: Runtime> ForthVM<R> {
Ok(())
}
/// WORDS ( -- ) Print all visible dictionary words.
fn do_words(&mut self) {
let names = self.dictionary.visible_words();
let mut out = self.output.lock().unwrap();
for name in &names {
out.push_str(name);
out.push(' ');
}
}
/// Register Search-Order word set words.
fn register_search_order(&mut self) -> anyhow::Result<()> {
// FORTH-WORDLIST ( -- wid )
@@ -5553,6 +5565,17 @@ impl<R: Runtime> ForthVM<R> {
Ok(())
}
/// Register WORDS for the Programming-Tools word set.
fn register_words(&mut self) -> anyhow::Result<()> {
let pending = Arc::clone(&self.pending_define);
let func: HostFn = Box::new(move |_ctx: &mut dyn HostAccess| {
pending.lock().unwrap().push(40); // WORDS action
Ok(())
});
self.register_host_primitive("WORDS", false, func)?;
Ok(())
}
/// Register UNESCAPE, SUBSTITUTE, REPLACES for the String word set.
fn register_string_substitution(&mut self) -> anyhow::Result<()> {
// UNESCAPE ( c-addr1 u1 c-addr2 -- c-addr2 u2 )
@@ -7942,6 +7965,27 @@ mod tests {
);
}
// ===================================================================
// WORDS (Programming-Tools)
// ===================================================================
#[test]
fn test_words_lists_defined_words() {
let output = eval_output("WORDS");
// Should contain standard primitives
assert!(output.contains("DUP"));
assert!(output.contains("DROP"));
assert!(output.contains("SWAP"));
assert!(output.contains("+"));
assert!(output.contains("WORDS"));
}
#[test]
fn test_words_includes_user_defined() {
let output = eval_output(": MYTEST 42 ; WORDS");
assert!(output.contains("MYTEST"));
}
// ===================================================================
// Double DOES>: Forth 2012 WEIRD: W1 test
// ===================================================================