From ab4cc9a28bbdae8e284b961c490f28c287eecd76 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 19:47:00 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20let=20mut=20=E6=94=B9=E4=B8=BA=20var=20?= =?UTF-8?q?=E5=85=B3=E9=94=AE=E5=AD=97=E5=A3=B0=E6=98=8E=E5=8F=AF=E5=8F=98?= =?UTF-8?q?=E5=8F=98=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- docs/language-reference.md | 24 ++++++++++++------------ src/lexer/lexer.c | 2 +- src/lexer/token.c | 2 +- src/lexer/token.h | 2 +- src/parser/parser.c | 15 +++++++-------- src/sema/sema.c | 2 +- test/programs/06_mut_while.l | 2 +- test/programs/09_compound_assign.l | 2 +- test/test_sema.c | 2 +- 10 files changed, 27 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index a7ee7be..305eebd 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ graph TB | 无返回值 | `void` | 函数默认 | | 类型别名 | `type` | `type Meters = i64;` | -- `let` 不可变 + `let mut` 可变,类型推断 +- `let` 不可变 + `var` 可变,类型推断 - `i64` → `f64` 自动提升 ### 控制流 diff --git a/docs/language-reference.md b/docs/language-reference.md index 5a27475..90c8814 100644 --- a/docs/language-reference.md +++ b/docs/language-reference.md @@ -83,19 +83,19 @@ let flag = true; // 类型推断为 bool ### 可变变量 ```rust -let mut count: i64 = 0; // 可变变量 +var count: i64 = 0; // 可变变量 count = count + 1; // 赋值 count += 1; // 复合赋值 (等价于 count = count + 1) ``` -> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。 +> **规则**: 对 `let` 声明的不可变变量赋值会在编译时报错。可变变量用 `var` 声明。 ### 类型标注语法 ```rust -let name: Type = value; // 完整写法 -let name = value; // 类型推断 -let mut name: Type = value; // 可变变量 +let name: Type = value; // 完整写法(不可变) +let name = value; // 类型推断(不可变) +var name: Type = value; // 可变变量 ``` --- @@ -177,7 +177,7 @@ if x > 0 { ### while 循环 ```rust -let mut i: i64 = 0; +var i: i64 = 0; while i < 5 { print_i64(i); i += 1; @@ -194,7 +194,7 @@ for i in 0 to 5 { // 输出: 0 1 2 3 4 ``` -`for i in start to 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 @@ -373,8 +373,8 @@ print_i64(arr[1]); // 200 ### 循环遍历 ```rust -let mut arr: [i64; 5] = arr; -let mut i: i64 = 0; +var arr: [i64; 5] = arr; +var i: i64 = 0; while i < 5 { arr[i] = i * 10; i += 1; @@ -499,10 +499,10 @@ fn main() -> i64 { ```rust 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 { arr[i] = i * i; i += 1; @@ -564,7 +564,7 @@ l_lang.exe source.l --emit-ir ``` 类型: 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 控制流: if/else while for i in 0 to N match 函数: fn name(p: T) -> Ret { return expr; } diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 9882c34..9d55eaa 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -55,7 +55,7 @@ static Token lex_number(Lexer* l) { 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 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("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN); KW("to", TOK_TO); diff --git a/src/lexer/token.c b/src/lexer/token.c index 482a923..fcf7a73 100644 --- a/src/lexer/token.c +++ b/src/lexer/token.c @@ -5,7 +5,7 @@ #include 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_STRUCT] = "struct", [TOK_TYPE] = "type", [TOK_ENUM] = "enum", [TOK_IMPL] = "impl", [TOK_MATCH] = "match", diff --git a/src/lexer/token.h b/src/lexer/token.h index fc69f00..fb2e8d3 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -6,7 +6,7 @@ // === Token 类型枚举 === 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_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID, diff --git a/src/parser/parser.c b/src/parser/parser.c index 1dcc413..40fe190 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -472,11 +472,10 @@ static AstNode* parse_block(Parser* p, ErrorInfo* error) { static AstNode* parse_statement(Parser* p, ErrorInfo* error) { const Token* t = peek(p); - if (t->kind == TOK_LET) { - advance(p); - bool is_mut = false; - if (peek(p)->kind == TOK_MUT) { is_mut = true; advance(p); } - const Token* name = expect(p, TOK_IDENT, error, "let 后应为变量名"); + if (t->kind == TOK_LET || t->kind == TOK_VAR) { + bool is_mut = (advance(p)->kind == TOK_VAR); + const Token* name = expect(p, TOK_IDENT, error, + is_mut ? "var 后应为变量名" : "let 后应为变量名"); if (!name) return NULL; // 可选的类型标注 TypeKind annot_type = TYPE_UNKNOWN; @@ -558,11 +557,11 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) { if (!body) return NULL; // 脱糖: 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); - // 构建: 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)); // 构建: i < end (while 条件) @@ -589,7 +588,7 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) { // 构建: while i < end { ... body ... ; i = i + 1; } 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 = arena_alloc_impl(p->arena, 2 * sizeof(AstNode*)); memcpy(stmts, stmts_arr, 2 * sizeof(AstNode*)); diff --git a/src/sema/sema.c b/src/sema/sema.c index 43beee9..071c20a 100644 --- a/src/sema/sema.c +++ b/src/sema/sema.c @@ -683,7 +683,7 @@ static void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* } if (!sym->is_mut) { error_add(errors, "", node->loc.line, node->loc.col, - "不能对不可变变量 '%s' 赋值(需用 let mut 声明)", + "不能对不可变变量 '%s' 赋值(需用 var 声明)", node->as.assign_stmt.name); node->type.kind = TYPE_ERROR; break; diff --git a/test/programs/06_mut_while.l b/test/programs/06_mut_while.l index 9520090..eebd55b 100644 --- a/test/programs/06_mut_while.l +++ b/test/programs/06_mut_while.l @@ -1,5 +1,5 @@ fn main() -> i64 { - let mut i: i64 = 0; + var i: i64 = 0; while i < 5 { print_i64(i); i = i + 1; diff --git a/test/programs/09_compound_assign.l b/test/programs/09_compound_assign.l index dd21a54..d01dfdf 100644 --- a/test/programs/09_compound_assign.l +++ b/test/programs/09_compound_assign.l @@ -1,5 +1,5 @@ fn main() -> i64 { - let mut x: i64 = 10; + var x: i64 = 10; x += 5; print_i64(x); // 15 x -= 3; diff --git a/test/test_sema.c b/test/test_sema.c index 3215097..6b5d0b1 100644 --- a/test/test_sema.c +++ b/test/test_sema.c @@ -55,7 +55,7 @@ void test_let_mut_assign_ok() { Arena a = arena_create(1); size_t tc; ErrorInfo lex_err = {0}; 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); ASSERT(toks != NULL); ErrorInfo parse_err = {0};