feat: 重构编译器以支持函数定义和调用,添加新的字节码以支持函数调用

另外,我很高兴地宣布,fib(40) 递归法 在我的平台, i5-13490f,只需要 6600ms, fib(30) 56ms
这是历史性的一刻!
This commit is contained in:
2026-03-07 00:34:52 +08:00
parent 1fe9ccf7ea
commit 6dbecbbdc0
13 changed files with 477 additions and 127 deletions

View File

@@ -175,6 +175,67 @@ namespace Fig
return {};
}
Result<void, Error> Compiler::compileFnDefStmt(FnDefStmt *stmt)
{
std::uint8_t funcReg = DeclareLocal(stmt->localId);
// 创建子函数编译状态
// 传入 current 作为 enclosing用于后续支持闭包 Upvalue 查找
FuncState childState(stmt->name, current);
allProtos.push_back(childState.proto);
std::uint16_t protoIdx = static_cast<std::uint16_t>(allProtos.size() - 1);
globalFuncMap[stmt->localId] = protoIdx; // 把函数的local id映射到protoIdx
{
FuncStateProtector stateGuard(this, &childState);
AllocReg();
// 将参数映射为子函数的初始局部变量 (R0, R1...)
for (Param *p : stmt->params)
{
PosParam *posParam = static_cast<PosParam *>(p); // TODO: 其他参数支持...
// 按顺序分配寄存器
DeclareLocal(posParam->localId);
}
// B编译函数体语句
auto bodyRes = compileStmt(stmt->body);
if (!bodyRes)
return bodyRes;
// 隐式返回 null
std::uint8_t resReg = AllocReg();
Emit(Op::iABC(OpCode::LoadNull, resReg, 0, 0));
Emit(Op::iABC(OpCode::Return, resReg, 0, 0));
}
// 5. 检查是否是 main 函数
if (stmt->name == U"main")
{
this->mainFuncIndex = protoIdx;
}
Emit(Op::iABx(OpCode::LoadFn, funcReg, protoIdx));
return {};
}
Result<void, Error> Compiler::compileReturnStmt(ReturnStmt *stmt)
{
auto res = compileExpr(stmt->value);
if (!res)
{
return std::unexpected(res.error());
}
Emit(Op::iABC(OpCode::Return, *res, 0, 0));
return {};
}
Result<void, Error> Compiler::compileStmt(Stmt *stmt) // 编译语句
{
switch (stmt->type)
@@ -206,6 +267,14 @@ namespace Fig
case AstType::WhileStmt: {
return compileWhileStmt(static_cast<WhileStmt *>(stmt));
}
case AstType::FnDefStmt: {
return compileFnDefStmt(static_cast<FnDefStmt *>(stmt));
}
case AstType::ReturnStmt: {
return compileReturnStmt(static_cast<ReturnStmt *>(stmt));
}
}
return Result<void, Error>();