# 编译与运行

## 最快的路子：命令行

```
vml run examples/c/app/tetris.c        # 源码 → 直接跑
vml run ~/main.vml                 # 文本汇编 → 跑
vml run ~/main.vmb                 # 字节码 → 跑（最快）
```

`vml run` **自动识别**扩展名，不用你操心走哪条路。

## 在文件页点点点

**文件** 页 → 点文件名 → 菜单里选：

- **VML 编译** → 生成下一级产物（`.c`→`.vml`，`.vml`→`.vmb`）
- **VML 运行** → 直接跑

产物会出现在**同一个目录**下，同名。同名文件已存在时会问「覆盖 / 重命名 / 取消」。

## 手机上编译要多久

- **C 语言最慢**：一份带标准库的程序，前端编译 + 链接**要一两分钟**（手机上真的是一分钟量级）
- Python / Lua / BASIC 这类脚本语言快得多（几秒）
- **`.vmb` 装载几乎瞬时** —— 所以同一个程序反复跑，先编成 `.vmb` 再跑最省时间

> 编译期间不要以为卡死了：输入框那格会显示 `⋯`，跑完提示符 `~>` 会回来。

## 编译卡住会不会出不来

不会。前端编译是同步的、**没有任何取消入口**，所以宿主加了一道**看门狗**：
180 秒还没编完就把控制权交还给你（那个编译线程本身没法中止，只是不让界面卡着）。

## 为什么 `.vml` 还能单独存在

- **能读**：它是文本，你能直接看到编译器生成的指令
- **能改**：手写汇编也是合法的（`vml test` 跑的就是一段内置汇编）
- **能当中间产物**：`.c` 编一次成 `.vml`，之后反复汇编成 `.vmb` 就不用再走前端了

## 编译参数（设置 → 编译）

**设置 → 编译** 里能调几个编译器行为参数，**改完下一次编译生效**。

| 项 | 默认 | 说明 |
|---|---|---|
| 优化级别 | 关闭 | **四档**：关闭 / 初步 / 中度 / 极致（见下） |
| 编译警告 | 不报 | 打开后编译期的警告会显示出来（基本 = `-Wall`，更多 = `-Wextra`） |
| 把警告当错误 | 关 | 有警告就当成编译失败（`-Werror`） |
| 调试输出 | 关 | 打开前端里的诊断分支，以及编译结束时的警告计数 |
| 浮点（float/double） | 硬件 | 改成「关闭」= 遇到浮点代码**直接编译报错** |
| 64 位整数（long/int64） | 硬件 | 同上 |

### 优化四档

| 档 | 做什么 | 实测（46 字节的 hello.c） |
|---|---|---|
| **关闭** | 一条指令都不删 | 69637 条指令 / 2.0 MB |
| **初步** | 清掉跳转之后用不到的填充代码 | 69637 条 / 2.0 MB（基本不变） |
| **中度** | 加上**死代码消除**：删掉没被调用的库函数 | **28 条 / 3.1 KB** |
| **极致** | 再删冗余跳转、清数据段、去掉 `.linked` 声明 | **27 条 / 670 字节** |

> **这才是"打开优化真的变小"**：一个 hello world 从 **2.0 MB 降到 670 字节**，
> 因为它本来就把整个标准库链了进来，而其中 99% 是被调用的函数一个都没有。
>
> **游戏上没这么夸张**（它们本来就用得多）：俄罗斯方块 74754 → 6282 条、
> 五子棋 72921 → 3544 条、大猩猩(BASIC) 103437 → 29863 条。
>
> **优化不会改变程序行为** —— 27 门语言的示例在四档下的输出**逐字节相同**（有判据盯着）。
> 它的规矩是"只删确定用不到的东西"：遇到间接跳转、取函数地址、中断向量表这些
> 静态看不全的情形，**宁可留着不删**。

> **未使用的东西会被丢掉**：没人引用的全局变量、常量、字符串、整片库数据段
> （正弦表、调色板那些）都不会进产物。这不是某一档的专属 —— 数据段清理一直生效，
> 中度以上因为删了库函数，连带清掉的更多。

> **「关闭」是报错，不是降级** —— 它用来确认"这个程序到底用没用浮点/64 位"，
> 而不是让程序悄悄变慢。软浮点（soft）本平台没有对应的库，所以不提供这个档。

> 这些参数**不影响默认行为**：不动它们（优化=关闭）时，编出来的东西与从前**逐字节相同**。
