forth/demo/demo_std.fth · 6591 字节 · 下载原文
\ demo_std.fth —— Forth 第一层:**标准输入输出**(std)
\ demo_std.fth —— Forth layer one: **standard input/output** (std)
\
\ 这一层只用 Forth 自己的输出词:`." …"`(打印字面量)、`.`(打印栈顶)、
\ This layer uses only Forth's own output words: `." …"` (print a literal), `.` (print the top of the stack),
\ `CR`(换行)、`EMIT`(打印一个字符)。不碰 Crt / 图形 / 宿主 `ui_*` ——
\ `CR` (newline), `EMIT` (print one character). It touches neither Crt / graphics / the host `ui_*` ——
\ 所以它在任何后端上都是同一份行为,也是四份 demo 里唯一有"逐字节确定性输出"
\ so its behavior is the same on every backend, and it is the only one of the four demos with a "byte-for-byte deterministic output"
\ 判据的一份。
\ criterion.
\
\ 跑法(桌面 vmlcli):
\ dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll Examples/forth/demo_std.fth
\
\ 期望输出(逐字节):
\ Expected output (byte-for-byte; each line below is printed in Chinese and the line under it is its translation):
\ === Forth 标准输出 demo ===
\ === Forth std output demo ===
\ 字符串: 你好,世界
\ String: hello, world
\ 整数: 42
\ Integer: 42
\ 计算: 7 * 6 = 42
\ Computed: 7 * 6 = 42
\ 整除: 17 5 / = 3
\ Integer division: 17 5 / = 3
\ 循环求和: 1..10 = 55
\ Loop sum: 1..10 = 55
\ 阶乘: 10! = 3628800
\ Factorial: 10! = 3628800
\ === done ===
\
\ ◆ 三条本前端的写法要求(都是实测出来的)
\ ◆ Three writing requirements of this frontend (all measured in practice)
\
\ ① **栈是唯一的参数通道**:`17 5 /` 把 17、5 先后压栈再除。`.` 会吃掉栈顶,
\ ① **The stack is the only parameter channel**: `17 5 /` pushes 17 and 5 and then divides. `.` eats the top of the stack,
\ 所以一行里**只能有一个 `.`** —— 要打两个数就分两行(或 `SWAP`)。
\ so there can be **only one `.` per line** —— to print two numbers, use two lines (or `SWAP`).
\
\ ② 循环用 `DO … LOOP`,循环变量是 `I`:
\ ② Loops use `DO … LOOP`, and the loop variable is `I`:
\ `0 11 1 DO I + LOOP` 从 1 加到 10(Forth 的 `DO` 上限**不含**)
\ `0 11 1 DO I + LOOP` sums from 1 to 10 (Forth's `DO` upper bound is **exclusive**)
\ 写成词定义更清楚:`: SUM10 0 11 1 DO I + LOOP ;` 然后 `SUM10 .`
\ written as a word definition it is clearer: `: SUM10 0 11 1 DO I + LOOP ;` then `SUM10 .`
\
\ ③ ~~⚠ **本前端的 `MOD` 是坏的:它编成了加法**(实测)。~~
\ ③ ~~⚠ **This frontend's `MOD` is broken: it compiles into addition** (measured).~~
\ ✅ **已修好(2026-10-04 复验)**:`10 3 MOD` ⇒ **1**(旧记 13)、`100 7 MOD` ⇒ **2**(旧记 107)。
\ ✅ **Fixed (re-verified 2026-10-04)**: `10 3 MOD` => **1** (previously recorded as 13), `100 7 MOD` => **2** (previously recorded as 107).
\ (当年的根因:`CodeGenerator.Operations.cs` 把 `TokenType.MOD` 映射成字符串 `"MOD"`,
\ (Root cause at the time: `CodeGenerator.Operations.cs` mapped `TokenType.MOD` to the string `"MOD"`,
\ 而基类 `GetArithmeticInstruction(op, type)` 那张表只认 `"%"` ⇒ 落到 `_ => OpCode.ADD`,汇编里就是 `add`。)
\ while the base class's `GetArithmeticInstruction(op, type)` table only recognized `"%"` ⇒ it fell through to `_ => OpCode.ADD`, i.e. a plain `add` in the assembly.)
\ ⇒ 本文件仍照旧**一次取模都没有**(写法无害);新写的代码不必再绕,直接用 `MOD` 即可。
\ ⇒ This file still takes **not one modulus** as before (harmless); new code need not work around it — just use `MOD`.
\
\ ◆ ~~顺带记一条同样是实测的边界:**多参数词不可靠**。~~
\ ◆ ~~One more measured boundary, noted in passing: **multi-parameter words are unreliable**.~~
\ ✅ **已修好(2026-10-04 复验)**:`: ADD2 ( a b -- c ) + ; 5 7 ADD2 .` ⇒ **12**(旧记 7);
\ ✅ **Fixed (re-verified 2026-10-04)**: `: ADD2 ( a b -- c ) + ; 5 7 ADD2 .` => **12** (previously recorded as 7);
\ `100 ui_math_rand .` 也真的打出 0..100 的随机数(实测 **97**,旧记"把实参原样吐回 100")。
\ and `100 ui_math_rand .` really prints a random number in 0..100 (measured **97**; previously recorded as echoing the argument back as 100).
\ (当年根因:用户词调用把返回地址 `R15` 压在数据栈上、插在实参中间,参数多于一个就串位。)
\ (Root cause at the time: the user-word call pushed the return address `R15` onto the data stack between the
\ arguments, so more than one parameter went out of step.)
\ 本文件里所有词仍然是零参/一参(写法无害);新写的代码不必再受这条限制。
\ Every word in this file still takes zero or one parameter (harmless); new code need not obey this limit.
\ 界面语言:0 = 中文 / 1 = 英文(ui_scr_get_language 是 syscall,开局查一次存进 LANG)
\ UI language: 0 = Chinese / 1 = English (ui_scr_get_language is a syscall: query it once at startup into LANG)
VARIABLE LANG
ui_scr_get_language LANG !
LANG @ 0= IF ." === Forth 标准输出 demo ===" ELSE ." === Forth std output demo ===" THEN CR
\ ① 字符串字面量(含中文 —— 源码按 UTF-8 存)
\ ① string literals (including Chinese —— the source is stored as UTF-8)
LANG @ 0= IF ." 字符串: 你好,世界" ELSE ." String: hello, world" THEN CR
\ ② 整数
\ ② integer
LANG @ 0= IF ." 整数: " ELSE ." Integer: " THEN 42 . CR
\ ③ 整数运算
\ ③ integer arithmetic
LANG @ 0= IF ." 计算: 7 * 6 = " ELSE ." Computed: 7 * 6 = " THEN 7 6 * . CR
\ ④ 整除
\ ④ integer division
LANG @ 0= IF ." 整除: 17 5 / = " ELSE ." Integer division: 17 5 / = " THEN 17 5 / . CR
\ ⑤ 循环求和 1..10(词定义里做,返回值落在栈上)
\ ⑤ loop sum 1..10 (done inside a word definition; the return value lands on the stack)
: SUM10 ( -- n ) 0 11 1 DO I + LOOP ;
LANG @ 0= IF ." 循环求和: 1..10 = " ELSE ." Loop sum: 1..10 = " THEN SUM10 . CR
\ ⑥ 循环求阶乘 10!
\ ⑥ loop factorial 10!
: FAC10 ( -- n ) 1 11 1 DO I * LOOP ;
LANG @ 0= IF ." 阶乘: 10! = " ELSE ." Factorial: 10! = " THEN FAC10 . CR
." === done ===" CR