From 2baf762d8246721cee6905a6fcc9d09e5104ee71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E8=88=AA=E5=AE=87?= <3364451258@qq.com> Date: Fri, 5 Jun 2026 21:02:05 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20README/CHANGELOG/=E8=AF=AD=E8=A8=80?= =?UTF-8?q?=E5=8F=82=E8=80=83=E6=9B=B4=E6=96=B0=E8=87=B3=20v0.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 17 +++++++++ README.md | 33 ++++++++++------- docs/language-reference.md | 76 +++++++++++++++++++++++++++++++++++--- 3 files changed, 108 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c53d8a..c36f403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ # Changelog +## 0.6.0 (2026-06-05) + +### Added +- 新类型: `i32` (32位有符号整数), `u64` (64位无符号整数), `char` (单字符) + 字符字面量 `'A'` +- guard 语句: `guard x >= 0 else { return -1; }` (parser 去糖为 if-else) +- 命名参数: `draw_rect(width: 10, height: 20)` 任意顺序传参,sema 重排序 +- 管道 `|>`: `10 |> double() |> add(5)` → `add(double(10), 5)` (F#/Elixir 风格) +- 字符串插值: `"Hello, \(name)!"` → `"Hello, " + name + "!"` (Swift 风格) +- 4 个新集成测试: 25_new_types ~ 29_interp + +### Changed +- **语法差异化**: `let mut` → `var`, `[T; N]` → `T[N]`, `..` → `to`, `impl` → `extend` +- 类型隐式转换: `can_implicit_convert()` 加宽规则 + codegen `coerce_int()` +- 符号表扩展: `Symbol.param_names` 支持命名参数匹配 +- AST 扩展: `CALL_EXPR`/`METHOD_CALL` 增加 `arg_names` 字段 +- 测试: 158 单元 (41+15+74+28) + 29 集成 + ## 0.5.0 (2026-06-05) ### Added diff --git a/README.md b/README.md index 1a3a1df..6e4071d 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@

