feat: L Language v0.1 编译器完整实现
5 阶段编译流水线: 词法分析 → 语法分析(Pratt) → 语义分析(类型推断) → LLVM IR → .exe 模块: - lexer: 手写状态机, 40 种 Token, // 和 /* */ 注释 - parser: Pratt 表达式解析(9 级优先级) + 递归下降语句/函数 - ast: 14 种节点类型 + 工厂函数 - sema: 作用域链符号表 + 类型推断 + 类型检查 - codegen: AST → LLVM-C API, print_i64/f64/bool 内建 - driver: 命令行 + 流水线串联 + 错误报告 - util: Arena bump allocator (8MB) 测试: 65 单元测试(词法41+语法15+语义9) + 5 集成测试 全部通过 语言特性: i64/f64/bool/void, let不可变变量, if/else, while, 递归函数
This commit is contained in:
+113
@@ -0,0 +1,113 @@
|
||||
#include "ast.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
// 使用宏简化节点创建
|
||||
#define NEW(alloc, k) \
|
||||
AstNode* n = (AstNode*)arena_alloc_impl(alloc, sizeof(AstNode)); \
|
||||
n->kind = (k); n->type.kind = TYPE_UNKNOWN; \
|
||||
n->line = line; n->col = col
|
||||
|
||||
AstNode* ast_make_program(void* alloc, AstNode** fns, size_t count, int line, int col) {
|
||||
NEW(alloc, AST_PROGRAM);
|
||||
n->as.program.functions = fns;
|
||||
n->as.program.fn_count = count;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_function(void* alloc, const char* name, AstNode** params, size_t pcount,
|
||||
TypeKind ret, AstNode* body, int line, int col) {
|
||||
NEW(alloc, AST_FUNCTION);
|
||||
n->as.function.name = name; n->as.function.params = params;
|
||||
n->as.function.param_count = pcount; n->as.function.return_type = ret;
|
||||
n->as.function.body = body;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_parameter(void* alloc, const char* name, TypeKind type, int line, int col) {
|
||||
NEW(alloc, AST_PARAMETER);
|
||||
n->as.parameter.name = name; n->as.parameter.type = type;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_block(void* alloc, AstNode** stmts, size_t count, int line, int col) {
|
||||
NEW(alloc, AST_BLOCK);
|
||||
n->as.block.stmts = stmts; n->as.block.stmt_count = count;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_let(void* alloc, const char* name, TypeKind annot_type, bool has_type_annot, AstNode* init, int line, int col) {
|
||||
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.init = init;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_if(void* alloc, AstNode* cond, AstNode* then_b, AstNode* else_b, int line, int col) {
|
||||
NEW(alloc, AST_IF_STMT);
|
||||
n->as.if_stmt.cond = cond; n->as.if_stmt.then_block = then_b;
|
||||
n->as.if_stmt.else_block = else_b;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_while(void* alloc, AstNode* cond, AstNode* body, int line, int col) {
|
||||
NEW(alloc, AST_WHILE_STMT);
|
||||
n->as.while_stmt.cond = cond; n->as.while_stmt.body = body;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_return(void* alloc, AstNode* expr, int line, int col) {
|
||||
NEW(alloc, AST_RETURN_STMT);
|
||||
n->as.return_stmt.expr = expr;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_expr_stmt(void* alloc, AstNode* expr, int line, int col) {
|
||||
NEW(alloc, AST_EXPR_STMT);
|
||||
n->as.expr_stmt.expr = expr;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_binary(void* alloc, BinaryOp op, AstNode* left, AstNode* right, int line, int col) {
|
||||
NEW(alloc, AST_BINARY_EXPR);
|
||||
n->as.binary.op = op; n->as.binary.left = left; n->as.binary.right = right;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_unary(void* alloc, BinaryOp op, AstNode* operand, int line, int col) {
|
||||
NEW(alloc, AST_UNARY_EXPR);
|
||||
n->as.unary.op = op; n->as.unary.operand = operand;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_call(void* alloc, const char* name, AstNode** args, size_t count, int line, int col) {
|
||||
NEW(alloc, AST_CALL_EXPR);
|
||||
n->as.call.name = name; n->as.call.args = args; n->as.call.arg_count = count;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_literal_i64(void* alloc, int64_t val, int line, int col) {
|
||||
NEW(alloc, AST_LITERAL_EXPR);
|
||||
n->as.literal.lit_type = TYPE_I64; n->as.literal.i64_val = val;
|
||||
n->type.kind = TYPE_I64;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_literal_f64(void* alloc, double val, int line, int col) {
|
||||
NEW(alloc, AST_LITERAL_EXPR);
|
||||
n->as.literal.lit_type = TYPE_F64; n->as.literal.f64_val = val;
|
||||
n->type.kind = TYPE_F64;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_literal_bool(void* alloc, bool val, int line, int col) {
|
||||
NEW(alloc, AST_LITERAL_EXPR);
|
||||
n->as.literal.lit_type = TYPE_BOOL; n->as.literal.bool_val = val;
|
||||
n->type.kind = TYPE_BOOL;
|
||||
return n;
|
||||
}
|
||||
|
||||
AstNode* ast_make_ident(void* alloc, const char* name, int line, int col) {
|
||||
NEW(alloc, AST_IDENT_EXPR);
|
||||
n->as.ident.name = name;
|
||||
return n;
|
||||
}
|
||||
Reference in New Issue
Block a user