diff --git a/src/Bytecode/Bytecode.hpp b/src/Bytecode/Bytecode.hpp index 23718ec..27847b7 100644 --- a/src/Bytecode/Bytecode.hpp +++ b/src/Bytecode/Bytecode.hpp @@ -20,9 +20,17 @@ namespace Fig enum class OpCode : std::uint8_t { - Exit, // 结束运行 - LoadK, // iABx 模式: R[A] = Constants[Bx] - Return, // iA 模式: 返回 R[A] 的值 + Exit, // 结束运行 + LoadK, // iABx 模式: R[A] = Constants[Bx] + LoadTrue, // iABC: R[A] = true + LoadFalse, // iABC: R[A] = false + LoadNull, // iABC: R[A] = null + + FastCall, // iABC: A: ProtoIdx, B: 函数起始寄存器 + Call, // 动态派发 iABC: A: 函数体对象寄存器 B: 函数起始寄存器 + Return, // iABC 模式: 返回 R[A] 的值 + + LoadFn, // 惰性装修, iABx: R[A] = new FunctionObject... Jmp, // iAsBx: ip += sBx 无条件跳转 JmpIfFalse, // iAsBx: 如果 R[A] 为假, ip += sBx diff --git a/src/Compiler/CompileTest.cpp b/src/Compiler/CompileTest.cpp index 3d6155d..1dc8a91 100644 --- a/src/Compiler/CompileTest.cpp +++ b/src/Compiler/CompileTest.cpp @@ -1,9 +1,10 @@ +#include +#include +#include #include #include -#include -#include #include -#include + #include #include @@ -24,7 +25,7 @@ int main() return 1; } - Lexer lexer(manager.GetSource(), fileName); + Lexer lexer(manager.GetSource(), fileName); Parser parser(lexer, manager, fileName); const auto &program_result = parser.Parse(); @@ -34,25 +35,32 @@ int main() return 1; } Program *program = *program_result; - - Compiler compiler(fileName, manager); - const auto &proto_result = compiler.Compile(program); - if (!proto_result) + + Compiler compiler(fileName, manager); + const auto &comp_result = compiler.Compile(program); + if (!comp_result) { - ReportError(proto_result.error(), manager); + ReportError(comp_result.error(), manager); return 1; } - Proto *proto = *proto_result; + CompiledModule *compiledModule = *comp_result; - std::cout << "=== Constant Pool ===" << '\n'; - for (size_t i = 0; i < proto->constants.size(); ++i) + size_t cnt = 0; + for (Proto *proto : compiledModule->protos) { - std::print("[{}] {}\n", i, proto->constants[i].ToString()); + std::cout << "=====================\n" + << "Proto: " << cnt++ << '\n'; + std::cout << "=== Constant Pool ===" << '\n'; + for (size_t i = 0; i < proto->constants.size(); ++i) + { + std::print("[{}] {}\n", i, proto->constants[i].ToString()); + } + + DumpCode(proto->code); + + std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl; } - DumpCode(proto->code); - - std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl; return 0; } \ No newline at end of file diff --git a/src/Compiler/Compiler.cpp b/src/Compiler/Compiler.cpp index 4807703..59afd67 100644 --- a/src/Compiler/Compiler.cpp +++ b/src/Compiler/Compiler.cpp @@ -9,9 +9,8 @@ namespace Fig { - Result Compiler::Compile(Program *program) + Result Compiler::Compile(Program *program) { - current->proto = new Proto(); current->freeReg = 0; for (Stmt *stmt : program->nodes) @@ -22,7 +21,16 @@ namespace Fig return std::unexpected(result.error()); } } + + if (mainFuncIndex != -1) + { + std::uint8_t baseReg = AllocReg(); + Emit(Op::iABC(OpCode::FastCall, mainFuncIndex, baseReg, 0)); + } + Emit(Op::iABC(OpCode::Exit, 0, 0, 0)); // 一定要退出,这是虚拟机退出信号,否则ub - return current->proto; + + CompiledModule *compiledModule = new CompiledModule(fileName, allProtos); + return compiledModule; } }; // namespace Fig \ No newline at end of file diff --git a/src/Compiler/Compiler.hpp b/src/Compiler/Compiler.hpp index 24cdb73..651cdce 100644 --- a/src/Compiler/Compiler.hpp +++ b/src/Compiler/Compiler.hpp @@ -19,7 +19,7 @@ namespace Fig { - // 编译产物 + // 编译产物-函数 struct Proto { DynArray code; @@ -34,7 +34,7 @@ namespace Fig int depth; // 物理作用域深度(用于 EndScope 释放寄存器) }; - inline constexpr int MAX_LOCALS = 250; + inline constexpr int MAX_LOCALS = 250; inline constexpr int MAX_CONSTANTS = UINT16_MAX + 1; // 任何跨函数、跨模块的编译,都压入弹出这个 State @@ -58,6 +58,25 @@ namespace Fig // 注意:这里不 delete proto,因为 proto 是要作为编译产物吐出去的 }; + struct CompiledModule + { + String name; // 供调试/打印 + DynArray protos; // 扁平化函数原型 + + CompiledModule(String _name, DynArray _protos) : + name(std::move(_name)), protos(std::move(_protos)) + { + } + + ~CompiledModule() + { + for (auto *p : protos) + { + delete p; + } + } + }; + class Compiler { private: @@ -65,7 +84,13 @@ namespace Fig SourceManager &manager; FuncState *current = nullptr; // 永远指向当前正在编译的上下文 + + int mainFuncIndex = -1; + HashMap globalFuncMap; // localid -> ProtoIdx + public: + DynArray allProtos; + struct FuncStateProtector { Compiler *compiler; @@ -89,6 +114,7 @@ namespace Fig { // 初始化顶级作用域 current = new FuncState("global", nullptr); + allProtos.push_back(current->proto); // 最顶层, bootstrapper } ~Compiler() @@ -102,7 +128,8 @@ namespace Fig } } - Result Compile(Program *program); + Result Compile(Program *program); + private: void PushState(String _name) { @@ -158,10 +185,9 @@ namespace Fig std::uint16_t AddConstant(Value v) { - // TODO: 查重 auto it = std::find(current->proto->constants.begin(), current->proto->constants.end(), v); - if (it != current->proto->constants.end()) + if (it != current->proto->constants.end()) { return std::distance(current->proto->constants.begin(), it); } @@ -245,6 +271,8 @@ namespace Fig Result compileLeftValue( Expr *); // 左值对象,可以是变量、结构体字段或模块对象 + Result compileCallExpr(CallExpr *); + Result compileExpr(Expr *); /* Statements */ @@ -252,6 +280,8 @@ namespace Fig Result compileBlockStmt(BlockStmt *); Result compileIfStmt(IfStmt *); Result compileWhileStmt(WhileStmt *); + Result compileFnDefStmt(FnDefStmt *); + Result compileReturnStmt(ReturnStmt *); Result compileStmt(Stmt *); }; @@ -271,6 +301,10 @@ namespace Fig switch (op) { + case OpCode::Exit: { + break; + } + case OpCode::Mov: { // iABx 模式 std::uint16_t bx = (inst >> 16) & 0xFFFF; @@ -292,6 +326,22 @@ namespace Fig break; } + case OpCode::FastCall: + { + std::uint8_t b = (inst >> 16) & 0xFF; + std::cout << std::format("Proto{:<3} R[{}]+", a, b); + break; + } + case OpCode::Call: + { + std::uint8_t b = (inst >> 16) & 0xFF; + std::cout << std::format("R{:<3} R[{}]+", a, b); + break; + } + + case OpCode::LoadTrue: + case OpCode::LoadFalse: + case OpCode::LoadNull: case OpCode::Add: case OpCode::Sub: case OpCode::Mul: @@ -308,17 +358,24 @@ namespace Fig std::cout << std::format("R{}", a); break; } - default: { - std::cout << "?"; + + case OpCode::LoadFn: { + std::uint16_t bx = (inst >> 16) & 0xFFFF; + std::cout << std::format("R{:<3} Proto[{}]", a, bx); break; } + + // default: { + // std::cout << "?"; + // break; + // } } std::cout << '\n'; } inline void DumpCode(const DynArray &code) { - std::cout << "=== Bytecode ===\n"; + std::cout << " Bytecode\n"; for (std::size_t i = 0; i < code.size(); ++i) { DisassembleInstruction(code[i], i); diff --git a/src/Compiler/ExprCompiler.cpp b/src/Compiler/ExprCompiler.cpp index a4aab72..a4b54a1 100644 --- a/src/Compiler/ExprCompiler.cpp +++ b/src/Compiler/ExprCompiler.cpp @@ -65,19 +65,17 @@ namespace Fig assert("false" && "CompileLiteral: unsupport literal"); } - std::uint8_t targetReg = AllocReg(); + std::uint8_t targetReg = AllocReg(); if (current->proto->constants.size() >= MAX_CONSTANTS) { - return std::unexpected(Error( - ErrorType::TooManyConstants, + return std::unexpected(Error(ErrorType::TooManyConstants, std::format("constant limit exceeded: {}", MAX_CONSTANTS), "How did you write such code? try global variable or split file", - makeSourceLocation(lit) - )); + makeSourceLocation(lit))); } - std::uint16_t kIndex = AddConstant(v); + std::uint16_t kIndex = AddConstant(v); Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex)); return targetReg; @@ -230,6 +228,75 @@ namespace Fig return 0; } } + + Result Compiler::compileCallExpr(CallExpr *expr) + { + bool isStatic = false; // 是否为单纯的 fn(...) 静态函数调用 + int protoIdx = -1; + + if (expr->callee->type == AstType::IdentiExpr) + { + IdentiExpr *id = static_cast(expr->callee); + // 如果是函数名且深度为 0 (全局/扁平函数池) + if (id->resolvedType->tag == TypeTag::Function && id->resolvedDepth == 0) + { + if (globalFuncMap.contains(id->localId)) + { + isStatic = true; + protoIdx = globalFuncMap[id->localId]; + } + } + } + + std::uint8_t baseReg = AllocReg(); + + if (!isStatic) + { + auto calleeRes = compileExpr(expr->callee); + if (!calleeRes) + { + return calleeRes; + } + + if (*calleeRes != baseReg) + { + Emit(Op::iABx(OpCode::Mov, baseReg, *calleeRes)); + } + } + + for (size_t i = 0; i < expr->args.size(); ++i) + { + std::uint8_t argTarget = AllocReg(); + auto argRes = compileExpr(expr->args.args[i]); + if (!argRes) + { + return argRes; + } + + if (*argRes != argTarget) + { + Emit(Op::iABx(OpCode::Mov, argTarget, *argRes)); + } + } + + std::uint8_t expectRet = 1; + + if (isStatic) + { + Emit(Op::iABC(OpCode::FastCall, (std::uint8_t) protoIdx, baseReg, expectRet)); + } + else + { + Emit(Op::iABC(OpCode::Call, baseReg, baseReg, expectRet)); + } + + for (size_t i = 0; i < expr->args.args.size(); ++i) + { + current->freeReg--; + } + return baseReg; // 返回值起点 + } + Result Compiler::compileExpr( Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID { @@ -242,6 +309,7 @@ namespace Fig case AstType::IdentiExpr: { return compileLeftValue(expr); // 左值直接转换成右值 } + case AstType::LiteralExpr: { LiteralExpr *lit = static_cast(expr); @@ -253,9 +321,14 @@ namespace Fig std::uint8_t targetReg = *result; return targetReg; } + case AstType::InfixExpr: { return compileInfixExpr(static_cast(expr)); } + + case AstType::CallExpr: { + return compileCallExpr(static_cast(expr)); + } } } } // namespace Fig \ No newline at end of file diff --git a/src/Compiler/StmtCompiler.cpp b/src/Compiler/StmtCompiler.cpp index 39bb3be..f88bab8 100644 --- a/src/Compiler/StmtCompiler.cpp +++ b/src/Compiler/StmtCompiler.cpp @@ -175,6 +175,67 @@ namespace Fig return {}; } + Result 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(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(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 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 Compiler::compileStmt(Stmt *stmt) // 编译语句 { switch (stmt->type) @@ -206,6 +267,14 @@ namespace Fig case AstType::WhileStmt: { return compileWhileStmt(static_cast(stmt)); } + + case AstType::FnDefStmt: { + return compileFnDefStmt(static_cast(stmt)); + } + + case AstType::ReturnStmt: { + return compileReturnStmt(static_cast(stmt)); + } } return Result(); diff --git a/src/Object/Object.cpp b/src/Object/Object.cpp index aa3b08f..c6031e5 100644 --- a/src/Object/Object.cpp +++ b/src/Object/Object.cpp @@ -9,7 +9,7 @@ namespace Fig { - constexpr String Value::ToString() const + String Value::ToString() const { if (IsNull()) { diff --git a/src/Object/ObjectBase.hpp b/src/Object/ObjectBase.hpp index 0d7a21a..ae90e1b 100644 --- a/src/Object/ObjectBase.hpp +++ b/src/Object/ObjectBase.hpp @@ -182,7 +182,7 @@ namespace Fig // 类函数 [[nodiscard]] - constexpr String ToString() const; + String ToString() const; }; /* diff --git a/src/Sema/Analyzer.cpp b/src/Sema/Analyzer.cpp index d23c9e7..b243c21 100644 --- a/src/Sema/Analyzer.cpp +++ b/src/Sema/Analyzer.cpp @@ -282,7 +282,8 @@ namespace Fig } TypeInfo *valueType = stmt->value->resolvedType; - if (currentReturnType != typeCtx.GetAny() && currentReturnType != valueType) + + if (!currentReturnType->isAny() && !valueType->isAny() && currentReturnType != valueType) { return std::unexpected(Error(ErrorType::TypeError, std::format("return type mismatch: expects '{}', got `{}`", @@ -500,6 +501,36 @@ namespace Fig return {}; } + Result Analyzer::analyzeCallExpr(CallExpr *expr) + { + auto calleeRes = analyzeExpr(expr->callee); + if (!calleeRes) + { + return calleeRes; + } + + if (expr->callee->resolvedType != typeCtx.GetAny() + && expr->callee->resolvedType != typeCtx.GetFunction()) + { + return std::unexpected(Error(ErrorType::TypeError, + std::format("object `{}` is not callable", expr->callee->toString()), + "none", + makeSourceLocation(expr->callee))); + } + + for (auto *arg : expr->args.args) + { + auto argRes = analyzeExpr(arg); + if (!argRes) + { + return argRes; + } + } + expr->resolvedType = typeCtx.GetAny(); + + return {}; + } + Result Analyzer::analyzeStmt(Stmt *stmt) { if (!stmt) @@ -596,10 +627,17 @@ namespace Fig return {}; } - case AstType::IdentiExpr: return analyzeIdentiExpr(static_cast(expr)); + case AstType::IdentiExpr: { + return analyzeIdentiExpr(static_cast(expr)); + } - case AstType::InfixExpr: + case AstType::InfixExpr: { return analyzeInfixExpr(static_cast(expr)); + } + + case AstType::CallExpr: { + return analyzeCallExpr(static_cast(expr)); + } // TODO: PrefixExpr (前缀), CallExpr (函数调用), MemberExpr (属性访问) diff --git a/src/Sema/Analyzer.hpp b/src/Sema/Analyzer.hpp index 0d50b87..21f3206 100644 --- a/src/Sema/Analyzer.hpp +++ b/src/Sema/Analyzer.hpp @@ -87,6 +87,7 @@ namespace Fig Result analyzeIdentiExpr(IdentiExpr *); Result analyzeInfixExpr(InfixExpr *); + Result analyzeCallExpr(CallExpr *); Result analyzeStmt(Stmt *); Result analyzeExpr(Expr *); diff --git a/src/VM/VM.cpp b/src/VM/VM.cpp index 35b22b8..d51001d 100644 --- a/src/VM/VM.cpp +++ b/src/VM/VM.cpp @@ -7,79 +7,85 @@ #include -#define BINARY_ARITHMETIC_OP(opCode, op) \ - case OpCode::opCode: { \ - std::uint8_t b = decodeB(inst); \ - std::uint8_t c = decodeC(inst); \ - Value lhs = registers[b]; \ - Value rhs = registers[c]; \ - if (lhs.IsInt() && rhs.IsInt()) [[likely]] \ - { \ - registers[a] = Value::FromInt(lhs.AsInt() op rhs.AsInt()); \ - } \ - else if (lhs.IsDouble() && rhs.IsDouble()) [[likely]] \ - { \ - registers[a] = Value::FromDouble(lhs.AsDouble() op rhs.AsDouble()); \ - } \ - /* 隐式类型提升:Int 与 Double 混合运算 */ \ - else if (lhs.IsInt() && rhs.IsDouble()) [[likely]] \ - { \ - registers[a] = Value::FromDouble(lhs.AsInt() op rhs.AsDouble()); \ - } \ - else if (lhs.IsDouble() && rhs.IsInt()) [[likely]] \ - { \ - registers[a] = Value::FromDouble(lhs.AsDouble() op rhs.AsInt()); \ - } \ - else \ - { \ - assert(false && "VM Runtime Error: Unsupported types for arithmetic operation"); \ - } \ - break; \ +#define BINARY_ARITHMETIC_OP(opCode, op) \ + case OpCode::opCode: { \ + std::uint8_t b = decodeB(inst); \ + std::uint8_t c = decodeC(inst); \ + Value lhs = currentFrame->registerBase[b]; \ + Value rhs = currentFrame->registerBase[c]; \ + if (lhs.IsInt() && rhs.IsInt()) [[likely]] \ + { \ + currentFrame->registerBase[a] = Value::FromInt(lhs.AsInt() op rhs.AsInt()); \ + } \ + else if (lhs.IsDouble() && rhs.IsDouble()) [[likely]] \ + { \ + currentFrame->registerBase[a] = Value::FromDouble(lhs.AsDouble() op rhs.AsDouble()); \ + } \ + /* 隐式类型提升:Int 与 Double 混合运算 */ \ + else if (lhs.IsInt() && rhs.IsDouble()) [[likely]] \ + { \ + currentFrame->registerBase[a] = Value::FromDouble(lhs.AsInt() op rhs.AsDouble()); \ + } \ + else if (lhs.IsDouble() && rhs.IsInt()) [[likely]] \ + { \ + currentFrame->registerBase[a] = Value::FromDouble(lhs.AsDouble() op rhs.AsInt()); \ + } \ + else \ + { \ + assert(false && "VM Runtime Error: Unsupported types for arithmetic operation"); \ + } \ + break; \ } -#define BINARY_COMPARE_OP(opCode, op) \ - case OpCode::opCode: { \ - std::uint8_t b = decodeB(inst); \ - std::uint8_t c = decodeC(inst); \ - Value lhs = registers[b]; \ - Value rhs = registers[c]; \ - if (lhs.IsInt() && rhs.IsInt()) [[likely]] \ - { \ - registers[a] = (lhs.AsInt() op rhs.AsInt()) ? Value::GetTrueInstance() : Value::GetFalseInstance(); \ - } \ - else if (lhs.IsDouble() && rhs.IsDouble()) [[likely]] \ - { \ - registers[a] = (lhs.AsDouble() op rhs.AsDouble()) ? Value::GetTrueInstance() : Value::GetFalseInstance(); \ - } \ - else if (lhs.IsInt() && rhs.IsDouble()) [[likely]] \ - { \ - registers[a] = (lhs.AsInt() op rhs.AsDouble()) ? Value::GetTrueInstance() : Value::GetFalseInstance(); \ - } \ - else if (lhs.IsDouble() && rhs.IsInt()) [[likely]] \ - { \ - registers[a] = (lhs.AsDouble() op rhs.AsInt()) ? Value::GetTrueInstance() : Value::GetFalseInstance(); \ - } \ - else \ - { \ - /* TODO: 非数字比较 */ \ - assert(false && "VM Runtime Error: Unsupported types for comparison"); \ - } \ - break; \ +#define BINARY_COMPARE_OP(opCode, op) \ + case OpCode::opCode: { \ + std::uint8_t b = decodeB(inst); \ + std::uint8_t c = decodeC(inst); \ + Value lhs = currentFrame->registerBase[b]; \ + Value rhs = currentFrame->registerBase[c]; \ + if (lhs.IsInt() && rhs.IsInt()) [[likely]] \ + { \ + currentFrame->registerBase[a] = (lhs.AsInt() op rhs.AsInt()) ? \ + Value::GetTrueInstance() : \ + Value::GetFalseInstance(); \ + } \ + else if (lhs.IsDouble() && rhs.IsDouble()) [[likely]] \ + { \ + currentFrame->registerBase[a] = (lhs.AsDouble() op rhs.AsDouble()) ? \ + Value::GetTrueInstance() : \ + Value::GetFalseInstance(); \ + } \ + else if (lhs.IsInt() && rhs.IsDouble()) [[likely]] \ + { \ + currentFrame->registerBase[a] = (lhs.AsInt() op rhs.AsDouble()) ? \ + Value::GetTrueInstance() : \ + Value::GetFalseInstance(); \ + } \ + else if (lhs.IsDouble() && rhs.IsInt()) [[likely]] \ + { \ + currentFrame->registerBase[a] = (lhs.AsDouble() op rhs.AsInt()) ? \ + Value::GetTrueInstance() : \ + Value::GetFalseInstance(); \ + } \ + else \ + { \ + /* TODO: 非数字比较 */ \ + assert(false && "VM Runtime Error: Unsupported types for comparison"); \ + } \ + break; \ } namespace Fig { - Result VM::Execute(Proto *proto) + Result VM::Execute(CompiledModule *compiledModule) { - // 指令指针 (Instruction Pointer / PC) 和 常量池指针 - const Instruction *ip = proto->code.data(); - const Value *k = proto->constants.data(); + Proto *entry = compiledModule->protos[0]; + pushFrame(entry, registers); - // 核心解释器循环 (The Dispatch Loop) while (true) { // 取指并递增指针 - Instruction inst = *ip++; + Instruction inst = *(currentFrame->ip++); // 解码 OpCode 和 A 操作数 OpCode op = decodeOpCode(inst); @@ -92,34 +98,63 @@ namespace Fig case OpCode::LoadK: { std::uint16_t bx = decodeBx(inst); - registers[a] = k[bx]; // constants + currentFrame->registerBase[a] = currentFrame->getConstant(bx); // constants + break; + } + + case OpCode::LoadTrue: { + currentFrame->registerBase[a] = Value::GetTrueInstance(); + break; + } + + case OpCode::LoadFalse: { + currentFrame->registerBase[a] = Value::GetFalseInstance(); + break; + } + + case OpCode::LoadNull: { + currentFrame->registerBase[a] = Value::GetNullInstance(); + break; + } + + case OpCode::FastCall: { + Proto *proto = compiledModule->protos[a]; + std::uint8_t baseReg = decodeB(inst); + + pushFrame(proto, currentFrame->registerBase + baseReg); + break; + } + + case OpCode::Call: { break; } case OpCode::Return: { - return registers[a]; + *currentFrame->registerBase = currentFrame->registerBase[a]; + popFrame(); + break; } case OpCode::Jmp: { std::int16_t sbx = decodeSBx(inst); - ip += sbx; + currentFrame->ip += sbx; break; } case OpCode::JmpIfFalse: { - Value &v = registers[a]; + Value &v = currentFrame->registerBase[a]; bool cond = v.AsBool(); // 条件类型 Compiler检查 if (!cond) { std::int16_t sbx = decodeSBx(inst); - ip += sbx; + currentFrame->ip += sbx; } break; } case OpCode::Mov: { std::uint16_t bx = decodeBx(inst); - registers[a] = registers[bx]; + currentFrame->registerBase[a] = currentFrame->registerBase[bx]; break; } @@ -136,9 +171,9 @@ namespace Fig BINARY_COMPARE_OP(LessEqual, <=); - default: { - assert(false && "VM: Unknown OpCode encountered!"); - } + // default: { + // assert(false && "VM: Unknown OpCode encountered!"); + // } } } return Value::GetNullInstance(); diff --git a/src/VM/VM.hpp b/src/VM/VM.hpp index c13512e..04f8790 100644 --- a/src/VM/VM.hpp +++ b/src/VM/VM.hpp @@ -16,6 +16,18 @@ namespace Fig { + struct CallFrame + { + Proto *proto; // 当前执行的原型 + Instruction *ip; // 当前指令指针 + Value *registerBase; // 寄存器起点 + + inline Value getConstant(std::uint16_t idx) + { + return proto->constants[idx]; + } + }; + class VM { private: @@ -24,6 +36,8 @@ namespace Fig // 一次性分配 Value registers[MAX_REGISTERS]; + DynArray frames; + CallFrame *currentFrame; public: VM() { @@ -34,6 +48,26 @@ namespace Fig } private: + + void pushFrame(Proto *proto, Value *base) + { + frames.push_back({ + proto, + proto->code.data(), + base + }); + currentFrame = &frames.back(); + } + + void popFrame() + { + frames.pop_back(); + if (!frames.empty()) + { + currentFrame = &frames.back(); + } + } + inline OpCode decodeOpCode(Instruction inst) { return static_cast(inst & 0xFF); @@ -61,7 +95,7 @@ namespace Fig public: // 执行入口:接收 Proto - Result Execute(Proto *proto); + Result Execute(CompiledModule *); inline void PrintRegisters() { diff --git a/src/main.cpp b/src/main.cpp index 015a552..1bf91a9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,34 +50,53 @@ int main() std::cout << "analyzer: Program OK, PASSED\n"; Compiler compiler(fileName, manager); - const auto &proto_result = compiler.Compile(program); - if (!proto_result) + const auto &comp_result = compiler.Compile(program); + if (!comp_result) { - ReportError(proto_result.error(), manager); + ReportError(comp_result.error(), manager); return 1; } + + CompiledModule *compiledModule = *comp_result; - Proto *proto = *proto_result; - - std::cout << "=== Constant Pool ===" << '\n'; - for (size_t i = 0; i < proto->constants.size(); ++i) + size_t cnt = 0; + for (Proto *proto : compiledModule->protos) { - std::print("[{}] {}\n", i, proto->constants[i].ToString()); + std::cout << "\n" + << "Proto: " << cnt++ << '\n'; + std::cout << " Constant Pool" << '\n'; + for (size_t i = 0; i < proto->constants.size(); ++i) + { + std::print("[{}] {}\n", i, proto->constants[i].ToString()); + } + + DumpCode(proto->code); + + std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl; } - - DumpCode(proto->code); - - std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl; - + VM vm; - auto result_ = vm.Execute(proto); + using Clock = std::chrono::high_resolution_clock; + + Clock clock; + + auto start = clock.now(); + + auto result_ = vm.Execute(compiledModule); + + auto end = clock.now(); + auto duration = end - start; + if (!result_) { ReportError(result_.error(), manager); return 1; } + Value result = *result_; std::cout << "result: " << result.ToString() << "\n"; + std::cout << "execution cost: " << std::chrono::duration_cast(duration).count() << "ms\n"; + vm.PrintRegisters(); } \ No newline at end of file