diff --git a/src/Ast/Base.hpp b/src/Ast/Base.hpp index 1a0df74..28f3f46 100644 --- a/src/Ast/Base.hpp +++ b/src/Ast/Base.hpp @@ -42,6 +42,7 @@ namespace Fig SourceLocation location; virtual String toString() const = 0; + virtual ~AstNode(){}; }; struct Program; diff --git a/src/Bytecode/Bytecode.hpp b/src/Bytecode/Bytecode.hpp index cf27d5c..23718ec 100644 --- a/src/Bytecode/Bytecode.hpp +++ b/src/Bytecode/Bytecode.hpp @@ -24,6 +24,9 @@ namespace Fig LoadK, // iABx 模式: R[A] = Constants[Bx] Return, // iA 模式: 返回 R[A] 的值 + Jmp, // iAsBx: ip += sBx 无条件跳转 + JmpIfFalse, // iAsBx: 如果 R[A] 为假, ip += sBx + Mov, // iABx: R[A] = R[Bx] Add, // iABC: R[A] = R[B] + R[C] Sub, // iABC: R[A] = R[B] - R[C] @@ -52,10 +55,18 @@ namespace Fig } // [OpCode: 8] [A: 8] [B: 8] [C: 8] - [[nodiscard]] inline constexpr Instruction iABC(OpCode op, std::uint8_t a, std::uint8_t b, std::uint8_t c) + [[nodiscard]] inline constexpr Instruction iABC( + OpCode op, std::uint8_t a, std::uint8_t b, std::uint8_t c) { return static_cast(op) | (static_cast(a) << 8) | (static_cast(b) << 16) | (static_cast(c) << 24); } + + [[nodiscard]] + inline constexpr Instruction iAsBx(OpCode op, std::uint8_t a, std::int16_t sbx) + { + return static_cast(op) | (static_cast(a) << 8) + | (static_cast(static_cast(sbx)) << 16); + } } // namespace Op } // namespace Fig \ No newline at end of file diff --git a/src/Compiler/Compiler.hpp b/src/Compiler/Compiler.hpp index 376c72f..17d4be7 100644 --- a/src/Compiler/Compiler.hpp +++ b/src/Compiler/Compiler.hpp @@ -61,7 +61,8 @@ namespace Fig SourceManager &manager; FuncState *current = nullptr; // 永远指向当前正在编译的上下文 public: - Compiler(String _fileName, SourceManager &_manager) : fileName(std::move(_fileName)), manager(_manager) + Compiler(String _fileName, SourceManager &_manager) : + fileName(std::move(_fileName)), manager(_manager) { // 初始化顶级作用域 current = new FuncState("global", nullptr); @@ -196,7 +197,9 @@ namespace Fig { if (it->depth < current->scopeDepth && !it->isPublic) { - assert(false && "ResolveLocal: Attempt to access a private variable from an outer scope!"); + assert( + false + && "ResolveLocal: Attempt to access a private variable from an outer scope!"); } return it->reg; @@ -204,7 +207,9 @@ namespace Fig } // 如果在本 Frame 没找到,那就是外层函数的变量 (闭包 Upvalue) 或者全局变量 (Global)。 - assert(false && "ResolveLocal: Variable not found in current frame (Upvalue/Global not implemented yet)!"); + assert( + false + && "ResolveLocal: Variable not found in current frame (Upvalue/Global not implemented yet)!"); return UINT8_MAX; } @@ -221,6 +226,33 @@ namespace Fig return reg; } + // 发射一条跳转指令,并返回它在代码数组里的绝对索引 (Index) + int EmitJump(OpCode op, std::uint8_t aReg = 0) + { + // 预填 0 + Emit(Op::iAsBx(op, aReg, 0)); + return current->proto->code.size() - 1; + } + + // 填真实偏移量到那条指令里 + void PatchJump(int instructionIndex) + { + // 目标地址就是当前代码数组的末尾 + int target = current->proto->code.size(); + + // 相对偏移量 = 目标地址 - 指令自身所在的地址 - 1 + // (因为 VM 里的 ip 在取指后会自动 +1,所以偏移要减去 1) + int offset = target - instructionIndex - 1; + + if (offset < INT16_MIN || offset > INT16_MAX) + { + assert(false && "PatchJump: Jump offset exceeds 16-bit signed limit!"); + } + Instruction &inst = current->proto->code[instructionIndex]; + inst = (inst & 0x0000FFFF) + | (static_cast(static_cast(offset)) << 16); + } + SourceLocation makeSourceLocation(AstNode *node) { SourceLocation location = node->location; // copy @@ -232,14 +264,19 @@ namespace Fig Result CompileIdentiExpr(IdentiExpr *); Result CompileLiteral(LiteralExpr *); - Result CompileAssignment(InfixExpr *); // 编译赋值,由 CompileInfixExpr调用 + Result CompileAssignment( + InfixExpr *); // 编译赋值,由 CompileInfixExpr调用 Result CompileInfixExpr(InfixExpr *); - Result CompileLeftValue(Expr *); // 左值对象,可以是变量、结构体字段或模块对象 + Result CompileLeftValue( + Expr *); // 左值对象,可以是变量、结构体字段或模块对象 Result CompileExpr(Expr *); + /* Statements */ Result CompileVarDecl(VarDecl *); + Result CompileBlockStmt(BlockStmt *); + Result CompileIfStmt(IfStmt *); Result CompileStmt(Stmt *); }; @@ -270,6 +307,15 @@ namespace Fig std::cout << std::format("R{:<3} K[{}]", a, bx); break; } + + case OpCode::Jmp: + case OpCode::JmpIfFalse: { + // iAsBx + std::int16_t sbx = static_cast(inst >> 16); + std::cout << std::format("R{:<3} [{}]", a, sbx); + break; + } + case OpCode::Add: case OpCode::Sub: case OpCode::Mul: diff --git a/src/Compiler/ExprCompiler.cpp b/src/Compiler/ExprCompiler.cpp index 191edb5..dea52d6 100644 --- a/src/Compiler/ExprCompiler.cpp +++ b/src/Compiler/ExprCompiler.cpp @@ -20,7 +20,8 @@ namespace Fig } return ResolveLocal(ie->name); } - Result Compiler::CompileLiteral(LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value + Result Compiler::CompileLiteral( + LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value { const Token &token = lit->token; String lexeme = manager.GetSub(token.index, token.length); @@ -56,9 +57,10 @@ namespace Fig std::int32_t i = std::stoi(lexeme.toStdString()); v = Value::FromInt(i); } - - assert("false" && "CompileLiteral: unsupport literal"); - v = Value::GetNullInstance(); + else + { + assert("false" && "CompileLiteral: unsupport literal"); + } std::uint8_t targetReg = AllocReg(); std::uint16_t kIndex = AddConstant(v); @@ -66,7 +68,8 @@ namespace Fig Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex)); return targetReg; } - Result Compiler::CompileAssignment(InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用 + Result Compiler::CompileAssignment( + InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用 { // op必须为 = const auto &_lhsReg = CompileLeftValue(infix->left); // 必须为左值对象 @@ -172,7 +175,8 @@ namespace Fig } return resultReg; } - Result Compiler::CompileLeftValue(Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象 + Result Compiler::CompileLeftValue( + Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象 { switch (expr->type) { @@ -185,7 +189,8 @@ namespace Fig makeSourceLocation(expr))); } } - Result Compiler::CompileExpr(Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID + Result Compiler::CompileExpr( + Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID { switch (expr->type) { @@ -204,7 +209,7 @@ namespace Fig { return std::unexpected(result.error()); } - std::uint8_t targetReg = *result; + std::uint8_t targetReg = *result; return targetReg; } case AstType::InfixExpr: { diff --git a/src/Compiler/StmtCompiler.cpp b/src/Compiler/StmtCompiler.cpp index 171691f..085b7f9 100644 --- a/src/Compiler/StmtCompiler.cpp +++ b/src/Compiler/StmtCompiler.cpp @@ -37,6 +37,117 @@ namespace Fig } return Result(); } + + Result Compiler::CompileBlockStmt(BlockStmt *blockStmt) + { + for (Stmt *stmt : blockStmt->nodes) + { + const auto &result = CompileStmt(stmt); + if (!result) + { + return result; + } + } + return {}; + } + + Result 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 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) + { + const auto &result = CompileStmt(stmt->alternate); + if (!result) + { + return result; + } + } + for (int exitIndex : exitJumps) + { + PatchJump(exitIndex); // 回填所有跳转出口的指令 + } + return {}; + } Result Compiler::CompileStmt(Stmt *stmt) // 编译语句 { if (stmt->type == AstType::ExprStmt) @@ -48,11 +159,20 @@ namespace Fig { return std::unexpected(result.error()); } + FreeReg(*result); } else if (stmt->type == AstType::VarDecl) { return CompileVarDecl(static_cast(stmt)); } + else if (stmt->type == AstType::BlockStmt) + { + return CompileBlockStmt(static_cast(stmt)); + } + else if (stmt->type == AstType::IfStmt) + { + return CompileIfStmt(static_cast(stmt)); + } return Result(); } }; // namespace Fig \ No newline at end of file diff --git a/src/Parser/StmtParser.cpp b/src/Parser/StmtParser.cpp index 0deea81..ae40431 100644 --- a/src/Parser/StmtParser.cpp +++ b/src/Parser/StmtParser.cpp @@ -94,6 +94,7 @@ namespace Fig } if (!match(TokenType::RightParen)) { + delete *result; return std::unexpected(Error(ErrorType::SyntaxError, "unclosed parenthese in if condition", "insert `)`", @@ -155,6 +156,7 @@ namespace Fig state = State::ParsingIf; if (!match(TokenType::RightParen)) { + delete *result; return std::unexpected(Error(ErrorType::SyntaxError, "unclosed parenthese in if condition", "insert `)`", diff --git a/src/VM/VM.cpp b/src/VM/VM.cpp index 7fd25cf..ef0c910 100644 --- a/src/VM/VM.cpp +++ b/src/VM/VM.cpp @@ -89,12 +89,34 @@ namespace Fig case OpCode::Exit: { return Value::GetNullInstance(); } + case OpCode::LoadK: { std::uint16_t bx = decodeBx(inst); registers[a] = k[bx]; // constants break; } + case OpCode::Return: { + return registers[a]; + } + + case OpCode::Jmp: { + std::int16_t sbx = decodeSBx(inst); + ip += sbx; + break; + } + + case OpCode::JmpIfFalse: { + Value &v = registers[a]; + bool cond = v.AsBool(); // 条件类型 Compiler检查 + if (!cond) + { + std::int16_t sbx = decodeSBx(inst); + ip += sbx; + } + break; + } + case OpCode::Mov: { std::uint16_t bx = decodeBx(inst); registers[a] = registers[bx]; @@ -113,9 +135,6 @@ namespace Fig BINARY_COMPARE_OP(GreaterEqual, >=); BINARY_COMPARE_OP(LessEqual, <=); - case OpCode::Return: { - return registers[a]; - } default: { assert(false && "VM: Unknown OpCode encountered!"); diff --git a/src/VM/VM.hpp b/src/VM/VM.hpp index abb1485..c13512e 100644 --- a/src/VM/VM.hpp +++ b/src/VM/VM.hpp @@ -54,6 +54,10 @@ namespace Fig { return (inst >> 24) & 0xFF; } + inline std::int16_t decodeSBx(Instruction inst) + { + return static_cast(inst >> 16); + } public: // 执行入口:接收 Proto