← 都来码 / Dolaima← 例程索引javascript/demo/demo_std.js原文

javascript/demo/demo_std.js · 9089 字节 · 下载原文

// demo_std.js —— **第 1 层:标准输入输出**(JavaScript 的 console.log)

// demo_std.js -- **layer 1: standard output** (JavaScript's console.log)

//

// 这一层就是语言自己的标准输出:往 stdout 写文本。

// This layer is just the language's own standard output: writing text to stdout.

// 也是最基础的一层,也是**唯一有逐字节确定性判据**的一层 —— 下面的输出

// It is also the most basic layer, and the **only one with a byte-for-byte deterministic criterion** -- the output below

// 跑两遍完全一样(不读输入、不用随机数、不看时间)。

// is identical on two runs (it reads no input, uses no random numbers and looks at no clock).

//

// ## 判据

// ## The criterion

//

//     vmlcli Examples/javascript/demo_std.js

//

// 期望 stdout 逐字节等于本文件末尾「期望输出」那段。

// The expected stdout is byte-for-byte equal to the "expected output" block at the end of this file.

//

// ## ⚠ 本前端实测的三条限制(写 demo 时避开)

// ## ⚠ Three measured limitations of this frontend (avoid them when writing a demo)

//

//   · ~~**字符串 + 数字编出来的结果是错的**~~ —— ✅ **已修(v0.96.831,清单 BUG-04)**:

//     现在 `"a=" + a` 真的拼出 `a=17`(字符串拼接走 `js_string_concat`)。

//   · ~~**String + number compiles to a wrong result**~~ -- ✅ **fixed (v0.96.831, list item BUG-04)**:

//     `"a=" + a` now really yields `a=17` (concatenation goes through `js_string_concat`).

//   · (以下是**修复前**的旧记录,留着备查)**字符串 + 数字编出来的结果是错的** —— `console.log("a=" + a)` 打出

//   · **String + number compiles to a wrong result** -- `console.log("a=" + a)` prints

//     `2109`(地址量级的值),`console.log("line " + i)` 打出 `1059/1060/1061`。

//     `2109` (an address-sized value), and `console.log("line " + i)` prints `1059/1060/1061`.

//     所以本 demo **一个 `"..." + n` 都不用**,靠 `console.log` 的**多实参**

//     So this demo uses **not a single `"..." + n`**, relying instead on the **multiple arguments** of `console.log`

//     (`console.log("a=", a)` → `a=17`,数字实参本身是对的)。

//     (`console.log("a=", a)` -> `a=17`; the numeric argument itself is correct).

//   · `console.log` **不插分隔符**:`console.log("line", i)` 打出 `line0`。

//   · `console.log` **inserts no separator**: `console.log("line", i)` prints `line0`.

//   · **没有 `String(n)` / `n.toString()`**(两个都报「未定义的函数」),

//   · **There is no `String(n)` / `n.toString()`** (both report "undefined function"),

//     而 `int_to_str(n)` 恒返回 `0`(实测)⇒ 数字转字符串这条路是断的。

//     and `int_to_str(n)` always returns `0` (measured) => the number-to-string path is broken.

//     彩色控制台那一层因此改用**字面量光标坐标**,见 demo_tty.js。

//     The color console layer therefore uses **literal cursor coordinates**, see demo_tty.js.

//   ⚠ **2026-10-04 复验仍成立**:三条都还在 —— `console.log("a=" + a)` 打出 `1721`(地址量级),`console.log("line " + i)` 打出 `1712`;

//   ⚠ **still holds on 2026-10-04**: all three remain -- `console.log("a=" + a)` prints `1721` (address-sized value), `console.log("line " + i)` prints `1712`;

//     `console.log("line", 3)` 打出 `line3`(不插分隔符);`String(5)` / `a.toString()` 都报「未定义的函数」;

//     `console.log("line", 3)` prints `line3` (no separator); `String(5)` / `a.toString()` both report 「undefined function」;

//     `int_to_str(123)` 仍不可用(`console.log` 打出地址 `1721`,trace-draw 里该串画成 `str="0"`)。

//     `int_to_str(123)` is still unusable (`console.log` prints the address `1721`; in trace-draw the string draws as `str="0"`).

//

// ## 外部函数:~~必须显式声明~~ —— ✅ **2026-10-04 复验:库函数不声明也能解析;不认识的函数名改报编译错误**

// ## External functions: ~~must be declared explicitly~~ -- ✅ **re-checked 2026-10-04: library functions resolve without a declaration, and an unknown function name is now a compile error**

//

// ~~对不认识的函数名,本前端会先找 `func_<名>`、都没有就**把名字当变量**、~~

