Compare commits
4 Commits
9a256d9be1
...
6fc599e6c2
| Author | SHA1 | Date | |
|---|---|---|---|
| 6fc599e6c2 | |||
| 175f8a6658 | |||
| ab4cc9a28b | |||
| a28d33854c |
@@ -87,18 +87,18 @@ graph TB
|
|||||||
| 字符串 | `str` | `"hello"` |
|
| 字符串 | `str` | `"hello"` |
|
||||||
| 结构体 | `struct` | `Point { x: i64, y: i64 }` |
|
| 结构体 | `struct` | `Point { x: i64, y: i64 }` |
|
||||||
| 枚举 | `enum` | `Color { Red, Green, Blue }` |
|
| 枚举 | `enum` | `Color { Red, Green, Blue }` |
|
||||||
| 数组 | `[T; N]` | `[i64; 10]` |
|
| 数组 | `T[N]` | `i64[10]` |
|
||||||
| 无返回值 | `void` | 函数默认 |
|
| 无返回值 | `void` | 函数默认 |
|
||||||
| 类型别名 | `type` | `type Meters = i64;` |
|
| 类型别名 | `type` | `type Meters = i64;` |
|
||||||
|
|
||||||
- `let` 不可变 + `let mut` 可变,类型推断
|
- `let` 不可变 + `var` 可变,类型推断
|
||||||
- `i64` → `f64` 自动提升
|
- `i64` → `f64` 自动提升
|
||||||
|
|
||||||
### 控制流
|
### 控制流
|
||||||
|
|
||||||
- `if` / `else` / `else if`
|
- `if` / `else` / `else if`
|
||||||
- `while` 循环
|
- `while` 循环
|
||||||
- `for i in 0..10` (去糖为 while)
|
- `for i in 0 to 10` (去糖为 while)
|
||||||
- `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else)
|
- `match expr { pat => { ... } _ => { ... } }` (去糖为 if-else)
|
||||||
- `return`
|
- `return`
|
||||||
|
|
||||||
@@ -106,7 +106,7 @@ graph TB
|
|||||||
|
|
||||||
- 多参数、递归、struct 参数/返回值
|
- 多参数、递归、struct 参数/返回值
|
||||||
- 返回类型校验
|
- 返回类型校验
|
||||||
- `impl StructName { fn method(self: Type) -> Ret { ... } }`
|
- `extend StructName { fn method(self: Type) -> Ret { ... } }`
|
||||||
- `instance.method(args)` 调用
|
- `instance.method(args)` 调用
|
||||||
- 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str`
|
- 内建函数:`print_i64`, `print_f64`, `print_bool`, `print_str`
|
||||||
|
|
||||||
|
|||||||
+22
-22
@@ -83,19 +83,19 @@ let flag = true; // 类型推断为 bool
|
|||||||
### 可变变量
|
### 可变变量
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut count: i64 = 0; // 可变变量
|
var count: i64 = 0; // 可变变量
|
||||||
count = count + 1; // 赋值
|
count = count + 1; // 赋值
|
||||||
count += 1; // 复合赋值 (等价于 count = count + 1)
|
count += 1; // 复合赋值 (等价于 count = count + 1)
|
||||||
```
|
```
|
||||||
|
|
||||||
> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。
|
> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。可变变量用 `var` 声明。
|
||||||
|
|
||||||
### 类型标注语法
|
### 类型标注语法
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let name: Type = value; // 完整写法
|
let name: Type = value; // 完整写法(不可变)
|
||||||
let name = value; // 类型推断
|
let name = value; // 类型推断(不可变)
|
||||||
let mut name: Type = value; // 可变变量
|
var name: Type = value; // 可变变量
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -177,7 +177,7 @@ if x > 0 {
|
|||||||
### while 循环
|
### while 循环
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut i: i64 = 0;
|
var i: i64 = 0;
|
||||||
while i < 5 {
|
while i < 5 {
|
||||||
print_i64(i);
|
print_i64(i);
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -188,13 +188,13 @@ while i < 5 {
|
|||||||
### for 循环
|
### for 循环
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
for i in 0..5 {
|
for i in 0 to 5 {
|
||||||
print_i64(i);
|
print_i64(i);
|
||||||
}
|
}
|
||||||
// 输出: 0 1 2 3 4
|
// 输出: 0 1 2 3 4
|
||||||
```
|
```
|
||||||
|
|
||||||
`for i in start..end` 等价于 `let mut i = start; while i < end { ...; i += 1; }`
|
`for i in start to end` 等价于 `var i = start; while i < end { ...; i += 1; }`
|
||||||
|
|
||||||
### match
|
### match
|
||||||
|
|
||||||
@@ -297,10 +297,10 @@ fn print_point(p: Point) -> void {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### impl — 方法
|
### extend — 方法
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
impl Point {
|
extend Point {
|
||||||
fn new(x: i64, y: i64) -> Point {
|
fn new(x: i64, y: i64) -> Point {
|
||||||
return Point { x: x, y: y };
|
return Point { x: x, y: y };
|
||||||
}
|
}
|
||||||
@@ -314,7 +314,7 @@ let p = Point.new(10, 20); // 方法调用
|
|||||||
print_i64(p.get_x()); // 10
|
print_i64(p.get_x()); // 10
|
||||||
```
|
```
|
||||||
|
|
||||||
- `impl StructName { fn ... }` 定义方法
|
- `extend StructName { fn ... }` 为结构体扩展方法
|
||||||
- 第一个参数必须是 `self: StructName`
|
- 第一个参数必须是 `self: StructName`
|
||||||
- 调用: `instance.method(args)`
|
- 调用: `instance.method(args)`
|
||||||
|
|
||||||
@@ -350,10 +350,10 @@ let is_red = (c == Color::Red); // false
|
|||||||
### 声明类型
|
### 声明类型
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let arr: [i64; 5] = arr; // 声明未初始化的 5 个 i64 数组
|
let arr: i64[5] = arr; // 声明未初始化的 5 个 i64 数组
|
||||||
```
|
```
|
||||||
|
|
||||||
数组类型语法: `[元素类型; 大小]`
|
数组类型语法: `元素类型[大小]`(后置维度)
|
||||||
|
|
||||||
- `= arr` 是固定写法,表示声明未初始化的数组(`arr` 是变量名自身)
|
- `= arr` 是固定写法,表示声明未初始化的数组(`arr` 是变量名自身)
|
||||||
- 大小必须是整数常量
|
- 大小必须是整数常量
|
||||||
@@ -373,8 +373,8 @@ print_i64(arr[1]); // 200
|
|||||||
### 循环遍历
|
### 循环遍历
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
let mut arr: [i64; 5] = arr;
|
var arr: i64[5] = arr;
|
||||||
let mut i: i64 = 0;
|
var i: i64 = 0;
|
||||||
while i < 5 {
|
while i < 5 {
|
||||||
arr[i] = i * 10;
|
arr[i] = i * 10;
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -456,7 +456,7 @@ struct Student {
|
|||||||
score: i64,
|
score: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Student {
|
extend Student {
|
||||||
fn new(id: i64, score: i64) -> Student {
|
fn new(id: i64, score: i64) -> Student {
|
||||||
return Student { name_id: id, score: score };
|
return Student { name_id: id, score: score };
|
||||||
}
|
}
|
||||||
@@ -499,10 +499,10 @@ fn main() -> i64 {
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let mut arr: [i64; 5] = arr;
|
var arr: i64[5] = arr;
|
||||||
|
|
||||||
// 填充数组
|
// 填充数组
|
||||||
let mut i: i64 = 0;
|
var i: i64 = 0;
|
||||||
while i < 5 {
|
while i < 5 {
|
||||||
arr[i] = i * i;
|
arr[i] = i * i;
|
||||||
i += 1;
|
i += 1;
|
||||||
@@ -563,14 +563,14 @@ l_lang.exe source.l --emit-ir
|
|||||||
## 快速参考卡片
|
## 快速参考卡片
|
||||||
|
|
||||||
```
|
```
|
||||||
类型: i64 f64 bool str void struct enum [T;N]
|
类型: i64 f64 bool str void struct enum T[N]
|
||||||
声明: let x = val let mut x = val
|
声明: let x = val var x = val
|
||||||
let x: Type = val type Alias = Type
|
let x: Type = val type Alias = Type
|
||||||
控制流: if/else while for i in 0..N match
|
控制流: if/else while for i in 0 to N match
|
||||||
函数: fn name(p: T) -> Ret { return expr; }
|
函数: fn name(p: T) -> Ret { return expr; }
|
||||||
结构体: struct Name { f: Type } Name { f: val }
|
结构体: struct Name { f: Type } Name { f: val }
|
||||||
枚举: enum Name { A, B, C } Name::B
|
枚举: enum Name { A, B, C } Name::B
|
||||||
方法: impl T { fn m(self: T) } obj.m()
|
方法: extend T { fn m(self: T) } obj.m()
|
||||||
内建: print_i64 print_f64 print_bool print_str
|
内建: print_i64 print_f64 print_bool print_str
|
||||||
运算符: + - * / % == != < > <= >= && || ! += -= *= /=
|
运算符: + - * / % == != < > <= >= && || ! += -= *= /=
|
||||||
注释: // 行注释 /* 块注释 */
|
注释: // 行注释 /* 块注释 */
|
||||||
|
|||||||
+3
-3
@@ -55,15 +55,16 @@ static Token lex_number(Lexer* l) {
|
|||||||
static TokenKind check_keyword(const Token* tok) {
|
static TokenKind check_keyword(const Token* tok) {
|
||||||
#define KW(s, k) if (tok->length == sizeof(s)-1 && memcmp(tok->start, s, sizeof(s)-1) == 0) return k
|
#define KW(s, k) if (tok->length == sizeof(s)-1 && memcmp(tok->start, s, sizeof(s)-1) == 0) return k
|
||||||
KW("fn", TOK_FN); KW("let", TOK_LET);
|
KW("fn", TOK_FN); KW("let", TOK_LET);
|
||||||
KW("mut", TOK_MUT);
|
KW("var", TOK_VAR);
|
||||||
KW("if", TOK_IF); KW("else", TOK_ELSE);
|
KW("if", TOK_IF); KW("else", TOK_ELSE);
|
||||||
KW("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN);
|
KW("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN);
|
||||||
|
KW("to", TOK_TO);
|
||||||
KW("return", TOK_RETURN);
|
KW("return", TOK_RETURN);
|
||||||
KW("i64", TOK_I64); KW("f64", TOK_F64);
|
KW("i64", TOK_I64); KW("f64", TOK_F64);
|
||||||
KW("bool", TOK_BOOL); KW("str", TOK_STR);
|
KW("bool", TOK_BOOL); KW("str", TOK_STR);
|
||||||
KW("void", TOK_VOID);
|
KW("void", TOK_VOID);
|
||||||
KW("struct", TOK_STRUCT); KW("type", TOK_TYPE);
|
KW("struct", TOK_STRUCT); KW("type", TOK_TYPE);
|
||||||
KW("enum", TOK_ENUM); KW("impl", TOK_IMPL); KW("match", TOK_MATCH);
|
KW("enum", TOK_ENUM); KW("extend", TOK_EXTEND); KW("match", TOK_MATCH);
|
||||||
KW("_", TOK_UNDERSCORE);
|
KW("_", TOK_UNDERSCORE);
|
||||||
KW("true", TOK_TRUE); KW("false", TOK_FALSE);
|
KW("true", TOK_TRUE); KW("false", TOK_FALSE);
|
||||||
#undef KW
|
#undef KW
|
||||||
@@ -137,7 +138,6 @@ Token* lex(Arena* a, const char* source, const char* filename,
|
|||||||
else if (c == '>') { tokens[idx++] = make_token(&l, TOK_GT, l.pos, 1); advance(&l); }
|
else if (c == '>') { tokens[idx++] = make_token(&l, TOK_GT, l.pos, 1); advance(&l); }
|
||||||
else if (c == '&' && peek_next(&l) == '&') { tokens[idx++] = make_token(&l, TOK_AND_AND, l.pos, 2); advance(&l); advance(&l); }
|
else if (c == '&' && peek_next(&l) == '&') { tokens[idx++] = make_token(&l, TOK_AND_AND, l.pos, 2); advance(&l); advance(&l); }
|
||||||
else if (c == '|' && peek_next(&l) == '|') { tokens[idx++] = make_token(&l, TOK_PIPE_PIPE, l.pos, 2); advance(&l); advance(&l); }
|
else if (c == '|' && peek_next(&l) == '|') { tokens[idx++] = make_token(&l, TOK_PIPE_PIPE, l.pos, 2); advance(&l); advance(&l); }
|
||||||
else if (c == '.' && peek_next(&l) == '.') { tokens[idx++] = make_token(&l, TOK_DOT_DOT, l.pos, 2); advance(&l); advance(&l); }
|
|
||||||
else if (c == '.') { tokens[idx++] = make_token(&l, TOK_DOT, l.pos, 1); advance(&l); }
|
else if (c == '.') { tokens[idx++] = make_token(&l, TOK_DOT, l.pos, 1); advance(&l); }
|
||||||
else if (c == '[') { tokens[idx++] = make_token(&l, TOK_LBRACKET, l.pos, 1); advance(&l); }
|
else if (c == '[') { tokens[idx++] = make_token(&l, TOK_LBRACKET, l.pos, 1); advance(&l); }
|
||||||
else if (c == ']') { tokens[idx++] = make_token(&l, TOK_RBRACKET, l.pos, 1); advance(&l); }
|
else if (c == ']') { tokens[idx++] = make_token(&l, TOK_RBRACKET, l.pos, 1); advance(&l); }
|
||||||
|
|||||||
+3
-3
@@ -5,9 +5,9 @@
|
|||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
static const char* NAMES[] = {
|
static const char* NAMES[] = {
|
||||||
[TOK_FN] = "fn", [TOK_LET] = "let", [TOK_MUT] = "mut", [TOK_IF] = "if",
|
[TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_IF] = "if",
|
||||||
[TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return",
|
[TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return",
|
||||||
[TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_IMPL] = "impl",
|
[TOK_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_EXTEND] = "extend",
|
||||||
[TOK_MATCH] = "match",
|
[TOK_MATCH] = "match",
|
||||||
[TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void",
|
[TOK_I64] = "i64", [TOK_F64] = "f64", [TOK_BOOL] = "bool", [TOK_STR] = "str", [TOK_VOID] = "void",
|
||||||
[TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串",
|
[TOK_INT_LIT] = "整数", [TOK_FLOAT_LIT] = "浮点数", [TOK_STR_LIT] = "字符串",
|
||||||
@@ -18,7 +18,7 @@ static const char* NAMES[] = {
|
|||||||
[TOK_EQ_EQ] = "==", [TOK_BANG_EQ] = "!=",
|
[TOK_EQ_EQ] = "==", [TOK_BANG_EQ] = "!=",
|
||||||
[TOK_LT] = "<", [TOK_GT] = ">", [TOK_LT_EQ] = "<=", [TOK_GT_EQ] = ">=",
|
[TOK_LT] = "<", [TOK_GT] = ">", [TOK_LT_EQ] = "<=", [TOK_GT_EQ] = ">=",
|
||||||
[TOK_AND_AND] = "&&", [TOK_PIPE_PIPE] = "||", [TOK_BANG] = "!",
|
[TOK_AND_AND] = "&&", [TOK_PIPE_PIPE] = "||", [TOK_BANG] = "!",
|
||||||
[TOK_ARROW] = "->", [TOK_DOT_DOT] = "..", [TOK_MATCH_ARROW] = "=>",
|
[TOK_ARROW] = "->", [TOK_TO] = "to", [TOK_MATCH_ARROW] = "=>",
|
||||||
[TOK_PLUS_EQ] = "+=", [TOK_MINUS_EQ] = "-=", [TOK_STAR_EQ] = "*=", [TOK_SLASH_EQ] = "/=",
|
[TOK_PLUS_EQ] = "+=", [TOK_MINUS_EQ] = "-=", [TOK_STAR_EQ] = "*=", [TOK_SLASH_EQ] = "/=",
|
||||||
[TOK_LPAREN] = "(", [TOK_RPAREN] = ")",
|
[TOK_LPAREN] = "(", [TOK_RPAREN] = ")",
|
||||||
[TOK_LBRACE] = "{", [TOK_RBRACE] = "}",
|
[TOK_LBRACE] = "{", [TOK_RBRACE] = "}",
|
||||||
|
|||||||
+3
-3
@@ -6,8 +6,8 @@
|
|||||||
// === Token 类型枚举 ===
|
// === Token 类型枚举 ===
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// 关键字
|
// 关键字
|
||||||
TOK_FN, TOK_LET, TOK_MUT, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN,
|
TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN,
|
||||||
TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_IMPL, TOK_MATCH,
|
TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_MATCH,
|
||||||
// 类型关键字
|
// 类型关键字
|
||||||
TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
|
TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
|
||||||
// 字面量
|
// 字面量
|
||||||
@@ -18,7 +18,7 @@ typedef enum {
|
|||||||
TOK_PLUS, TOK_MINUS, TOK_STAR, TOK_SLASH, TOK_PERCENT,
|
TOK_PLUS, TOK_MINUS, TOK_STAR, TOK_SLASH, TOK_PERCENT,
|
||||||
TOK_EQ_EQ, TOK_BANG_EQ, TOK_LT, TOK_GT, TOK_LT_EQ, TOK_GT_EQ,
|
TOK_EQ_EQ, TOK_BANG_EQ, TOK_LT, TOK_GT, TOK_LT_EQ, TOK_GT_EQ,
|
||||||
TOK_AND_AND, TOK_PIPE_PIPE, TOK_BANG,
|
TOK_AND_AND, TOK_PIPE_PIPE, TOK_BANG,
|
||||||
TOK_ARROW, TOK_DOT_DOT, TOK_MATCH_ARROW,
|
TOK_ARROW, TOK_TO, TOK_MATCH_ARROW,
|
||||||
TOK_PLUS_EQ, TOK_MINUS_EQ, TOK_STAR_EQ, TOK_SLASH_EQ,
|
TOK_PLUS_EQ, TOK_MINUS_EQ, TOK_STAR_EQ, TOK_SLASH_EQ,
|
||||||
// 分隔符
|
// 分隔符
|
||||||
TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE,
|
TOK_LPAREN, TOK_RPAREN, TOK_LBRACE, TOK_RBRACE,
|
||||||
|
|||||||
+37
-39
@@ -282,32 +282,12 @@ static TypeKind token_to_type(TokenKind k) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// === 类型表达式解析(内置类型/结构体名/数组类型)===
|
// === 类型表达式解析(内置类型/结构体名/数组类型)===
|
||||||
|
// 数组支持后置语法: T[N], T[N][M] 等
|
||||||
static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
|
static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
|
||||||
const Token* t = peek(p);
|
const Token* t = peek(p);
|
||||||
|
|
||||||
// 数组类型: [element_type; size]
|
|
||||||
if (t->kind == TOK_LBRACKET) {
|
|
||||||
advance(p); // 跳过 '['
|
|
||||||
TypeInfo elem = parse_type_expr(p, error);
|
|
||||||
if (elem.kind == TYPE_ERROR) return elem;
|
|
||||||
if (!expect(p, TOK_SEMICOLON, error, "数组类型中缺少 ';'")) {
|
|
||||||
TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti;
|
|
||||||
}
|
|
||||||
const Token* size_tok = expect(p, TOK_INT_LIT, error, "数组大小必须是整数常量");
|
|
||||||
if (!size_tok) { TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti; }
|
|
||||||
int64_t size = tok_int_value(size_tok);
|
|
||||||
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) {
|
|
||||||
TypeInfo ti = {0}; ti.kind = TYPE_ERROR; return ti;
|
|
||||||
}
|
|
||||||
TypeInfo ti = {0};
|
|
||||||
ti.kind = TYPE_ARRAY;
|
|
||||||
ti.element_type = elem.kind;
|
|
||||||
ti.element_struct_name = elem.struct_name;
|
|
||||||
ti.array_size = size;
|
|
||||||
return ti;
|
|
||||||
}
|
|
||||||
|
|
||||||
TypeInfo ti = {0};
|
TypeInfo ti = {0};
|
||||||
|
|
||||||
|
// 解析基础类型
|
||||||
if (tok_is_type(t->kind)) {
|
if (tok_is_type(t->kind)) {
|
||||||
advance(p);
|
advance(p);
|
||||||
ti.kind = token_to_type(t->kind);
|
ti.kind = token_to_type(t->kind);
|
||||||
@@ -319,7 +299,26 @@ static TypeInfo parse_type_expr(Parser* p, ErrorInfo* error) {
|
|||||||
error->message = "无效的类型"; error->filename = p->filename;
|
error->message = "无效的类型"; error->filename = p->filename;
|
||||||
error->line = t->line; error->col = t->col;
|
error->line = t->line; error->col = t->col;
|
||||||
ti.kind = TYPE_ERROR;
|
ti.kind = TYPE_ERROR;
|
||||||
|
return ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 后置数组维度: Type[N] → TYPE_ARRAY
|
||||||
|
if (peek(p)->kind == TOK_LBRACKET) {
|
||||||
|
advance(p); // 跳过 '['
|
||||||
|
const Token* size_tok = expect(p, TOK_INT_LIT, error, "数组大小必须是整数常量");
|
||||||
|
if (!size_tok) { ti.kind = TYPE_ERROR; return ti; }
|
||||||
|
int64_t size = tok_int_value(size_tok);
|
||||||
|
if (!expect(p, TOK_RBRACKET, error, "缺少 ']'")) {
|
||||||
|
ti.kind = TYPE_ERROR; return ti;
|
||||||
|
}
|
||||||
|
TypeInfo arr_ti = {0};
|
||||||
|
arr_ti.kind = TYPE_ARRAY;
|
||||||
|
arr_ti.element_type = ti.kind;
|
||||||
|
arr_ti.element_struct_name = ti.struct_name;
|
||||||
|
arr_ti.array_size = size;
|
||||||
|
return arr_ti;
|
||||||
|
}
|
||||||
|
|
||||||
return ti;
|
return ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,11 +471,10 @@ static AstNode* parse_block(Parser* p, ErrorInfo* error) {
|
|||||||
static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
||||||
const Token* t = peek(p);
|
const Token* t = peek(p);
|
||||||
|
|
||||||
if (t->kind == TOK_LET) {
|
if (t->kind == TOK_LET || t->kind == TOK_VAR) {
|
||||||
advance(p);
|
bool is_mut = (advance(p)->kind == TOK_VAR);
|
||||||
bool is_mut = false;
|
const Token* name = expect(p, TOK_IDENT, error,
|
||||||
if (peek(p)->kind == TOK_MUT) { is_mut = true; advance(p); }
|
is_mut ? "var 后应为变量名" : "let 后应为变量名");
|
||||||
const Token* name = expect(p, TOK_IDENT, error, "let 后应为变量名");
|
|
||||||
if (!name) return NULL;
|
if (!name) return NULL;
|
||||||
// 可选的类型标注
|
// 可选的类型标注
|
||||||
TypeKind annot_type = TYPE_UNKNOWN;
|
TypeKind annot_type = TYPE_UNKNOWN;
|
||||||
@@ -546,8 +544,8 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
|||||||
AstNode* start_expr = parse_expr(p, error);
|
AstNode* start_expr = parse_expr(p, error);
|
||||||
if (!start_expr) return NULL;
|
if (!start_expr) return NULL;
|
||||||
|
|
||||||
// 解析 '..'
|
// 解析 'to'
|
||||||
if (!expect(p, TOK_DOT_DOT, error, "缺少 '..'")) return NULL;
|
if (!expect(p, TOK_TO, error, "缺少 'to'")) return NULL;
|
||||||
|
|
||||||
// 解析结束表达式
|
// 解析结束表达式
|
||||||
AstNode* end_expr = parse_expr(p, error);
|
AstNode* end_expr = parse_expr(p, error);
|
||||||
@@ -557,12 +555,12 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
|||||||
AstNode* body = parse_block(p, error);
|
AstNode* body = parse_block(p, error);
|
||||||
if (!body) return NULL;
|
if (!body) return NULL;
|
||||||
|
|
||||||
// 脱糖: for i in start..end { body; }
|
// 脱糖: for i in start to end { body; }
|
||||||
// → { let mut i = start; while i < end { body; i = i + 1; } }
|
// → { var i = start; while i < end { body; i = i + 1; } }
|
||||||
|
|
||||||
const char* vname = arena_strdup_impl(p->arena, var_name->start, var_name->length);
|
const char* vname = arena_strdup_impl(p->arena, var_name->start, var_name->length);
|
||||||
|
|
||||||
// 构建: let mut i = start;
|
// 构建: var i = start;
|
||||||
AstNode* let_stmt = ast_make_let(p->arena, vname, TYPE_UNKNOWN, false, true, start_expr, NULL, 0, NULL, 0, tok_loc(var_name));
|
AstNode* let_stmt = ast_make_let(p->arena, vname, TYPE_UNKNOWN, false, true, start_expr, NULL, 0, NULL, 0, tok_loc(var_name));
|
||||||
|
|
||||||
// 构建: i < end (while 条件)
|
// 构建: i < end (while 条件)
|
||||||
@@ -589,7 +587,7 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
|||||||
// 构建: while i < end { ... body ... ; i = i + 1; }
|
// 构建: while i < end { ... body ... ; i = i + 1; }
|
||||||
AstNode* while_loop = ast_make_while(p->arena, cond, new_body, tok_loc(t));
|
AstNode* while_loop = ast_make_while(p->arena, cond, new_body, tok_loc(t));
|
||||||
|
|
||||||
// 包装: { let mut i = start; while i < end { ... } }
|
// 包装: { var i = start; while i < end { ... } }
|
||||||
AstNode* stmts_arr[2] = { let_stmt, while_loop };
|
AstNode* stmts_arr[2] = { let_stmt, while_loop };
|
||||||
AstNode** stmts = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*));
|
AstNode** stmts = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*));
|
||||||
memcpy(stmts, stmts_arr, 2 * sizeof(AstNode*));
|
memcpy(stmts, stmts_arr, 2 * sizeof(AstNode*));
|
||||||
@@ -779,21 +777,21 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
|||||||
AstNode* enum_decl = ast_make_enum_decl(p.arena, arena_strdup_impl(p.arena, name->start, name->length), v_arr, vcount, tok_loc(name));
|
AstNode* enum_decl = ast_make_enum_decl(p.arena, arena_strdup_impl(p.arena, name->start, name->length), v_arr, vcount, tok_loc(name));
|
||||||
if (enum_count >= 64) { error->message = "枚举过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
if (enum_count >= 64) { error->message = "枚举过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||||
enums[enum_count++] = enum_decl;
|
enums[enum_count++] = enum_decl;
|
||||||
} else if (peek(&p)->kind == TOK_IMPL) {
|
} else if (peek(&p)->kind == TOK_EXTEND) {
|
||||||
const Token* i_tok = advance(&p);
|
const Token* i_tok = advance(&p);
|
||||||
const Token* st_name = expect(&p, TOK_IDENT, error, "impl 后应为结构体名");
|
const Token* st_name = expect(&p, TOK_IDENT, error, "extend 后应为结构体名");
|
||||||
if (!st_name) return NULL;
|
if (!st_name) return NULL;
|
||||||
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
|
if (!expect(&p, TOK_LBRACE, error, "缺少 '{'")) return NULL;
|
||||||
AstNode* methods[64]; int mcount = 0;
|
AstNode* methods[64]; int mcount = 0;
|
||||||
while (peek(&p)->kind != TOK_RBRACE && !error->message) {
|
while (peek(&p)->kind != TOK_RBRACE && !error->message) {
|
||||||
if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
if (mcount >= 64) { error->message = "方法过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||||
if (peek(&p)->kind != TOK_FN) { error->message = "impl 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
if (peek(&p)->kind != TOK_FN) { error->message = "extend 块内只允许 fn"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||||
methods[mcount++] = parse_function(&p, error);
|
methods[mcount++] = parse_function(&p, error);
|
||||||
}
|
}
|
||||||
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
|
if (!expect(&p, TOK_RBRACE, error, "缺少 '}'")) return NULL;
|
||||||
AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
|
AstNode** m_arr = arena_alloc_impl(p.arena, mcount * sizeof(AstNode*));
|
||||||
memcpy(m_arr, methods, mcount * sizeof(AstNode*));
|
memcpy(m_arr, methods, mcount * sizeof(AstNode*));
|
||||||
if (impl_count >= 64) { error->message = "impl 块过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
if (impl_count >= 64) { error->message = "extend 块过多 (最多64)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||||
impls[impl_count++] = ast_make_impl_block(p.arena,
|
impls[impl_count++] = ast_make_impl_block(p.arena,
|
||||||
arena_strdup_impl(p.arena, st_name->start, st_name->length),
|
arena_strdup_impl(p.arena, st_name->start, st_name->length),
|
||||||
m_arr, mcount, tok_loc(i_tok));
|
m_arr, mcount, tok_loc(i_tok));
|
||||||
@@ -801,7 +799,7 @@ AstNode* parse(Arena* a, const Token* tokens, size_t count,
|
|||||||
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
if (fn_count >= 256) { error->message = "函数过多 (最多256)"; error->filename = p.filename; error->line = peek(&p)->line; error->col = peek(&p)->col; return NULL; }
|
||||||
functions[fn_count++] = parse_function(&p, error);
|
functions[fn_count++] = parse_function(&p, error);
|
||||||
} else {
|
} else {
|
||||||
error->message = "顶层只允许 fn、struct、type、enum 或 impl";
|
error->message = "顶层只允许 fn、struct、type、enum 或 extend";
|
||||||
error->filename = p.filename;
|
error->filename = p.filename;
|
||||||
error->line = peek(&p)->line;
|
error->line = peek(&p)->line;
|
||||||
error->col = peek(&p)->col;
|
error->col = peek(&p)->col;
|
||||||
|
|||||||
+1
-1
@@ -683,7 +683,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena*
|
|||||||
}
|
}
|
||||||
if (!sym->is_mut) {
|
if (!sym->is_mut) {
|
||||||
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
error_add(errors, "<sema>", node->loc.line, node->loc.col,
|
||||||
"不能对不可变变量 '%s' 赋值(需用 let mut 声明)",
|
"不能对不可变变量 '%s' 赋值(需用 var 声明)",
|
||||||
node->as.assign_stmt.name);
|
node->as.assign_stmt.name);
|
||||||
node->type.kind = TYPE_ERROR;
|
node->type.kind = TYPE_ERROR;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let mut i: i64 = 0;
|
var i: i64 = 0;
|
||||||
while i < 5 {
|
while i < 5 {
|
||||||
print_i64(i);
|
print_i64(i);
|
||||||
i = i + 1;
|
i = i + 1;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let mut x: i64 = 10;
|
var x: i64 = 10;
|
||||||
x += 5;
|
x += 5;
|
||||||
print_i64(x); // 15
|
print_i64(x); // 15
|
||||||
x -= 3;
|
x -= 3;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
for i in 0..5 {
|
for i in 0 to 5 {
|
||||||
print_i64(i);
|
print_i64(i);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let start: i64 = 10;
|
let start: i64 = 10;
|
||||||
let end: i64 = 15;
|
let end: i64 = 15;
|
||||||
for n in start..end {
|
for n in start to end {
|
||||||
print_i64(n);
|
print_i64(n);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let arr: [i64; 3] = arr;
|
let arr: i64[3] = arr;
|
||||||
arr[0] = 10;
|
arr[0] = 10;
|
||||||
arr[1] = 20;
|
arr[1] = 20;
|
||||||
arr[2] = 30;
|
arr[2] = 30;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
struct Point { x: i64, y: i64 }
|
struct Point { x: i64, y: i64 }
|
||||||
|
|
||||||
impl Point {
|
extend Point {
|
||||||
fn get_x(self: Point) -> i64 {
|
fn get_x(self: Point) -> i64 {
|
||||||
return self.x;
|
return self.x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
struct Point { x: i64, y: i64 }
|
struct Point { x: i64, y: i64 }
|
||||||
|
|
||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let arr: [Point; 2] = arr;
|
let arr: Point[2] = arr;
|
||||||
arr[0] = Point { x: 10, y: 20 };
|
arr[0] = Point { x: 10, y: 20 };
|
||||||
arr[1] = Point { x: 30, y: 40 };
|
arr[1] = Point { x: 30, y: 40 };
|
||||||
print_i64(arr[0].x);
|
print_i64(arr[0].x);
|
||||||
|
|||||||
+2
-2
@@ -292,13 +292,13 @@ void test_codegen_array() {
|
|||||||
|
|
||||||
/* 构造 AST:
|
/* 构造 AST:
|
||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
let arr: [i64; 3] = arr;
|
let arr: i64[3] = arr;
|
||||||
arr[0] = 10;
|
arr[0] = 10;
|
||||||
print_i64(arr[0]);
|
print_i64(arr[0]);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// let arr: [i64; 3] = arr;
|
// let arr: i64[3] = arr;
|
||||||
AstNode* arr_init = ast_make_ident(&a, "arr", loc_at(1, 1));
|
AstNode* arr_init = ast_make_ident(&a, "arr", loc_at(1, 1));
|
||||||
AstNode* let_stmt = ast_make_let(&a, "arr", TYPE_ARRAY, true, false,
|
AstNode* let_stmt = ast_make_let(&a, "arr", TYPE_ARRAY, true, false,
|
||||||
arr_init, NULL, TYPE_I64, NULL, 3, loc_at(1, 1));
|
arr_init, NULL, TYPE_I64, NULL, 3, loc_at(1, 1));
|
||||||
|
|||||||
+5
-5
@@ -55,7 +55,7 @@ void test_let_mut_assign_ok() {
|
|||||||
Arena a = arena_create(1);
|
Arena a = arena_create(1);
|
||||||
size_t tc; ErrorInfo lex_err = {0};
|
size_t tc; ErrorInfo lex_err = {0};
|
||||||
Token* toks = lex(&a,
|
Token* toks = lex(&a,
|
||||||
"fn main() { let mut x: i64 = 0; x = 42; print_i64(x); return; }",
|
"fn main() { var x: i64 = 0; x = 42; print_i64(x); return; }",
|
||||||
"test", &tc, &lex_err);
|
"test", &tc, &lex_err);
|
||||||
ASSERT(toks != NULL);
|
ASSERT(toks != NULL);
|
||||||
ErrorInfo parse_err = {0};
|
ErrorInfo parse_err = {0};
|
||||||
@@ -265,7 +265,7 @@ void test_array_ok() {
|
|||||||
Arena a = arena_create(1);
|
Arena a = arena_create(1);
|
||||||
size_t tc; ErrorInfo lex_err = {0};
|
size_t tc; ErrorInfo lex_err = {0};
|
||||||
Token* toks = lex(&a,
|
Token* toks = lex(&a,
|
||||||
"fn main() { let arr: [i64; 3] = arr; arr[0]; return; }",
|
"fn main() { let arr: i64[3] = arr; arr[0]; return; }",
|
||||||
"test", &tc, &lex_err);
|
"test", &tc, &lex_err);
|
||||||
ASSERT(toks != NULL);
|
ASSERT(toks != NULL);
|
||||||
ErrorInfo parse_err = {0};
|
ErrorInfo parse_err = {0};
|
||||||
@@ -282,7 +282,7 @@ void test_array_index_type_error() {
|
|||||||
Arena a = arena_create(1);
|
Arena a = arena_create(1);
|
||||||
size_t tc; ErrorInfo lex_err = {0};
|
size_t tc; ErrorInfo lex_err = {0};
|
||||||
Token* toks = lex(&a,
|
Token* toks = lex(&a,
|
||||||
"fn main() { let arr: [i64; 3] = arr; arr[true]; return; }",
|
"fn main() { let arr: i64[3] = arr; arr[true]; return; }",
|
||||||
"test", &tc, &lex_err);
|
"test", &tc, &lex_err);
|
||||||
ASSERT(toks != NULL);
|
ASSERT(toks != NULL);
|
||||||
ErrorInfo parse_err = {0};
|
ErrorInfo parse_err = {0};
|
||||||
@@ -316,7 +316,7 @@ void test_array_assign_ok() {
|
|||||||
Arena a = arena_create(1);
|
Arena a = arena_create(1);
|
||||||
size_t tc; ErrorInfo lex_err = {0};
|
size_t tc; ErrorInfo lex_err = {0};
|
||||||
Token* toks = lex(&a,
|
Token* toks = lex(&a,
|
||||||
"fn main() { let arr: [i64; 3] = arr; arr[0] = 42; return; }",
|
"fn main() { let arr: i64[3] = arr; arr[0] = 42; return; }",
|
||||||
"test", &tc, &lex_err);
|
"test", &tc, &lex_err);
|
||||||
ASSERT(toks != NULL);
|
ASSERT(toks != NULL);
|
||||||
ErrorInfo parse_err = {0};
|
ErrorInfo parse_err = {0};
|
||||||
@@ -335,7 +335,7 @@ void test_method_call_ok() {
|
|||||||
Arena a = arena_create(1);
|
Arena a = arena_create(1);
|
||||||
size_t tc; ErrorInfo lex_err = {0};
|
size_t tc; ErrorInfo lex_err = {0};
|
||||||
Token* toks = lex(&a,
|
Token* toks = lex(&a,
|
||||||
"struct Point { x: i64, y: i64 } impl Point { fn get_x(self: Point) -> i64 { return self.x; } } fn main() -> i64 { let p: Point = Point { x: 42, y: 0 }; return p.get_x(); }",
|
"struct Point { x: i64, y: i64 } extend Point { fn get_x(self: Point) -> i64 { return self.x; } } fn main() -> i64 { let p: Point = Point { x: 42, y: 0 }; return p.get_x(); }",
|
||||||
"test", &tc, &lex_err);
|
"test", &tc, &lex_err);
|
||||||
ASSERT(toks != NULL);
|
ASSERT(toks != NULL);
|
||||||
ErrorInfo parse_err = {0};
|
ErrorInfo parse_err = {0};
|
||||||
|
|||||||
Reference in New Issue
Block a user