# R

向量语言，写法与桌面 R 接近。

## 在手机上怎么跑

```
vml run examples/r/test/sysinfo.r
```

编译要等一会儿（C 那种要一两分钟，脚本类语言几秒）。程序跑起来后**屏幕底部就是手柄**，
方向键 + 四个动作键都在；点右上角返回可以回到命令行。

## 写法要点

- 直接调用 `ui_*`
- 状态可以放向量里

## 示例

| 文件 | 演示什么 |
|---|---|
| `test/catch.r` | 接方块 |
| `test/file_io.r` | 读写文件 |
| `test/parserexpf_demo.r` | 调用共享库解析表达式 |
| `test/sysinfo.r` | 设备信息 |

同目录还有：`demo/demo_std.r`、`test/libs.r`、`tty/demo_tty.r`、`ui/demo_ui.r`

---

下面的内容是**从 VML 源码里直接带的**（`third_party/vml/VMLPrepares/RCompiler/`）：
`README` 讲这个前端支持什么、怎么编；`语言规范` 讲语法本身。
上游一改，这里重新生成就是最新的。

## 语言规范

### R 语言编译器规范说明

> «bold»版本«/»：v1.0 | «bold»日期«/»：2026-07-06 | «bold»修订者«/»：深圳市探索智能科技有限公司

#### 元数据

| 项目 | 说明 |
|------|------|
| «bold»标准«/» | R 4.x 子集 (S 语言兼容) |
| «bold»语言诞生年份«/» | 1993 |
| «bold»完成度«/» | ~96% |
| «bold»文件扩展名«/» | `.r` |
| «bold»编译器入口«/» | `RCompiler.RCompiler.Compile()` |
| «bold»插件注册«/» | `RCompilerPlugin : CompilerPluginExBase` |
| «bold»语言分类«/» | 统计分析语言 |

#### 概述

R 语言是一种用于统计计算和图形展示的编程语言和环境。本编译器实现了 R 语言的核心语法子集，支持向量化数据操作、统计函数、控制流和自定义函数定义。编译产物为 VML 汇编，可进一步翻译到 16 种目标架构。

编译器架构遵循标准 VML 前端模式：

```
R 源码 (.r) → Lexer (Lexer.cs) → Token 流
             → Parser (Parser.cs) → AST (ASTNode.cs)
             → CodeGenerator (CodeGenerator*.cs) → VML 程序
```

入口文件 `RCompiler.cs` 编排整个编译流水线，包括预处理、词法分析、语法分析、代码生成和标准库链接。

#### 支持的特性

##### 数据类型

| 类型 | R 表示 | 内部表示 | 说明 |
|------|--------|----------|------|
| `numeric` | `42`, `3.14`, `1.5e-10` | `int` / `float` | 整数和浮点数。R 中 integer 可加 `L` 后缀（如 `42L`），解析时 `L` 被去除 |
| `character` | `"hello"`, `'world'` | `string` (data section) | 字符串字面量，支持双引号、单引号、反引号三种定界符 |
| `logical` | `TRUE`, `FALSE` | `int` (1 / 0) | 布尔值映射为整数 |
| `NULL` | `NULL` | `int` (0) | 空值，R0 置零 |
| `NA` | `NA` | `int` (`int.MinValue`) | 缺失值，使用哨兵值表示 |
| `Inf` | `Inf` | `float` (`float.PositiveInfinity`) | 无穷大 |

注意：当前实现中 numeric 的 integer 和 float 在运行时不做严格类型区分。科学计数法（如 `1.5e-10`、`2E+3`）被完整支持。

##### 赋值运算符

R 支持三种赋值形式，优先级从高到低：

```r
# 1. 左赋值（推荐风格）
x <- 42
y <- c(1, 2, 3)

# 2. 等号赋值（函数参数风格）
x = 42

# 3. 超级赋值（父环境赋值）
x <<- 42
```

- `<-` 和 `=` 在当前作用域分配变量
- `<<-` 标记为超级赋值，用于向父作用域写入（当前编译器实现中与 `<-` 行为等价，作用域层级尚未完全实现）
- 赋值表达式返回右值，支持链式赋值：`a <- b <- 10`

