diff --git a/crates/core/boot.fth b/crates/core/boot.fth index 38d71f8..c7b69ac 100644 --- a/crates/core/boot.fth +++ b/crates/core/boot.fth @@ -305,3 +305,19 @@ : DFALIGN FALIGN ; \ .S keeps its Rust host function (complex stack introspection). + +\ --------------------------------------------------------------- +\ Phase 8: Parse-ahead sugar +\ --------------------------------------------------------------- + +\ S ( "name" -- ) ( -- c-addr u at run time ) +\ +\ State-smart "quote the next whitespace-delimited token as a string". +\ Interpret-mode: leave ( c-addr u ) pointing into the input buffer. +\ Compile-mode: append run-time semantics that push the copied string +\ (identical to writing S" name" inline). +\ +\ This is the string analogue of [CHAR] (for chars) and ['] (for xts). +\ Comparable to Lisp's quote: S foo is to a string what ' foo is to an xt. +\ Inside a : definition the compiled code is bit-identical to S" foo". +: S PARSE-NAME STATE @ IF SLITERAL THEN ; IMMEDIATE diff --git a/crates/core/src/outer.rs b/crates/core/src/outer.rs index f94ad92..8d030a7 100644 --- a/crates/core/src/outer.rs +++ b/crates/core/src/outer.rs @@ -7550,6 +7550,36 @@ mod tests { assert_eq!(eval_output(": TEST S\" World\" TYPE ; TEST"), "World"); } + // =================================================================== + // New words: S (state-smart parse-next-token-as-string) + // =================================================================== + + #[test] + fn test_s_interpret_type() { + assert_eq!(eval_output("S hello TYPE"), "hello"); + } + + #[test] + fn test_s_interpret_length() { + // S pushes ( c-addr u ); NIP leaves the length on top. + assert_eq!(eval_stack("S foo NIP"), vec![3]); + } + + #[test] + fn test_s_compile_mode() { + assert_eq!(eval_output(": GREET S world TYPE ; GREET"), "world"); + } + + #[test] + fn test_s_compile_stored_literal() { + // The string compiled into a colon def must still be readable after + // the enclosing input line is gone. + let mut vm = ForthVM::::new().unwrap(); + vm.evaluate(": NAME S kelvar ;").unwrap(); + vm.evaluate("NAME TYPE").unwrap(); + assert_eq!(vm.take_output(), "kelvar"); + } + // =================================================================== // New words: COUNT // ===================================================================