diff --git a/src/ast/ast.c b/src/ast/ast.c index c6541dc..ab79c1b 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -67,6 +67,7 @@ AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool h NEW(alloc, AST_LET_STMT); n->as.let_stmt.name = name; n->as.let_stmt.annot_type = annot_type; n->as.let_stmt.has_type_annot = has_type_annot; n->as.let_stmt.is_mut = is_mut; + n->as.let_stmt.is_const = false; n->as.let_stmt.init = init; n->as.let_stmt.struct_type_name = struct_type_name; n->as.let_stmt.annot_element_type = annot_elem_type; diff --git a/src/ast/ast.h b/src/ast/ast.h index aa4b9dc..435f5cc 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -78,7 +78,7 @@ struct AstNode { // AST_BLOCK struct { struct AstNode** stmts; size_t stmt_count; } block; // AST_LET_STMT - struct { const char* name; TypeKind annot_type; bool has_type_annot; bool is_mut; struct AstNode* init; + struct { const char* name; TypeKind annot_type; bool has_type_annot; bool is_mut; bool is_const; struct AstNode* init; const char* struct_type_name; TypeKind annot_element_type; const char* annot_element_struct_name; int64_t annot_array_size; } let_stmt; // AST_ASSIGN_STMT diff --git a/src/lexer/lexer.c b/src/lexer/lexer.c index 87f41d7..203b304 100644 --- a/src/lexer/lexer.c +++ b/src/lexer/lexer.c @@ -57,6 +57,7 @@ static TokenKind check_keyword(const Token* tok) { KW("fn", TOK_FN); KW("let", TOK_LET); KW("var", TOK_VAR); KW("if", TOK_IF); KW("else", TOK_ELSE); KW("guard", TOK_GUARD); + KW("const", TOK_CONST); KW("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN); KW("to", TOK_TO); KW("step", TOK_STEP); KW("return", TOK_RETURN); diff --git a/src/lexer/token.c b/src/lexer/token.c index eb1a293..6d34c2e 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_VAR] = "var", [TOK_IF] = "if", [TOK_GUARD] = "guard", + [TOK_FN] = "fn", [TOK_LET] = "let", [TOK_VAR] = "var", [TOK_CONST] = "const", [TOK_IF] = "if", [TOK_GUARD] = "guard", [TOK_PUB] = "pub", [TOK_MOD] = "mod", [TOK_USE] = "use", [TOK_TRAIT] = "trait", [TOK_SELF] = "Self", [TOK_ELSE] = "else", [TOK_WHILE] = "while", [TOK_FOR] = "for", [TOK_IN] = "in", [TOK_RETURN] = "return", diff --git a/src/lexer/token.h b/src/lexer/token.h index 0bb48d8..56a346b 100644 --- a/src/lexer/token.h +++ b/src/lexer/token.h @@ -6,7 +6,7 @@ // === Token 类型枚举 === typedef enum { // 关键字 - TOK_FN, TOK_LET, TOK_VAR, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, TOK_GUARD, + TOK_FN, TOK_LET, TOK_VAR, TOK_CONST, TOK_IF, TOK_ELSE, TOK_WHILE, TOK_FOR, TOK_IN, TOK_RETURN, TOK_GUARD, TOK_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_DEFER, TOK_MATCH, TOK_PUB, TOK_MOD, TOK_USE, TOK_TRAIT, TOK_SELF, // 类型关键字 diff --git a/src/parser/parser.c b/src/parser/parser.c index 3509ddd..c6c8128 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -118,10 +118,11 @@ AstNode* parse_block(Parser* p, ErrorInfo* error) { AstNode* parse_statement(Parser* p, ErrorInfo* error) { const Token* t = peek(p); - 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 (t->kind == TOK_LET || t->kind == TOK_VAR || t->kind == TOK_CONST) { + TokenKind decl_kind = advance(p)->kind; + bool is_mut = (decl_kind == TOK_VAR); + bool is_const = (decl_kind == TOK_CONST); + const Token* name = expect(p, TOK_IDENT, error, "变量名"); if (!name) return NULL; // 可选的类型标注 TypeKind annot_type = TYPE_UNKNOWN; @@ -144,10 +145,12 @@ AstNode* parse_statement(Parser* p, ErrorInfo* error) { AstNode* init = parse_expr(p, error); if (!init) return NULL; if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) return NULL; - return ast_make_let(p->arena, + AstNode* let_node = ast_make_let(p->arena, arena_strdup_impl(p->arena, name->start, name->length), annot_type, has_type_annot, is_mut, init, struct_type_name, annot_elem_type, annot_elem_struct, annot_arr_size, tok_loc(t)); + let_node->as.let_stmt.is_const = is_const; + return let_node; } if (t->kind == TOK_IF) { diff --git a/src/sema/sema.c b/src/sema/sema.c index e1f212c..f117ff4 100644 --- a/src/sema/sema.c +++ b/src/sema/sema.c @@ -319,6 +319,10 @@ void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* a) { "变量 '%s' 重复定义", node->as.let_stmt.name); } else { sym->is_mut = node->as.let_stmt.is_mut; + sym->is_const = node->as.let_stmt.is_const; + if (node->as.let_stmt.is_const && node->as.let_stmt.init->kind == AST_LITERAL_EXPR) { + sym->const_value = node->as.let_stmt.init->as.literal.i64_val; + } if (var_struct_name) { sym->type = TYPE_STRUCT; sym->struct_type_name = var_struct_name; diff --git a/src/sema/symbol.h b/src/sema/symbol.h index 1a58933..ba04f07 100644 --- a/src/sema/symbol.h +++ b/src/sema/symbol.h @@ -11,6 +11,8 @@ typedef struct Symbol { SymbolKind kind; TypeKind type; // 变量/参数的类型 bool is_mut; // 变量是否可变(可被赋值) + bool is_const; // 编译期常量 (const 声明) + int64_t const_value; // 编译期常量值 // 函数特有 TypeKind return_type; const char* return_struct_type_name; // 返回类型为 struct 时的类型名