aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorov-4 <hausemasterstream@gmail.com>2026-01-29 14:24:05 +0000
committerov-4 <hausemasterstream@gmail.com>2026-01-29 14:24:05 +0000
commit943ed04b775949e8bc4948bcb8d762a32ab14f76 (patch)
tree5c8d09bcd702558e1fba25e176712a1697a6c7e7
parent4573880fcc32bd76a72a4ae713190cd997194583 (diff)
Added array
-rw-r--r--CMakeLists.txt5
-rw-r--r--include/cps/AST.h37
-rw-r--r--include/cps/ArrayHandler.h50
-rw-r--r--include/cps/CodeGen.h28
-rw-r--r--include/cps/Lexer.h57
-rw-r--r--include/cps/Parser.h4
-rw-r--r--lib/CodeGen/ArrayHandler.cc230
-rw-r--r--lib/CodeGen/CodeGen.cc39
-rw-r--r--lib/Lexer/Lexer.cc3
-rw-r--r--lib/Parser/Parser.cc121
10 files changed, 521 insertions, 53 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a2342e1..8330e33 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,7 +14,10 @@ include_directories(include)
add_library(CPSLexer lib/Lexer/Lexer.cc)
add_library(CPSParser lib/Parser/Parser.cc)
-add_library(CPSCodeGen lib/CodeGen/CodeGen.cc)
+add_library(CPSCodeGen
+ lib/CodeGen/CodeGen.cc
+ lib/CodeGen/ArrayHandler.cc
+)
llvm_map_components_to_libnames(llvm_libs core support native irreader)
diff --git a/include/cps/AST.h b/include/cps/AST.h
index 1473c45..aaf81cb 100644
--- a/include/cps/AST.h
+++ b/include/cps/AST.h
@@ -24,6 +24,16 @@ public:
const std::string &getName() const { return Name; }
};
+class ArrayAccessExprAST : public ExprAST {
+ std::string Name;
+ std::vector<std::unique_ptr<ExprAST>> Indices;
+public:
+ ArrayAccessExprAST(const std::string &Name, std::vector<std::unique_ptr<ExprAST>> Indices)
+ : Name(Name), Indices(std::move(Indices)) {}
+ const std::string &getName() const { return Name; }
+ const std::vector<std::unique_ptr<ExprAST>> &getIndices() const { return Indices; }
+};
+
class BinaryExprAST : public ExprAST {
int Op;
std::unique_ptr<ExprAST> LHS, RHS;
@@ -47,6 +57,21 @@ public:
const std::string &getName() const { return Name; }
};
+class ArrayDeclareStmtAST : public StmtAST {
+ std::string Name;
+ std::vector<std::pair<std::unique_ptr<ExprAST>, std::unique_ptr<ExprAST>>> Bounds;
+ std::string Type;
+public:
+ ArrayDeclareStmtAST(const std::string &Name,
+ std::vector<std::pair<std::unique_ptr<ExprAST>, std::unique_ptr<ExprAST>>> Bounds,
+ const std::string &Type)
+ : Name(Name), Bounds(std::move(Bounds)), Type(Type) {}
+
+ const std::string &getName() const { return Name; }
+ const std::vector<std::pair<std::unique_ptr<ExprAST>, std::unique_ptr<ExprAST>>> &getBounds() const { return Bounds; }
+ const std::string &getType() const { return Type; }
+};
+
class AssignStmtAST : public StmtAST {
std::string Name;
std::unique_ptr<ExprAST> Expr;
@@ -57,6 +82,18 @@ public:
ExprAST *getExpr() const { return Expr.get(); }
};
+class ArrayAssignStmtAST : public StmtAST {
+ std::string Name;
+ std::vector<std::unique_ptr<ExprAST>> Indices;
+ std::unique_ptr<ExprAST> Expr;
+public:
+ ArrayAssignStmtAST(const std::string &Name, std::vector<std::unique_ptr<ExprAST>> Indices, std::unique_ptr<ExprAST> Expr)
+ : 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(); }
+};
+
class InputStmtAST : public StmtAST {
std::string Name;
public:
diff --git a/include/cps/ArrayHandler.h b/include/cps/ArrayHandler.h
new file mode 100644
index 0000000..5052de4
--- /dev/null
+++ b/include/cps/ArrayHandler.h
@@ -0,0 +1,50 @@
+#pragma once
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "cps/AST.h"
+#include <map>
+#include <string>
+#include <vector>
+
+namespace cps {
+
+struct ArrayMetadata {
+ int Rank;
+ llvm::Type* ElementType;
+ std::vector<llvm::Value*> LowerBounds;
+ std::vector<llvm::Value*> UpperBounds;
+ std::vector<llvm::Value*> Multipliers;
+};
+
+class CodeGen;
+
+class ArrayHandler {
+ llvm::LLVMContext *TheContext;
+ llvm::IRBuilder<> *Builder;
+ llvm::Module *TheModule;
+ std::map<std::string, llvm::AllocaInst*> *NamedValues;
+
+ std::map<std::string, ArrayMetadata> ArrayTable;
+
+ llvm::FunctionCallee MallocFunc;
+ llvm::FunctionCallee FreeFunc;
+
+ llvm::Value* computeFlatIndex(const std::string &Name, const std::vector<llvm::Value*> &Indices);
+
+ void emitPrintLoop(const std::string &Name, int CurrentDim, std::vector<llvm::Value*> CurrentIndices, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr);
+
+public:
+ ArrayHandler(llvm::LLVMContext &C, llvm::IRBuilder<> &B, llvm::Module &M, std::map<std::string, llvm::AllocaInst*> &NV);
+
+ void setupExternalFunctions();
+
+ void emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG);
+ void emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG);
+
+ llvm::Value* emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG);
+
+ bool tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr);
+};
+
+}
diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h
index 9be6cc7..8bf5819 100644
--- a/include/cps/CodeGen.h
+++ b/include/cps/CodeGen.h
@@ -1,40 +1,46 @@
#pragma once
-#include "cps/AST.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
+#include "cps/AST.h"
#include <map>
+#include <memory>
namespace cps {
+class ArrayHandler;
+
class CodeGen {
std::unique_ptr<llvm::LLVMContext> TheContext;
std::unique_ptr<llvm::Module> TheModule;
std::unique_ptr<llvm::IRBuilder<>> Builder;
std::map<std::string, llvm::AllocaInst*> NamedValues;
-
- llvm::AllocaInst *CreateEntryBlockAlloca(llvm::Function *TheFunction,
- const std::string &VarName);
+
+ std::unique_ptr<ArrayHandler> Arrays;
llvm::FunctionCallee PrintfFunc;
llvm::FunctionCallee ScanfFunc;
llvm::Value *PrintfFormatStr;
llvm::Value *ScanfFormatStr;
-
- llvm::Value *emitExpr(ExprAST *Expr);
- void emitStmt(StmtAST *Stmt);
-
+
+ void SetupExternalFunctions();
+ llvm::AllocaInst *CreateEntryBlockAlloca(llvm::Function *TheFunction, const std::string &VarName);
+
void emitIfStmt(IfStmtAST *Stmt);
void emitWhileStmt(WhileStmtAST *Stmt);
void emitRepeatStmt(RepeatStmtAST *Stmt);
void emitForStmt(ForStmtAST *Stmt);
- void SetupExternalFunctions();
-
public:
CodeGen();
+ ~CodeGen();
void compile(const std::vector<std::unique_ptr<StmtAST>> &Statements);
void print();
+
+ llvm::Value *emitExpr(ExprAST *Expr);
+ void emitStmt(StmtAST *Stmt);
+
+ friend class ArrayHandler;
};
-} // namespace cps
+}
diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h
index a03c3f6..a7a6218 100644
--- a/include/cps/Lexer.h
+++ b/include/cps/Lexer.h
@@ -1,39 +1,46 @@
#pragma once
#include <string>
-#include <iostream>
namespace cps {
enum Token {
tok_eof = -1,
+
tok_declare = -2,
- tok_integer_kw = -3, // INTEGER
+ tok_integer_kw = -3,
tok_input = -4,
tok_output = -5,
- tok_identifier = -6,
- tok_number = -7,
- tok_assign = -8, // <-
- tok_colon = -9, // :
-
- tok_if = -10,
- tok_then = -11,
- tok_else = -12,
- tok_endif = -13,
- tok_while = -14,
- tok_do = -15,
- tok_endwhile = -16,
- tok_repeat = -17,
- tok_until = -18,
- tok_for = -19,
- tok_to = -24,
- tok_step = -25,
- tok_next = -26,
+ tok_if = -6,
+ tok_then = -7,
+ tok_else = -8,
+ tok_endif = -9,
+
+ tok_while = -10,
+ tok_do = -11,
+ tok_endwhile = -12,
+
+ tok_repeat = -13,
+ tok_until = -14,
+
+ tok_for = -15,
+ tok_to = -16,
+ tok_step = -17,
+ tok_next = -18,
+
+ tok_array = -19,
+ tok_of = -20,
- tok_eq = -20, // =
- tok_ne = -21, // <>
- tok_le = -22, // <=
- tok_ge = -23 // >=
+ tok_identifier = -100,
+ tok_number = -101,
+
+ tok_assign = -200, // <-
+ tok_eq = -201, // =
+ tok_ne = -202, // <>
+ tok_le = -203, // <=
+ tok_ge = -204, // >=
+
+ tok_colon = -300 // :
};
class Lexer {
@@ -44,4 +51,4 @@ public:
int gettok();
};
-} // namespace cps
+}
diff --git a/include/cps/Parser.h b/include/cps/Parser.h
index b685fb2..f5be655 100644
--- a/include/cps/Parser.h
+++ b/include/cps/Parser.h
@@ -29,7 +29,9 @@ class Parser {
std::unique_ptr<StmtAST> ParseWhileStmt();
std::unique_ptr<StmtAST> ParseRepeatStmt();
std::unique_ptr<StmtAST> ParseForStmt();
-
+
+ std::unique_ptr<StmtAST> ParseDeclare();
+
public:
Parser(Lexer &L);
std::vector<std::unique_ptr<StmtAST>> Parse();
diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc
new file mode 100644
index 0000000..470cffa
--- /dev/null
+++ b/lib/CodeGen/ArrayHandler.cc
@@ -0,0 +1,230 @@
+#include "cps/ArrayHandler.h"
+#include "cps/CodeGen.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+
+using namespace llvm;
+using namespace cps;
+
+ArrayHandler::ArrayHandler(LLVMContext &C, IRBuilder<> &B, Module &M, std::map<std::string, AllocaInst*> &NV)
+ : TheContext(&C), Builder(&B), TheModule(&M), NamedValues(&NV) {
+ setupExternalFunctions();
+}
+
+void ArrayHandler::setupExternalFunctions() {
+ std::vector<Type*> MallocArgs;
+ MallocArgs.push_back(Type::getInt64Ty(*TheContext));
+
+ FunctionType *MallocType = FunctionType::get(PointerType::getUnqual(*TheContext), MallocArgs, false);
+ MallocFunc = TheModule->getOrInsertFunction("malloc", MallocType);
+
+ std::vector<Type*> FreeArgs;
+ FreeArgs.push_back(PointerType::getUnqual(*TheContext));
+ FunctionType *FreeType = FunctionType::get(Type::getVoidTy(*TheContext), FreeArgs, false);
+ FreeFunc = TheModule->getOrInsertFunction("free", FreeType);
+}
+
+void ArrayHandler::emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG) {
+ std::string Name = Stmt->getName();
+ int Rank = Stmt->getBounds().size();
+
+ std::vector<Value*> Lows, Highs, Dims;
+ Value *TotalElements = ConstantInt::get(*TheContext, APInt(64, 1));
+
+ for (const auto &Pair : Stmt->getBounds()) {
+ Value *L = CG.emitExpr(Pair.first.get());
+ Value *R = CG.emitExpr(Pair.second.get());
+
+ if (!L || !R) return;
+
+ Value *L64 = Builder->CreateSExt(L, Type::getInt64Ty(*TheContext));
+ Value *R64 = Builder->CreateSExt(R, Type::getInt64Ty(*TheContext));
+
+ Lows.push_back(L);
+ Highs.push_back(R);
+
+ Value *Diff = Builder->CreateSub(R64, L64);
+ Value *DimSize = Builder->CreateAdd(Diff, ConstantInt::get(*TheContext, APInt(64, 1)));
+ Dims.push_back(DimSize);
+
+ TotalElements = Builder->CreateMul(TotalElements, DimSize);
+ }
+
+ std::vector<Value*> Multipliers(Rank);
+ Multipliers[Rank - 1] = ConstantInt::get(*TheContext, APInt(32, 1));
+
+ for (int i = Rank - 2; i >= 0; --i) {
+ Value *NextMult = Multipliers[i+1];
+ Value *NextDimSize = Dims[i+1];
+ Value *NextDimSize32 = Builder->CreateTrunc(NextDimSize, Type::getInt32Ty(*TheContext));
+ Multipliers[i] = Builder->CreateMul(NextMult, NextDimSize32);
+ }
+
+ ArrayMetadata Meta;
+ Meta.Rank = Rank;
+ Meta.ElementType = Type::getInt32Ty(*TheContext);
+ Meta.LowerBounds = Lows;
+ Meta.UpperBounds = Highs;
+ Meta.Multipliers = Multipliers;
+ ArrayTable[Name] = Meta;
+
+
+ Value *ElemSize = ConstantInt::get(*TheContext, APInt(64, 4));
+ Value *TotalBytes = Builder->CreateMul(TotalElements, ElemSize);
+
+ CallInst *Ptr = Builder->CreateCall(MallocFunc, TotalBytes);
+
+ Function *TheFunction = Builder->GetInsertBlock()->getParent();
+ IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
+
+ AllocaInst *Alloca = TmpB.CreateAlloca(PointerType::getUnqual(*TheContext), nullptr, Name);
+
+ Builder->CreateStore(Ptr, Alloca);
+ (*NamedValues)[Name] = Alloca;
+}
+
+Value* ArrayHandler::computeFlatIndex(const std::string &Name, const std::vector<Value*> &Indices) {
+ if (ArrayTable.find(Name) == ArrayTable.end()) return nullptr;
+ const auto &Meta = ArrayTable[Name];
+
+ Value *Offset = ConstantInt::get(*TheContext, APInt(32, 0));
+
+ for (size_t i = 0; i < Indices.size(); ++i) {
+ Value *Idx = Indices[i];
+ Value *Lower = Meta.LowerBounds[i];
+ Value *Diff = Builder->CreateSub(Idx, Lower);
+ Value *Term = Builder->CreateMul(Diff, Meta.Multipliers[i]);
+ Offset = Builder->CreateAdd(Offset, Term);
+ }
+ return Offset;
+}
+
+Value* ArrayHandler::emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG) {
+ std::string Name = Expr->getName();
+ if (ArrayTable.find(Name) == ArrayTable.end()) {
+ fprintf(stderr, "Error: Undeclared array %s\n", Name.c_str());
+ return nullptr;
+ }
+
+ const auto &Meta = ArrayTable[Name];
+ if (Expr->getIndices().size() != Meta.Rank) {
+ fprintf(stderr, "Error: Incorrect number of indices for %s\n", Name.c_str());
+ return nullptr;
+ }
+
+ std::vector<Value*> Indices;
+ for (const auto &IdxExpr : Expr->getIndices()) {
+ Indices.push_back(CG.emitExpr(IdxExpr.get()));
+ }
+
+ Value *Offset = computeFlatIndex(Name, Indices);
+
+ AllocaInst *Alloca = (*NamedValues)[Name];
+ Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
+ Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
+ Value *ElemPtr = Builder->CreateGEP(Type::getInt32Ty(*TheContext), IntPtr, Offset);
+
+ return Builder->CreateLoad(Type::getInt32Ty(*TheContext), ElemPtr);
+}
+
+void ArrayHandler::emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG) {
+ std::string Name = Stmt->getName();
+ if (ArrayTable.find(Name) == ArrayTable.end()) {
+ fprintf(stderr, "Error: Undeclared array %s\n", Name.c_str());
+ return;
+ }
+
+ std::vector<Value*> Indices;
+ for (const auto &IdxExpr : Stmt->getIndices()) {
+ Indices.push_back(CG.emitExpr(IdxExpr.get()));
+ }
+
+ Value *Val = CG.emitExpr(Stmt->getExpr());
+ Value *Offset = computeFlatIndex(Name, Indices);
+
+ AllocaInst *Alloca = (*NamedValues)[Name];
+ Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
+ Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
+ Value *ElemPtr = Builder->CreateGEP(Type::getInt32Ty(*TheContext), IntPtr, Offset);
+
+ Builder->CreateStore(Val, ElemPtr);
+}
+
+bool ArrayHandler::tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr) {
+ std::string Name;
+ std::vector<Value*> Indices;
+
+ if (auto *Var = dynamic_cast<VariableExprAST*>(Expr)) {
+ Name = Var->getName();
+ if (ArrayTable.find(Name) == ArrayTable.end()) return false;
+ }
+ else if (auto *Acc = dynamic_cast<ArrayAccessExprAST*>(Expr)) {
+ Name = Acc->getName();
+ if (ArrayTable.find(Name) == ArrayTable.end()) return false;
+
+ for (const auto &Idx : Acc->getIndices()) {
+ Indices.push_back(CG.emitExpr(Idx.get()));
+ }
+ } else {
+ return false;
+ }
+
+ const auto &Meta = ArrayTable[Name];
+
+ if (Indices.size() == Meta.Rank) {
+ return false;
+ }
+
+ emitPrintLoop(Name, Indices.size(), Indices, PrintfFunc, FmtStr);
+ return true;
+}
+
+void ArrayHandler::emitPrintLoop(const std::string &Name, int CurrentDim, std::vector<Value*> CurrentIndices, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr) {
+ const auto &Meta = ArrayTable[Name];
+
+ if (CurrentDim == Meta.Rank) {
+ Value *Offset = computeFlatIndex(Name, CurrentIndices);
+
+ AllocaInst *Alloca = (*NamedValues)[Name];
+ Value *RawPtr = Builder->CreateLoad(PointerType::getUnqual(*TheContext), Alloca);
+ Value *IntPtr = Builder->CreateBitCast(RawPtr, PointerType::getUnqual(*TheContext));
+ Value *ElemPtr = Builder->CreateGEP(Type::getInt32Ty(*TheContext), IntPtr, Offset);
+ Value *Val = Builder->CreateLoad(Type::getInt32Ty(*TheContext), ElemPtr);
+
+ std::vector<Value*> Args;
+ Args.push_back(FmtStr);
+ Args.push_back(Val);
+ Builder->CreateCall(PrintfFunc, Args);
+ return;
+ }
+
+ Function *TheFunction = Builder->GetInsertBlock()->getParent();
+ BasicBlock *LoopBB = BasicBlock::Create(*TheContext, "arr_loop", TheFunction);
+ BasicBlock *AfterBB = BasicBlock::Create(*TheContext, "arr_after", TheFunction);
+
+ IRBuilder<> TmpB(&TheFunction->getEntryBlock(), TheFunction->getEntryBlock().begin());
+ AllocaInst *LoopVar = TmpB.CreateAlloca(Type::getInt32Ty(*TheContext), nullptr, "idx");
+
+ Value *Start = Meta.LowerBounds[CurrentDim];
+ Value *End = Meta.UpperBounds[CurrentDim];
+
+ Builder->CreateStore(Start, LoopVar);
+ Builder->CreateBr(LoopBB);
+
+ Builder->SetInsertPoint(LoopBB);
+ Value *CurVal = Builder->CreateLoad(Type::getInt32Ty(*TheContext), LoopVar);
+
+ std::vector<Value*> NextIndices = CurrentIndices;
+ NextIndices.push_back(CurVal);
+ emitPrintLoop(Name, CurrentDim + 1, NextIndices, PrintfFunc, FmtStr);
+
+ Value *NextVal = Builder->CreateAdd(CurVal, ConstantInt::get(*TheContext, APInt(32, 1)));
+ Builder->CreateStore(NextVal, LoopVar);
+
+ Value *Cond = Builder->CreateICmpSLE(NextVal, End);
+ Builder->CreateCondBr(Cond, LoopBB, AfterBB);
+
+ Builder->SetInsertPoint(AfterBB);
+}
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
index 31d113a..57d76eb 100644
--- a/lib/CodeGen/CodeGen.cc
+++ b/lib/CodeGen/CodeGen.cc
@@ -1,15 +1,20 @@
#include "cps/CodeGen.h"
+#include "cps/ArrayHandler.h"
#include "llvm/IR/Verifier.h"
#include "cps/Lexer.h"
using namespace llvm;
using namespace cps;
+CodeGen::~CodeGen() = default;
+
CodeGen::CodeGen() {
TheContext = std::make_unique<LLVMContext>();
TheModule = std::make_unique<Module>("cps_module", *TheContext);
Builder = std::make_unique<IRBuilder<>>(*TheContext);
+ Arrays = std::make_unique<ArrayHandler>(*TheContext, *Builder, *TheModule, NamedValues);
+
SetupExternalFunctions();
}
@@ -24,6 +29,8 @@ void CodeGen::SetupExternalFunctions() {
PrintfFormatStr = Builder->CreateGlobalStringPtr("%d\n", "fmt_nl", 0, TheModule.get());
ScanfFormatStr = Builder->CreateGlobalStringPtr("%d", "fmt_in", 0, TheModule.get());
+
+ Arrays->setupExternalFunctions();
}
AllocaInst *CodeGen::CreateEntryBlockAlloca(Function *TheFunction, const std::string &VarName) {
@@ -64,8 +71,14 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
fprintf(stderr, "Error: Unknown variable name %s\n", Var->getName().c_str());
return nullptr;
}
+
return Builder->CreateLoad(Type::getInt32Ty(*TheContext), A, Var->getName().c_str());
}
+
+
+ if (auto *ArrAcc = dynamic_cast<ArrayAccessExprAST*>(Expr)) {
+ return Arrays->emitArrayAccess(ArrAcc, *this);
+ }
if (auto *Bin = dynamic_cast<BinaryExprAST*>(Expr)) {
Value *L = emitExpr(Bin->getLHS());
@@ -234,6 +247,16 @@ void CodeGen::emitForStmt(ForStmtAST *Stmt) {
void CodeGen::emitStmt(StmtAST *Stmt) {
if (!Stmt) return;
+ if (auto *ArrDecl = dynamic_cast<ArrayDeclareStmtAST*>(Stmt)) {
+ Arrays->emitArrayDeclare(ArrDecl, *this);
+ return;
+ }
+
+ if (auto *ArrAssign = dynamic_cast<ArrayAssignStmtAST*>(Stmt)) {
+ Arrays->emitArrayAssign(ArrAssign, *this);
+ return;
+ }
+
if (auto *Decl = dynamic_cast<DeclareStmtAST*>(Stmt)) {
Function *TheFunction = Builder->GetInsertBlock()->getParent();
AllocaInst *Alloca = CreateEntryBlockAlloca(TheFunction, Decl->getName());
@@ -261,12 +284,16 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
}
}
else if (auto *Out = dynamic_cast<OutputStmtAST*>(Stmt)) {
- Value *Val = emitExpr(Out->getExpr());
- if (Val) {
- std::vector<Value*> Args;
- Args.push_back(PrintfFormatStr);
- Args.push_back(Val);
- Builder->CreateCall(PrintfFunc, Args);
+ bool handled = Arrays->tryEmitArrayOutput(Out->getExpr(), *this, PrintfFunc, PrintfFormatStr);
+
+ if (!handled) {
+ Value *Val = emitExpr(Out->getExpr());
+ if (Val) {
+ std::vector<Value*> Args;
+ Args.push_back(PrintfFormatStr);
+ Args.push_back(Val);
+ Builder->CreateCall(PrintfFunc, Args);
+ }
}
}
else if (auto *IfStmt = dynamic_cast<IfStmtAST*>(Stmt)) {
diff --git a/lib/Lexer/Lexer.cc b/lib/Lexer/Lexer.cc
index 7f7a167..fdaa3a5 100644
--- a/lib/Lexer/Lexer.cc
+++ b/lib/Lexer/Lexer.cc
@@ -39,6 +39,9 @@ int Lexer::gettok() {
if (IdentifierStr == "STEP") return tok_step;
if (IdentifierStr == "NEXT") return tok_next;
+ if (IdentifierStr == "ARRAY") return tok_array;
+ if (IdentifierStr == "OF") return tok_of;
+
return tok_identifier;
}
diff --git a/lib/Parser/Parser.cc b/lib/Parser/Parser.cc
index 7a1af89..a85b151 100644
--- a/lib/Parser/Parser.cc
+++ b/lib/Parser/Parser.cc
@@ -39,6 +39,30 @@ std::unique_ptr<ExprAST> Parser::ParseNumberExpr() {
std::unique_ptr<ExprAST> Parser::ParseIdentifierExpr() {
std::string IdName = Lex.IdentifierStr;
getNextToken();
+
+ if (CurTok == '[') {
+ getNextToken();
+ std::vector<std::unique_ptr<ExprAST>> Indices;
+
+ while (true) {
+ auto Exp = ParseExpression();
+ if (!Exp) return nullptr;
+ Indices.push_back(std::move(Exp));
+
+ if (CurTok == ']') {
+ break;
+ }
+ if (CurTok == ',') {
+ getNextToken();
+ continue;
+ }
+ fprintf(stderr, "Error: Expected ',' or ']' in array index\n");
+ return nullptr;
+ }
+ getNextToken();
+ return std::make_unique<ArrayAccessExprAST>(IdName, std::move(Indices));
+ }
+
return std::make_unique<VariableExprAST>(IdName);
}
@@ -104,6 +128,72 @@ std::vector<std::unique_ptr<StmtAST>> Parser::Parse() {
return Statements;
}
+std::unique_ptr<StmtAST> Parser::ParseDeclare() {
+ getNextToken();
+ if (CurTok != tok_identifier) return nullptr;
+ std::string Name = Lex.IdentifierStr;
+ getNextToken();
+
+ if (CurTok != tok_colon) return nullptr;
+ getNextToken();
+
+ if (CurTok == tok_array) {
+ getNextToken();
+ if (CurTok != '[') {
+ fprintf(stderr, "Error: Expected '[' after ARRAY\n");
+ return nullptr;
+ }
+ getNextToken();
+
+ std::vector<std::pair<std::unique_ptr<ExprAST>, std::unique_ptr<ExprAST>>> Bounds;
+
+ while (true) {
+ auto Lower = ParseExpression();
+ if (!Lower) return nullptr;
+
+ if (CurTok != tok_colon) {
+ fprintf(stderr, "Error: Expected ':' in array range (e.g. 1:10)\n");
+ return nullptr;
+ }
+ getNextToken();
+
+ auto Upper = ParseExpression();
+ if (!Upper) return nullptr;
+
+ Bounds.push_back({std::move(Lower), std::move(Upper)});
+
+ if (CurTok == ']') break;
+ if (CurTok == ',') {
+ getNextToken();
+ continue;
+ }
+ fprintf(stderr, "Error: Expected ',' or ']' in array dims\n");
+ return nullptr;
+ }
+ getNextToken();
+
+ if (CurTok != tok_of) {
+ fprintf(stderr, "Error: Expected OF after array dims\n");
+ return nullptr;
+ }
+ getNextToken();
+
+ if (CurTok != tok_integer_kw) {
+ fprintf(stderr, "Error: Only INTEGER arrays supported currently\n");
+ return nullptr;
+ }
+ getNextToken();
+
+ return std::make_unique<ArrayDeclareStmtAST>(Name, std::move(Bounds), "INTEGER");
+ }
+ else if (CurTok == tok_integer_kw) {
+ getNextToken();
+ return std::make_unique<DeclareStmtAST>(Name);
+ }
+
+ return nullptr;
+}
+
std::unique_ptr<StmtAST> Parser::ParseIfStmt() {
getNextToken();
auto Cond = ParseExpression();
@@ -248,19 +338,32 @@ std::unique_ptr<StmtAST> Parser::ParseForStmt() {
std::unique_ptr<StmtAST> Parser::ParseStatement() {
if (CurTok == tok_declare) {
- getNextToken();
- if (CurTok != tok_identifier) return nullptr;
- std::string Name = Lex.IdentifierStr;
- getNextToken();
- if (CurTok != tok_colon) return nullptr;
- getNextToken();
- if (CurTok != tok_integer_kw) return nullptr;
- getNextToken();
- return std::make_unique<DeclareStmtAST>(Name);
+ return ParseDeclare();
}
else if (CurTok == tok_identifier) {
std::string Name = Lex.IdentifierStr;
getNextToken();
+
+ if (CurTok == '[') {
+ getNextToken();
+ std::vector<std::unique_ptr<ExprAST>> Indices;
+ while (true) {
+ auto Exp = ParseExpression();
+ Indices.push_back(std::move(Exp));
+ if (CurTok == ']') break;
+ if (CurTok == ',') getNextToken();
+ }
+ getNextToken();
+
+ if (CurTok != tok_assign) {
+ fprintf(stderr, "Error: Expected '<-' after array access in assignment\n");
+ return nullptr;
+ }
+ getNextToken();
+ auto Expr = ParseExpression();
+ return std::make_unique<ArrayAssignStmtAST>(Name, std::move(Indices), std::move(Expr));
+ }
+
if (CurTok != tok_assign) return nullptr;
getNextToken();
auto Expr = ParseExpression();