##### 算术运算符

| 运算符 | 语法 | 说明 |
|--------|------|------|
| 加法 | `a + b` | 数值相加 |
| 减法 | `a - b` | 数值相减 |
| 乘法 | `a * b` | 数值相乘 |
| 除法 | `a / b` | 浮点除法 |
| 幂运算 | `a ^ b` | 指数运算 |
| 取模 | `a %% b` | 整数取余（注意必须为两个 `%` 符号） |

##### 比较运算符

| 运算符 | 语法 | 说明 |
|--------|------|------|
| 等于 | `a == b` | 相等比较 |
| 不等于 | `a != b` | 不等比较 |
| 小于 | `a < b` | 小于比较 |
| 大于 | `a > b` | 大于比较 |
| 小于等于 | `a <= b` | 小于或等于 |
| 大于等于 | `a >= b` | 大于或等于 |

比较结果返回整数 `1` (TRUE) 或 `0` (FALSE)。

##### 逻辑运算符

| 运算符 | 语法 | 说明 |
|--------|------|------|
| 逻辑与 | `a & b` | 短路求值 (映射为 `&&`) |
| 逻辑或 | `a \| b` | 短路求值 (映射为 `\|\|`) |
| 逻辑非 | `!a` | 一元取反 |

注意：当前实现不区分向量化的 `&`/`|` 和短路求值的 `&&`/`||`，所有逻辑运算均执行短路求值。R0 = 0 视为 FALSE，非零视为 TRUE。

##### 函数

```r
# 函数定义
add <- function(a, b) {
    return(a + b)
}

# 无参函数
greet <- function() {
    return("Hello")
}

# 隐式返回：函数体最后一个表达式的值即为返回值
square <- function(x) {
    x * x
}
```

- 使用 `function(params) { body }` 语法定义匿名函数，通过 `<-` 赋值给变量名
- 参数列表可以为空
- `return(expr)` 提前返回，`return expr`（无括号）也受支持
- 函数体最后一个表达式的值隐式作为返回值
- 函数调用：`name(arg1, arg2, ...)`，参数从右向左压栈，返回值在 R0 寄存器
- 函数内部有独立的变量作用域（参数压入当前栈帧，函数退出时恢复）

##### 控制流

###### if / else

```r
if (x > 0) {
    print("positive")
} else {
    print("non-positive")
}

# else if 链（嵌套解析）
if (x > 0) {
    print("positive")
} else if (x < 0) {
    print("negative")
} else {
    print("zero")
}
```

条件表达式求值后与 0 比较：`CMP R0, 0; JE`。非零为真。

###### while 循环

```r
i <- 1
while (i <= 10) {
    print(i)
    i <- i + 1
}
```

前测试循环：条件为假时跳过循环体。

###### for 循环

```r
for (i in 1:5) {
    print(i)
}

for (x in c(10, 20, 30)) {
    print(x)
}
```

- `for (variable in sequence) { body }` 语法
- 迭代变量在每次循环中被赋予序列的当前元素值
- 支持 `c()` 向量和范围表达式
- 序列长度在编译时确定（仅支持常量长度序列）

###### repeat 循环

```r
repeat {
    # 必须包含 break 条件，否则为无限循环
    if (condition) {
        break
    }
}
```

无限循环，必须使用 `break` 显式退出。

###### break 和 next

```r
# break: 退出最内层循环
for (i in 1:10) {
    if (i > 5) {
        break
    }
}

# next: 跳过当前迭代，进入下一次循环
for (i in 1:10) {
    if (i %% 2 == 0) {
        next
    }
    print(i)  # 只打印奇数
}
```

- `break` 跳转到循环结束标签
- `next` 跳转到循环条件检查标签（等价于 C 语言 `continue`）
- 在循环外使用会导致编译错误

##### 向量 (Vectors)

```r
# c() 构造函数
x <- c(1, 2, 3, 4, 5)
y <- c(TRUE, FALSE, TRUE)
z <- c()  # 空向量，返回 NULL

# 范围运算符
1:10    # 整数序列，解析为特殊调用
```