- version + version C LLVM GCC @@ -16,18 +16,20 @@ ## 简介 -L Language 是一门学习型编译语言,手写词法分析、递归下降 + Pratt 解析、语义分析和 LLVM IR 代码生成,最终生成原生可执行文件。语法借鉴 Rust,类型系统支持类型推断。 +L Language 是一门学习型编译语言,手写词法分析、递归下降 + Pratt 解析、语义分析和 LLVM IR 代码生成,最终生成原生可执行文件。语法博采众长(Rust/Swift/Elixir),拥有管道、字符串插值、命名参数等独有特性。 📖 **[语言参考手册](docs/language-reference.md)** — 完整的语法、类型、示例教程 ```rust -fn fib(n: i64) -> i64 { - if n < 2 { return n; } - return fib(n - 1) + fib(n - 2); +fn double(x: i64) -> i64 { + return x * 2; } fn main() -> i64 { - print_i64(fib(10)); // 输出 55 + let name = "L"; + print_str("Hello, \(name)!"); // 字符串插值 + let result = 10 |> double() |> double(); // 管道 + print_i64(result); // 40 return 0; } ``` @@ -41,8 +43,8 @@ fn main() -> i64 { ```mermaid graph TB subgraph 前端["编译器前端"] - Lexer[词法分析器
手写状态机
40 种 Token] - Parser[语法分析器
递归下降 + Pratt
14 种 AST 节点] + Lexer[词法分析器
手写状态机
55+ 种 Token] + Parser[语法分析器
递归下降 + Pratt
25 种 AST 节点] Sema[语义分析器
作用域链 + 类型推断
类型检查 + 错误收集] end @@ -69,13 +71,13 @@ graph TB | 模块 | 输入 | 输出 | 核心结构 | |------|------|------|----------| | `lexer/` | `char*` 源码 | `Token[]` | `Token` {kind, start, length, line, col} | -| `parser/` | `Token[]` | `AstNode*` | 14 种节点 (Program..IdentExpr) | +| `parser/` | `Token[]` | `AstNode*` | 25 种节点 (Program..MethodCall) | | `ast/` | — | 工厂函数 | `AstNode` {kind, type, as{union}} | | `sema/` | `AstNode*` | 类型标注 | `Scope` 作用域链 + `Symbol` 符号表 | | `codegen/` | `AstNode*` | `LLVMModuleRef` | `CgCtx` {module, builder, var_table} | | `driver/` | 命令行参数 | exit code | 流水线串联 + 错误报告 | -## 功能 (v0.5) +## 功能 (v0.6) ### 类型系统 @@ -103,6 +105,7 @@ graph TB - `while` 循环 - `for i in 0 to 10` (去糖为 while) - `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else) +- `guard x >= 0 else { return -1; }` (去糖为 if-else) - `return` ### 函数 & 方法 @@ -111,11 +114,15 @@ graph TB - 返回类型校验 - `extend StructName { fn method(self: Type) -> Ret { ... } }` - `instance.method(args)` 调用 +- **命名参数**:`draw_rect(width: 10, height: 20)` 任意顺序传参 +- **管道 `|>`**:`10 |> double() |> add(5)` 数据流从左到右 - 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str` -### 运算符 +### 运算符 & 语法糖 -`+ - * / %` `== != < > <= >=` `&& || !` `+= -= *= /=` `str + str` +`+ - * / %` `== != < > <= >=` `&& || !` `+= -= *= /=` `|>` `str + str` + +- **字符串插值**:`"Hello, \(name)!"` → `"Hello, " + name + "!"` ### 内存管理 @@ -159,7 +166,7 @@ mingw32-make -j4 # 构建 cd build && mingw32-make -j4 -# 运行全部测试 (158 单元 + 24 集成) +# 运行全部测试 (158 单元 + 29 集成) ./l_lang_lexer_test.exe # 词法分析 (41 tests) ./l_lang_test.exe # 语法分析 (15 tests) ./l_lang_sema_test.exe # 语义分析 (74 tests) diff --git a/docs/language-reference.md b/docs/language-reference.md index 704586b..fc8832b 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -1,6 +1,6 @@ # L Language 语言参考手册 -> 版本 v0.5 | 158 测试全部通过 | LLVM 后端编译型语言 +> 版本 v0.6 | 158 单元 + 29 集成测试全部通过 | LLVM 后端编译型语言 --- @@ -54,9 +54,12 @@ l_lang.exe hello.l -o hello.exe | 类型 | 关键字 | 范围/说明 | 示例 | |------|--------|----------|------| -| 整数 | `i64` | 64位有符号,`-2^63 ~ 2^63-1` | `42`, `-7`, `0` | +| 32位整数 | `i32` | 32位有符号,`-2^31 ~ 2^31-1` | `100` | +| 64位整数 | `i64` | 64位有符号,`-2^63 ~ 2^63-1` | `42`, `-7`, `0` | +| 无符号整数 | `u64` | 64位无符号,`0 ~ 2^64-1` | `999` | | 浮点 | `f64` | 64位双精度 | `3.14`, `-0.5`, `1.0` | | 布尔 | `bool` | `true` 或 `false` | `true`, `false` | +| 字符 | `char` | 单字符,ASCII | `'A'`, `'\n'` | | 字符串 | `str` | UTF-8 文本 | `"Hello"`, `"你好"` | | 空类型 | `void` | 无返回值 | 用于函数返回类型 | @@ -242,6 +245,67 @@ let result = add(3, 5); greet(); ``` +### 命名参数 + +调用函数时可以标注参数名,命名参数可任意顺序,但必须放在位置参数之后: + +```rust +fn draw_rect(x: i64, y: i64, w: i64, h: i64) -> void { + // ... +} + +draw_rect(0, 0, 100, 200); // 全位置 +draw_rect(x: 1, y: 2, w: 10, h: 20); // 全命名 +draw_rect(0, 0, w: 10, h: 20); // 混用 +draw_rect(w: 10, h: 20, x: 1, y: 2); // 命名任意顺序 +``` + +用 `:` 分隔参数名和值(与类型标注 `name: Type` 视觉统一)。 + +### guard 语句 + +guard 是提前返回的语法糖,用于提前处理异常条件: + +```rust +fn abs(x: i64) -> i64 { + guard x >= 0 else { return -x; } + return x; +} +// guard x >= 0 else { ... } 去糖为: +// if !(x >= 0) { ... } +``` + +- `else` 块必须用花括号,通常包含 `return`/`continue` 等跳转 +- guard 让正常路径的代码保持在左侧,提高可读性 + +### 管道 `|>` + +管道将数据从左到右流经函数,LHS 作为 RHS 函数调用的第一个参数(F#/Elixir 风格): + +```rust +fn double(x: i64) -> i64 { return x * 2; } +fn add(a: i64, b: i64) -> i64 { return a + b; } + +let result = 10 |> double() |> add(5); +// 去糖为: add(double(10), 5) → 25 +``` + +- 管道右侧必须是函数调用(带括号) +- 管道优先级低于所有算术运算符 + +### 字符串插值 + +用 `\(expr)` 在字符串中嵌入表达式(Swift 风格,`\` 与 C 转义字符视觉一致): + +```rust +let name = "World"; +let msg = "Hello, \(name)!"; +print_str(msg); // Hello, World! +``` + +- 去糖为字符串拼接: `"Hello, " + name + "!"` +- 字面量 `\(` 写作 `\\(`,反斜杠写作 `\\` + --- ## 7. 结构体 @@ -563,15 +627,17 @@ l_lang.exe source.l --emit-ir ## 快速参考卡片 ``` -类型: i64 f64 bool str void struct enum T[N] +类型: i32 i64 u64 f64 bool char str void struct enum T[N] 声明: let x = val var x = val let x: Type = val type Alias = Type -控制流: if/else while for i in 0 to N match +控制流: if/else while for i in 0 to N match guard 函数: fn name(p: T) -> Ret { return expr; } + func(name: val) 命名参数 expr |> func() 管道 结构体: struct Name { f: Type } Name { f: val } 枚举: enum Name { A, B, C } Name::B 方法: extend T { fn m(self: T) } obj.m() 内建: print_i64 print_f64 print_bool print_str -运算符: + - * / % == != < > <= >= && || ! += -= *= /= +运算符: + - * / % == != < > <= >= && || ! += -= *= /= |> +插值: "Hello, \(name)!" 注释: // 行注释 /* 块注释 */ ```