feat: let mut 改为 var 关键字声明可变变量
This commit is contained in:
@@ -91,7 +91,7 @@ graph TB
|
|||||||
| 无返回值 | `void` | 函数默认 |
|
| 无返回值 | `void` | 函数默认 |
|
||||||
| 类型别名 | `type` | `type Meters = i64;` |
|
| 类型别名 | `type` | `type Meters = i64;` |
|
||||||
|
|
||||||
- `let` 不可变 + `let mut` 可变,类型推断
|
- `let` 不可变 + `var` 可变,类型推断
|
||||||
- `i64` → `f64` 自动提升
|
- `i64` → `f64` 自动提升
|
||||||
|
|
||||||
### 控制流
|
### 控制流
|
||||||
|
|||||||
+12
-12
@@ -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;
|
||||||
@@ -194,7 +194,7 @@ for i in 0 to 5 {
|
|||||||
// 输出: 0 1 2 3 4
|
// 输出: 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
|
### match
|
||||||
|
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -564,7 +564,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 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 to 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; }
|
||||||
|
|||||||
+1
-1
@@ -55,7 +55,7 @@ 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("to", TOK_TO);
|
||||||
|
|||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
#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_IMPL] = "impl",
|
||||||
[TOK_MATCH] = "match",
|
[TOK_MATCH] = "match",
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
// === 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_IMPL, TOK_MATCH,
|
||||||
// 类型关键字
|
// 类型关键字
|
||||||
TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
|
TOK_I64, TOK_F64, TOK_BOOL, TOK_STR, TOK_VOID,
|
||||||
|
|||||||
+7
-8
@@ -472,11 +472,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;
|
||||||
@@ -558,11 +557,11 @@ static AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
|||||||
if (!body) return NULL;
|
if (!body) return NULL;
|
||||||
|
|
||||||
// 脱糖: for i in start to 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 +588,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*));
|
||||||
|
|||||||
+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
-1
@@ -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};
|
||||||
|
|||||||
Reference in New Issue
Block a user