- 向量通过 `c()` 函数构造，在解析器中作为 `SeqNode` AST 节点特别处理
- 向量在堆上分配（`SYSCALL 2` = malloc），每个元素占 4 字节
- 元素按顺序存储在连续内存中
- 空向量 `c()` 返回 0 (NULL)
- 范围运算符 `start:end` 被解析为对 `:` 函数的调用
- «bold»不支持«/»：命名向量、类型强制转换、向量回收（recycling）

##### 索引

```r
x <- c(10, 20, 30, 40)
a <- x[1]   # 10 (R 索引从 1 开始)
b <- x[3]   # 30
```

- 使用 `[index]` 语法，1-based 索引
- 内部实现：索引减 1，乘以 4（字偏移），从基址加载
- 索引表达式可以是任意表达式：`x[i + 1]`
- «bold»不支持«/»：负索引（排除）、逻辑索引、多维索引、`[[` 提取运算符、切片 `x[2:4]`

##### 注释

```r
# 这是单行注释
x <- 1  # 行尾注释
```

仅支持 `#` 开头的单行注释。不支持多行注释。

##### 科学计数法

```r
x <- 1.5e-10   # 1.5 × 10^-10
y <- 2.0E+5    # 200000
z <- 3e8        # 300000000
```

词法分析器完整解析科学计数法：尾数、小数点、`e`/`E`、可选符号、指数。

##### 标识符规则

- 以字母、下划线或点号开头（点号后必须跟字母或下划线）
- 后续字符：字母、数字、下划线、点号
- 区分大小写：`x` 和 `X` 是不同的变量
- 关键字不可作为标识符使用
- 示例合法标识符：`x`, `_private`, `.hidden`, `my.var`, `data_1`

##### source() 导入

```r
source("lib/utils.r")
```

`source()` 调用以正则表达式从源码中提取（预处理阶段前解析），将指定的 `.r` 文件内容链接到当前程序。这是一个编译时机制，非运行时函数调用。

#### 表达式优先级表

优先级从高到低排列（数字越小优先级越高）：

| 优先级 | 运算符 | 结合性 | 说明 |
|--------|--------|--------|------|
| 1 | `()` `[]` `$` `:` `f()` | 左结合 | 分组、索引、成员访问、范围、函数调用 |
| 2 | `-` (一元) `!` `+` (一元) | 右结合 | 一元负号、逻辑非、一元正号 |
| 3 | `^` | 右结合 | 幂运算 |
| 4 | `*` `/` `%%` | 左结合 | 乘、除、取模 |
| 5 | `+` `-` | 左结合 | 加、减 |
| 6 | `==` `!=` `<` `>` `<=` `>=` | 左结合 | 比较运算符 |
| 7 | `&` | 左结合 | 逻辑与 |
| 8 | `\|` | 左结合 | 逻辑或 |
| 9 | `<-` `<<-` `=` | 右结合 | 赋值 |

#### 预定义宏

编译器在预处理阶段（`Preprocessor`）注入以下宏：

| 宏名称 | 典型值 | 说明 |
|--------|--------|------|
| `__VML__` | `1` | 指示代码正在 VML 工具链中编译 |
| `__VML_VERSION__` | `"1.65.32"` | VML 工具链版本号 |
| `__R__` | `1` | 指示当前编译语言为 R |
| `__DATE__` | `"Jun 02 2026"` | 编译日期 |
| `__TIME__` | `"15:30:00"` | 编译时间 |

这些宏可以通过预处理器指令 `#ifdef`、`#ifndef`、`#if` 等使用，支持条件编译。

#### 限制与不支持的特性

当前实现为🟢 生产可用级别，以下 R 语言核心特性尚未支持：

##### 对象系统

- «bold»S3 对象«/»：类和泛型函数机制（`class<-`、`UseMethod`、`NextMethod`）
- «bold»S4 对象«/»：正式类定义和方法分派（`setClass`、`setMethod`）
- «bold»RC (Reference Classes)«/»：引用类
- «bold»R6 类«/»：现代 OOP 系统

##### 数据结构

