From ec950551fd68aa6176c51eeb14edb416e61fc35e Mon Sep 17 00:00:00 2001 From: Oleksandr Kozachuk Date: Wed, 15 Apr 2026 19:28:26 +0200 Subject: [PATCH] =?UTF-8?q?boot:=20add=20`S`=20=E2=80=94=20state-smart=20p?= =?UTF-8?q?arse-next-token-as-string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `S name` is the string analogue of `[CHAR] x` and `['] name`: parses the next whitespace-delimited token, state-smart. Interpret: leaves ( c-addr u ) pointing into the input buffer. Compile: appends run-time push of the copied bytes (identical code to writing S" name" inline). One line in boot.fth, leverages the existing PARSE-NAME + SLITERAL. Zero runtime overhead inside : definitions. --- crates/core/boot.fth | 16 ++++++++++++++++ crates/core/src/outer.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) 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 // ===================================================================