06d80f441a
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>
102 lines
4.5 KiB
C
102 lines
4.5 KiB
C
#include "sema_internal.h"
|
|
|
|
// 将 AST 中所有匹配 type_param_name 的类型引用替换为 concrete_type
|
|
void subst_ast_types(AstNode* node, const char* tparam, TypeKind concrete, const char* concrete_sname);
|
|
|
|
void subst_type_info(TypeInfo* ti, const char* tparam, TypeKind concrete, const char* concrete_sname) {
|
|
if (ti->kind == TYPE_STRUCT && ti->struct_name && strcmp(ti->struct_name, tparam) == 0) {
|
|
ti->kind = concrete;
|
|
ti->struct_name = concrete_sname;
|
|
}
|
|
}
|
|
|
|
void subst_ast_types(AstNode* node, const char* tparam, TypeKind concrete, const char* concrete_sname) {
|
|
if (!node) return;
|
|
// 替换节点自身类型
|
|
subst_type_info(&node->type, tparam, concrete, concrete_sname);
|
|
switch (node->kind) {
|
|
case AST_PROGRAM:
|
|
for (size_t i = 0; i < node->as.program.fn_count; i++)
|
|
subst_ast_types(node->as.program.functions[i], tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_FUNCTION:
|
|
if (node->as.function.return_type == TYPE_STRUCT
|
|
&& node->as.function.return_struct_type_name
|
|
&& strcmp(node->as.function.return_struct_type_name, tparam) == 0) {
|
|
node->as.function.return_type = concrete;
|
|
node->as.function.return_struct_type_name = concrete_sname;
|
|
}
|
|
for (size_t i = 0; i < node->as.function.param_count; i++)
|
|
subst_ast_types(node->as.function.params[i], tparam, concrete, concrete_sname);
|
|
subst_ast_types(node->as.function.body, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_PARAMETER:
|
|
if (node->as.parameter.type == TYPE_STRUCT && node->as.parameter.struct_type_name
|
|
&& strcmp(node->as.parameter.struct_type_name, tparam) == 0) {
|
|
node->as.parameter.type = concrete;
|
|
node->as.parameter.struct_type_name = concrete_sname;
|
|
}
|
|
break;
|
|
case AST_BLOCK:
|
|
for (size_t i = 0; i < node->as.block.stmt_count; i++)
|
|
subst_ast_types(node->as.block.stmts[i], tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_LET_STMT:
|
|
if (node->as.let_stmt.annot_type == TYPE_STRUCT && node->as.let_stmt.struct_type_name
|
|
&& strcmp(node->as.let_stmt.struct_type_name, tparam) == 0) {
|
|
node->as.let_stmt.annot_type = concrete;
|
|
node->as.let_stmt.struct_type_name = concrete_sname;
|
|
}
|
|
subst_ast_types(node->as.let_stmt.init, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_IF_STMT:
|
|
subst_ast_types(node->as.if_stmt.cond, tparam, concrete, concrete_sname);
|
|
subst_ast_types(node->as.if_stmt.then_block, tparam, concrete, concrete_sname);
|
|
subst_ast_types(node->as.if_stmt.else_block, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_WHILE_STMT:
|
|
subst_ast_types(node->as.while_stmt.cond, tparam, concrete, concrete_sname);
|
|
subst_ast_types(node->as.while_stmt.body, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_RETURN_STMT:
|
|
subst_ast_types(node->as.return_stmt.expr, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_EXPR_STMT:
|
|
subst_ast_types(node->as.expr_stmt.expr, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_BINARY_EXPR:
|
|
subst_ast_types(node->as.binary.left, tparam, concrete, concrete_sname);
|
|
subst_ast_types(node->as.binary.right, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_UNARY_EXPR:
|
|
subst_ast_types(node->as.unary.operand, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_CALL_EXPR:
|
|
for (size_t i = 0; i < node->as.call.arg_count; i++)
|
|
subst_ast_types(node->as.call.args[i], tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_ASSIGN_STMT:
|
|
subst_ast_types(node->as.assign_stmt.value, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_FIELD_ACCESS:
|
|
subst_ast_types(node->as.field_access.object, tparam, concrete, concrete_sname);
|
|
break;
|
|
case AST_STRUCT_INIT:
|
|
for (size_t i = 0; i < node->as.struct_init.field_count; i++)
|
|
subst_ast_types(node->as.struct_init.field_values[i], tparam, concrete, concrete_sname);
|
|
break;
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
// 单态化全局状态
|
|
// 单态化队列: 泛型函数调用时生成的具象化函数
|
|
AstNode* mono_queue[256];
|
|
size_t mono_count = 0;
|
|
Arena* mono_arena = NULL;
|
|
AstNode* g_program = NULL; // 当前 AST_PROGRAM(用于查找泛型函数模板)
|
|
|
|
// lambda 队列: 分析时创建的闭包函数
|
|
AstNode* lambda_queue[256];
|
|
size_t lambda_count = 0;
|