# Ada

«bold»静态强类型«/»，骨架像 Pascal 但语法独立（`is … begin … end`、`procedure` / `function`、`loop … exit when`、«bold»一基数组«/»）。

「完整运算 + 控制流 + 函数调用」三件齐备，能写一般小程序；引 `with VML_UI;` 之后 `ui_*` 与 `VML_*` 常量直接可用。

## 在手机上怎么跑

```
vml run examples/ada/fizzbuzz.adb
```

编译要等一会儿（C 那种要一两分钟，脚本类语言几秒）。程序跑起来后**屏幕底部就是手柄**，
方向键 + 四个动作键都在；点右上角返回可以回到命令行。

## 写法要点

- `with Ada.Text_IO; use Ada.Text_IO;` 之后用 `Put_Line` / `Put` / `New_Line` 输出（绑到本平台的打印库，«bold»不需要 Ada 工具链«/»）
- 要画图 / 收输入就写一行 `with VML_UI;`，然后直接调 `ui_*` 与 `VML_*` 常量（`Lib/ada/vml_ui.adb` 里登记了 183 个函数名与 175 个常量）
- «bold»数组下标是一基的«/»：`A(1)` 是第一个元素
- 数值转字符串用 `Integer'Image(X)` / `Float'Image(X)`，字符串并置用 `&`

## 示例

| 文件 | 演示什么 |
|---|---|
| `fizzbuzz.adb` | FizzBuzz（`for` + `if/elsif/else` + `mod`） |
| `hello.adb` | 最小程序（声明区 + `Put_Line` + 字符串并置） |
| `primes.adb` | 素数筛（一基数组 + `function` / `procedure`） |

## 实测踩过的坑

- ⚠ «bold»`mod` 与 `rem` 落到同一条 `MOD` 指令«/» —— «bold»负数上的语义不承诺«/»（正数上两者一致）。
- ⚠ 数组«bold»只支持一维«/»；写多维下标会«bold»报错«/»（不是静默算错）。
- ⚠ «bold»`declare` 块没有块作用域«/»：声明就地提升，同名跨块会互相覆盖。
- `Float` 是 «bold»32 位«/»（走 `mathf` 一族）；没有 `Long_Float`（64 位双精度）的完整支持。
- «bold»记录 / 变体记录 / 泛型 / 异常 / 任务 / 包（真语义）/ 访问类型«/»未实现（`package body` 只做宽容跳过）；`case` 语句与 `goto` 也明确不做。
- 字符串是«bold»指针语义«/»：`S := "xy"` 是«bold»换指向«/»，不是就地改写。

---

下面的内容是**从 VML 源码里直接带的**（`third_party/vml/VMLPrepares/AdaCompiler/`）：
`README` 讲这个前端支持什么、怎么编；`语言规范` 讲语法本身。
上游一改，这里重新生成就是最新的。

## 语言规范

### Ada 子集语言规范

> 本文件描述的是«bold»本前端实际接受的语法子集«/»，不是 Ada 2012 标准。
> 判据是 `scripts/vml-ada-probe/run.sh`（14 条用例，全部要能红）。

> «bold»版本«/»：v1.0 | «bold»日期«/»：2026-10-13 | «bold»修订者«/»：深圳市探索智能科技有限公司

#### 规范标准

| 字段 | 值 |
|:-----|:----|
| «bold»目标标准«/» | Ada 83/95 子集 |
| «bold»发布年份«/» | 1983 |
| «bold»完成度«/» | 子集（未逐项统计） |
| «bold»测试«/» | 14 通过 / 0 失败 |

#### 关键字

`procedure` `function` `is` `begin` `end` `if` `then` `elsif` `else` `while`
`loop` `for` `in` `reverse` `return` `declare` `type` `subtype` `array` `of`
`null` `and` `or` `not` `xor` `mod` `rem` `exit` `when` `with` `use` `range`
`others` `abs` `constant` `out` `true` `false` `all` `renames` `package` `body`
`pragma`