// ~~For an unknown function name this frontend first looks for `func_<name>`, and if that is missing it **treats the name as a variable**,~~

// ~~编成「MOVE R1, var_<名>;CALL R0」⇒ 运行期跳野地址。~~(那是**旧行为**,✅ **已修好**:现在直接编译失败)

// ~~compiling "MOVE R1, var_<name>; CALL R0" => a wild jump at run time.~~ (that was the **old behaviour**, ✅ **fixed**: it is now a compile error)

//   实测:不认识的函数名 `noSuchFunc(3)` → `error: 未定义的函数 'noSuchFunc'`;

//   measured: an unknown function name `noSuchFunc(3)` -> `error: undefined function 'noSuchFunc'`;

//   而**库函数不用声明也能解析** —— 把本文件的 `#include "vml_ui.js"` 从 /tmp 副本删掉,`✔ 编译完成` 且照常跑完(`ui_scr_get_language()` 取到真值)。

//   while **library functions resolve without a declaration** -- delete `#include "vml_ui.js"` from a /tmp copy and it still `✔ compiles` and runs to completion (`ui_scr_get_language()` returns the real value).

//   (所以那条 `#include` 是**显式引用**、不是强制项 —— 本文件**照旧**留着它,能跑就别动。)

//   (so that `#include` is an **explicit reference**, not a mandatory item -- this file **keeps** it anyway; if it runs, leave it alone.)

// `console.log` 是前端内建的,不用声明。

// `console.log` is built into the frontend, so it needs no declaration.


// UI 库声明走显式引用(文件由 GenLib 产出),不再手抄原型。

// UI declarations come from an explicit include (file generated by GenLib), not hand-copied prototypes.

#include "vml_ui.js"

// 界面语言:开局查一次(`ui_scr_get_language` 是 syscall,别每处都调)

// UI language: queried once at start (`ui_scr_get_language` is a syscall, do not call it everywhere)

let lang = ui_scr_get_language();

const A = 17;
const B = 25;

console.log("=== demo_std (JavaScript) ===");
// ⚠ 这里用**单行 `if/else`** 而不是三元 —— `console.log` 对**非字面量**实参一律编成

// ⚠ A **one-line `if/else`** is used here instead of a ternary -- `console.log` compiles a **non-literal** argument

//   `print_int`(实测:`console.log(cond ? "a" : "b")` 打出的是字符串地址,不是文字),

//   to `print_int` (measured: `console.log(cond ? "a" : "b")` prints the string address, not the text),

//   只有**字面量**实参才走字符串输出。三元的写法留给 `print_str` / `println` / `ui_*`。

//   and only a **literal** argument goes down the string path. The ternary is left to `print_str` / `println` / `ui_*`.

if (lang == 0) { console.log("纯字符串一行"); } else { console.log("A plain string line"); }
if (lang == 0) { console.log("转义:制表\t反斜杠\\引号\""); } else { console.log("escapes: tab\tbackslash\\quote\""); }

console.log("a=", A, " b=", B);
console.log("a+b=", A + B, " a-b=", A - B, " a*b=", A * B);
console.log("a/b=", A / B, " a%b=", A % B);
if (lang == 0) { console.log("负数: ", 0 - A, " ", 0 - (A * B)); } else { console.log("negatives: ", 0 - A, " ", 0 - (A * B)); }

// 循环算一个结果,证明这一层和语言本身是通的

// Compute one result in a loop, proving this layer and the language itself are wired up

let i = 1;
let total = 0;
while (i <= 10) {
    total = total + i * i;
    i = i + 1;
}
console.log("1^2+...+10^2 = ", total);

// 九九表的一小段(多行)

// A short stretch of the multiplication table (several lines)

i = 1;
while (i <= 5) {
    console.log(i, " x 7 = ", i * 7);
    i = i + 1;
}

if (lang == 0) { console.log("=== 完成 ==="); } else { console.log("=== done ==="); }

// ── 期望输出(逐字节)────────────────────────────────────────────

// -- Expected output (byte-for-byte; each line below is printed in Chinese, and the line under it is its translation) --

// === demo_std (JavaScript) ===

// 纯字符串一行

// A plain string line

// 转义:制表	反斜杠\引号"

// Escapes: tab\tbackslash\\quote"

// a=17 b=25

// a+b=42 a-b=-8 a*b=425

// a/b=0.68 a%b=17

// 负数: -17 -425

// Negative numbers: -17 -425

// 1^2+...+10^2 = 385

// 1 x 7 = 7

// 2 x 7 = 14

// 3 x 7 = 21

// 4 x 7 = 28

// 5 x 7 = 35

// === 完成 ===

// === Done ===

// ────────────────────────────────────────────────────────────────