feat: 闭包/lambda — 匿名函数表达式
fn(x: T) -> R { body } 作为表达式, 可赋值给变量并间接调用。
全流水线实现:
- Parser: TOK_FN 前缀 → AST_LAMBDA 节点
- Sema: 自动生成 __lambda_N 顶层函数 + 符号注册
- Sema: analyze_call_expr 支持 TYPE_CLOSURE 变量调用
- Codegen: lambda 表达式返回函数指针(i64), 调用点载入+IntToPtr+间接call
- VarEntry.closure_fn 追踪闭包变量对应的生成函数
限制(MVP v0.1): 非捕获 lambda, 返回类型固定 i64
+6 sema 测试 + 1 集成测试, 209 测试全部通过
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
+11
-4
@@ -9,11 +9,14 @@ LLVMValueRef find_var(CgCtx* ctx, const char* name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void add_var(CgCtx* ctx, const char* name, LLVMValueRef alloca, LLVMTypeRef alloca_type) {
|
||||
VarEntry* add_var(CgCtx* ctx, const char* name, LLVMValueRef alloca, LLVMTypeRef alloca_type) {
|
||||
VarEntry* e = arena_alloc(ctx->arena, sizeof(*e));
|
||||
if (!e) return;
|
||||
e->name = name; e->alloca = alloca; e->alloca_type = alloca_type; e->next = ctx->var_table;
|
||||
if (!e) return NULL;
|
||||
e->name = name; e->alloca = alloca; e->alloca_type = alloca_type;
|
||||
e->closure_fn = NULL;
|
||||
e->next = ctx->var_table;
|
||||
ctx->var_table = e;
|
||||
return e;
|
||||
}
|
||||
|
||||
// === 函数表 ===
|
||||
@@ -134,7 +137,11 @@ void codegen_stmt(CgCtx* ctx, AstNode* node) {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
add_var(ctx, node->as.let_stmt.name, alloca, var_type);
|
||||
VarEntry* ve = add_var(ctx, node->as.let_stmt.name, alloca, var_type);
|
||||
// 若 init 是 lambda, 记录闭包函数名供后续调用
|
||||
if (node->as.let_stmt.init &&
|
||||
node->as.let_stmt.init->kind == AST_LAMBDA && ve)
|
||||
ve->closure_fn = node->as.let_stmt.init->as.lambda.generated_name;
|
||||
|
||||
// 自动内存管理: 只追踪 str 堆分配 (拼接/malloc)
|
||||
// struct 是栈上值类型,不能 free();含 str 字段时 v0.5 扩展
|
||||
|
||||
Reference in New Issue
Block a user