aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-16 10:04:27 +0000
committer_ov4 <ov4@ov4.org>2026-10-16 10:04:27 +0000
commit45c9d37eb27d204a6202b33cb37e890af0171357 (patch)
treedba23170b16053c5e1ec4bf78efc2a533cb94a4e /include
parent522742e9df7fc5ac596ce4aa53d41b31e4f6a030 (diff)
feat(control-flow): implement ordered CASE OF matching
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'include')
-rw-r--r--include/cps/AST.h16
-rw-r--r--include/cps/CodeGen.h9
-rw-r--r--include/cps/Lexer.h25
-rw-r--r--include/cps/Parser.h10
4 files changed, 53 insertions, 7 deletions
diff --git a/include/cps/AST.h b/include/cps/AST.h
index e3c6bc5..87c9341 100644
--- a/include/cps/AST.h
+++ b/include/cps/AST.h
@@ -168,6 +168,22 @@ public:
const std::vector<std::unique_ptr<ExprAST>> &getExprs() const { return Exprs; }
};
+struct CaseBranch {
+ std::unique_ptr<ExprAST> Lower, Upper; // Null Lower denotes OTHERWISE.
+ std::vector<std::unique_ptr<StmtAST>> Body;
+ int Line;
+};
+
+class CaseStmtAST : public StmtAST {
+ std::string Selector;
+ std::vector<CaseBranch> Branches;
+public:
+ CaseStmtAST(std::string Selector, std::vector<CaseBranch> Branches)
+ : Selector(std::move(Selector)), Branches(std::move(Branches)) {}
+ const std::string &getSelector() const { return Selector; }
+ const std::vector<CaseBranch> &getBranches() const { return Branches; }
+};
+
class IfStmtAST : public StmtAST {
std::unique_ptr<ExprAST> Cond;
std::vector<std::unique_ptr<StmtAST>> ThenStmts;
diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h
index 72b96c6..4259d63 100644
--- a/include/cps/CodeGen.h
+++ b/include/cps/CodeGen.h
@@ -70,13 +70,17 @@ class CodeGen {
llvm::Value *convertNumericValue(llvm::Value *Val, const TypeInfo *Source,
const TypeInfo *Target);
llvm::Value *emitCast(CastExprAST *Cast);
- llvm::Value *emitCBinaryOp(BinaryExprAST *Bin, const TypeInfo *Left, const TypeInfo *Right);
+ llvm::Value *emitBinaryOp(int Op, llvm::Value *L, const TypeInfo *LT,
+ llvm::Value *R, const TypeInfo *RT, int Line);
+ llvm::Value *emitCBinaryOp(int Op, llvm::Value *L, const TypeInfo *Left,
+ llvm::Value *R, const TypeInfo *Right, int Line);
void emitCOutput(llvm::Value *Val, const TypeInfo *Info, bool AppendNewline);
void emitCInput(const SymbolInfo *Symbol, const TypeInfo *Info);
// TYPE-system registration (Designator.cc) and operators (TypeCheckGen.cc).
void runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statements);
- llvm::Value *emitUserKindBinaryOp(BinaryExprAST *Bin, const TypeInfo *LT, const TypeInfo *RT);
+ llvm::Value *emitUserKindBinaryOp(int Op, llvm::Value *L, const TypeInfo *LT,
+ llvm::Value *R, const TypeInfo *RT, int Line);
// An addressable location and the pseudocode type stored there.
struct LValueInfo {
@@ -95,6 +99,7 @@ class CodeGen {
void emitDeclareStmt(DeclareStmtAST *Stmt);
void emitOutputValue(llvm::Value *Val, const TypeInfo *TypeInfo, bool AppendNewline = true);
+ void emitCaseStmt(CaseStmtAST *Stmt);
void emitIfStmt(IfStmtAST *Stmt);
void emitTryStmt(TryStmtAST *Stmt);
void emitWhileStmt(WhileStmtAST *Stmt);
diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h
index 2f6f231..7f3d5b5 100644
--- a/include/cps/Lexer.h
+++ b/include/cps/Lexer.h
@@ -2,6 +2,7 @@
#include <istream>
#include <string>
#include <cstdint>
+#include <deque>
namespace cps {
@@ -13,6 +14,10 @@ enum Token {
tok_input = -4,
tok_output = -5,
+ tok_case = -40,
+ tok_endcase = -41,
+ tok_otherwise = -42,
+
tok_if = -6,
tok_then = -7,
tok_else = -8,
@@ -105,18 +110,32 @@ class Lexer {
std::istream &Input;
int LastChar = ' ';
int CurrentLine = 1;
+ int TokenLine = 1;
bool HadError = false;
+ struct TokenData {
+ int Kind, Line;
+ std::string Identifier, String;
+ int64_t Integer;
+ double Real;
+ char Character;
+ };
+ std::deque<TokenData> Lookahead;
+ int readToken();
+ TokenData captureToken(int Kind) const;
+ void restoreToken(const TokenData &Token);
public:
explicit Lexer(std::istream &Input) : Input(Input) {}
std::string IdentifierStr;
std::string StringVal;
- int64_t NumVal;
- double RealVal;
+ int64_t NumVal = 0;
+ double RealVal = 0;
char CharVal = '\0';
int gettok();
- int getLine() const { return CurrentLine; }
+ int peekToken(unsigned Offset = 0);
+ int peekLine(unsigned Offset = 0);
+ int getLine() const { return TokenLine; }
bool hadError() const { return HadError; }
};
diff --git a/include/cps/Parser.h b/include/cps/Parser.h
index 5713587..921480d 100644
--- a/include/cps/Parser.h
+++ b/include/cps/Parser.h
@@ -16,7 +16,10 @@ namespace cps {
class Parser {
Lexer &Lex;
- int CurTok;
+ int CurTok = tok_eof;
+ bool StartsLine = true;
+ bool ParsingCaseLabel = false;
+ std::vector<unsigned> CaseBodyDepths;
unsigned NumErrors = 0;
unsigned BlockDepth = 0; // ParseBlock nesting; 1 = top level
@@ -41,7 +44,10 @@ class Parser {
std::unique_ptr<StmtAST> ParseStatement();
std::unique_ptr<StmtAST> ParseStatementImpl();
- std::vector<std::unique_ptr<StmtAST>> ParseBlock(std::initializer_list<int> Terminators);
+ std::vector<std::unique_ptr<StmtAST>> ParseBlock(std::initializer_list<int> Terminators, bool CaseBody = false);
+ bool isCaseLabel();
+ bool atCaseBoundary();
+ std::unique_ptr<StmtAST> ParseCaseStmt();
std::optional<std::vector<std::unique_ptr<ExprAST>>> ParseExprList(char CloseDelim, bool AllowEmpty);
void syncToStatementStart();
std::unique_ptr<StmtAST> ParseIfStmt();