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

dart/demo/demo_std.dart · 9961 字节 · 下载原文

// demo_std.dart —— **第 1 层:标准输入输出**(Dart 的 `print`)

// demo_std.dart — **Layer 1: standard input/output** (Dart's `print`)

//

// 这一层是每门语言自己的"往标准输出写文本"。

// This layer is each language's own way of "writing text to stdout".

//

// ## ⚠ 写之前先量过:Dart 前端的 `+` **字符串拼接不可用**

// ## ⚠ Measured before writing: the Dart frontend's `+` **cannot concatenate strings**

//

// 实测(2026-09-24,`vmlcli Examples/dart/demo_std.dart`):

// Measured (2026-09-24, `vmlcli Examples/dart/demo_std.dart`):

//

//     print("num=" + n.toString() + "\n");   →  未定义的函数 'func__dot_toString'

//     print("num=" + n.toString() + "\n");   →  undefined function 'func__dot_toString'

//     print("num=" + n + "\n");              →  编得过,打出的是数字/乱码,不是那句话

//     print("num=" + n + "\n");              →  compiles, but prints a number/garbage, not that sentence

//

// 而**单实参**的调用全部正常:

// while **single-argument** calls are all fine:

//

//     print("纯字面量\n")   ✔      print(42)   ✔      print(someIntVar)   ✔

//     print("a plain literal\n")   ✔      print(42)   ✔      print(someIntVar)   ✔

//

// ⚠ **`print` 自带换行**(Dart 语义;本前端 v0.96.847 起实现正确)⇒「标签 + 值」要落在同一行时

// ⚠ **`print` appends its own newline** (Dart semantics; correct in this frontend since v0.96.847) ⇒ when a label

//   必须用**库函数** `print_str` / `print_int` / `println_int`(都不带换行)。本 demo 照此写,

//   and its value must share a line, use the **library** functions `print_str` / `print_int` / `println_int` (no newline).

//   `print` 只用在本来就该独占一行的地方。

//   `print` is used only where the line is its own.

// 也不用 `.toString()`。这不是风格选择,是绕开上面那条。

// and never using `.toString()`. That is not a style choice, it is how the above is worked around.

//

// ## ⚠ 转义序列也只认 `\n`

// ## ⚠ Only `\n` is recognized among escape sequences

//

// `print("\x1b[31m")` 会原样打出 `x1b[31m`(六个字符,不是 ESC)。要发 ESC 只能

// `print("\x1b[31m")` prints `x1b[31m` literally (six characters, not ESC). To emit ESC you can only

// `putchar(27)`(见 `demo_tty.dart`)。本 demo 只用 `\n`。

// use `putchar(27)` (see `demo_tty.dart`). This demo uses only `\n`.

//

// ## 判据

// ## Criteria

//

//     vmlcli Examples/dart/demo_std.dart

//

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

// Expects stdout to equal the "expected output" block at the end of the file, byte for byte.


// 调库函数的声明**由下面那一行 `import 'vml_ui.dart';` 提供**(2026-10-01 起)——

// Declarations for the library calls **come from the `import 'vml_ui.dart';` line below** (since 2026-10-01) —

// 那是 `tools/GenLib` 产出的声明文件,**不要手写**;本文件里**不再手抄 `external` 块**。

// that file is generated by `tools/GenLib` and **must not be hand-edited**; no hand-copied `external` block here any more.

// ⚠ **实测:把 `import` 删掉也照样编得过、跑得对**(链接器会把 `func_print_str` 之类剥前缀兜底)

// ⚠ **Measured: deleting the `import` still compiles and runs** (the linker strips the `func_` prefix as a fallback)

// ⇒ 它是「**文档级**」的显式引用,不是强制门;理由与判据见 `docs/UI库导入约定.md` §九。

// ⇒ it is a **documentation-level** explicit reference, not an enforced gate.

//   The doc that pins this is the repo note on explicit UI imports, section 9.

// `println_str` / `print_str` / `println_int` 由 `Lib/shared/io.vml` 提供,

// `println_str` / `print_str` / `println_int` are provided by `Lib/shared/io.vml`,

// 经 `builtins.vml`(`vmltool.config.xml` 的 `DefaultLibs`)进每一门语言的链接。

// They enter every language's link through `builtins.vml` (`DefaultLibs` in `vmltool.config.xml`).


#include "../../../Lib/dart/vml_ui.dart"
import 'vml_ui.dart';   // UI / base library declarations (generated by GenLib, do not hand-edit)


// 纯函数(不碰任何可变全局状态)—— 这几个是好的

// pure functions (touching no mutable global state) — these few are fine

int square(int v) {
  return v * v;
}

int fib(int n) {
  if (n < 2) {
    return n;
  }
  return fib(n - 1) + fib(n - 2);
}

String digitName(int d) {
  if (d == 0) { return "zero"; }
  if (d == 1) { return "one"; }
  if (d == 2) { return "two"; }
  return "many";
}

