重构类型系统并改进诊断功能
- 更新了类型系统,新增了类型并优化了结构。 - 引入了基类型和派生类,用于函数、结构体和接口类型。 - 实现了类型上下文,用于管理内置类型和类型解析。 - 添加了诊断类,用于收集和报告警告和错误。 - 通过改进错误处理增强了虚拟机执行,以应对递归限制问题。 - 实现了反汇编器,将字节码转换为代码,以改善调试和分析。 - 添加了新的抽象语法树节点,用于成员表达式、对象初始化、接口和结构体定义。 - 引入了语义错误测试,包括重定义、未声明的变量和无效的结构字段。
This commit is contained in:
@@ -1,282 +1,215 @@
|
||||
/*!
|
||||
@file src/Compiler/StmtCompiler.cpp
|
||||
@brief 编译器实现(语句部分)
|
||||
@author PuqiAR (im@puqiar.top)
|
||||
@date 2026-02-19
|
||||
@brief 语句编译器实现:实装水位线机制,彻底消灭硬编码寄存器释放
|
||||
*/
|
||||
|
||||
#include <Ast/Stmt/FnDefStmt.hpp>
|
||||
#include <Ast/Stmt/IfStmt.hpp>
|
||||
#include <Ast/Stmt/VarDecl.hpp>
|
||||
#include <Ast/Stmt/WhileStmt.hpp>
|
||||
#include <Compiler/Compiler.hpp>
|
||||
|
||||
|
||||
namespace Fig
|
||||
{
|
||||
Result<void, Error> Compiler::compileVarDecl(VarDecl *varDecl)
|
||||
Result<void, Error> Compiler::compileStmt(Stmt *stmt)
|
||||
{
|
||||
if (current->freeReg > MAX_LOCALS)
|
||||
if (stmt == nullptr)
|
||||
{
|
||||
return std::unexpected(Error(ErrorType::TooManyLocals,
|
||||
std::format("local limit exceeded: {}", MAX_LOCALS),
|
||||
"try split function or use arrays/structs...",
|
||||
makeSourceLocation(varDecl)));
|
||||
return {};
|
||||
}
|
||||
|
||||
std::uint8_t varReg;
|
||||
if (varDecl->initExpr)
|
||||
{
|
||||
auto result = compileExpr(varDecl->initExpr);
|
||||
if (!result)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
}
|
||||
std::uint8_t resultReg = *result;
|
||||
varReg = DeclareLocal(varDecl->localId, resultReg); // 复用临时计算结果寄存器
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: 未初始化提供初始值
|
||||
varReg = DeclareLocal(varDecl->localId);
|
||||
}
|
||||
|
||||
return Result<void, Error>();
|
||||
}
|
||||
|
||||
Result<void, Error> Compiler::compileBlockStmt(BlockStmt *blockStmt)
|
||||
{
|
||||
for (Stmt *stmt : blockStmt->nodes)
|
||||
{
|
||||
auto result = compileStmt(stmt);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void, Error> Compiler::compileIfStmt(IfStmt *stmt)
|
||||
{
|
||||
/*
|
||||
if cond1
|
||||
{
|
||||
}
|
||||
else if cond2 #1
|
||||
{
|
||||
}
|
||||
else if cond3 #2
|
||||
{
|
||||
}
|
||||
else #3
|
||||
{
|
||||
}
|
||||
quit #4
|
||||
|
||||
Bytecode:
|
||||
JmpIfFalse cond1 #1
|
||||
; consequent内容
|
||||
; ...
|
||||
; if条件为true, 跳过所有 else/elseif
|
||||
|
||||
Jmp #4
|
||||
|
||||
; #1
|
||||
JmpIfFalse cond2 #2
|
||||
; consequent
|
||||
|
||||
Jmp #4
|
||||
|
||||
; #2
|
||||
JmpIfFalse cond3 #3
|
||||
; consequent
|
||||
|
||||
Jmp #4
|
||||
|
||||
; #3
|
||||
; 没有一次执行分支
|
||||
; else部分
|
||||
; ...
|
||||
|
||||
#4
|
||||
|
||||
*/
|
||||
std::vector<int> exitJumps; // 所有分支都要跳到最后,收集所有jump最后回填
|
||||
const auto &condResult = compileExpr(stmt->cond);
|
||||
if (!condResult)
|
||||
{
|
||||
return std::unexpected(condResult.error());
|
||||
}
|
||||
std::uint8_t condReg = *condResult;
|
||||
int jumpToNext = EmitJump(OpCode::JmpIfFalse, condReg);
|
||||
FreeReg(condReg);
|
||||
|
||||
const auto &blockResult = compileStmt(stmt->consequent);
|
||||
if (!blockResult)
|
||||
{
|
||||
return blockResult;
|
||||
}
|
||||
|
||||
exitJumps.push_back(EmitJump(OpCode::Jmp)); // 执行完if直接跳到出口
|
||||
PatchJump(jumpToNext); // 回填,跳到下一个else/elseif
|
||||
|
||||
for (auto *elif : stmt->elifs)
|
||||
{
|
||||
const auto &elifCondResult = compileExpr(elif->cond);
|
||||
if (!elifCondResult)
|
||||
return std::unexpected(elifCondResult.error());
|
||||
std::uint8_t elifCondReg = *elifCondResult;
|
||||
|
||||
jumpToNext = EmitJump(OpCode::JmpIfFalse, elifCondReg);
|
||||
FreeReg(elifCondReg);
|
||||
|
||||
const auto &blockResult = compileStmt(elif->consequent);
|
||||
if (!blockResult)
|
||||
{
|
||||
return blockResult;
|
||||
}
|
||||
exitJumps.push_back(EmitJump(OpCode::Jmp)); // 执行完else if,跳到出口
|
||||
PatchJump(jumpToNext); // 跳到下一个分支
|
||||
}
|
||||
|
||||
if (stmt->alternate)
|
||||
{
|
||||
auto result = compileStmt(stmt->alternate);
|
||||
if (!result)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
for (int exitIndex : exitJumps)
|
||||
{
|
||||
PatchJump(exitIndex); // 回填所有跳转出口的指令
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void, Error> Compiler::compileWhileStmt(WhileStmt *stmt)
|
||||
{
|
||||
int beginIns = current->proto->code.size() - 1;
|
||||
|
||||
auto condRegResult = compileExpr(stmt->cond);
|
||||
if (!condRegResult)
|
||||
{
|
||||
return std::unexpected(condRegResult.error());
|
||||
}
|
||||
|
||||
std::uint8_t condReg = *condRegResult;
|
||||
|
||||
int exitJump = EmitJump(OpCode::JmpIfFalse, condReg);
|
||||
auto bodyResult = compileBlockStmt(stmt->body);
|
||||
|
||||
if (!bodyResult)
|
||||
{
|
||||
return bodyResult;
|
||||
}
|
||||
Emit(Op::iAsBx(
|
||||
OpCode::Jmp, 0, beginIns - current->proto->code.size())); // 回到开头对condition求值
|
||||
PatchJump(exitJump);
|
||||
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)
|
||||
{
|
||||
case AstType::ExprStmt: {
|
||||
ExprStmt *exprStmt = static_cast<ExprStmt *>(stmt);
|
||||
Expr *expr = exprStmt->expr;
|
||||
auto result = compileExpr(expr);
|
||||
if (!result)
|
||||
case AstType::BlockStmt: {
|
||||
auto *b = static_cast<BlockStmt *>(stmt);
|
||||
for (auto *n : b->nodes)
|
||||
{
|
||||
return std::unexpected(result.error());
|
||||
auto res = compileStmt(n);
|
||||
if (!res)
|
||||
return res;
|
||||
}
|
||||
FreeReg(*result);
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::VarDecl: {
|
||||
return compileVarDecl(static_cast<VarDecl *>(stmt));
|
||||
}
|
||||
auto *v = static_cast<VarDecl *>(stmt);
|
||||
if (current->enclosing == nullptr) // 处理全局变量
|
||||
{
|
||||
Register mark = current->freereg; // 记录水位线
|
||||
auto regRes = compileExpr(v->initExpr);
|
||||
if (!regRes)
|
||||
return std::unexpected(regRes.error());
|
||||
|
||||
case AstType::BlockStmt: {
|
||||
return compileBlockStmt(static_cast<BlockStmt *>(stmt));
|
||||
}
|
||||
emit(Op::iABx(
|
||||
OpCode::SetGlobal, *regRes, static_cast<uint16_t>(getGlobalID(v->name))));
|
||||
current->freereg = mark; // 释放初始化表达式的临时占用
|
||||
}
|
||||
else
|
||||
{
|
||||
// 抬升水位,锁死局部变量的物理槽位
|
||||
Register targetReg = static_cast<Register>(v->localId);
|
||||
while (current->freereg <= targetReg)
|
||||
{
|
||||
auto allocRes = allocateReg(v->location);
|
||||
if (!allocRes)
|
||||
{
|
||||
return std::unexpected(allocRes.error());
|
||||
}
|
||||
}
|
||||
|
||||
case AstType::IfStmt: {
|
||||
return compileIfStmt(static_cast<IfStmt *>(stmt));
|
||||
}
|
||||
|
||||
case AstType::WhileStmt: {
|
||||
return compileWhileStmt(static_cast<WhileStmt *>(stmt));
|
||||
auto regRes = compileExpr(v->initExpr, targetReg);
|
||||
if (!regRes)
|
||||
return std::unexpected(regRes.error());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::FnDefStmt: {
|
||||
return compileFnDefStmt(static_cast<FnDefStmt *>(stmt));
|
||||
}
|
||||
|
||||
case AstType::ReturnStmt: {
|
||||
return compileReturnStmt(static_cast<ReturnStmt *>(stmt));
|
||||
}
|
||||
}
|
||||
auto *f = static_cast<FnDefStmt *>(stmt);
|
||||
|
||||
return Result<void, Error>();
|
||||
// 物理连线:对接 Compile() 第一阶段预分配的 Proto
|
||||
Proto *p = module->protos[f->resolvedSymbol->index];
|
||||
|
||||
FuncState fs(p, current);
|
||||
FuncState *old = current;
|
||||
current = &fs;
|
||||
|
||||
auto res = compileStmt(f->body);
|
||||
if (!res)
|
||||
return res;
|
||||
|
||||
// 窥孔拦截:防死代码污染
|
||||
if (p->code.empty() || static_cast<OpCode>(p->code.back() & 0xFF) != OpCode::Return)
|
||||
{
|
||||
emit(Op::iABC(OpCode::Return, 0, 0, 0));
|
||||
}
|
||||
|
||||
current = old;
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::IfStmt: {
|
||||
auto *i = static_cast<IfStmt *>(stmt);
|
||||
DynArray<int> exitJumps;
|
||||
|
||||
Register mark = current->freereg; // 记录水位线
|
||||
auto r_cond = compileExpr(i->cond);
|
||||
if (!r_cond)
|
||||
return std::unexpected(r_cond.error());
|
||||
|
||||
int jmpToNext = static_cast<int>(current->proto->code.size());
|
||||
emit(Op::iAsBx(OpCode::JmpIfFalse, *r_cond, 0));
|
||||
current->freereg = mark; // 回收条件表达式临时槽位
|
||||
|
||||
if (auto r = compileStmt(i->consequent); !r)
|
||||
return r;
|
||||
exitJumps.push_back(static_cast<int>(current->proto->code.size()));
|
||||
emit(Op::iAsBx(OpCode::Jmp, 0, 0));
|
||||
|
||||
int targetIdx = static_cast<int>(current->proto->code.size());
|
||||
current->proto->code[jmpToNext] = Op::iAsBx(
|
||||
OpCode::JmpIfFalse, *r_cond, static_cast<int16_t>(targetIdx - jmpToNext - 1));
|
||||
|
||||
for (auto *elif : i->elifs)
|
||||
{
|
||||
Register elifMark = current->freereg;
|
||||
auto ec = compileExpr(elif->cond);
|
||||
if (!ec)
|
||||
return std::unexpected(ec.error());
|
||||
|
||||
int nextElif = static_cast<int>(current->proto->code.size());
|
||||
emit(Op::iAsBx(OpCode::JmpIfFalse, *ec, 0));
|
||||
current->freereg = elifMark; // 回收 elif 临时槽位
|
||||
|
||||
if (auto r = compileStmt(elif->consequent); !r)
|
||||
return r;
|
||||
exitJumps.push_back(static_cast<int>(current->proto->code.size()));
|
||||
emit(Op::iAsBx(OpCode::Jmp, 0, 0));
|
||||
|
||||
int target = static_cast<int>(current->proto->code.size());
|
||||
current->proto->code[nextElif] = Op::iAsBx(
|
||||
OpCode::JmpIfFalse, *ec, static_cast<int16_t>(target - nextElif - 1));
|
||||
}
|
||||
|
||||
if (i->alternate)
|
||||
{
|
||||
if (auto r = compileStmt(i->alternate); !r)
|
||||
return r;
|
||||
}
|
||||
|
||||
int endIdx = static_cast<int>(current->proto->code.size());
|
||||
for (int pos : exitJumps)
|
||||
{
|
||||
current->proto->code[pos] =
|
||||
Op::iAsBx(OpCode::Jmp, 0, static_cast<int16_t>(endIdx - pos - 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::WhileStmt: {
|
||||
auto *w = static_cast<WhileStmt *>(stmt);
|
||||
int startIdx = static_cast<int>(current->proto->code.size());
|
||||
|
||||
Register mark = current->freereg; // 记录水位线
|
||||
auto r_cond = compileExpr(w->cond);
|
||||
if (!r_cond)
|
||||
return std::unexpected(r_cond.error());
|
||||
|
||||
int exitJmpIdx = static_cast<int>(current->proto->code.size());
|
||||
emit(Op::iAsBx(OpCode::JmpIfFalse, *r_cond, 0));
|
||||
current->freereg = mark; // 回收循环条件临时槽位
|
||||
|
||||
if (auto r = compileStmt(w->body); !r)
|
||||
return r;
|
||||
|
||||
int backJmpIdx = static_cast<int>(current->proto->code.size());
|
||||
emit(Op::iAsBx(OpCode::Jmp, 0, static_cast<int16_t>(startIdx - backJmpIdx - 1)));
|
||||
|
||||
int endIdx = static_cast<int>(current->proto->code.size());
|
||||
current->proto->code[exitJmpIdx] = Op::iAsBx(
|
||||
OpCode::JmpIfFalse, *r_cond, static_cast<int16_t>(endIdx - exitJmpIdx - 1));
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::ReturnStmt: {
|
||||
auto *rs = static_cast<ReturnStmt *>(stmt);
|
||||
Register mark = current->freereg; // 记录水位线
|
||||
Register retReg;
|
||||
|
||||
if (rs->value)
|
||||
{
|
||||
auto r = compileExpr(rs->value);
|
||||
if (!r)
|
||||
return std::unexpected(r.error());
|
||||
retReg = *r;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto r = allocateReg(rs->location);
|
||||
if (!r)
|
||||
return std::unexpected(r.error());
|
||||
emit(Op::iABC(OpCode::LoadNull, *r, 0, 0));
|
||||
retReg = *r;
|
||||
}
|
||||
|
||||
emit(Op::iABC(OpCode::Return, retReg, 0, 0));
|
||||
current->freereg = mark; // 回收返回值计算的占用
|
||||
break;
|
||||
}
|
||||
|
||||
case AstType::ExprStmt: {
|
||||
Register mark = current->freereg; // 记录水位线
|
||||
auto reg = compileExpr(static_cast<ExprStmt *>(stmt)->expr);
|
||||
if (!reg)
|
||||
return std::unexpected(reg.error());
|
||||
|
||||
current->freereg = mark; // 彻底抛弃孤立表达式的副作用
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}; // namespace Fig
|
||||
} // namespace Fig
|
||||
Reference in New Issue
Block a user