- «bold»list()«/»：递归列表（仅实现了 `c()` 原子向量）
- «bold»data.frame«/»：表格数据结构
- «bold»matrix«/»：多维矩阵（`matrix()`、`%*%` 矩阵乘法）
- «bold»array«/»：多维数组（`array()`、`dim<-`）
- «bold»factor«/»：分类变量
- «bold»names / attributes«/»：属性系统（`names<-`、`attr<-`、`attributes<-`）
- «bold»环境 (environment)«/»：环境对象和词法作用域层级

##### 函数式编程

- «bold»apply 家族«/»：`apply()`、`lapply()`、`sapply()`、`tapply()`、`mapply()` 等
- «bold»闭包«/»：词法作用域中捕获自由变量的函数
- «bold»`...` (dots)«/»：可变参数
- «bold»`on.exit()`«/»：函数退出钩子
- «bold»`invisible()`«/»：不可见返回

##### 公式接口

- «bold»公式对象«/»：`y ~ x1 + x2`（统计建模核心语法）
- 相关函数：`lm()`、`glm()`、`terms()`、`model.frame()`

##### 向量化运算

- «bold»向量回收 (recycling)«/»：不等长向量运算时的自动扩展
- «bold»逐元素运算«/»：所有运算符当前为标量操作，不自动对向量广播
- «bold»向量化 ifelse()«/»：条件向量选择

##### 包和库

- «bold»library() / require()«/»：包加载机制
- «bold»CRAN 包«/»：任何第三方包
- «bold»命名空间«/»：`::` 和 `:::` 运算符
- «bold»base/recommended 包«/»：R 自带的统计和图形包

##### 其他

- «bold»管道运算符«/»：`|>` (原生管道) 和 `%>%` (magrittr)
- «bold»switch()«/»：多分支选择
- «bold»tryCatch()«/»：异常处理
- «bold»R 复数类型«/»：`complex`
- «bold»R 原始类型«/»：`raw`
- «bold»字符串操作函数«/»：`paste()`、`sprintf()`、`gsub()` 等（需通过 C 共享库手动实现）
- «bold»绘图系统«/»：图形设备接口
- «bold»S4 泛型«/»：`setGeneric`、`setMethod`
- «bold»延迟求值«/»：R 的惰性参数求值语义
- «bold»R 的 `[` `[[` `$` 作为函数«/»：运算符的函数形式
- «bold»负索引与逻辑索引«/»：`x[-1]`、`x[x > 5]`
- «bold»列表命名元素«/»：`x[["name"]]`
- «bold»formals() / body()«/»：函数对象内省

#### 编译器实现细节

##### 文件结构

```
VMLPrepares/RCompiler/
├── Token.cs                      # Token 类型定义与值载体
├── Lexer.cs                      # 词法分析器（继承 LexerBase）
├── ASTNode.cs                    # 抽象语法树节点定义
├── Parser.cs                     # 递归下降语法分析器
├── CodeGenerator.cs              # 代码生成主入口
├── CodeGenerator.Expressions.cs  # 表达式代码生成
├── CodeGenerator.Statements.cs   # 语句代码生成
├── RCompiler.cs                  # 编译器入口与流水线编排
├── RCompilerPlugin.cs            # 插件注册
├── Program.cs                    # CLI 入口
└── RCompiler.csproj              # 项目文件
```

##### 寄存器约定

遵循 VML 标准调用约定：

| 寄存器 | 用途 |
|--------|------|
| R0 | 累加器 / 函数返回值 |
| R12 | 帧指针 (BP) |
| R13 | 栈指针 (SP) |
| R15 | 返回地址 (RA) |

##### 内存模型

- 局部变量：在栈帧内分配，通过 `R12-offset` 寻址
- 全局变量：在 data section 中分配，通过标签 `var_name` 寻址
- 未知变量首次赋值时自动在栈上分配空间（4 字节对齐）
- 向量元素：堆分配（`SYSCALL 2` / malloc），返回基址指针

##### 函数调用约定

- 参数从右向左压栈
- `CALL func_<name>` 跳转到函数体标签
- 被调函数：
  - 序言：`PUSH R15; PUSH R12; MOVE R12, R13`
  - 体：执行语句。参数在栈帧内通过 `R12-<offset>` 访问
  - 尾声：`POP R12; RET`
- 返回值通过 R0 传递

##### 字符串处理