void main() {
  int a = 17;
  int b = 25;
  int i = 0;
  int sum = 0;

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

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

  int lang = ui_scr_get_language();

  // ── 1. 字符串 ──

  // ── 1. Strings ──

  print_str("=== demo_std (Dart) ===\n");
  // ⚠ **`print` 自带换行**(Dart 语义:先 `toString()` 再补一个 `\n`;本前端 v0.96.847 起实现正确)。

  //    所以「标签 + 值要落在同一行」的地方一律用库函数 —— `print_str` / `print_int` / `println_int`

  //    都**不带**换行;`print` 只用在本来就该独占一行的地方,下面这行就是:

  print("this line comes from print() and carries its own newline");
  // ⚠ 分支过的字符串**不是字面量** ⇒ 必须走 `print_str`(本前端 `print(非字面量)` 打的是指针,见文件头)

  // ⚠ A branched string is **not a literal** => it must go through `print_str` (this frontend's `print(non-literal)` prints a pointer, see the file header)

  print_str(lang == 0 ? "纯字面量一行\n" : "a plain literal, one line\n");

  // ── 2. 标签 + 值 分开写(⚠ 不用 `+`,见文件头)──

  // ── 2. Label + value written separately (⚠ don't use `+`, see the file header) ──

  print_str("a=");       println_int(a);
  print_str("b=");       println_int(b);
  print_str("a+b=");     println_int(a + b);
  print_str("a-b=");     println_int(a - b);
  print_str("a*b=");     println_int(a * b);
  print_str("a/b=");     println_int(a ~/ b);      // 整除写 ~/

  // integer division is written ~/

  print_str("a%b=");     println_int(a % b);
  print_str(lang == 0 ? "负数:" : "Negative: "); println_int(0 - a);

  // ── 3. 进制与宽度 ──

  // ── 3. Number bases and widths ──

  print_str(lang == 0 ? "十进制=" : "Decimal=");   println_int(255);
  print_str(lang == 0 ? "十六进制=" : "Hex="); println_int(255);

  // ── 4. 函数调用(含递归)──

  // ── 4. Function calls (including recursion) ──

  print_str("square(9)="); println_int(square(9));
  print_str("fib(10)=");   println_int(fib(10));
  // ⚠ 这里**必须用 `print_str`(库函数),不能用 `print`**:

  // ⚠ Here you **must use `print_str` (the library function), not `print`**:

  //   `print(<返回 String 的调用>)` 打出来的是**指针**(实测 `1024 1029 1033 1037`),

  //   `print(<a call returning String>)` prints a **pointer** (measured `1024 1029 1033 1037`),

  //   只有 `print("字面量")` 和 `print(局部 String 变量)` 才是真的打字符串。

  //   only `print("literal")` and `print(a local String variable)` really print the string.

  print_str("digitName: ");
  print_str(digitName(0)); print_str(" ");
  print_str(digitName(1)); print_str(" ");
  print_str(digitName(2)); print_str(" ");
  // 收尾换行用库里的 println_str —— Dart 的 print 打换行时会多带一个回车符

  // Use the library's println_str for the trailing newline — Dart's print carries an extra carriage return when printing a newline

  println_str(digitName(9));

  // ── 5. 数组 + 循环 ──

  // ── 5. Arrays + loops ──

  //   ⚠ 数组**留在 main 里**:文件级可变状态在 Dart / Kotlin / Swift / Go 那几门上都出过

  //   ⚠ Arrays **stay inside main**: file-level mutable state has gone wrong on Dart / Kotlin / Swift / Go

  //     问题(最典型是 Kotlin 的文件级 `arrayOf` 读回 0),这里不冒这个险。

  //     (most typically Kotlin's file-level `arrayOf` reading back 0), and this doesn't take that risk.

  List<int> v = [1, 4, 9, 16, 25, 36];
  while (i < 6) {
    sum = sum + v[i];
    i = i + 1;
  }
  print_str("1^2+...+6^2 = "); println_int(sum);

  // ── 6. 九九表的一小段 ──

  // ── 6. A small slice of the multiplication table ──

  i = 1;
  while (i <= 5) {
    print_int(i);            // `print_int` 也不带换行(`print` 会独占一行)

    print_str(" x 7 = ");
    println_int(i * 7);
    i = i + 1;
  }

  print_str(lang == 0 ? "=== 完成 ===\n" : "=== done ===\n");
}

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

// === demo_std (Dart) ===

// this line comes from print() and carries its own newline

// 纯字面量一行

// A plain literal, one line

// a=17

// b=25

// a+b=42

// a-b=-8

// a*b=425

// a/b=0

// a%b=17

// 负数:-17

// Negative: -17

// 十进制=255

// Decimal=255

// 十六进制=255

// Hex=255

// square(9)=81

// fib(10)=55

// digitName: zero one two many

// 1^2+...+6^2 = 91

// 1 x 7 = 7

// 2 x 7 = 14

// 3 x 7 = 21

// 4 x 7 = 28

// 5 x 7 = 35

// === 完成 ===

// === done ===

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