From e44bdc6a2a0cf624b08046ecc7e5c5d5d9d2d66c Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 16 Oct 2026 13:21:05 +0000 Subject: fix(compiler): correct CIE semantics and diagnostic locations Use standard WHILE headers and default-public class fields, resolve pseudocode identifiers without case sensitivity, and check signed i64 literal boundaries before conversion. Preserve source locations across recursive emission and function diagnostics. Add 22 regression cases and update compiler examples and documentation. Validated all 69 CTest entries with the original Linux Actions seed and verified the release package's embedded, native and IR output paths. --- include/cps/AST.h | 27 ++++++++++++++++----------- include/cps/ArrayHandler.h | 11 ++++++----- include/cps/CodeGen.h | 7 +++++-- include/cps/FileAST.h | 16 ++++------------ include/cps/FunctionAST.h | 8 ++------ include/cps/FunctionGen.h | 14 +++++++++----- include/cps/Identifier.h | 27 +++++++++++++++++++++++++++ include/cps/Lexer.h | 5 ++--- include/cps/Parser.h | 6 +++++- include/cps/TypeAST.h | 6 ++---- include/cps/TypeSystem.h | 5 +++-- 11 files changed, 81 insertions(+), 51 deletions(-) create mode 100644 include/cps/Identifier.h (limited to 'include') diff --git a/include/cps/AST.h b/include/cps/AST.h index 1afc359..5aadc21 100644 --- a/include/cps/AST.h +++ b/include/cps/AST.h @@ -6,8 +6,18 @@ namespace cps { -class ExprAST { +class SourceLocation { + int SourceLine = 0; public: + explicit SourceLocation(int Line = 0) : SourceLine(Line) {} + virtual ~SourceLocation() = default; + int getLine() const { return SourceLine; } + void setLine(int Line) { SourceLine = Line; } +}; + +class ExprAST : public SourceLocation { +public: + using SourceLocation::SourceLocation; virtual ~ExprAST() = default; }; @@ -56,13 +66,11 @@ public: class ArrayAccessExprAST : public ExprAST { std::string Name; std::vector> Indices; - int Line; public: ArrayAccessExprAST(const std::string &Name, std::vector> Indices, int Line) - : Name(Name), Indices(std::move(Indices)), Line(Line) {} + : ExprAST(Line), Name(Name), Indices(std::move(Indices)) {} const std::string &getName() const { return Name; } const std::vector> &getIndices() const { return Indices; } - int getLine() const { return Line; } }; class UnaryExprAST : public ExprAST { @@ -78,18 +86,17 @@ public: class BinaryExprAST : public ExprAST { int Op; std::unique_ptr LHS, RHS; - int Line; public: BinaryExprAST(int Op, std::unique_ptr LHS, std::unique_ptr RHS, int Line) - : Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)), Line(Line) {} + : ExprAST(Line), Op(Op), LHS(std::move(LHS)), RHS(std::move(RHS)) {} int getOp() const { return Op; } ExprAST *getLHS() const { return LHS.get(); } ExprAST *getRHS() const { return RHS.get(); } - int getLine() const { return Line; } }; -class StmtAST { +class StmtAST : public SourceLocation { public: + using SourceLocation::SourceLocation; virtual ~StmtAST() = default; }; @@ -154,14 +161,12 @@ class ArrayAssignStmtAST : public StmtAST { std::string Name; std::vector> Indices; std::unique_ptr Expr; - int Line; public: ArrayAssignStmtAST(const std::string &Name, std::vector> Indices, std::unique_ptr Expr, int Line) - : Name(Name), Indices(std::move(Indices)), Expr(std::move(Expr)), Line(Line) {} + : StmtAST(Line), Name(Name), Indices(std::move(Indices)), Expr(std::move(Expr)) {} const std::string &getName() const { return Name; } const std::vector> &getIndices() const { return Indices; } ExprAST *getExpr() const { return Expr.get(); } - int getLine() const { return Line; } }; class InputStmtAST : public StmtAST { diff --git a/include/cps/ArrayHandler.h b/include/cps/ArrayHandler.h index def174a..843bdc8 100644 --- a/include/cps/ArrayHandler.h +++ b/include/cps/ArrayHandler.h @@ -1,4 +1,5 @@ #pragma once +#include "cps/Identifier.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -28,10 +29,10 @@ class ArrayHandler { llvm::LLVMContext *TheContext; llvm::IRBuilder<> *Builder; llvm::Module *TheModule; - std::map *Symbols; + IdentifierMap *Symbols; TypeSystem &Types; - std::map ArrayTable; + IdentifierMap ArrayTable; RuntimeCheck &RuntimeChecker; llvm::FunctionCallee MallocFunc; @@ -63,7 +64,7 @@ public: ArrayHandler(llvm::LLVMContext &C, llvm::IRBuilder<> &B, llvm::Module &M, - std::map &Sym, + IdentifierMap &Sym, TypeSystem &TS, RuntimeCheck &RC); @@ -89,12 +90,12 @@ public: // Swap in a fresh table (function bodies get their own scope, mirroring // the Symbols save/clear/restore discipline); returns the previous table. - std::map exchangeTable(std::map NewTable); + IdentifierMap exchangeTable(IdentifierMap NewTable); // Copy for block-scoping: control-flow bodies snapshot before and restore // after, so an array declared inside a branch cannot be referenced past it // (its buffer setup and bound SSA values live inside the branch). - std::map snapshotTable() const { return ArrayTable; } + IdentifierMap snapshotTable() const { return ArrayTable; } // Callee side of an array parameter: rebuild metadata from the incoming // data pointer + per-dim bounds. MakeCopy (BYVAL) mallocs and memcpys the diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h index 2ba5e79..3c80eb8 100644 --- a/include/cps/CodeGen.h +++ b/include/cps/CodeGen.h @@ -1,4 +1,6 @@ #pragma once +#include "llvm/Support/SaveAndRestore.h" +#include "cps/Identifier.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -27,10 +29,11 @@ class CodeGen { std::unique_ptr TheContext; std::unique_ptr TheModule; std::unique_ptr> Builder; - std::map Symbols; + int DiagnosticLine = 0; + IdentifierMap Symbols; struct ConstantScope { unsigned ID; - std::map> Saved; + IdentifierMap> Saved; }; std::vector ConstantScopes = {{0, {}}}; unsigned NextScopeID = 1; diff --git a/include/cps/FileAST.h b/include/cps/FileAST.h index 04bd06a..a151597 100644 --- a/include/cps/FileAST.h +++ b/include/cps/FileAST.h @@ -9,55 +9,47 @@ namespace cps { class OpenFileStmtAST : public StmtAST { std::unique_ptr FileName; FileMode Mode; - int Line; public: OpenFileStmtAST(std::unique_ptr FileName, FileMode Mode, int Line) - : FileName(std::move(FileName)), Mode(Mode), Line(Line) {} + : StmtAST(Line), FileName(std::move(FileName)), Mode(Mode) {} ExprAST *getFileName() const { return FileName.get(); } FileMode getMode() const { return Mode; } - int getLine() const { return Line; } }; class ReadFileStmtAST : public StmtAST { std::unique_ptr FileName; std::string VarName; - int Line; public: ReadFileStmtAST(std::unique_ptr FileName, const std::string &VarName, int Line) - : FileName(std::move(FileName)), VarName(VarName), Line(Line) {} + : StmtAST(Line), FileName(std::move(FileName)), VarName(VarName) {} ExprAST *getFileName() const { return FileName.get(); } const std::string &getVarName() const { return VarName; } - int getLine() const { return Line; } }; class WriteFileStmtAST : public StmtAST { std::unique_ptr FileName; std::unique_ptr Data; - int Line; public: WriteFileStmtAST(std::unique_ptr FileName, std::unique_ptr Data, int Line) - : FileName(std::move(FileName)), Data(std::move(Data)), Line(Line) {} + : StmtAST(Line), FileName(std::move(FileName)), Data(std::move(Data)) {} ExprAST *getFileName() const { return FileName.get(); } ExprAST *getData() const { return Data.get(); } - int getLine() const { return Line; } }; class CloseFileStmtAST : public StmtAST { std::unique_ptr FileName; - int Line; public: CloseFileStmtAST(std::unique_ptr FileName, int Line) - : FileName(std::move(FileName)), Line(Line) {} + : StmtAST(Line), FileName(std::move(FileName)) {} ExprAST *getFileName() const { return FileName.get(); } - int getLine() const { return Line; } }; } // namespace cps diff --git a/include/cps/FunctionAST.h b/include/cps/FunctionAST.h index 66ac728..0c2d0b5 100644 --- a/include/cps/FunctionAST.h +++ b/include/cps/FunctionAST.h @@ -58,29 +58,25 @@ public: class CallExprAST : public ExprAST { std::string Callee; std::vector> Args; - int Line; public: CallExprAST(const std::string &Callee, std::vector> Args, int Line) - : Callee(Callee), Args(std::move(Args)), Line(Line) {} + : ExprAST(Line), Callee(Callee), Args(std::move(Args)) {} const std::string &getCallee() const { return Callee; } const std::vector> &getArgs() const { return Args; } - int getLine() const { return Line; } }; class CallStmtAST : public StmtAST { std::string Callee; std::vector> Args; - int Line; public: CallStmtAST(const std::string &Callee, std::vector> Args, int Line) - : Callee(Callee), Args(std::move(Args)), Line(Line) {} + : StmtAST(Line), Callee(Callee), Args(std::move(Args)) {} const std::string &getCallee() const { return Callee; } const std::vector> &getArgs() const { return Args; } - int getLine() const { return Line; } }; diff --git a/include/cps/FunctionGen.h b/include/cps/FunctionGen.h index 80c91ea..4bf4519 100644 --- a/include/cps/FunctionGen.h +++ b/include/cps/FunctionGen.h @@ -1,4 +1,5 @@ #pragma once +#include "cps/Identifier.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "cps/FunctionAST.h" @@ -34,6 +35,7 @@ struct ParamSig { // dispatch on declared parameter types and modes instead of inferring them // back from LLVM types. struct FuncSig { + std::string Name; std::string ReturnTypeName; std::vector Params; }; @@ -55,10 +57,12 @@ private: TypeSystem &Types; ExceptionHandler &Exceptions; - std::map &Symbols; + IdentifierMap &Symbols; bool &HadError; + int &DiagnosticLine; + void reportError(const char *Fmt, ...); - std::map Signatures; + IdentifierMap Signatures; ArrayParamBinder BindArrayParam; void createArgumentAllocas(llvm::Function *F, const std::vector &Params); @@ -69,9 +73,9 @@ public: llvm::IRBuilder<> &B, TypeSystem &TS, ExceptionHandler &EH, - std::map &Sym, - bool &HadErrorFlag) - : Context(C), Module(M), Builder(B), Types(TS), Exceptions(EH), Symbols(Sym), HadError(HadErrorFlag) {} + IdentifierMap &Sym, + bool &HadErrorFlag, int &Line) + : Context(C), Module(M), Builder(B), Types(TS), Exceptions(EH), Symbols(Sym), HadError(HadErrorFlag), DiagnosticLine(Line) {} llvm::Type *getLLVMType(const std::string &TypeName); diff --git a/include/cps/Identifier.h b/include/cps/Identifier.h new file mode 100644 index 0000000..c35f636 --- /dev/null +++ b/include/cps/Identifier.h @@ -0,0 +1,27 @@ +#pragma once +#include +#include +#include +#include + +namespace cps { + +inline unsigned char foldIdentifier(unsigned char C) { + return C >= 'A' && C <= 'Z' ? C + ('a' - 'A') : C; +} + +struct IdentifierLess { + bool operator()(const std::string &A, const std::string &B) const { + return std::lexicographical_compare(A.begin(), A.end(), B.begin(), B.end(), + [](unsigned char L, unsigned char R) { return foldIdentifier(L) < foldIdentifier(R); }); + } +}; + +inline bool sameIdentifier(const std::string &A, const std::string &B) { + return !IdentifierLess{}(A, B) && !IdentifierLess{}(B, A); +} + +template using IdentifierMap = std::map; +using IdentifierSet = std::set; + +} // namespace cps diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h index efedec8..749ae0b 100644 --- a/include/cps/Lexer.h +++ b/include/cps/Lexer.h @@ -25,7 +25,6 @@ enum Token { tok_endif = -9, tok_while = -10, - tok_do = -11, tok_endwhile = -12, tok_repeat = -13, @@ -116,7 +115,7 @@ class Lexer { struct TokenData { int Kind, Line; std::string Identifier, String; - int64_t Integer; + uint64_t Integer; double Real; char Character; }; @@ -129,7 +128,7 @@ public: std::string IdentifierStr; std::string StringVal; - int64_t NumVal = 0; + uint64_t NumVal = 0; double RealVal = 0; char CharVal = '\0'; diff --git a/include/cps/Parser.h b/include/cps/Parser.h index 0079c8b..fdbb99a 100644 --- a/include/cps/Parser.h +++ b/include/cps/Parser.h @@ -1,4 +1,5 @@ #pragma once +#include "cps/Identifier.h" #include "cps/Lexer.h" #include "cps/AST.h" #include "cps/TypeAST.h" @@ -24,7 +25,7 @@ class Parser { unsigned BlockDepth = 0; // ParseBlock nesting; 1 = top level std::map BinopPrecedence; - std::set TypeNames = { + IdentifierSet TypeNames = { "INTEGER", "REAL", "BOOLEAN", "STRING", "CHAR", "VOID", "C_INT", "C_CHAR", "C_STRING", "C_DOUBLE" }; @@ -33,7 +34,9 @@ class Parser { int GetTokPrecedence(); std::unique_ptr ParseExpression(); + std::unique_ptr ParseUnaryImpl(); std::unique_ptr ParseUnary(); + std::unique_ptr ParsePrimaryImpl(); std::unique_ptr ParsePrimary(); std::unique_ptr ParseBinOpRHS(int ExprPrec, std::unique_ptr LHS); @@ -71,6 +74,7 @@ class Parser { std::unique_ptr ParseCallStmt(); std::unique_ptr ParseReturnStmt(); std::optional> ParsePrototypeArgs(bool AllowByRef); + bool ParseIntegerValue(bool Negative, int64_t &Out); bool ParseSignedIntBound(int64_t &Out); std::unique_ptr ParseOpenFile(); diff --git a/include/cps/TypeAST.h b/include/cps/TypeAST.h index 873ca4a..edf2ee5 100644 --- a/include/cps/TypeAST.h +++ b/include/cps/TypeAST.h @@ -81,7 +81,7 @@ public: const std::vector &getFields() const { return Fields; } }; -// CLASS with explicitly PUBLIC/PRIVATE fields, ending in ENDCLASS. +// CLASS with default-public or explicit PUBLIC/PRIVATE fields, ending in ENDCLASS. // Storage and value semantics are inherited from record declarations. class ClassTypeDeclAST : public RecordTypeDeclAST { public: @@ -107,17 +107,15 @@ struct DesignatorAccess { class DesignatorExprAST : public ExprAST { std::string BaseName; std::vector Accesses; - int Line; public: DesignatorExprAST(const std::string &BaseName, std::vector Accesses, int Line) - : BaseName(BaseName), Accesses(std::move(Accesses)), Line(Line) {} + : ExprAST(Line), BaseName(BaseName), Accesses(std::move(Accesses)) {} const std::string &getBaseName() const { return BaseName; } const std::vector &getAccesses() const { return Accesses; } - int getLine() const { return Line; } }; // ^ — address-of. The operand is a designator by construction, diff --git a/include/cps/TypeSystem.h b/include/cps/TypeSystem.h index b615ed8..8bee6b9 100644 --- a/include/cps/TypeSystem.h +++ b/include/cps/TypeSystem.h @@ -1,4 +1,5 @@ #pragma once +#include "cps/Identifier.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" @@ -112,8 +113,8 @@ struct SymbolInfo { class TypeSystem { llvm::LLVMContext &Context; - std::map Types; - std::map EnumConstants; + IdentifierMap Types; + IdentifierMap EnumConstants; void registerBuiltins(); const TypeInfo *registerType(const std::string &TypeName, -- cgit v1.3.1-4-g156e