- 字符串字面量存储在 data section 中，带唯一标签 `str_<guid>`
- 使用 `MOVE R0, label` 将字符串地址加载到 R0
- 重复字符串共享同一标签（通过 `_stringCache` 字典去重）

##### 标准输出

当前编译器无内置 `print()` 实现。输出需通过 VML SYSCALL 或 BIOS 调用实现，或链接 C 共享库中的 `printf` 函数。

##### R 转换为 VML 的典型映射

| R 构造 | VML 指令序列 |
|--------|-------------|
| `x <- 10` | `MOVE R0, 10; MOVE [R12-x], R0` |
| `a + b` | `MOVE R0, [R12-a]; MOVE R0, [R12-b]; ADD R0, R0, R0` |
| `if (x) { ... }` | `MOVE R0, [R12-x]; CMP R0, 0; JE else_label; ...; LABEL else_label` |
| `while (x) { ... }` | `LABEL while_start; MOVE R0, [R12-x]; CMP R0, 0; JE wend; ...; JMP while_start; LABEL wend` |
| `for (i in c(1,2,3)) { ... }` | 索引初始化 + 条件检查循环 + 每次迭代加载序列元素值 |
| `return(x)` | `MOVE R0, [R12-x]; POP R12; RET` |
| `f(x, y)` | `MOVE R0, [R12-y]; PUSH R0; MOVE R0, [R12-x]; PUSH R0; CALL func_f` |
| `v[i]` | 计算基址 + (i-1)*4，间接加载 |
| `c(1, 2, 3)` | `SYSCALL 2` (malloc 12) + 依次存储元素 + 恢复基址到 R0 |

---

#### 🆕 字符串编码 (v1.65.19)

该语言编译器通过共享库 (Lib/shared/) 间接使用 VML 字符串体系。

| 伪指令 | 宽度 | 编码 | C 类型 |
|:------|:----:|:-----|:--------|
| `.string` | 8-bit | UTF-8 | `char*` |
| `.wstring` | 16-bit | UTF-16LE | `wchar_t*` |
| `.ustring` | 32-bit | UTF-32LE | `char32_t*` |

«bold»MCU 模式«/» (默认): 字符串输出为 UTF-8 (`.string`)
«bold»OS 模式«/»: 可通过 `VML_WSTRING` 宏判断编码

共享库已提供宽字符串转换函数 (wchar.h/uchar.h)，各语言编译器可按需使用。

## 编译器 README

### R 编译器

«bold»路径«/»: `VMLPrepares/RCompiler/`
«bold»完成度«/»: ~96% | 🟢 生产可用
«bold»标准库«/»: `Lib/r/`

#### 功能
- ✅ 词法分析 + 语法分析 + 代码生成 (Lexer/Parser/CodeGenerator)
- ✅ 控制流 (if/else/for/while/repeat/break/next)
- ✅ 函数: function() 定义/参数/return/匿名函数
- ✅ 赋值: <- / <<- / = 运算符
- ✅ 数据结构: c() 向量 / list() / 公式 ~ 运算符
- ✅ %in% 运算符
- ✅ 科学计数法数值
- ✅ 31 测试 0 失败
- ⚠️ S3/S4 对象系统 — 未实现
- ⚠️ data.frame/matrix — 未实现
- ✅ C 风格预处理 (#ifdef/#ifndef/#define/#include)

#### 编译模式

##### MCU 模式（默认 `--mode mcu`）
MCU 模式针对单片机/裸机环境优化。

«bold»跳过«/»:
- source() 动态加载
- S3/S4 对象系统
- 图形设备

«bold»保留«/»:
- 基本统计运算
- 向量操作 (c/seq/rep)
- print 映射到 UART

##### OS 模式（`--mode os`）
OS 模式支持全部语言特性。

##### RAM 级别
- `--ram k`：KB级别
- `--ram m`：MB级别（默认）
- `--ram g`：GB级别

#### 使用
```bash
dotnet run --project VMLTool -- input.r -o output.vml
```

#### 测试
- `VMLTests/NewCompilerTests.cs` — 31 测试 (0 失败)
- `VMLTests/FullPipelineTests.cs` — 全管线测试
- `Examples/r/` — 示例程序 (start/factorial/file_io/info)