#### 概述
支持 Ada 83/95 子集，编译为 VML 汇编代码。词法器把标识符«bold»统一规范成小写«/»（Ada 名称大小写不敏感，凡按名字查表/比对的地方因此天然一致），之后走「词法 → 递归下降解析 → 代码生成」三段流水线；`with` / `use` 只做«bold»语法接受«/»，I/O 绑到本平台的 `print_str` / `print_int` / `print_float` / `newline`，库导入读 `Lib/ada/<名>.adb` 声明文件：`function` / `procedure` 后面的名字登记为«bold»外部函数«/»，`NAME : constant Integer := 123;` 当«bold»编译期字面量«/»。

#### 支持的语言特性

本前端接受的语言特性按下方原有章节组织，每节都写明「收什么写法、是什么语义」：

- «bold»词法«/»：注释（`--` 到行尾）、标识符、整数字面量（十进制 + 带基数 `16#FF#`）、浮点、字符串（转义是 `""`）、字符、运算符 —— §0
- «bold»编译单元与库导入«/»：`with` / `use`、`Lib/ada/*.adb` 声明文件 —— §1、§7
- «bold»声明«/»（`is` 与 `begin` 之间）：子程序、变量、常量、类型与子类型、数组 —— §2
- «bold»语句«/»：赋值、`if` / `elsif` / `else`、`while` / `for`（含 `reverse`）、`exit` / `return`、`declare` 块 —— §3
- «bold»表达式«/»：Ada 优先级（从低到高）与比较 / 逻辑 / 算术运算 —— §4
- «bold»内建函数与属性«/»：`Put_Line` / `Put` / `New_Line`、`'Image` / `'Value` / `'Length` / `'First` / `'Last`、数学库 —— §5
- «bold»类型与存储«/»：`Integer` / `Float` / `Boolean` / `Character` / `String` / 一维数组及其寄存器类 —— §6
- «bold»明确不做«/»：记录 / 泛型 / 异常 / 任务 / 访问类型 / `case` / `goto` 等 —— §8

详见下方各节。

#### 0. 词法

| 元素 | 规则 |
|---|---|
| 注释 | `--` 到行尾（«bold»没有块注释«/»） |
| 标识符 | 字母/下划线开头，字母/数字/下划线续；«bold»大小写不敏感«/»（词法器统一规范成小写再查表） |
| 整数字面量 | 十进制（`_` 作分隔符）、«bold»带基数«/» `16#FF#` / `2#1010#` |
| 浮点字面量 | `1.5` / `1.0E3`（`1..5` 是区间，不会误读） |
| 字符串 | `"…"`，«bold»转义是 `""`«/»（没有反斜杠转义） |
| 字符 | `'A'`（属性引用的撇号 `X'Image` 与它按"后跟一个字符再跟一个撇号"区分） |
| 运算符 | `+ - * / & = /= < > <= >= := => ** .. . , ; : ( ) ' | <>`（`<>` 与 `/=` 同义） |

«bold»关键字«/»：`procedure function is begin end if then elsif else while loop for in reverse return
declare type subtype array of null and or not xor mod rem exit when with use range others abs
constant out true false all renames package body pragma`

#### 1. 编译单元

```
[with <名>;]*            -- 库导入（见 §7）
[use <名>;]*             -- 只做语法接受
procedure Main is
   <声明区>
begin
   <语句序列>
end Main;
```

`procedure X is null;` 也可以（空程序）。

#### 2. 声明（在 `is` 与 `begin` 之间）

```
X : Integer;                       -- 变量（默认值 = 0 / 空串 / false）
X : Integer := 10;                 -- 带初值
A, B : Integer;                    -- 一条声明多个名字
K : constant Integer := 5;         -- 常量（本子集当普通变量处理）

type T is array (1 .. 5) of Integer;   -- 一维数组类型（**一基**）
type U is array (0 .. 9) of Float;

procedure P(A : Integer; B : out Integer) is <声明区> begin <语句> end P;
function  F(A : Integer) return Integer is <声明区> begin <语句> end F;
```

«bold»形参模式«/»写在名字之后（Ada 的写法）：`X : out Integer` / `X : in out Integer`。
`out` / `in out` 按«bold»引用«/»传递（形参槽里是调用方变量的地址）；实参必须是变量或数组元素。

