stage1 修复设计问题 实现ast2ir

This commit is contained in:
zzy
2026-08-05 08:14:23 +08:00
parent 8ac59dfaa1
commit 2ccee5f1cf
14 changed files with 3694 additions and 91 deletions

66
SPL.md
View File

@@ -432,7 +432,7 @@ fn name(x: i32 = 0) { ... }
声明 静态约束 动态语义
FnDecl 名称唯一,签名完整。 仅定义。
TypeDecl 同作用域名称唯一。 定义类型别名或聚合体,编译时解析。
VarDecl (容器级) var: 必须初始化类型完整。const: 初始化必须编译期可求值。 const 编译时计算var 启动初始化一次。
VarDecl var: 必须初始化,类型完整。 const: 初始化必须编译期可求值。 const 编译时计算var 启动初始化一次。
ConstDecl 必须编译期可求值。 编译期常量。
ComptimeStmt 内部代码全部在编译时执行。 编译时执行,可生成声明。
DirectiveBlock @id { } / #id { } 为扩展占位,无预定义行为。未识别指令触发警告/错误。 同左。
@@ -478,12 +478,21 @@ type T = TypeExpr — 完全同义。
匹配: match 必须穷举 (或含 _),否则编译错误。
### 聚合体内的成员函数(就是普通函数)
在 struct / union / enum 体内的 `fn` 声明就是普通函数,进入该聚合 def 的成员列表(与字段、变体并列)。**无"方法"概念、无隐式接收者、无 self 魔法**:需要实例时,实例以普通参数显式传入(首参命名 self 只是习惯,无特殊语义)。
- 聚合类型 (以及文件 $root) 同时是**命名空间**,其内 fn 即该命名空间下的具名函数。
- 调用**只能命名空间限定**: `TypeName.fn(args)`(如 `Vec.at(&vec, i)`)。**禁止 `expr.fn(args)` 用表达式实例点调其成员函数**。
- 命名空间内相互调用用裸名 `fn(...)`
- `.` 仅用于字段/变体/路径选择 (`vec.len``.Some[5]``Token.Tag.kw_null`),不是函数调用通道。
- 函数名、字段名、变体名同存于聚合 def 的成员列表,名称互斥(同一聚合内同名冲突为编译错误)。
## 名称解析
1. 函数内部 (参数 + 块局部,每个 {} 建立子 scope)。
2. $root文件聚合的 scope所有顶层声明 (fn/type/var/const) 都是其成员。
无独立"全局"命名空间。$root 抽象不写死:@import(xxx) 返回的匿名结构即该模块当时的 $root多文件时切换。字段/变体名不在 scope map 中 (存于聚合 def 的成员列表),裸名查找天然不命中字段;路径 a.b.c 首段裸名查 scope、后续段查聚合成员。
无独立"全局"命名空间。$root 抽象不写死:@import(xxx) 返回的匿名结构即该模块当时的 $root多文件时切换。字段/变体/命名空间函数名不在 scope map 中 (存于聚合 def 的成员列表),裸名查找天然不命中字段/函数;命名空间函数只能经 `TypeName.fn` 限定调用,禁止 `expr.fn(...)` 实例点调;路径 a.b.c 首段裸名查 scope、后续段查聚合成员。
## 变量与常量
var x: T 或 var x := init: 可变量。
@@ -585,7 +594,9 @@ defer { ... }: 退出作用域时以后进先出执行。
浮点 f64布尔 bool。
null -> ?T 隐式转换
字符 'c'(含转义)默认 u8视为整数字面量可参与拓宽
null空指针字面量。当前语言无 ?Tnull 仅用于指针或切片的比较、赋值、初始化及聚合字段;其他用法为错误。
### 运算符
算术/位运算: 操作数类型必须完全一致或由字面量推导,无隐式提升。
@@ -615,6 +626,8 @@ expr(args) 可调用 函数调用
结构体字面量: Type { .f1 = v1, ... }。
匿名聚合字面量: .{ .f1 = v1, ... }。省去显式类型名,必须出现在能由上下文推导目标聚合类型的语境 (变量初始化带类型、赋值、字段值等);无法推导目标类型则编译错误。切片可用 .{ .ptr = p, .len = n } 构造。
块表达式: { ... }。
comptime { ... } / comptime expr;: 编译时求值,不可引用运行时变量。
@@ -628,6 +641,8 @@ comptime { ... } / comptime expr;: 编译时求值,不可引用运行时变量
函数类型: fn(T1, T2) RetType。
`_``ptr` 关键字不能作为独立类型 (单独出现为编译错误)`_` 只能以 `*_` 形式作指针目标,语义为"任意指针"`ptr` 关键字当前保留未启用。
*_ 的特殊规则:
*T -> *_: 允许,必须警告。
@@ -638,9 +653,7 @@ comptime { ... } / comptime expr;: 编译时求值,不可引用运行时变量
其他隐式转换:
整数字面量适配更大类型
null -> ?T。
null -> 指针/切片空值
其余必须显式 as。
@@ -648,13 +661,15 @@ null -> ?T。
区间类型 Range
语法 a..b 或 a..。
内部结构: { begin: i64, end: ?i64 } (具体整数类型可能由上下文决定,默认为 i64)。
内部结构: { begin: <int>, end: <int> },其中 <int> 为边界整数类型 (左右边界类型一致,默认/通常为 isize 或 usize无界端 end 存为空值表示无穷)。
a..b: begin = a, end = b。
a..: begin = a, end = null
a..: begin = a, end = 空值 (无界)
用作迭代器时: 产生从 begin end-1 的整数 (若 end 为 null 则无穷)。在 for 中与其他序列配合时,无界的区间自动取其配对序列的长度作为上界 (等于 0..other.len)如果配对序列也是无界则无限循环
Range 是一等类型 (值类型,同聚合行为),其 begin / end 可作为字段直接访问 (expr.begin / expr.end)访问类型即边界整数类型
用作迭代器时: 产生从 begin 到 end-1 的整数 (若 end 为空值则无穷),元素类型即边界整数类型 (与 begin/end 一致)。在 for 中与其他序列配合时,无界的区间自动取其配对序列的长度作为上界 (等于 0..other.len),如果配对序列也是无界则无限循环。
切片类型 []T
内部结构: { ptr: *T, len: usize }。
@@ -732,13 +747,13 @@ void: 大小为 0表示无值仅用于函数返回或指针。
从数组构造: array[a..b] 产生切片。
### 区间类型
a..b 或 a..: 类型为 Range内部结构 { begin: isize, end: ?isize }
a..b 或 a..: 类型为 Range内部结构 { begin: <int>, end: <int> }<int> 为边界整数类型 (左右边界一致,默认 isize 或 usize无界端 end 存空值)
a..b: end 为 b。
a..: end 为 null (无界)。
a..: end 为空值 (无界)。
Range 是值类型同聚合类型行为。
Range 是值类型同聚合类型行为begin / end 可作为字段直接访问
用于迭代和切片边界。
@@ -747,10 +762,10 @@ fn(参数类型列表) 返回类型
函数值本身的大小和表示未指定 (闭包待定),但函数名作为标识符使用时具有指针语义 (类似函数指针)。
### 可选类型(暂时不需要实现)
### 可选类型(预留,当前不实现)
?T: 可为 null 的类型。内部表示同 T 但附加一个判别 (可能通过 null 指针表示,视 T 而定)。?T 的大小和对齐与 T 相同或扩展为可容纳 null 的形式 (具体实现定义)。
null 字面量只能出现在需要 ?T 的上下文中
当前阶段未实现 ?Tnull 以"指针/切片的空值"语义生效 (见"特殊类型"与"类型兼容性")
### 聚合类型
struct: 字段连续排列 (可能有对齐填充),每个字段有自己的类型。赋值是逐字段拷贝。
@@ -772,7 +787,7 @@ enum: 带标签的联合体,每个变体可有载荷。大小实现定义,
### 特殊类型
void: 无法实例化,仅用于返回或指针目标。
null: 不是独立类型,仅用于初始化赋值给 ?T
null: 不是独立类型,是"指针/切片空值"字面量,仅用于指针或切片的初始化赋值、比较及聚合字段
## 类型兼容性与隐式转换
下表中,“允许”表示可自动转换,否则需要显式 as 转换。警告列表明编译器必须输出诊断信息,不可静默。
@@ -782,12 +797,10 @@ T (任意) T 是 无 相同类型
*T *_ 是 警告: “丢失类型信息”
*_ *T 是 警告: “不安全的指针重解释”
[N]T []T 是 无 数组到切片强制转换
整数字面量 整数类型 U 是 (若值在 U 范围内) 无 字面量自动拓宽
整数字面量 整数类型 U 是 (若值在 U 范围内) 无 字面量自动拓宽 (含字符 'c' 视为 u8)
i32 i64 否 — 需显式 as i64防止意外
i64 i32 否 — 窄化必须显式
null ?T 是 无 空值初始化
?T T 否 — 需显式解包 (如 orelse但语言暂未定义将来扩展)
T ?T 是 无 提升为可选
null *T / []T 是 无 空指针/空切片初始化、比较、赋值、聚合字段
浮点字面量 f32 是 (值可表示则) 无
f64 f32 否 — 窄化需显式
bool 整数 否 —
@@ -795,9 +808,11 @@ bool 整数 否 —
注:
?T (可选类型) 为预留特性当前阶段未实现null 语义以"指针/切片的空值"生效,见本表 null 行。
隐式转换不会嵌套传递。例如 *T 到 *_ 是警告转换,但不因此进一步允许 *_ 到 **T 的隐式转换。
字面量拓宽仅适用于整数字面量直接出现在需要更宽整数类型的上下文 (如赋值给 i64 变量,或作为 Range 的边界Range 内部为 isize所以 0..5 中的 0 和 5 会拓宽为 isize)。
字面量拓宽仅适用于整数字面量直接出现在需要更宽整数类型的上下文 (如赋值给 i64 变量,或作为 Range 的边界Range 内部为 isize所以 0..5 中的 0 和 5 会拓宽为 isize;字符 'c' 同视为整数字面量)。
所有其他未列出的类型转换均需显式 as。
@@ -811,7 +826,7 @@ FLOAT -> f64
true / false -> bool
null -> 必须从上下文推导出 ?T无法推导则报错。
null -> 必须从上下文推导出 *T 或 []T 的空值 (当前无 ?T),用于比较/赋值/字段;无法推导或用于非指针上下文则报错。
字符串字面量 -> []u8 (具体待定)
@@ -936,7 +951,7 @@ ForRange 提供表达式列表 [E1, E2, ...]。as 后标识符列表 [v1, v2, ..
对于 Ei:
若为 Range: 每次迭代产出的值类型为 isize (Range 的边界类型,这里默认 isize)。
若为 Range: 每次迭代产出的值类型为 Range 的边界整数类型 (即 begin/end 的类型,默认 isize 或 usize)。
若为 []T 或 [N]T: 产出元素类型为 T。
@@ -946,7 +961,7 @@ ForRange 提供表达式列表 [E1, E2, ...]。as 后标识符列表 [v1, v2, ..
长度协调规则:
若所有序列均为有界 (Range 有 end 不为 null,或切片长度已知),则循环次数为最短长度。
若所有序列均为有界 (Range 有 end 非空值,或切片长度已知),则循环次数为最短长度。
若存在无界 Range (如 0..),则要求循环中至少有一个有界序列,且该有界序列的长度将作为无界序列的上限。例如 for slice, 0.. as elem, idx0.. 的长度由 slice.len 决定。
@@ -960,8 +975,6 @@ for my_slice, 0.. as elem, idx { ... }
// 0..: Range 无界 -> idx: i64长度由 my_slice 决定
```
## 类型系统限制
无隐式类型提升 (除字面量整数拓宽和数组到切片外)。
无默认初始化: var x: T; 不初始化,警告/错误。
无隐式 deref 多级: . 仅自动解引用一层。
@@ -1008,7 +1021,7 @@ Function ← AttributeList? 'func' GLOBAL_IDENT '(' ParamDefs? ')' '->' Type
AttributeList ← Attribute (',' Attribute)*
Attribute ← '!' IDENTIFIER ( '(' Args? ')' )? // 标记,如 !export("C")
GLOBAL_IDENT ← '@' IDENTIFIER
GLOBAL_IDENT ← IDENTIFIER
ParamDefs ← LOCAL_IDENT ':' Type (',' LOCAL_IDENT ':' Type)*
Block ← '{' Stmt* '}'
@@ -1153,6 +1166,7 @@ CONSTANT ← INTEGER | FLOAT | STRING | 'true' | 'false' | 'null' | 'undefine
@control.br(bool, label, label) -> ! 条件分支:根据第一个参数跳转到第二或第三个(标签或者地址)。终止函数 (调用后控制流不返回)。
@control.jmp(label) -> ! 无条件跳转(跳转到标签或者地址)。终止函数。
@control.call(FT)(%fn:FT, %args...) -> %ret 按目标平台调用约定调用函数指针 %fnFT 为 fn<param_types...->ret_type>
@control.param(T)(%idx: usize) -> T 返回idx的函数参数(编译期检查是否越界)
@control.ret(T)(%val?) 按目标平台调用约定从当前函数返回T 为返回值类型void 时不带参数
@control.unreachable() -> ! 标记不可达代码
@control.trap() -> ! 触发运行时陷阱