aboutsummaryrefslogtreecommitdiff
path: root/include/cps
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-16 13:21:05 +0000
committer_ov4 <ov4@ov4.org>2026-10-16 13:21:05 +0000
commite44bdc6a2a0cf624b08046ecc7e5c5d5d9d2d66c (patch)
treef5276cc0dd2f34e4d30a58f80223912265a1c5a0 /include/cps
parente1e789ac0249149a4aa1671f5f9260d488cb617a (diff)
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.
Diffstat (limited to 'include/cps')
-rw-r--r--include/cps/AST.h27
-rw-r--r--include/cps/ArrayHandler.h11
-rw-r--r--include/cps/CodeGen.h7
-rw-r--r--include/cps/FileAST.h16
-rw-r--r--include/cps/FunctionAST.h8
-rw-r--r--include/cps/FunctionGen.h14
-rw-r--r--include/cps/Identifier.h27
-rw-r--r--include/cps/Lexer.h5
-rw-r--r--include/cps/Parser.h6
-rw-r--r--include/cps/TypeAST.h6
-rw-r--r--include/cps/TypeSystem.h5
11 files changed, 81 insertions, 51 deletions
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<std::unique_ptr<ExprAST>> Indices;
- int Line;
public:
ArrayAccessExprAST(const std::string &Name, std::vector<std::unique_ptr<ExprAST>> 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<std::unique_ptr<ExprAST>> &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<ExprAST> LHS, RHS;
- int Line;
public:
BinaryExprAST(int Op, std::unique_ptr<ExprAST> LHS, std::unique_ptr<ExprAST> 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<std::unique_ptr<ExprAST>> Indices;
std::unique_ptr<ExprAST> Expr;
- int Line;
public:
ArrayAssignStmtAST(const std::string &Name, std::vector<std::unique_ptr<ExprAST>> Indices, std::unique_ptr<ExprAST> 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<std::unique_ptr<ExprAST>> &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<std::string, SymbolInfo> *Symbols;
+ IdentifierMap<SymbolInfo> *Symbols;
TypeSystem &Types;
- std::map<std::string, ArrayMetadata> ArrayTable;
+ IdentifierMap<ArrayMetadata> ArrayTable;
RuntimeCheck &RuntimeChecker;
llvm::FunctionCallee MallocFunc;
@@ -63,7 +64,7 @@ public:
ArrayHandler(llvm::LLVMContext &C,
llvm::IRBuilder<> &B,
llvm::Module &M,
- std::map<std::string, SymbolInfo> &Sym,
+ IdentifierMap<SymbolInfo> &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<std::string, ArrayMetadata> exchangeTable(std::map<std::string, ArrayMetadata> NewTable);
+ IdentifierMap<ArrayMetadata> exchangeTable(IdentifierMap<ArrayMetadata> 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<std::string, ArrayMetadata> snapshotTable() const { return ArrayTable; }
+ IdentifierMap<ArrayMetadata> 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<llvm::LLVMContext> TheContext;
std::unique_ptr<llvm::Module> TheModule;
std::unique_ptr<llvm::IRBuilder<>> Builder;
- std::map<std::string, SymbolInfo> Symbols;
+ int DiagnosticLine = 0;
+ IdentifierMap<SymbolInfo> Symbols;
struct ConstantScope {
unsigned ID;
- std::map<std::string, std::optional<SymbolInfo>> Saved;
+ IdentifierMap<std::optional<SymbolInfo>> Saved;
};
std::vector<ConstantScope> 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<ExprAST> FileName;
FileMode Mode;
- int Line;
public:
OpenFileStmtAST(std::unique_ptr<ExprAST> 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<ExprAST> FileName;
std::string VarName;
- int Line;
public:
ReadFileStmtAST(std::unique_ptr<ExprAST> 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<ExprAST> FileName;
std::unique_ptr<ExprAST> Data;
- int Line;
public:
WriteFileStmtAST(std::unique_ptr<ExprAST> FileName, std::unique_ptr<ExprAST> 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<ExprAST> FileName;
- int Line;
public:
CloseFileStmtAST(std::unique_ptr<ExprAST> 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<std::unique_ptr<ExprAST>> Args;
- int Line;
public:
CallExprAST(const std::string &Callee, std::vector<std::unique_ptr<ExprAST>> 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<std::unique_ptr<ExprAST>> &getArgs() const { return Args; }
- int getLine() const { return Line; }
};
class CallStmtAST : public StmtAST {
std::string Callee;
std::vector<std::unique_ptr<ExprAST>> Args;
- int Line;
public:
CallStmtAST(const std::string &Callee, std::vector<std::unique_ptr<ExprAST>> 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<std::unique_ptr<ExprAST>> &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<ParamSig> Params;
};
@@ -55,10 +57,12 @@ private:
TypeSystem &Types;
ExceptionHandler &Exceptions;
- std::map<std::string, SymbolInfo> &Symbols;
+ IdentifierMap<SymbolInfo> &Symbols;
bool &HadError;
+ int &DiagnosticLine;
+ void reportError(const char *Fmt, ...);
- std::map<std::string, FuncSig> Signatures;
+ IdentifierMap<FuncSig> Signatures;
ArrayParamBinder BindArrayParam;
void createArgumentAllocas(llvm::Function *F, const std::vector<ParamDecl> &Params);
@@ -69,9 +73,9 @@ public:
llvm::IRBuilder<> &B,
TypeSystem &TS,
ExceptionHandler &EH,
- std::map<std::string, SymbolInfo> &Sym,
- bool &HadErrorFlag)
- : Context(C), Module(M), Builder(B), Types(TS), Exceptions(EH), Symbols(Sym), HadError(HadErrorFlag) {}
+ IdentifierMap<SymbolInfo> &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 <algorithm>
+#include <map>
+#include <set>
+#include <string>
+
+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<class T> using IdentifierMap = std::map<std::string, T, IdentifierLess>;
+using IdentifierSet = std::set<std::string, IdentifierLess>;
+
+} // 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<int, int> BinopPrecedence;
- std::set<std::string> 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<ExprAST> ParseExpression();
+ std::unique_ptr<ExprAST> ParseUnaryImpl();
std::unique_ptr<ExprAST> ParseUnary();
+ std::unique_ptr<ExprAST> ParsePrimaryImpl();
std::unique_ptr<ExprAST> ParsePrimary();
std::unique_ptr<ExprAST> ParseBinOpRHS(int ExprPrec, std::unique_ptr<ExprAST> LHS);
@@ -71,6 +74,7 @@ class Parser {
std::unique_ptr<StmtAST> ParseCallStmt();
std::unique_ptr<StmtAST> ParseReturnStmt();
std::optional<std::vector<ParamDecl>> ParsePrototypeArgs(bool AllowByRef);
+ bool ParseIntegerValue(bool Negative, int64_t &Out);
bool ParseSignedIntBound(int64_t &Out);
std::unique_ptr<StmtAST> 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<RecordFieldDecl> &getFields() const { return Fields; }
};
-// CLASS <name> with explicitly PUBLIC/PRIVATE fields, ending in ENDCLASS.
+// CLASS <name> 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<DesignatorAccess> Accesses;
- int Line;
public:
DesignatorExprAST(const std::string &BaseName,
std::vector<DesignatorAccess> 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<DesignatorAccess> &getAccesses() const { return Accesses; }
- int getLine() const { return Line; }
};
// ^<designator> — 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<std::string, TypeInfo> Types;
- std::map<std::string, EnumConstant> EnumConstants;
+ IdentifierMap<TypeInfo> Types;
+ IdentifierMap<EnumConstant> EnumConstants;
void registerBuiltins();
const TypeInfo *registerType(const std::string &TypeName,