#### 3. 语句

```
X := <表达式>;                 -- 赋值（目标可以是变量或数组元素 A(i)）
A(i) := <表达式>;
P(<实参>);                     -- 过程调用（无参过程写 `P;`）
P;                             -- 无参过程调用
if <条件> then … elsif <条件> then … else … end if;
while <条件> loop … end loop;
for I in <下界> .. <上界> loop … end loop;
for I in reverse <下界> .. <上界> loop … end loop;
loop … exit when <条件>; … end loop;     -- 也支持裸 `exit;`
exit when <条件>;              -- 只能出现在循环里（否则报错）
return;                        -- 过程
return <表达式>;               -- 函数
null;                          -- 空语句
declare <声明区> begin <语句序列> end;   -- 声明**就地提升**（不做块作用域）
```

#### 4. 表达式（Ada 优先级，从低到高）

```
or  xor                       -- 最低
and
=  /=  <  >  <=  >=  <>       -- 关系
+  -  &                       -- 加减与字符串并置（`&` 是并置）
not  -  +  abs                -- 一元
*  /  mod  rem                -- 乘除
**                            -- 幂（右结合）
```

«bold»求值结果落在哪里«/»：整数/布尔/指针在 `R0`，«bold»浮点在 `F0`«/»（与库函数的返回约定一致）。

类型规则：
- 任一侧是 `Float` ⇒ 整个算式按 «bold»32 位浮点«/»算（另一侧自动 `I2F`）。
- `=`/`/=` 两侧是字符串 ⇒ 走 `strcmp`；否则按整数/浮点比较。
- `and or xor` 两侧按真值归一成 0/1。
- `&` 一律按«bold»字符串并置«/»（写进一块新的 2 KiB 堆缓冲）。

#### 5. 内建函数与属性

| 形式 | 语义 |
|---|---|
| `Put_Line(X)` / `Put(X)` / `New_Line` | 输出（字符串→`print_str`、整数→`print_int`、浮点→`print_float`），`Put_Line` 末尾补换行 |
| `Integer'Image(X)` / `Float'Image(X)` | 数值转字符串（`int_to_str` / `float_to_str`） |
| `Integer'Value(S)` / `Float'Value(S)` | 字符串转数值 |
| `S'Length` | 字符串长度（`strlen`）；数组则给元素个数 |
| `A'Length` / `A'First` / `A'Last` | 数组的元素数 / 下界 / 上界（编译期常量） |
| `Character'Pos(C)` / `Character'Val(N)` | 字符 ↔ 码位（恒等，本子集里字符就是整数） |
| `abs(x)` / `min(a,b)` / `max(a,b)` | 共享数学库（整型与浮点各一套） |
| `sqrt/sin/cos/tan/exp/log(x)` | `Lib/shared/mathf.vml`（«bold»32 位浮点«/»） |
| `pow(x,y)` / `x «bold» y` | 浮点幂；整数 `«/»` 走 `ipow` |
| `Integer(x)` / `Float(x)` | 显式转换（自动插 `I2F`/`F2I`） |
| `strlen(s)` / `int_to_str(x)` / `float_to_str(x)` / `str_to_int(s)` / `str_to_float(s)` | 直接调共享库 |

#### 6. 类型与存储

| Ada 类型 | 表示 | 寄存器类 |
|---|---|---|
| `Integer` / `Natural` / `Positive` | 32 位有符号 | `R0` |
| `Float` | «bold»32 位 IEEE«/» | `F0` |
| `Boolean` | 0 / 1 | `R0` |
| `Character` | 码位（整数） | `R0` |
| `String` | «bold»指向字节串的指针«/»（不是值） | `R0` |
| 一维数组 | 数据段里连续 4 字节元素 | 地址在 `R0`/`R1` |

#### 7. 库导入

```
with VML_UI;      -- ⇒ 读 Lib/ada/vml_ui.adb，登记 ui_* 函数名与 VML_* 常量
```

