Files
l-language/src/codegen/codegen_internal.h
T
Serendipity f5c0650a97 feat: 闭包变量捕获 — 环境结构体 + 堆分配
lambda 可捕获外层变量, 自动构建环境结构体:

let base = 100;
let f = fn(x: i64) -> i64 { return x + base; };  // 捕获 base
f(50);  // → 150

全流水线实现:
- Sema: collect_free_vars 遍历 AST 收集自由变量
- AST function: captured/cap_types/cap_count 字段存储捕获信息
- Codegen: 闭包类型改为 struct {fn_ptr: i64, env_ptr: ptr}
- Codegen: lambda 表达式 malloc 环境结构体 + 存储捕获值
- Codegen: 生成函数签名添加 env_ptr 首个参数 (capturing only)
- Codegen: 函数体内通过 GEP 注册捕获变量到 var_table
- Codegen: 闭包调用自动提取 fn_ptr/env_ptr, 条件传递 env

非捕获 lambda 兼容: env_ptr=NULL, 不额外传参
嵌套 lambda 正确处理: 内层不穿透捕获外层变量

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-07 15:24:35 +08:00

94 lines
2.8 KiB
C

#ifndef CODEGEN_INTERNAL_H
#define CODEGEN_INTERNAL_H
#include "codegen.h"
#include "ast.h"
#include "arena.h"
#include "l_lang.h"
#include "visit.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/Types.h>
#include <string.h>
#include <stdio.h>
// 递归深度限制
extern int codegen_depth;
#define MAX_CODEGEN_DEPTH 1000
// AST program (由 sema 设置, codegen 读取)
extern AstNode* g_program;
// === 内部状态 ===
typedef struct VarEntry {
const char* name;
LLVMValueRef alloca;
LLVMTypeRef alloca_type;
const char* closure_fn; // 闭包对应的生成函数名
struct VarEntry* next;
} VarEntry;
typedef struct FnEntry {
const char* name;
LLVMValueRef fn;
TypeKind ret;
TypeKind* params;
bool* out_params; // 哪些参数是 out (引用传递)
size_t pc;
struct FnEntry* next;
} FnEntry;
typedef struct StructTypeEntry {
const char* name;
LLVMTypeRef llvm_type;
size_t field_count;
struct StructTypeEntry* next;
} StructTypeEntry;
typedef struct {
Arena* arena;
LLVMContextRef context;
LLVMModuleRef module;
LLVMBuilderRef builder;
VarEntry* var_table;
const char* error;
FnEntry* fn_table;
StructTypeEntry* struct_table;
LLVMValueRef printf_fn;
LLVMTypeRef printf_ty;
LLVMValueRef malloc_fn;
LLVMValueRef free_fn;
LLVMValueRef strlen_fn;
LLVMValueRef memcpy_fn;
LLVMValueRef* cleanup_list;
size_t cleanup_count;
size_t cleanup_cap;
AstNode* defer_exprs[64];
size_t defer_count;
} CgCtx;
// === 类型映射 ===
LLVMTypeRef to_llvm_type(CgCtx* ctx, TypeKind kind);
LLVMValueRef to_llvm_const(LLVMTypeRef ty, AstNode* lit);
LLVMTypeRef type_info_to_llvm(CgCtx* ctx, const TypeInfo* ti);
LLVMValueRef coerce_int(CgCtx* ctx, LLVMValueRef val, LLVMTypeRef from_ty, LLVMTypeRef to_ty);
// === 表操作 ===
LLVMValueRef find_var(CgCtx* ctx, const char* name);
VarEntry* add_var(CgCtx* ctx, const char* name, LLVMValueRef alloca, LLVMTypeRef alloca_type);
LLVMValueRef find_fn(CgCtx* ctx, const char* name);
FnEntry* find_fn_entry(CgCtx* ctx, const char* name);
void add_fn(CgCtx* ctx, const char* name, LLVMValueRef fn, bool* out_params, size_t pc);
void add_struct_type(CgCtx* ctx, const char* name, LLVMTypeRef ty, size_t fc);
LLVMTypeRef find_struct_type(CgCtx* ctx, const char* name);
// === 内存清理 ===
void cleanup_add(CgCtx* ctx, LLVMValueRef alloca);
void cleanup_emit(CgCtx* ctx, size_t from_mark);
// === 代码生成函数 ===
void codegen_expr_init(void);
LLVMValueRef codegen_expr(CgCtx* ctx, AstNode* node);
void codegen_stmt(CgCtx* ctx, AstNode* node);
#endif