feat: const 编译期常量 — const N = 42;
Token(77): +TOK_CONST, AST_LET_STMT 新增 is_const, Symbol 新增 const_value sema: 字面量初始化自动折叠为编译期常量值 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -67,6 +67,7 @@ AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool h
|
|||||||
NEW(alloc, AST_LET_STMT);
|
NEW(alloc, AST_LET_STMT);
|
||||||
n->as.let_stmt.name = name; n->as.let_stmt.annot_type = annot_type;
|
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.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.init = init;
|
||||||
n->as.let_stmt.struct_type_name = struct_type_name;
|
n->as.let_stmt.struct_type_name = struct_type_name;
|
||||||
n->as.let_stmt.annot_element_type = annot_elem_type;
|
n->as.let_stmt.annot_element_type = annot_elem_type;
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ struct AstNode {
|
|||||||
// AST_BLOCK
|
// AST_BLOCK
|
||||||
struct { struct AstNode** stmts; size_t stmt_count; } block;
|
struct { struct AstNode** stmts; size_t stmt_count; } block;
|
||||||
// AST_LET_STMT
|
// 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;
|
const char* struct_type_name;
|
||||||
TypeKind annot_element_type; const char* annot_element_struct_name; int64_t annot_array_size; } let_stmt;
|
TypeKind annot_element_type; const char* annot_element_struct_name; int64_t annot_array_size; } let_stmt;
|
||||||
// AST_ASSIGN_STMT
|
// AST_ASSIGN_STMT
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ static TokenKind check_keyword(const Token* tok) {
|
|||||||
KW("fn", TOK_FN); KW("let", TOK_LET);
|
KW("fn", TOK_FN); KW("let", TOK_LET);
|
||||||
KW("var", TOK_VAR);
|
KW("var", TOK_VAR);
|
||||||
KW("if", TOK_IF); KW("else", TOK_ELSE); KW("guard", TOK_GUARD);
|
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("while", TOK_WHILE); KW("for", TOK_FOR); KW("in", TOK_IN);
|
||||||
KW("to", TOK_TO); KW("step", TOK_STEP);
|
KW("to", TOK_TO); KW("step", TOK_STEP);
|
||||||
KW("return", TOK_RETURN);
|
KW("return", TOK_RETURN);
|
||||||
|
|||||||
+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_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_PUB] = "pub", [TOK_MOD] = "mod", [TOK_USE] = "use",
|
||||||
[TOK_TRAIT] = "trait", [TOK_SELF] = "Self",
|
[TOK_TRAIT] = "trait", [TOK_SELF] = "Self",
|
||||||
[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",
|
||||||
|
|||||||
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
// === Token 类型枚举 ===
|
// === Token 类型枚举 ===
|
||||||
typedef enum {
|
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_STRUCT, TOK_TYPE, TOK_ENUM, TOK_EXTEND, TOK_DEFER, TOK_MATCH, TOK_PUB, TOK_MOD, TOK_USE,
|
||||||
TOK_TRAIT, TOK_SELF,
|
TOK_TRAIT, TOK_SELF,
|
||||||
// 类型关键字
|
// 类型关键字
|
||||||
|
|||||||
+8
-5
@@ -118,10 +118,11 @@ AstNode* parse_block(Parser* p, ErrorInfo* error) {
|
|||||||
AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
||||||
const Token* t = peek(p);
|
const Token* t = peek(p);
|
||||||
|
|
||||||
if (t->kind == TOK_LET || t->kind == TOK_VAR) {
|
if (t->kind == TOK_LET || t->kind == TOK_VAR || t->kind == TOK_CONST) {
|
||||||
bool is_mut = (advance(p)->kind == TOK_VAR);
|
TokenKind decl_kind = advance(p)->kind;
|
||||||
const Token* name = expect(p, TOK_IDENT, error,
|
bool is_mut = (decl_kind == TOK_VAR);
|
||||||
is_mut ? "var 后应为变量名" : "let 后应为变量名");
|
bool is_const = (decl_kind == TOK_CONST);
|
||||||
|
const Token* name = expect(p, TOK_IDENT, error, "变量名");
|
||||||
if (!name) return NULL;
|
if (!name) return NULL;
|
||||||
// 可选的类型标注
|
// 可选的类型标注
|
||||||
TypeKind annot_type = TYPE_UNKNOWN;
|
TypeKind annot_type = TYPE_UNKNOWN;
|
||||||
@@ -144,10 +145,12 @@ AstNode* parse_statement(Parser* p, ErrorInfo* error) {
|
|||||||
AstNode* init = parse_expr(p, error);
|
AstNode* init = parse_expr(p, error);
|
||||||
if (!init) return NULL;
|
if (!init) return NULL;
|
||||||
if (!expect(p, TOK_SEMICOLON, error, "缺少 ';'")) 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),
|
arena_strdup_impl(p->arena, name->start, name->length),
|
||||||
annot_type, has_type_annot, is_mut, init, struct_type_name,
|
annot_type, has_type_annot, is_mut, init, struct_type_name,
|
||||||
annot_elem_type, annot_elem_struct, annot_arr_size, tok_loc(t));
|
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) {
|
if (t->kind == TOK_IF) {
|
||||||
|
|||||||
@@ -319,6 +319,10 @@ void analyze_node(AstNode* node, Scope* scope, ErrorList* errors, Arena* a) {
|
|||||||
"变量 '%s' 重复定义", node->as.let_stmt.name);
|
"变量 '%s' 重复定义", node->as.let_stmt.name);
|
||||||
} else {
|
} else {
|
||||||
sym->is_mut = node->as.let_stmt.is_mut;
|
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) {
|
if (var_struct_name) {
|
||||||
sym->type = TYPE_STRUCT;
|
sym->type = TYPE_STRUCT;
|
||||||
sym->struct_type_name = var_struct_name;
|
sym->struct_type_name = var_struct_name;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ typedef struct Symbol {
|
|||||||
SymbolKind kind;
|
SymbolKind kind;
|
||||||
TypeKind type; // 变量/参数的类型
|
TypeKind type; // 变量/参数的类型
|
||||||
bool is_mut; // 变量是否可变(可被赋值)
|
bool is_mut; // 变量是否可变(可被赋值)
|
||||||
|
bool is_const; // 编译期常量 (const 声明)
|
||||||
|
int64_t const_value; // 编译期常量值
|
||||||
// 函数特有
|
// 函数特有
|
||||||
TypeKind return_type;
|
TypeKind return_type;
|
||||||
const char* return_struct_type_name; // 返回类型为 struct 时的类型名
|
const char* return_struct_type_name; // 返回类型为 struct 时的类型名
|
||||||
|
|||||||
Reference in New Issue
Block a user