- 声明文件里 `function` / `procedure` 后面的名字被登记为«bold»外部函数«/»：调用时不报"未定义"，
  直接发 `CALL <名>`，由«bold»链接器«/»解析到 `Lib/ada/builtin.vml` 链进来的实现体。
- `NAME : constant Integer := 123;` 被当作«bold»编译期字面量«/»。
- 找不到 `Lib/ada/<名>.adb` «bold»不报错«/»（`with Ada.Text_IO;` 这类标准库名在我们的绑定里本来就没有文件）。
- 带点的名字（`with Ada.Text_IO;`）«bold»不做库解析«/»。

#### 8. 未实现（明确不做）

记录/变体记录 / 任务与保护对象 / 异常 / 泛型 / 包（真语义）/ 访问类型与指针 /
多维数组 / `Long_Float` `Long_Integer` 的完整支持 / 重载与命名实参 / `case` 语句 / `goto`。

## 编译器 README

### Ada 编译器（子集）

«bold»路径«/»: `VMLPrepares/AdaCompiler/`
«bold»扩展名«/»: `.adb`（另收 `.ads` / `.ada`）
«bold»状态«/»: 🟡 子集可用 —— 「完整运算 + 控制流 + 函数调用」齐备，能写一般小程序
«bold»库«/»: `Lib/ada/`（`builtin.vml` 自动链接表 + 声明文件）
«bold»判据«/»: `scripts/vml-ada-probe/run.sh`（用例在 `bugs/vml_ada_bugs/`）

#### 为什么要它

本仓加一门语言的判据是「«bold»完整运算 + 控制流 + 函数调用«/»才算语言」——不做「只能跑 hello」的壳。
Ada 是本仓没有的一门«bold»静态强类型、类 Pascal 骨架、但语法独立«/»的语言（`is … begin … end`、
`procedure/function`、`loop/exit when`、`with`/`use`、一基数组、`'Image` 属性）。

#### 结构（9 个源文件，继承基类，不另起炉灶）

| 文件 | 作用 |
|---|---|
| `TokenType.cs` | 词法单元类型 + `Token`（实现 `ITokenPosition`） |
| `Lexer.cs` | 继承 `LexerBase`：`--` 注释、字符串（`""` 转义）、字符字面量 `'c'`、带基数字面量 `16#FF#`、Ada 运算符 |
| `ASTNode.cs` | AST（声明 / 语句 / 表达式） |
| `Parser.cs` | 继承 `ParserBase<Token,TokenType>`：编译单元、声明区、语句、Ada 优先级的表达式 |
| `CodeGenerator.cs` | 继承 `CodeGeneratorBase`：存储模型 + 表达式/语句/子程序/数组/字符串/浮点代码生成 |
| `AdaCompiler.cs` | 静态 `Compile` / `CompileFile` / `CompileFileWithIncludes` + `with X;` 声明文件加载 |
| `AdaPlugin.cs` | 派生 `CompilerPluginExBase`（`Name`/`Description`/`SupportedExtensions`/三个 Func） |
| `AdaCompiler.csproj` | «bold»`OutputType=Exe`«/»（开发期自带 `Main`；见 csproj 里的注释） |
| `Program.cs` | `SimpleCompilerProgram("ada", "VML_ADA_LIB", …)` |

#### 覆盖的语法（实测通过）

- «bold»程序骨架«/»：`procedure Main is … begin … end Main;`、`with Ada.Text_IO; use Ada.Text_IO;`
- «bold»声明区«/»：`X : Integer := 0;`、`A, B : Integer;`、`type T is array (1 .. 5) of Integer;`、嵌套子程序
- «bold»赋值«/»：`X := …;`、`A(i) := …;`（«bold»一基«/»下标）
- «bold»运算«/»：`+ - * / mod rem **`、`= /= < > <= >=`、`and or not xor`、字符串并置 `&`
- «bold»控制流«/»：`if/elsif/else/end if`、`while … loop`、`for I in 1 .. 10 loop`（含 `in reverse`）、
  `loop … exit when …; end loop;`、`declare … begin … end;`
