feat: 数组类型语法 [T; N] 改为 T[N] 后置语法
This commit is contained in:
@@ -87,7 +87,7 @@ 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;` |
|
||||||
|
|
||||||
|
|||||||
@@ -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,7 +373,7 @@ print_i64(arr[1]); // 200
|
|||||||
### 循环遍历
|
### 循环遍历
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
var arr: [i64; 5] = arr;
|
var arr: i64[5] = arr;
|
||||||
var i: i64 = 0;
|
var i: i64 = 0;
|
||||||
while i < 5 {
|
while i < 5 {
|
||||||
arr[i] = i * 10;
|
arr[i] = i * 10;
|
||||||
@@ -499,7 +499,7 @@ fn main() -> i64 {
|
|||||||
|
|
||||||
```rust
|
```rust
|
||||||
fn main() -> i64 {
|
fn main() -> i64 {
|
||||||
var arr: [i64; 5] = arr;
|
var arr: i64[5] = arr;
|
||||||
|
|
||||||
// 填充数组
|
// 填充数组
|
||||||
var i: i64 = 0;
|
var i: i64 = 0;
|
||||||
@@ -563,7 +563,7 @@ 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 var 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 to N match
|
控制流: if/else while for i in 0 to N match
|
||||||
|
|||||||
+22
-23
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,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));
|
||||||
|
|||||||
+3
-3
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user