diff --git a/Fig-VSCode/bin/Fig-LSP.exe b/Fig-VSCode/bin/Fig-LSP.exe index bc6e237..a5a4bcf 100644 Binary files a/Fig-VSCode/bin/Fig-LSP.exe and b/Fig-VSCode/bin/Fig-LSP.exe differ diff --git a/src/Ast/Ast.hpp b/src/Ast/Ast.hpp index e18d5fa..d533941 100644 --- a/src/Ast/Ast.hpp +++ b/src/Ast/Ast.hpp @@ -16,4 +16,5 @@ #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/src/Ast/Base.hpp b/src/Ast/Base.hpp index 17e6011..27b046e 100644 --- a/src/Ast/Base.hpp +++ b/src/Ast/Base.hpp @@ -36,7 +36,8 @@ namespace Fig ExprStmt, // 表达式语句,如 println(1) VarDecl, // 变量声明 IfStmt, // If语句 - ElseIfStmt, // ElseIf语句,不准悬空 + ElseIfStmt, // ElseIf语句,不准悬空,平铺式else if + WhileStmt, // while语句 }; struct AstNode { diff --git a/src/Ast/Expr/IdentiExpr.hpp b/src/Ast/Expr/IdentiExpr.hpp index 1da9471..1c78260 100644 --- a/src/Ast/Expr/IdentiExpr.hpp +++ b/src/Ast/Expr/IdentiExpr.hpp @@ -16,9 +16,17 @@ namespace Fig { String name; - // Analyzer槽位,存储具体深度 - int resolvedDepth = -1; // 代表未解析 - bool isGlobal = false; // 是否全局/对外公开 (isPublic) + // Analyzer槽位 + + // 寻址空间 + bool isGlobal = false; // 是否全局, 全局变量存哈希/堆 + + // 仅 isGlobal = false 有效 + int resolvedDepth = -1; // 用于获取闭包上值, -1 代表未解析 + + // 栈内槽位 + int localId = -1; // 局部变量id, -1 未解析 + IdentiExpr() { diff --git a/src/Ast/Stmt/VarDecl.hpp b/src/Ast/Stmt/VarDecl.hpp index 781f611..2d94883 100644 --- a/src/Ast/Stmt/VarDecl.hpp +++ b/src/Ast/Stmt/VarDecl.hpp @@ -19,6 +19,8 @@ namespace Fig bool isInfer; // 是否用了 := 类型推断 Expr *initExpr; + int localId = -1; + VarDecl() { type = AstType::VarDecl; diff --git a/src/Ast/Stmt/WhileStmt.hpp b/src/Ast/Stmt/WhileStmt.hpp new file mode 100644 index 0000000..0a1bc31 --- /dev/null +++ b/src/Ast/Stmt/WhileStmt.hpp @@ -0,0 +1,37 @@ +/*! + @file src/Ast/Stmt/WhileStmt.hpp + @brief WhileStmt定义 + @author PuqiAR (im@puqiar.top) + @date 2026-02-24 +*/ + +#pragma once + +#include + +namespace Fig +{ + struct WhileStmt final : public Stmt + { + Expr *cond; + BlockStmt *body; + + WhileStmt() + { + type = AstType::WhileStmt; + } + + WhileStmt(Expr *_cond, BlockStmt *_body, SourceLocation _location) : + cond(_cond), + body(_body) + { + type = AstType::WhileStmt; + location = std::move(_location); + } + + virtual String toString() const override + { + return std::format("", cond->toString(), body->toString()); + } + }; +}; // namespace Fig \ No newline at end of file diff --git a/src/Compiler/Compiler.cpp b/src/Compiler/Compiler.cpp index ce0fc2d..4807703 100644 --- a/src/Compiler/Compiler.cpp +++ b/src/Compiler/Compiler.cpp @@ -16,7 +16,7 @@ namespace Fig for (Stmt *stmt : program->nodes) { - const auto &result = CompileStmt(static_cast(stmt)); + auto result = compileStmt(static_cast(stmt)); if (!result) { return std::unexpected(result.error()); diff --git a/src/Compiler/Compiler.hpp b/src/Compiler/Compiler.hpp index 17d4be7..014b55e 100644 --- a/src/Compiler/Compiler.hpp +++ b/src/Compiler/Compiler.hpp @@ -29,12 +29,14 @@ namespace Fig struct LocalVar { - bool isPublic; // 是否向上级/同级其他域公开 - String name; - std::uint8_t reg; // 寄存器(相对 frame base 的寄存器 id) - int depth; // 作用域深度 + int localId; // AST 传来的纯数字 ID + std::uint8_t reg; // 分配到的物理寄存器 ID + int depth; // 物理作用域深度(用于 EndScope 释放寄存器) }; + static constexpr int MAX_LOCALS = 250; + static constexpr int MAX_CONSTANTS = UINT16_MAX; + // 任何跨函数、跨模块的编译,都压入弹出这个 State struct FuncState { @@ -46,9 +48,12 @@ namespace Fig int scopeDepth = 0; DynArray locals; + std::uint8_t fastRegMap[UINT8_MAX + 1]; // 256, 索引 = localId, 值 = 寄存器 id + FuncState(String _name, FuncState *enc = nullptr) : name(std::move(_name)), enclosing(enc) { proto = new Proto(); + std::fill_n(fastRegMap, 256, UINT8_MAX); // 255代表未分配 } // 注意:这里不 delete proto,因为 proto 是要作为编译产物吐出去的 }; @@ -100,7 +105,7 @@ namespace Fig std::uint8_t AllocReg() { - if (current->freeReg >= 250) + if (current->freeReg >= 255) { assert(false && "Register overflow!"); } @@ -137,6 +142,13 @@ 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()) + { + return std::distance(current->proto->constants.begin(), it); + } + current->proto->constants.push_back(v); return static_cast(current->proto->constants.size() - 1); } @@ -156,73 +168,18 @@ namespace Fig } } - bool HasLocalInCurrentScope(const String &name) - { - // 逆向查重 - for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it) - { - if (it->depth < current->scopeDepth) - break; // 已经超出了当前深度,提前阻断 - if (it->name == name) - return true; - } - return false; - } - - bool HasLocal(const String &name) - { - for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it) - { - if (it->name == name) - { - if (it->depth == current->scopeDepth) - { - return true; // 同级不管 public直接捕获 - } - else if (it->isPublic) - { - return true; // 不同级变量 public才能被捕捉 - } - } - } - return false; - } - - std::uint8_t ResolveLocal(const String &name) - { - // 变量遮蔽: 永远先使用同级已有的变量, 所以逆向遍历 - for (auto it = current->locals.rbegin(); it != current->locals.rend(); ++it) - { - if (it->name == name) - { - if (it->depth < current->scopeDepth && !it->isPublic) - { - assert( - false - && "ResolveLocal: Attempt to access a private variable from an outer scope!"); - } - - return it->reg; - } - } - - // 如果在本 Frame 没找到,那就是外层函数的变量 (闭包 Upvalue) 或者全局变量 (Global)。 - assert( - false - && "ResolveLocal: Variable not found in current frame (Upvalue/Global not implemented yet)!"); - return UINT8_MAX; - } - - std::uint8_t DeclareLocal(bool isPublic, const String &name) + std::uint8_t DeclareLocal(int localId) { std::uint8_t reg = AllocReg(); - current->locals.push_back(LocalVar{isPublic, name, reg, current->scopeDepth}); + current->locals.push_back(LocalVar{localId, reg, current->scopeDepth}); + current->fastRegMap[localId] = reg; return reg; } - std::uint8_t DeclareLocal(bool isPublic, const String &name, std::uint8_t reg) + std::uint8_t DeclareLocal(int localId, std::uint8_t reg) // 表示复用哪个寄存器 { - current->locals.push_back(LocalVar{isPublic, name, reg, current->scopeDepth}); + current->locals.push_back(LocalVar{localId, reg, current->scopeDepth}); + current->fastRegMap[localId] = reg; return reg; } @@ -261,23 +218,25 @@ namespace Fig return location; } - Result CompileIdentiExpr(IdentiExpr *); - Result CompileLiteral(LiteralExpr *); + Result compileIdentiExpr(IdentiExpr *); + Result compileLiteral(LiteralExpr *); - Result CompileAssignment( + Result compileAssignment( InfixExpr *); // 编译赋值,由 CompileInfixExpr调用 - Result CompileInfixExpr(InfixExpr *); + Result compileInfixExpr(InfixExpr *); - Result CompileLeftValue( + Result compileLeftValue( Expr *); // 左值对象,可以是变量、结构体字段或模块对象 - Result CompileExpr(Expr *); + Result compileExpr(Expr *); /* Statements */ - Result CompileVarDecl(VarDecl *); - Result CompileBlockStmt(BlockStmt *); - Result CompileIfStmt(IfStmt *); - Result CompileStmt(Stmt *); + Result compileVarDecl(VarDecl *); + Result compileBlockStmt(BlockStmt *); + Result compileIfStmt(IfStmt *); + Result compileWhileStmt(WhileStmt *); + + Result compileStmt(Stmt *); }; inline void DisassembleInstruction(Instruction inst, std::size_t index) diff --git a/src/Compiler/ExprCompiler.cpp b/src/Compiler/ExprCompiler.cpp index a983cef..ec96d9d 100644 --- a/src/Compiler/ExprCompiler.cpp +++ b/src/Compiler/ExprCompiler.cpp @@ -9,18 +9,18 @@ namespace Fig { - Result Compiler::CompileIdentiExpr(IdentiExpr *ie) + Result Compiler::compileIdentiExpr(IdentiExpr *ie) { - // if (!HasLocal(ie->name)) - // { - // return std::unexpected(Error(ErrorType::UseUndeclaredIdentifier, - // std::format("`{}` has not been defined", ie->name), - // "none", - // makeSourceLocation(ie))); - // } - return ResolveLocal(ie->name); + // TODO: 处理全局变量和闭包 Upvalue + std::uint8_t targetReg = current->fastRegMap[ie->localId]; + + if (targetReg == UINT8_MAX) + { + assert(false && "Compiler Bug: Encountered unmapped localId in fastRegMap!"); + } + return targetReg; } - Result Compiler::CompileLiteral( + Result Compiler::compileLiteral( LiteralExpr *lit) // 编译字面量, 负责转换 token -> Value { const Token &token = lit->token; @@ -47,8 +47,8 @@ namespace Fig } else if (token.type == TokenType::LiteralNumber) { - // TODO: 更换为无异常手写数字解析版本 - if (lexeme.contains(U'.')) + // TODO: 更换为无异常手写数字解析版本 (charconv也可) + if (lexeme.contains(U'.') || lexeme.contains(U'e')) { // 非整数 double d = std::stod(lexeme.toStdString()); @@ -63,23 +63,34 @@ namespace Fig } std::uint8_t targetReg = AllocReg(); + + if (current->proto->constants.size() >= MAX_CONSTANTS) + { + 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) + )); + } + std::uint16_t kIndex = AddConstant(v); Emit(Op::iABx(OpCode::LoadK, targetReg, kIndex)); return targetReg; } - Result Compiler::CompileAssignment( + Result Compiler::compileAssignment( InfixExpr *infix) // 编译赋值,由 CompileInfixExpr调用 { // op必须为 = - const auto &_lhsReg = CompileLeftValue(infix->left); // 必须为左值对象 + const auto &_lhsReg = compileLeftValue(infix->left); // 必须为左值对象 if (!_lhsReg) { return _lhsReg; } std::uint8_t lhsReg = *_lhsReg; - const auto &_rhsReg = CompileExpr(infix->right); + const auto &_rhsReg = compileExpr(infix->right); std::uint8_t rhsReg = *_rhsReg; FreeReg(rhsReg); @@ -119,21 +130,21 @@ namespace Fig } return lhsReg; // 返回赋值的结果,支持连续赋值 } - Result Compiler::CompileInfixExpr( + Result Compiler::compileInfixExpr( InfixExpr *infix) // 编译中缀表达式,返回一个存放结果的寄存器 ID { if (infix->op >= BinaryOperator::Assign && infix->op <= BinaryOperator::BitXorAssign) { - return CompileAssignment(infix); + return compileAssignment(infix); } - const auto &_lhsReg = CompileExpr(infix->left); + const auto &_lhsReg = compileExpr(infix->left); if (!_lhsReg) { return _lhsReg; } std::uint8_t lhsReg = *_lhsReg; - const auto &_rhsReg = CompileExpr(infix->right); + const auto &_rhsReg = compileExpr(infix->right); if (!_rhsReg) { return _rhsReg; @@ -171,25 +182,52 @@ namespace Fig break; } + case BinaryOperator::Greater: { + Emit(Op::iABC(OpCode::Greater, resultReg, lhsReg, rhsReg)); + break; + } + + case BinaryOperator::GreaterEqual: { + Emit(Op::iABC(OpCode::GreaterEqual, resultReg, lhsReg, rhsReg)); + break; + } + + case BinaryOperator::Less: { + Emit(Op::iABC(OpCode::Less, resultReg, lhsReg, rhsReg)); + break; + } + + case BinaryOperator::LessEqual: { + Emit(Op::iABC(OpCode::LessEqual, resultReg, lhsReg, rhsReg)); + break; + } + + case BinaryOperator::Equal: { + Emit(Op::iABC(OpCode::Equal, resultReg, lhsReg, rhsReg)); + break; + } + default: assert(false && "CompileInfixExpr: op unsupported yet"); } return resultReg; } - Result Compiler::CompileLeftValue( + Result Compiler::compileLeftValue( Expr *expr) // 左值对象,可以是变量、结构体字段或模块对象 { switch (expr->type) { - case AstType::IdentiExpr: return CompileIdentiExpr(static_cast(expr)); + case AstType::IdentiExpr: + return compileIdentiExpr(static_cast(expr)); + // TODO: 数组切片(a[0])或对象属性(a.b) default: - return std::unexpected(Error(ErrorType::NotAnLvalue, - std::format("`{}` is not a lvalue, expect a valid lvalue", expr->toString()), - "none", - makeSourceLocation(expr))); + // Analyzer 有漏洞(编译器内部 + // 直接崩溃 + assert(false && "Compiler Bug: Invalid L-value bypassed Analyzer!"); + return 0; } } - Result Compiler::CompileExpr( + Result Compiler::compileExpr( Expr *expr) // 编译表达式,必定返回一个存放结果的寄存器 ID { switch (expr->type) @@ -199,12 +237,12 @@ namespace Fig case AstType::AstNode: assert(false && "CompileExpr: bad node type"); break; case AstType::IdentiExpr: { - return CompileLeftValue(expr); // 左值直接转换成右值 + return compileLeftValue(expr); // 左值直接转换成右值 } case AstType::LiteralExpr: { LiteralExpr *lit = static_cast(expr); - const auto &result = CompileLiteral(lit); + auto result = compileLiteral(lit); if (!result) { return std::unexpected(result.error()); @@ -213,7 +251,7 @@ namespace Fig return targetReg; } case AstType::InfixExpr: { - return CompileInfixExpr(static_cast(expr)); + return compileInfixExpr(static_cast(expr)); } } } diff --git a/src/Compiler/StmtCompiler.cpp b/src/Compiler/StmtCompiler.cpp index a7f4b63..10e9407 100644 --- a/src/Compiler/StmtCompiler.cpp +++ b/src/Compiler/StmtCompiler.cpp @@ -9,40 +9,40 @@ namespace Fig { - Result Compiler::CompileVarDecl(VarDecl *varDecl) + Result Compiler::compileVarDecl(VarDecl *varDecl) { - const String &name = varDecl->name; - // if (HasLocalInCurrentScope(name)) - // { - // return std::unexpected(Error(ErrorType::RedeclarationError, - // std::format("variable `{}` has already defined in this scope", name), - // "change its name", - // makeSourceLocation(varDecl))); - // } + if (current->freeReg > MAX_LOCALS) + { + return std::unexpected(Error(ErrorType::TooManyLocals, + std::format("local limit exceeded: {}", MAX_LOCALS), + "try split function or use arrays/structs...", + makeSourceLocation(varDecl))); + } + std::uint8_t varReg; if (varDecl->initExpr) { - const auto &result = CompileExpr(varDecl->initExpr); + auto result = compileExpr(varDecl->initExpr); if (!result) { return std::unexpected(result.error()); } std::uint8_t resultReg = *result; - varReg = resultReg; // 复用临时计算结果寄存器 - DeclareLocal(varDecl->isPublic, name, varReg); + varReg = DeclareLocal(varDecl->localId, resultReg); // 复用临时计算结果寄存器 } else { - varReg = DeclareLocal(varDecl->isPublic, name); + varReg = DeclareLocal(varDecl->localId); } + return Result(); } - Result Compiler::CompileBlockStmt(BlockStmt *blockStmt) + Result Compiler::compileBlockStmt(BlockStmt *blockStmt) { for (Stmt *stmt : blockStmt->nodes) { - const auto &result = CompileStmt(stmt); + auto result = compileStmt(stmt); if (!result) { return result; @@ -51,7 +51,7 @@ namespace Fig return {}; } - Result Compiler::CompileIfStmt(IfStmt *stmt) + Result Compiler::compileIfStmt(IfStmt *stmt) { /* if cond1 @@ -97,7 +97,7 @@ namespace Fig */ std::vector exitJumps; // 所有分支都要跳到最后,收集所有jump最后回填 - const auto &condResult = CompileExpr(stmt->cond); + const auto &condResult = compileExpr(stmt->cond); if (!condResult) { return std::unexpected(condResult.error()); @@ -106,7 +106,7 @@ namespace Fig int jumpToNext = EmitJump(OpCode::JmpIfFalse, condReg); FreeReg(condReg); - const auto &blockResult = CompileStmt(stmt->consequent); + const auto &blockResult = compileStmt(stmt->consequent); if (!blockResult) { return blockResult; @@ -117,7 +117,7 @@ namespace Fig for (auto *elif : stmt->elifs) { - const auto &elifCondResult = CompileExpr(elif->cond); + const auto &elifCondResult = compileExpr(elif->cond); if (!elifCondResult) return std::unexpected(elifCondResult.error()); std::uint8_t elifCondReg = *elifCondResult; @@ -125,7 +125,7 @@ namespace Fig jumpToNext = EmitJump(OpCode::JmpIfFalse, elifCondReg); FreeReg(elifCondReg); - const auto &blockResult = CompileStmt(elif->consequent); + const auto &blockResult = compileStmt(elif->consequent); if (!blockResult) { return blockResult; @@ -136,7 +136,7 @@ namespace Fig if (stmt->alternate) { - const auto &result = CompileStmt(stmt->alternate); + auto result = compileStmt(stmt->alternate); if (!result) { return result; @@ -148,31 +148,65 @@ namespace Fig } return {}; } - Result Compiler::CompileStmt(Stmt *stmt) // 编译语句 + + Result Compiler::compileWhileStmt(WhileStmt *stmt) { - if (stmt->type == AstType::ExprStmt) + int beginIns = current->proto->code.size() - 1; + + auto condRegResult = compileExpr(stmt->cond); + if (!condRegResult) { - ExprStmt *exprStmt = static_cast(stmt); - Expr *expr = exprStmt->expr; - const auto &result = CompileExpr(expr); - if (!result) - { - return std::unexpected(result.error()); + 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 Compiler::compileStmt(Stmt *stmt) // 编译语句 + { + switch (stmt->type) + { + case AstType::ExprStmt: { + ExprStmt *exprStmt = static_cast(stmt); + Expr *expr = exprStmt->expr; + auto result = compileExpr(expr); + if (!result) + { + return std::unexpected(result.error()); + } + FreeReg(*result); + break; + } + + case AstType::VarDecl: { + return compileVarDecl(static_cast(stmt)); + } + + case AstType::BlockStmt: { + return compileBlockStmt(static_cast(stmt)); + } + + case AstType::IfStmt: { + return compileIfStmt(static_cast(stmt)); + } + + case AstType::WhileStmt: { + return compileWhileStmt(static_cast(stmt)); } - 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/Error/Error.cpp b/src/Error/Error.cpp index aae2bfc..bed806c 100644 --- a/src/Error/Error.cpp +++ b/src/Error/Error.cpp @@ -56,6 +56,9 @@ namespace Fig case UseUndeclaredIdentifier: return "UseUndeclaredIdentifier"; case NotAnLvalue: return "NotAnLvalue"; case TypeError: return "TypeError"; + + case TooManyLocals: return "TooManyLocals"; + case TooManyConstants: return "TooManyConstants"; // default: return "Some one forgot to add case to `ErrorTypeToString`"; } } diff --git a/src/Error/Error.hpp b/src/Error/Error.hpp index 6a1948e..9c23e5e 100644 --- a/src/Error/Error.hpp +++ b/src/Error/Error.hpp @@ -47,6 +47,10 @@ namespace Fig UseUndeclaredIdentifier, NotAnLvalue, TypeError, + + // compile errors + TooManyLocals, + TooManyConstants, }; const char *ErrorTypeToString(ErrorType type); diff --git a/src/LSP/FigLSPServer.cpp b/src/LSP/LSPServer.cpp similarity index 100% rename from src/LSP/FigLSPServer.cpp rename to src/LSP/LSPServer.cpp diff --git a/src/Lexer/LexerTest.cpp b/src/Lexer/LexerTest.cpp index 915231a..81a5fe1 100644 --- a/src/Lexer/LexerTest.cpp +++ b/src/Lexer/LexerTest.cpp @@ -1,6 +1,7 @@ #include -#include #include +#include + #include @@ -24,18 +25,18 @@ int main() while (true) { - const auto &result = lexer.NextToken(); + auto result = lexer.NextToken(); if (!result.has_value()) { ReportError(result.error(), manager); break; } - const Token &token = *result; + const Token &token = *result; const String &lexeme = manager.GetSub(token.index, token.length); - const auto &type = magic_enum::enum_name(token.type); + const auto &type = magic_enum::enum_name(token.type); if (token.type == TokenType::EndOfFile) { - std::cout << "EOF: " << type << " at " << token.index << '\n'; + std::cout << "EOF: " << type << " at " << token.index << '\n'; break; } std::cout << lexeme << " --> " << type << '\n'; diff --git a/src/Parser/ExprParser.cpp b/src/Parser/ExprParser.cpp index 3f6e9cd..522b71d 100644 --- a/src/Parser/ExprParser.cpp +++ b/src/Parser/ExprParser.cpp @@ -11,14 +11,16 @@ namespace Fig { Result Parser::parseLiteralExpr() // 当前token为literal时调用 { - state = State::ParsingLiteralExpr; + StateProtector p(this, {State::ParsingLiteralExpr}); + const Token &literal_token = consumeToken(); LiteralExpr *node = new LiteralExpr(literal_token, makeSourceLocation(literal_token)); return node; } Result Parser::parseIdentiExpr() // 当前token为Identifier调用 { - state = State::ParsingIdentiExpr; + StateProtector p(this, {State::ParsingIdentiExpr}); + const Token &identifier = consumeToken(); IdentiExpr *node = new IdentiExpr( srcManager.GetSub(identifier.index, identifier.length), makeSourceLocation(identifier)); @@ -27,7 +29,8 @@ namespace Fig Result Parser::parseInfixExpr(Expr *lhs) // 当前token为 op { - state = State::ParsingInfixExpr; + StateProtector p(this, {State::ParsingInfixExpr}); + const Token &op_token = consumeToken(); BinaryOperator op = TokenToBinaryOp(op_token); BindingPower rbp = GetBinaryOpRBp(op); @@ -45,7 +48,8 @@ namespace Fig Result Parser::parsePrefixExpr() // 当前token为op { - state = State::ParsingPrefixExpr; + StateProtector p(this, {State::ParsingPrefixExpr}); + const Token &op_token = consumeToken(); UnaryOperator op = TokenToUnaryOp(op_token); @@ -64,7 +68,8 @@ namespace Fig Result Parser::parseIndexExpr( Expr *base) // 由 parseExpression调用, 当前token为 `[` { - state = State::ParsingIndexExpr; + StateProtector p(this, {State::ParsingIndexExpr}); + const Token &lbracket_token = consumeToken(); // consume `[` const auto &index_result = parseExpression(); @@ -89,7 +94,8 @@ namespace Fig Result Parser::parseCallExpr( Expr *callee) // 由 parseExpression调用, 当前token为 `(` { - state = State::ParsingCallExpr; + StateProtector p(this, {State::ParsingCallExpr}); + const Token &lparen_token = consumeToken(); // consume `(` FnCallArgs callArgs; @@ -137,52 +143,8 @@ namespace Fig return new CallExpr(callee, callArgs); } - const std::unordered_set &Parser::getBaseTerminators() + Result Parser::parseExpression(BindingPower rbp) { - static const std::unordered_set baseTerminators = {TokenType::Semicolon, - TokenType::RightParen, - TokenType::RightBracket, - TokenType::RightBrace, - TokenType::Comma, - TokenType::EndOfFile}; - return baseTerminators; - } - - std::unordered_set &Parser::getTerminators() - { - /* - - Syntax terminators: - ; ) ] } , EOF - */ - - static std::unordered_set terminators(getBaseTerminators()); - return terminators; - } - - void Parser::resetTermintors() - { - getTerminators() = getBaseTerminators(); - } - - bool Parser::shouldTerminate() - { - const Token &token = currentToken(); - const auto &terminators = getTerminators(); - return terminators.contains(token.type); - } - - Result Parser::parseExpression(BindingPower rbp, TokenType stop, TokenType stop2) - { - if (!getTerminators().contains(stop)) - { - getTerminators().insert(stop); - } - if (!getTerminators().contains(stop2)) - { - getTerminators().insert(stop2); - } - Expr *lhs = nullptr; Token token = currentToken(); @@ -191,7 +153,6 @@ namespace Fig const auto &lhs_result = parseIdentiExpr(); if (!lhs_result) { - resetTermintors(); return std::unexpected(lhs_result.error()); } lhs = *lhs_result; @@ -201,7 +162,6 @@ namespace Fig const auto &lhs_result = parseLiteralExpr(); if (!lhs_result) { - resetTermintors(); return std::unexpected(lhs_result.error()); } lhs = *lhs_result; @@ -211,7 +171,6 @@ namespace Fig const auto &lhs_result = parsePrefixExpr(); if (!lhs_result) { - resetTermintors(); return std::unexpected(lhs_result.error()); } lhs = *lhs_result; @@ -222,7 +181,6 @@ namespace Fig const auto &expr_result = parseExpression(0); if (!expr_result) { - resetTermintors(); return expr_result; } const Token &rparen_token = consumeToken(); // consume `)` @@ -238,7 +196,6 @@ namespace Fig if (!lhs) { - resetTermintors(); return std::unexpected(Error(ErrorType::ExpectedExpression, "expected expression", "insert expressions", @@ -252,10 +209,6 @@ namespace Fig { break; } - if (token.type == stop || token.type == stop2) - { - break; - } if (IsTokenOp(token.type /* isBinary = true */)) // 是否为二元运算符 { @@ -268,7 +221,7 @@ namespace Fig break; } - const auto &result = parseInfixExpr(lhs); + auto result = parseInfixExpr(lhs); if (!result) { resetTermintors(); diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 807f692..a9915af 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -5,7 +5,6 @@ @date 2026-02-14 */ - #include namespace Fig @@ -15,7 +14,7 @@ namespace Fig Program *program = new Program; while (!isEOF) { - const auto &result = parseStatement(); + auto result = parseStatement(); if (!result) { return std::unexpected(result.error()); @@ -29,4 +28,4 @@ namespace Fig } return program; } -}; \ No newline at end of file +}; // namespace Fig \ No newline at end of file diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp index 7921c0e..c325077 100644 --- a/src/Parser/Parser.hpp +++ b/src/Parser/Parser.hpp @@ -41,7 +41,7 @@ namespace Fig { return buffer[++index]; } - const auto &result = lexer.NextToken(); + auto result = lexer.NextToken(); if (!result) { ReportError(result.error(), srcManager); @@ -82,7 +82,7 @@ namespace Fig size_t peekIndex = index + lookahead; while (peekIndex >= buffer.size() && !isEOF) { - const auto &result = lexer.NextToken(); + auto result = lexer.NextToken(); if (!result) { ReportError(result.error(), srcManager); @@ -121,51 +121,146 @@ namespace Fig return false; } - inline Error makeUnexpectTokenError(const String &stmtType, const String &expect, const Token &tokenGot, std::source_location loc = std::source_location::current()) + inline Error makeUnexpectTokenError(const String &stmtType, + const String &expect, + const Token &tokenGot, + std::source_location loc = std::source_location::current()) { - return Error( - ErrorType::SyntaxError, - std::format("expect '{}' in {}, got `{}`", expect, stmtType, magic_enum::enum_name(tokenGot.type)), + return Error(ErrorType::SyntaxError, + std::format("expect '{}' in {}, got `{}`", + expect, + stmtType, + magic_enum::enum_name(tokenGot.type)), "none", makeSourceLocation(tokenGot), - loc - ); + loc); } - inline Error makeExpectSemicolonError(std::source_location loc = std::source_location::current()) + inline Error makeExpectSemicolonError( + std::source_location loc = std::source_location::current()) { - return Error( - ErrorType::SyntaxError, + return Error(ErrorType::SyntaxError, "expect ';' after statement", "insert ';'", makeSourceLocation(currentToken()), - loc - ); + loc); } public: - enum class State : std::uint8_t + struct State { - Standby, + enum StateType : std::uint8_t + { + Standby, - ParsingLiteralExpr, - ParsingIdentiExpr, + ParsingLiteralExpr, + ParsingIdentiExpr, - ParsingInfixExpr, - ParsingPrefixExpr, + ParsingInfixExpr, + ParsingPrefixExpr, - ParsingIndexExpr, - ParsingCallExpr, + ParsingIndexExpr, + ParsingCallExpr, - ParsingVarDecl, - ParsingIf, + ParsingVarDecl, + ParsingIf, + ParsingWhile, - } state; + } type = StateType::Standby; + std::unordered_set stopAt = {}; + }; + private: + const std::unordered_set &getBaseTerminators() + { + static const std::unordered_set baseTerminators = {TokenType::Semicolon, + TokenType::RightParen, + TokenType::RightBracket, + TokenType::RightBrace, + TokenType::Comma, + TokenType::EndOfFile}; + return baseTerminators; + } + + std::unordered_set &getTerminators() // 返回固定的终止符 + { + /* + Syntax terminators: + ; ) ] } , EOF + */ + + static std::unordered_set terminators(getBaseTerminators()); + return terminators; + } + + void resetTermintors() + { + getTerminators() = getBaseTerminators(); + } + bool shouldTerminate() // 判断是否终结 + { + const Token &token = currentToken(); + const auto &terminators = getTerminators(); + + if (terminators.contains(token.type)) + { + return true; + } + for (auto it = stateStack.rbegin(); it < stateStack.rend(); ++it) + { + if (it->stopAt.contains(token.type)) + { + return true; + } + } + return false; + } + + DynArray stateStack; + + State ¤tState() + { + return stateStack.back(); + } + + void pushState(State _state) + { + stateStack.push_back(std::move(_state)); + } + + void popState() + { + if (!stateStack.empty()) + { + stateStack.pop_back(); + } + } + + class StateProtector + { + Parser *parser; + + public: + StateProtector(Parser *p, const State &newState) : parser(p) + { + parser->pushState(newState); + } + + ~StateProtector() + { + parser->popState(); + } + + // 禁止拷贝 + StateProtector(const StateProtector &) = delete; + StateProtector &operator=(const StateProtector &) = delete; + }; + + public: Parser(Lexer &_lexer, SourceManager &_srcManager, String _fileName) : lexer(_lexer), srcManager(_srcManager), fileName(std::move(_fileName)) { - state = State::Standby; + pushState(State()); } private: @@ -175,33 +270,33 @@ namespace Fig return SourceLocation(SourcePosition(line, column, tok.length), fileName, "[internal parser]", - magic_enum::enum_name(state).data()); + magic_enum::enum_name(currentState().type).data()); } /* Expressions */ Result parseLiteralExpr(); // 当前token为literal时调用 Result parseIdentiExpr(); // 当前token为Identifier调用 - Result parseInfixExpr(Expr *); // 由 parseExpression递归调用, 当前token为op - Result parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op + Result parseInfixExpr( + Expr *); // 由 parseExpression递归调用, 当前token为op + Result parsePrefixExpr(); // 由 parseExpression递归调用, 当前token为op - Result parseIndexExpr(Expr *); // 由 parseExpression调用, 当前token为 `[` - Result parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(` + Result parseIndexExpr( + Expr *); // 由 parseExpression调用, 当前token为 `[` + Result parseCallExpr(Expr *); // 由 parseExpression调用, 当前token为 `(` - const std::unordered_set &getBaseTerminators(); - std::unordered_set &getTerminators(); // 返回固定的终止符 - void resetTermintors(); - bool shouldTerminate(); // 判断是否终结 - - Result parseExpression(BindingPower = 0, TokenType stop = TokenType::Semicolon, TokenType stop2 = TokenType::Semicolon); + Result parseExpression(BindingPower = 0); /* Statements */ - Result parseBlockStmt(); // 当前token为 { - Result parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var - Result parseIfStmt(); // 由 parseStatement调用, 当前token is if - Result parseStatement(); + Result parseBlockStmt(); // 当前token为 { + Result parseVarDecl(bool); // 由 parseStatement调用, 当前token为 var + Result parseIfStmt(); // 由 parseStatement调用, 当前token为 if + Result parseWhileStmt(); // 由 parseStatement调用, 当前token为 while + Result parseStatement(); public: Result Parse(); }; + +#define SET_STOP_AT(...) currentState().stopAt = {__VA_ARGS__}; }; // namespace Fig \ No newline at end of file diff --git a/src/Parser/ParserTest.cpp b/src/Parser/ParserTest.cpp index e89e467..e661ce1 100644 --- a/src/Parser/ParserTest.cpp +++ b/src/Parser/ParserTest.cpp @@ -16,9 +16,9 @@ int main() return 1; } - Lexer lexer(source, fileName); + Lexer lexer(source, fileName); Parser parser(lexer, srcManager, fileName); - const auto &result = parser.Parse(); + auto result = parser.Parse(); if (!result) { ReportError(result.error(), srcManager); diff --git a/src/Parser/StmtParser.cpp b/src/Parser/StmtParser.cpp index bf14675..785af60 100644 --- a/src/Parser/StmtParser.cpp +++ b/src/Parser/StmtParser.cpp @@ -19,14 +19,14 @@ namespace Fig { return std::unexpected(Error(ErrorType::SyntaxError, "unclosed braces in block stmt", - "insert `}`", + "insert '}'", location)); } if (match(TokenType::RightBrace)) { break; } - const auto &result = parseStatement(); + auto result = parseStatement(); if (!result) { return std::unexpected(result.error()); @@ -38,7 +38,7 @@ namespace Fig Result Parser::parseVarDecl( bool isPublic) // 由 parseStatement调用, 当前token为 var { - state = State::ParsingVarDecl; + StateProtector p(this, {State::ParsingVarDecl}); SourceLocation location = makeSourceLocation(consumeToken()); // consume `var` @@ -52,7 +52,8 @@ namespace Fig Expr *typeSpeicifer = nullptr; if (match(TokenType::Colon)) // `:` { - const auto &result = parseExpression(0, TokenType::Assign, TokenType::Walrus); + SET_STOP_AT(TokenType::Walrus, TokenType::Assign); + auto result = parseExpression(0); if (!result) { return std::unexpected(result.error()); @@ -61,10 +62,10 @@ namespace Fig } Expr *initExpr = nullptr; - bool isInfer = false; + bool isInfer = false; if (match(TokenType::Assign)) { - const auto &result = parseExpression(); + auto result = parseExpression(); if (!result) { return std::unexpected(result.error()); @@ -73,22 +74,21 @@ namespace Fig } else if (match(TokenType::Walrus)) // := { - if (typeSpeicifer) // 指定了类型同时使用 := + if (typeSpeicifer) // 指定了类型同时使用 := { - return std::unexpected(Error( - ErrorType::SyntaxError, + return std::unexpected(Error(ErrorType::SyntaxError, "used type infer but specifying the type", "change `:=` to '='", makeSourceLocation(prevToken()) // := - )); + )); } - const auto &result = parseExpression(); + auto result = parseExpression(); if (!result) { return std::unexpected(result.error()); } initExpr = *result; - isInfer = true; // 使用类型自动推断 := + isInfer = true; // 使用类型自动推断 := } if (!match(TokenType::Semicolon)) { @@ -100,14 +100,16 @@ namespace Fig Result Parser::parseIfStmt() // 由 parseStatement调用, 当前token is if { - state = State::ParsingIf; + StateProtector p(this, {State::ParsingIf}); + SourceLocation location = makeSourceLocation(consumeToken()); // consume `if` Expr *cond = nullptr; if (match(TokenType::LeftParen)) // match and consume `(` { const Token &lpToken = prevToken(); - const auto &result = parseExpression(0, TokenType::RightParen, TokenType::LeftBrace); + SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); + const auto &result = parseExpression(0); if (!result) { return std::unexpected(result.error()); @@ -124,21 +126,21 @@ namespace Fig } else { - const auto &result = parseExpression(0, TokenType::LeftBrace); + SET_STOP_AT(TokenType::LeftBrace); + auto result = parseExpression(0); if (!result) { return std::unexpected(result.error()); } cond = *result; } - state = State::ParsingIf; if (currentToken().type != TokenType::LeftBrace) { return std::unexpected( makeUnexpectTokenError("IfStmt", "LeftBrace `{`", currentToken())); } - const auto &result = parseBlockStmt(); + auto result = parseBlockStmt(); if (!result) { return std::unexpected(result.error()); @@ -167,13 +169,13 @@ namespace Fig if (match(TokenType::LeftParen)) // `(` { const Token &lpToken = prevToken(); - const auto &result = - parseExpression(0, TokenType::RightParen, TokenType::LeftBrace); + + SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); + const auto &result = parseExpression(0); if (!result) { return std::unexpected(result.error()); } - state = State::ParsingIf; if (!match(TokenType::RightParen)) { delete *result; @@ -186,25 +188,24 @@ namespace Fig } else { - const auto &result = parseExpression(0, TokenType::LeftBrace); + SET_STOP_AT(TokenType::LeftBrace); + auto result = parseExpression(0); if (!result) { return std::unexpected(result.error()); } - state = State::ParsingIf; - cond = *result; + cond = *result; } if (currentToken().type != TokenType::LeftBrace) { return std::unexpected( makeUnexpectTokenError("ElseIfStmt", "LeftBrace `{`", currentToken())); } - const auto &result = parseBlockStmt(); + auto result = parseBlockStmt(); if (!result) { return std::unexpected(result.error()); } - state = State::ParsingIf; BlockStmt *consequent = *result; ElseIfStmt *elif = new ElseIfStmt(cond, consequent, elseLocation); elifs.push_back(elif); @@ -224,12 +225,11 @@ namespace Fig return std::unexpected( makeUnexpectTokenError("ElseStmt", "LeftBrace `{`", currentToken())); } - const auto &result = parseBlockStmt(); + auto result = parseBlockStmt(); if (!result) { return std::unexpected(result.error()); } - state = State::ParsingIf; alternate = *result; } } @@ -237,9 +237,68 @@ namespace Fig return ifStmt; } + Result Parser::parseWhileStmt() // 由 parseStatement调用, 当前token为 while + { + StateProtector p(this, {State::ParsingWhile}); + + SourceLocation location = makeSourceLocation(consumeToken()); // consume `while` + + Expr *cond = nullptr; + if (match(TokenType::LeftParen)) + { + const Token &lpToken = prevToken(); + SET_STOP_AT(TokenType::RightParen, TokenType::LeftBrace); + + auto result = parseExpression(); + if (!result) + { + return std::unexpected(result.error()); + } + + if (!match(TokenType::RightParen)) + { + delete *result; + return std::unexpected(Error(ErrorType::SyntaxError, + "unclosed parenthese in while condition", + "insert ')'", + makeSourceLocation(lpToken))); + } + cond = *result; + } + else + { + SET_STOP_AT(TokenType::LeftBrace); + auto result = parseExpression(); + if (!result) + { + return std::unexpected(result.error()); + } + cond = *result; + } + + if (currentToken().type != TokenType::LeftBrace) + { + delete cond; + return std::unexpected( + makeUnexpectTokenError("while stmt", "left brace '{'", currentToken())); + } + + auto result = parseBlockStmt(); + if (!result) + { + delete cond; + return std::unexpected(result.error()); + } + BlockStmt *body = *result; + + WhileStmt *whileStmt = new WhileStmt(cond, body, location); + return whileStmt; + } + Result Parser::parseStatement() { - state = State::Standby; + StateProtector p(this, {State::Standby}); + if (currentToken().type == TokenType::Public) { consumeToken(); // consume `public` @@ -247,20 +306,38 @@ namespace Fig { return parseVarDecl(true); } + else + { + return std::unexpected( + makeUnexpectTokenError("public", "var/const/func/struct", currentToken())); + } } + + if (currentToken().type == TokenType::LeftBrace) + { + return parseBlockStmt(); + } + if (currentToken().type == TokenType::Variable) { return parseVarDecl(false); } + if (currentToken().type == TokenType::If) { return parseIfStmt(); } + if (currentToken().type == TokenType::While) + { + return parseWhileStmt(); + } + if (isEOF) { return nullptr; } + const auto &expr_result = parseExpression(); if (!expr_result) { diff --git a/src/Sema/Analyzer.cpp b/src/Sema/Analyzer.cpp index 724ccf1..c39b9e0 100644 --- a/src/Sema/Analyzer.cpp +++ b/src/Sema/Analyzer.cpp @@ -11,7 +11,8 @@ namespace Fig { Result Analyzer::analyzeVarDecl(VarDecl *stmt) { - if (env.Resolve(stmt->name) != std::nullopt) + auto sym = env.Resolve(stmt->name); + if (sym != std::nullopt && sym->depth == env.GetDepth()) { return std::unexpected(Error(ErrorType::RedeclarationError, std::format("variable `{}` has already defined in this scope", stmt->name), @@ -50,7 +51,7 @@ namespace Fig "none", makeSourceLocation(stmt->initExpr))); } - env.Define(stmt->name, declaredType, stmt->isPublic, false); + stmt->localId = env.Define(stmt->name, declaredType, stmt->isPublic, false); return {}; } @@ -63,12 +64,11 @@ namespace Fig } if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool) { - return std::unexpected(Error( - ErrorType::TypeError, - std::format("if condition must be boolean, got `{}`", magic_enum::enum_name(stmt->cond->resolvedType)), + return std::unexpected(Error(ErrorType::TypeError, + std::format("if condition must be boolean, got `{}`", + magic_enum::enum_name(stmt->cond->resolvedType)), "ensure condition is boolean", - makeSourceLocation(stmt->cond) - )); + makeSourceLocation(stmt->cond))); } auto consequentRes = analyzeStmt(stmt->consequent); if (!consequentRes) @@ -106,6 +106,31 @@ namespace Fig return {}; } + Result Analyzer::analyzeWhileStmt(WhileStmt *stmt) + { + auto condRes = analyzeExpr(stmt->cond); + if (!condRes) + { + return condRes; + } + + if (stmt->cond->resolvedType != TypeTag::Any && stmt->cond->resolvedType != TypeTag::Bool) + { + return std::unexpected(Error(ErrorType::TypeError, + std::format("while condition must be boolean, got `{}`", + magic_enum::enum_name(stmt->cond->resolvedType)), + "ensure condition is boolean", + makeSourceLocation(stmt->cond))); + } + + auto bodyRes = analyzeStmt(stmt->body); + if (!bodyRes) + { + return bodyRes; + } + return {}; + } + Result Analyzer::analyzeIdentiExpr(IdentiExpr *expr) { auto sym = env.Resolve(expr->name); @@ -117,8 +142,11 @@ namespace Fig makeSourceLocation(expr))); } // TODO: 引入 Module 跨文件 import,检查 isPublic - expr->resolvedType = sym->type; + expr->localId = sym->localId; + + expr->resolvedType = sym->type; expr->resolvedDepth = sym->depth; + expr->isGlobal = (sym->depth == 0); return {}; } @@ -138,7 +166,7 @@ namespace Fig switch (expr->op) { - // 1. 算术族 (+, -, *, /, **) + // 算术族 (+, -, *, /, **) case BinaryOperator::Add: if (lType == TypeTag::String && rType == TypeTag::String) { @@ -172,7 +200,7 @@ namespace Fig } break; - // 2. 整数特化族 (%, &, |, ^, <<, >>) + // 整数特化族 (%, &, |, ^, <<, >>) case BinaryOperator::Modulo: case BinaryOperator::BitAnd: case BinaryOperator::BitOr: @@ -196,8 +224,7 @@ namespace Fig } break; - - // 3. 比较族 (==, !=, <, >, <=, >=) + // 比较族 (==, !=, <, >, <=, >=) case BinaryOperator::Equal: case BinaryOperator::NotEqual: @@ -206,7 +233,8 @@ namespace Fig case BinaryOperator::LessEqual: case BinaryOperator::GreaterEqual: case BinaryOperator::Is: - if (lType != TypeTag::Any && rType != TypeTag::Any && lType != rType) // lType == rType放行 + if (lType != TypeTag::Any && rType != TypeTag::Any + && lType != rType) // lType == rType放行 { if (!((lType == TypeTag::Int && rType == TypeTag::Double) || (lType == TypeTag::Double && rType == TypeTag::Int))) @@ -217,7 +245,7 @@ namespace Fig makeSourceLocation(expr))); } } - + // TODO: 支持Struct后进行检查,右操作数是 Struct才合理 // 如 1.2 is Int --> false // 1 is Int --> true @@ -225,8 +253,7 @@ namespace Fig expr->resolvedType = TypeTag::Bool; break; - - // 4. 逻辑族 (&&, ||) + // 逻辑族 (&&, ||) case BinaryOperator::LogicalAnd: case BinaryOperator::LogicalOr: if (lType == TypeTag::Bool && rType == TypeTag::Bool) @@ -246,8 +273,7 @@ namespace Fig } break; - - // 5. 纯赋值与复合赋值族 (=, +=, -=, ...) + // 纯赋值与复合赋值族 (=, +=, -=, ...) case BinaryOperator::Assign: case BinaryOperator::AddAssign: case BinaryOperator::SubAssign: @@ -258,12 +284,11 @@ namespace Fig // 左侧必须是合法的 L-Value if (!isValidLvalue(expr->left)) { - return std::unexpected( - Error(ErrorType::NotAnLvalue, - "invalid assignment target", - "left side must be a variable, property, or indexable target", - makeSourceLocation(expr->left) // 错误精准定位到左侧节点 - )); + return std::unexpected(Error(ErrorType::NotAnLvalue, + "invalid assignment target", + "left side must be a variable, property, or indexable target", + makeSourceLocation(expr->left) // 错误精准定位到左侧节点 + )); } // 类型匹配拦截 (纯赋值) @@ -283,8 +308,7 @@ namespace Fig expr->resolvedType = lType; break; - - // 6. 成员访问 (.) + // 成员访问 (.) case BinaryOperator::MemberAccess: if (lType != TypeTag::Struct && lType != TypeTag::Any) { @@ -293,6 +317,15 @@ namespace Fig "check if the left side evaluates to an object", makeSourceLocation(expr->left))); } + if (expr->right->type != AstType::IdentiExpr) + { + return std::unexpected(Error( + ErrorType::SyntaxError, + std::format("expect field name after member access '.', got {}", expr->right->toString()), + "none", + makeSourceLocation(expr->right) + )); + } expr->resolvedType = TypeTag::Any; break; @@ -335,14 +368,18 @@ namespace Fig case AstType::IfStmt: { return analyzeIfStmt(static_cast(stmt)); } - - // TODO: 其他语句分析 - // default: - // return std::unexpected(Error(ErrorType::TypeError, - // "unsupported statement type in analyzer", - // "internal compiler error", - // makeSourceLocation(stmt))); + case AstType::WhileStmt: { + return analyzeWhileStmt(static_cast(stmt)); + } + + // TODO: 其他语句分析 + + // default: + // return std::unexpected(Error(ErrorType::TypeError, + // "unsupported statement type in analyzer", + // "internal compiler error", + // makeSourceLocation(stmt))); } return {}; } @@ -356,17 +393,13 @@ namespace Fig { case AstType::LiteralExpr: { auto *lit = static_cast(expr); - switch(lit->token.type) + switch (lit->token.type) { case TokenType::LiteralTrue: - case TokenType::LiteralFalse: - lit->resolvedType = TypeTag::Bool; - break; - - case TokenType::LiteralNull: - lit->resolvedType = TypeTag::Null; - break; - + case TokenType::LiteralFalse: lit->resolvedType = TypeTag::Bool; break; + + case TokenType::LiteralNull: lit->resolvedType = TypeTag::Null; break; + case TokenType::LiteralNumber: { const String &lexeme = manager.GetSub(lit->token.index, lit->token.length); if (lexeme.contains(U'.') || lexeme.contains(U'e')) @@ -385,9 +418,10 @@ namespace Fig break; } - default: + default: { lit->resolvedType = TypeTag::Any; break; + } } return {}; } diff --git a/src/Sema/Analyzer.hpp b/src/Sema/Analyzer.hpp index 3e99999..3aa2d66 100644 --- a/src/Sema/Analyzer.hpp +++ b/src/Sema/Analyzer.hpp @@ -56,6 +56,7 @@ namespace Fig Result analyzeVarDecl(VarDecl *); Result analyzeIfStmt(IfStmt *); + Result analyzeWhileStmt(WhileStmt *); Result analyzeIdentiExpr(IdentiExpr *); Result analyzeInfixExpr(InfixExpr *); diff --git a/src/Sema/AnalyzerTest.cpp b/src/Sema/AnalyzerTest.cpp index 33857d7..dc11b9b 100644 --- a/src/Sema/AnalyzerTest.cpp +++ b/src/Sema/AnalyzerTest.cpp @@ -24,10 +24,10 @@ int main() return 1; } - Lexer lexer(manager.GetSource(), fileName); + Lexer lexer(manager.GetSource(), fileName); Parser parser(lexer, manager, fileName); - const auto &result = parser.Parse(); + auto result = parser.Parse(); if (!result) { ReportError(result.error(), manager); diff --git a/src/Sema/Environment.hpp b/src/Sema/Environment.hpp index 7a6f7e6..077100e 100644 --- a/src/Sema/Environment.hpp +++ b/src/Sema/Environment.hpp @@ -7,15 +7,15 @@ #pragma once -#include #include #include +#include +#include #include namespace Fig { - // 记录在 Analyzer 中的符号元数据 struct Symbol { @@ -24,41 +24,108 @@ namespace Fig bool isPublic; int depth; // 词法作用域深度 bool isConstant; // 是否是 const 声明的不可变常量 (用于报错: 尝试修改常量) + + int localId = -1; // Analyzer 虚拟槽位分配 + }; + + // 作用域回档水位线 + struct ScopeWatermark + { + std::size_t symbolCount; + int savedLocalId; + }; + + // 语义分析函数上下文 (隔离局部变量 ID 空间) + struct SemaFuncState + { + SemaFuncState *enclosing = nullptr; + int currentDepth = 0; + int nextLocalId = 0; + DynArray scopeStack; }; class Environment { private: DynArray symbols; - int currentDepth = 0; + SemaFuncState *current = nullptr; public: + Environment() + { + current = new SemaFuncState(); + } + + ~Environment() + { + while (current) + { + SemaFuncState *prev = current->enclosing; + delete current; + current = prev; + } + } + + // 函数边界控 + + void EnterFunction() + { + SemaFuncState *newState = new SemaFuncState(); + newState->enclosing = current; + current = newState; + } + + void LeaveFunction() + { + assert(current && "Environment: Unmatched LeaveFunction"); + SemaFuncState *oldState = current; + current = oldState->enclosing; + delete oldState; + } + + // 词法作用域控制 + void EnterScope() { - currentDepth++; + current->currentDepth++; + current->scopeStack.push_back({symbols.size(), current->nextLocalId}); } + void LeaveScope() { - while (!symbols.empty() && symbols.back().depth > currentDepth) + assert(current->currentDepth > 0 && "Environment: Unmatched LeaveScope"); + current->currentDepth--; + + assert(!current->scopeStack.empty()); + ScopeWatermark archive = current->scopeStack.back(); + current->scopeStack.pop_back(); + + // 物理截断符号表,回滚槽位发号器以复用物理寄存器 + while (symbols.size() > archive.symbolCount) { symbols.pop_back(); } - currentDepth--; + current->nextLocalId = archive.savedLocalId; } - // 注册符号, 调用前确保无重复 (内部assert) - void Define(const String &name, TypeTag type, bool isPublic, bool isConst) + // 符号操作 + + // 注册符号, 返回分配的 localId。调用前内部执行同级作用域重定义断言 + int Define(const String &name, TypeTag type, bool isPublic, bool isConst) { for (auto it = symbols.rbegin(); it != symbols.rend(); ++it) { - if (it->depth < currentDepth) + if (it->depth < current->currentDepth) break; if (it->name == name) { assert(false && "Environment.Define: redefinition"); } } - symbols.push_back({name, type, isPublic, currentDepth, isConst}); + + int allocatedId = current->nextLocalId++; + symbols.push_back({name, type, isPublic, current->currentDepth, isConst, allocatedId}); + return allocatedId; } // 解析符号。找不到返回 nullopt @@ -74,7 +141,7 @@ namespace Fig int GetDepth() const { - return currentDepth; + return current->currentDepth; } }; } // namespace Fig \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 4ddf0f3..015a552 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,13 +3,15 @@ #include #include #include -#include #include +#include #include + +#include #include #include -#include + int main() { @@ -38,7 +40,7 @@ int main() } Program *program = *program_result; - Analyzer analyzer(manager); + Analyzer analyzer(manager); const auto &analyzeResult = analyzer.Analyze(program); if (!analyzeResult) { @@ -47,7 +49,6 @@ int main() } std::cout << "analyzer: Program OK, PASSED\n"; - Compiler compiler(fileName, manager); const auto &proto_result = compiler.Compile(program); if (!proto_result) @@ -67,10 +68,10 @@ int main() DumpCode(proto->code); std::cout << "\nMax Stack Size: " << (int) proto->maxStack << std::endl; - + VM vm; - const auto &result_ = vm.Execute(proto); + auto result_ = vm.Execute(proto); if (!result_) { ReportError(result_.error(), manager); diff --git a/xmake.lua b/xmake.lua index 248bafc..b9c36a6 100644 --- a/xmake.lua +++ b/xmake.lua @@ -101,7 +101,7 @@ target("LSP") add_files("src/Sema/Analyzer.cpp") - add_files("src/LSP/FigLSPServer.cpp") + add_files("src/LSP/LSPServer.cpp") set_filename("Fig-LSP")