- «bold»子程序«/»：`procedure`、`function … return T`、递归、无参过程/函数裸调、`out` / `in out` 形参（«bold»按引用«/»）
- «bold»类型«/»：`Integer` / `Float`(32 位) / `Boolean` / `Character` / `String`（= 指向字节串的指针）/ 一维数组
- «bold»输出«/»：`Put_Line` / `Put` / `New_Line`、`Integer'Image` / `Float'Image` / `Integer'Value` /
  `S'Length` / `A'Length` / `A'First` / `A'Last` / `Character'Pos` / `Character'Val`
- «bold»库«/»：字符串（`&` / `=` / `/= ` / `'Length` 走 `strcpy`/`strcat`/`strcmp`/`strlen`）、
  数学（`abs` `min` `max` `sqrt` `sin` `cos` `tan` `exp` `log` `**`）、
  `with VML_UI;` ⇒ `ui_*` 与 `VML_*` 常量

#### 存储模型（本子集定死，别混用）

- «bold»顶层变量 → 数据段槽«/»（`ada_<名>`）：任何子程序都能按标签访问，于是"内层子程序读外层声明"天然成立。
- «bold»子程序局部量 → 栈帧«/»（`R12-N`），«bold»形参 → `R12+(12+4i)`«/»（与另外 27 门一致）。
- «bold»数组恒放数据段«/»（`adaarr_<名>`，`int[]` 全零）：局部数组也放这儿 —— 代价是数组不参与递归重入。
- «bold»字符串 = 指向字节串的指针«/»；`&` 并置走 `strcpy`+`strcat` 写进一块新堆缓冲（每次 2 KiB）。

#### 输出与库绑定

`Ada.Text_IO` «bold»不依赖 GPL 工具链«/»：`Put_Line`/`Put`/`New_Line` 直接绑到本平台的
`print_str`/`print_int`/`print_float`/`newline`（`Lib/shared/builtins.vml`）。

`with X;` 是本子集的«bold»库导入«/»：它指向 `Lib/ada/<小写名>.adb` 声明文件，
里面的 `function`/`procedure` 名与 `NAME : constant Integer := 1;` 常量被登记给代码生成器
（函数名 → 外部 `CALL`，由链接器解析；常量 → 编译期字面量）。已经提供 `Lib/ada/vml_ui.adb`（183 个 `ui_*` + 175 个常量）。

#### 编译/运行（开发期）

```bash
# ① 编 AdaCompiler（本工程是 Exe，自带 Main）
dotnet build third_party/vml/VMLPrepares/AdaCompiler/AdaCompiler.csproj -c Release

# ② 产 .vml（VML_HOME 必须指向 third_party/vml，否则找不到 Lib/ada/*.vml）
cd third_party/vml && export VML_HOME="$PWD"
dotnet VMLPrepares/AdaCompiler/bin/Release/net10.0/AdaCompiler.dll Examples/ada/hello.adb -o /tmp/hello.vml

# ③ 汇编 + 链接 + 运行（vmlcli 认 `.vml` = 已经是汇编）
dotnet ../scripts/vmlcli/bin/Release/net10.0/vmlcli.dll /tmp/hello.vml
```

接线（把 Ada 并进 27 门那张注册表）见 [`INTEGRATION.md`](INTEGRATION.md)。

#### 已知限制（«bold»明确报错或有意不做«/»，不是悄悄错）

- `mod` 与 `rem` 都落到同一条 `MOD` 指令 —— «bold»负数语义不承诺«/»（本子集范围内两者在正数上一致）。
- 数组只支持«bold»一维«/»；多维下标会«bold»报错«/»（不是静默算错）。
- `declare` 块«bold»不做块作用域«/»：声明就地提升（同名跨块会互相覆盖）。
- `Float` 是 «bold»32 位«/»（`mathf` 一族）；没有 `Long_Float`（64 位双精度）的完整支持。
- 记录 / 变体记录 / 任务 / 异常 / 泛型 / 包（`package`）«bold»未实现«/»（`package body` 只做宽容跳过）。
- 字符串是«bold»指针语义«/»：`S : String := "abc"` 之后 `S := "xy"` 是«bold»换指向«/»，不是就地改写。
