feat: 结构体 struct — 最后一项 P0 功能

- lexer: TOK_STRUCT, TOK_DOT 关键字和运算符
- ast: AST_STRUCT_DECL/STRUCT_INIT/FIELD_ACCESS 3 种新节点
- parser: struct 声明 + .field 访问 + Name{field:val} 初始化
- sema: struct 类型符号表,字段类型解析,初始化字段检查
- codegen: LLVMStructType + extractvalue/insertvalue 字段操作
- 新增集成测试: 12_struct.l, 13_struct_nested.l
- 基于 Codex 分析报告 P0 #4

所有 P0 功能已全部完成。
This commit is contained in:
2026-06-05 12:21:22 +08:00
parent 620cec4d57
commit b390d390f3
17 changed files with 1521 additions and 47 deletions
+2
View File
@@ -62,6 +62,7 @@ static TokenKind check_keyword(const Token* tok) {
KW("i64", TOK_I64); KW("f64", TOK_F64);
KW("bool", TOK_BOOL); KW("str", TOK_STR);
KW("void", TOK_VOID);
KW("struct", TOK_STRUCT);
KW("true", TOK_TRUE); KW("false", TOK_FALSE);
#undef KW
return TOK_IDENT;
@@ -126,6 +127,7 @@ Token* lex(Arena* a, const char* source, const char* filename,
else if (c == '&' && peek_next(&l) == '&') { tokens[idx++] = make_token(&l, TOK_AND_AND, l.pos, 2); advance(&l); advance(&l); }
else if (c == '|' && peek_next(&l) == '|') { tokens[idx++] = make_token(&l, TOK_PIPE_PIPE, l.pos, 2); advance(&l); advance(&l); }
else if (c == '.' && peek_next(&l) == '.') { tokens[idx++] = make_token(&l, TOK_DOT_DOT, l.pos, 2); advance(&l); advance(&l); }
else if (c == '.') { tokens[idx++] = make_token(&l, TOK_DOT, l.pos, 1); advance(&l); }
else if (c == '(') { tokens[idx++] = make_token(&l, TOK_LPAREN, l.pos, 1); advance(&l); }
else if (c == ')') { tokens[idx++] = make_token(&l, TOK_RPAREN, l.pos, 1); advance(&l); }
else if (c == '{') { tokens[idx++] = make_token(&l, TOK_LBRACE, l.pos, 1); advance(&l); }