! demo_std.f90 —— Fortran 第一层：**标准输入输出**（std）
! demo_std.f90 -- Fortran layer one: **standard output** (std)
!
! 这一层只用 Fortran 自己的 `print`，不碰 Crt / 图形 / 宿主 `ui_*` ——
! This layer uses only Fortran's own `print`, touching neither Crt / graphics / the host `ui_*` --
! 所以它在任何后端上都是同一份行为，也是四份 demo 里唯一有"逐字节确定性输出"
! so its behavior is identical on every backend, and it is the only one of the four demos with a
! 判据的一份（另外几份只能验"编得过、跑得完、不挂死"）。
! "byte-for-byte deterministic output" criterion (the others can only verify "it compiles, it finishes, it does not hang").
!
! 跑法（桌面 vmlcli）：
! How to run (desktop vmlcli):
!   dotnet scripts/vmlcli/bin/Release/net10.0/vmlcli.dll Examples/fortran/demo_std.f90
!
! 期望输出（逐字节）：
! Expected output (byte-for-byte; each line below is printed in Chinese and the line under it is its translation):
!   === Fortran 标准输出 demo ===
!   === Fortran std output demo ===
!   字符串: 你好，世界
!   String: hello, world
!   整数: 42
!   Integer: 42
!   计算: 7 * 6 = 42
!   Computed: 7 * 6 = 42
!   整除: 17 / 5 = 3
!   Integer division: 17 / 5 = 3
!   取余: mod(17,5) = 2
!   Remainder: mod(17,5) = 2
!   循环求和: 1..10 = 55
!   Loop sum: 1..10 = 55
!   阶乘: 10! = 3628800
!   Factorial: 10! = 3628800
!   实数: 2.5 * 4.0 = 10
!   Real: 2.5 * 4.0 = 10
!   === done ===
!
! ◆ 一条**已修**的缺陷，留在这儿备查（本文件现在敢直接打浮点了，就是因为它修好了）
! ◆ One **already fixed** defect, kept here for reference (this file now dares to print floats directly because it was fixed)
!   （2026-10-04 复验仍成立：`print *, 2.5` ⇒ `2.5`、`print *, 2.5 * 4.0` ⇒ `10`。）
!   （Re-verified 2026-10-04, still holds: `print *, 2.5` => `2.5`, `print *, 2.5 * 4.0` => `10`.）
!
!     以前：`print *, 2.5` ⇒ `1075838976`、`print *, x * 4.0` ⇒ `1092616192`
!     Before: `print *, 2.5` => `1075838976`, `print *, x * 4.0` => `1092616192`
!     （1075838976 = 0x40200000 = 2.5f 的位模式、1092616192 = 0x41200000 = 10.0f 的）
!     (1075838976 = 0x40200000 = the bit pattern of 2.5f, 1092616192 = 0x41200000 = that of 10.0f)
!     —— 值算对了，只是 `print` 一律走**整数格式**那条路。
!     -- the value was computed correctly, but `print` always took the **integer format** path.
!
!     真身：`CompilerBase/CodeGeneratorBase.EmitPrintArgs` 只把 `isArgString` 转给
!     Root cause: `CompilerBase/CodeGeneratorBase.EmitPrintArgs` passed only `isArgString` on to
!     `EmitPrintArg`，**`isFloat` 走的是默认值 `false`** ⇒ 每个实参都 `CALL print_int`。
!     `EmitPrintArg`, and **`isFloat` took its default value `false`** => every argument did `CALL print_int`.
!     修法：给 `EmitPrintArgs` 追加了一个可选参数 `isArgFloat`（追加在末尾，
!     Fix: an optional parameter `isArgFloat` was appended to `EmitPrintArgs` (appended at the end,
!     老调用点的位置参数一个都不用动），Fortran 的 `GeneratePrint` 用现成的
!     so no positional argument at the old call sites has to change), and Fortran's `GeneratePrint` passes it in
!     `GetExprType(...) == F32/F64` 传进去。判据：`print *, 2.5` ⇒ `2.5`、
!     using the ready-made `GetExprType(...) == F32/F64`. Criterion: `print *, 2.5` => `2.5`,
!     `print *, x * 4.0`（`x=2.5`）⇒ `10`。
!
! ◆ ~~⚠ **仍未修**：`double precision` 的 **`d0` 后缀字面量恒为 0**~~
! ◆ ~~⚠ **Still not fixed**: for `double precision`, a **literal with the `d0` suffix is always 0**~~
!   ✅ **已修好（2026-10-04 复验）**：`double precision :: d` 下
!   ✅ **Fixed （re-verified 2026-10-04）**: with `double precision :: d`,
!     `print *, 1.25d0` ⇒ **1.25**（旧记 0）、`d = 9.5d0` / `print *, d` ⇒ **9.5**（旧记 0）。
!     `print *, 1.25d0` => **1.25** （previously 0）, `d = 9.5d0` / `print *, d` => **9.5** （previously 0）.
!     （而 `d = 1.25` 不带后缀 ⇒ 1.25 —— 这条路一直是对的。）
!     （and `d = 1.25` with no suffix => 1.25 — that route was always fine.）
!
!   ⇒ 本文件仍照旧**一个 `d0` 字面量都没有**，但那只是写法，不再是必需 ——
!   => This file still contains **not a single `d0` literal**, but that is now just a style choice, not a requirement —
!     新写的代码直接用 `1.25d0` 即可（不带后缀的十进制字面量当然还是好的）。
!     new code can simply write `1.25d0` （a suffix-less decimal literal still works too）.
!
! ◆ 三条本前端的写法要求（都是实测出来的，不是风格偏好）
! ◆ Three style requirements of this frontend (all measured, not style preferences)
!
!   ① **每条语句顶格写不受限，但 `print` 的输出格式是"列表式"** —— 每个实参之间
!   ① **Statements may start at column one without restriction, but `print`'s output format is "list-directed"** -- between each argument
!      由运行时自己补分隔（本平台是空格），所以 `print *, 'a', 'b'` 打出 `a b`。
!      the runtime inserts its own separator (a space on this platform), so `print *, 'a', 'b'` prints `a b`.
!      要紧凑就**拼进同一个字符串字面量**。
!      For a compact result, **put it all into one string literal**.
!
!   ② **整数 `/` 是整除**（Fortran 的语义本来就如此）：`17 / 5` = 3。
!   ② **Integer `/` is integer division** (that is Fortran's semantics anyway): `17 / 5` = 3.
!      取余用内建的 `mod(a, b)` —— 前端把它编成 VML 的原生 `MOD` 指令，
!      Use the built-in `mod(a, b)` for the remainder -- the frontend compiles it to VML's native `MOD` instruction
!      不走库调用（否则会去链一个不存在的 `func_mod`，实测炸过）。
!      instead of a library call (otherwise it links a nonexistent `func_mod`, which crashed in testing).
!
!   ③ `call xxx(...)` 与 `k = xxx(...)` **不是同一件事**：
!   ③ `call xxx(...)` and `k = xxx(...)` **are not the same thing**:
!      · `call putchar(27)` 编成 `CALL putchar`（裸名，找得到库里的实现）
!      · `call putchar(27)` compiles to `CALL putchar` (the bare name, which finds the library implementation)
!      · 但 `call ui_2d_rect(...)` 会编成 `CALL sub_ui_rect`，而**链接器只剥
!      · but `call ui_2d_rect(...)` compiles to `CALL sub_ui_rect`, and **the linker strips only
!        `func_`/`word_`/`method_`/`var_` 四种前缀，不含 `sub_`** ⇒ 碰不到 UI 库。
!        the four prefixes `func_`/`word_`/`method_`/`var_`, not `sub_`** => it never reaches the UI library.
!      所以调库函数一律写成**函数调用表达式**：`k = ui_2d_rect(...)`（编成 `func_ui_rect`）。
!      So library functions are always written as a **function-call expression**: `k = ui_2d_rect(...)` (compiles to `func_ui_rect`).
!      本文件不涉及，但 `demo_ui.f90` 全靠这一条。
!      This file is not affected, but `demo_ui.f90` depends entirely on this rule.

program demo_std
  implicit none
  integer :: i
  integer :: sum
  integer :: fact
  integer :: lang

  ! 界面语言：0 = 中文 / 1 = 英文（ui_scr_get_language 是 syscall，开局查一次）
  ! UI language: 0 = Chinese / 1 = English (ui_scr_get_language is a syscall, queried once at startup)
  lang = ui_scr_get_language()

  if (lang == 0) print *, '=== Fortran 标准输出 demo ==='
  if (lang /= 0) print *, '=== Fortran std output demo ==='

  ! ① 字符串字面量（含中文 —— 源码按 UTF-8 存，词法器直通）
  ! ① String literal (contains Chinese -- the source is stored as UTF-8 and the lexer passes it through)
  if (lang == 0) print *, '字符串: 你好，世界'
  if (lang /= 0) print *, 'String: hello, world'

  ! ② 整数
  ! ② Integer
  if (lang == 0) print *, '整数: 42'
  if (lang /= 0) print *, 'Integer: 42'

  ! ③ 整数运算
  ! ③ Integer arithmetic
  if (lang == 0) print *, '计算: 7 * 6 = 42'
  if (lang /= 0) print *, 'Computed: 7 * 6 = 42'

  ! ④ 整数除法与取余（`/` 整除；取余用内建 `mod`）
  ! ④ Integer division and remainder (`/` is integer division; the remainder uses the built-in `mod`)
  if (lang == 0) print *, '整除: 17 / 5 = 3'
  if (lang /= 0) print *, 'Integer division: 17 / 5 = 3'
  if (lang == 0) print *, '取余: mod(17,5) = 2'
  if (lang /= 0) print *, 'Remainder: mod(17,5) = 2'

  ! ⑤ 用变量真算一遍 —— 上面几行是字面量，这几行让编译器真的去算
  ! ⑤ Actually compute it with variables -- the lines above are literals, these make the compiler really compute
  sum = 0
  do i = 1, 10
    sum = sum + i
  end do
  if (lang == 0) print *, '循环求和: 1..10 =', sum
  if (lang /= 0) print *, 'Loop sum: 1..10 =', sum

  fact = 1
  do i = 1, 10
    fact = fact * i
  end do
  if (lang == 0) print *, '阶乘: 10! =', fact
  if (lang /= 0) print *, 'Factorial: 10! =', fact

  ! ⑥ 实数：`print` 现在能正确打浮点了（见文件头那条"已修"）
  ! ⑥ Reals: `print` can now print floats correctly (see the "already fixed" item in the file header)
  if (lang == 0) print *, '实数: 2.5 * 4.0 =', 2.5 * 4.0
  if (lang /= 0) print *, 'Real: 2.5 * 4.0 =', 2.5 * 4.0

  print *, '=== done ==='
end program demo_std
