add support to reading csv files

This commit is contained in:
Talles Amadeu 2025-12-09 13:41:58 -03:00
parent f8695b14e3
commit d345186370
11 changed files with 263 additions and 3 deletions

BIN
build/ast.o Normal file

Binary file not shown.

BIN
build/ast_printer.o Normal file

Binary file not shown.

BIN
build/codegen.o Normal file

Binary file not shown.

BIN
build/lexer.o Normal file

Binary file not shown.

BIN
build/main.o Normal file

Binary file not shown.

BIN
build/parser.o Normal file

Binary file not shown.

BIN
build/runtime.o Normal file

Binary file not shown.

View File

@ -38,6 +38,18 @@ CodeGen::CodeGen() {
// int sun_array_length(void* arr) // int sun_array_length(void* arr)
llvm::FunctionType* arrayLenType = llvm::FunctionType::get(llvm::Type::getInt32Ty(*context), {llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)}, false); llvm::FunctionType* arrayLenType = llvm::FunctionType::get(llvm::Type::getInt32Ty(*context), {llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)}, false);
llvm::Function::Create(arrayLenType, llvm::Function::ExternalLinkage, "sun_array_length", module.get()); llvm::Function::Create(arrayLenType, llvm::Function::ExternalLinkage, "sun_array_length", module.get());
// void* sun_read_csv(char* filename, char* separator, char* quote)
llvm::FunctionType* readCsvType = llvm::FunctionType::get(
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0),
{
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0), // filename
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0), // separator
llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0) // quote
},
false
);
llvm::Function::Create(readCsvType, llvm::Function::ExternalLinkage, "sun_read_csv", module.get());
} }
llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) { llvm::AllocaInst* CodeGen::createEntryBlockAlloca(llvm::Function* theFunction, const std::string& varName, llvm::Type* type) {
@ -133,6 +145,60 @@ void CodeGen::visit(AssignExpr& node) {
} }
void CodeGen::visit(CallExpr& node) { void CodeGen::visit(CallExpr& node) {
// Handle "readcsv" specially
if (node.callee == "readcsv") {
if (node.args.size() < 1 || node.args.size() > 3) {
std::cerr << "readcsv() takes 1 to 3 arguments." << std::endl;
lastValue = nullptr;
return;
}
node.args[0]->accept(*this);
llvm::Value* filenameVal = lastValue;
llvm::Value* sepVal;
if (node.args.size() >= 2) {
node.args[1]->accept(*this);
sepVal = lastValue;
} else {
sepVal = builder->CreateGlobalStringPtr(",");
}
llvm::Value* quoteVal;
if (node.args.size() >= 3) {
node.args[2]->accept(*this);
quoteVal = lastValue;
} else {
quoteVal = builder->CreateGlobalStringPtr("\"");
}
llvm::Function* readCsvFn = module->getFunction("sun_read_csv");
lastValue = builder->CreateCall(readCsvFn, {filenameVal, sepVal, quoteVal}, "csv_data");
lastClassName = "CSVArray";
return;
}
// Handle "len" specially
if (node.callee == "len") {
if (node.args.size() != 1) {
std::cerr << "len() takes exactly 1 argument." << std::endl;
lastValue = nullptr;
return;
}
node.args[0]->accept(*this);
llvm::Value* arrVal = lastValue;
// Cast to i8* if needed (it should be i8* already as void*)
if (arrVal->getType() != llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0)) {
arrVal = builder->CreateBitCast(arrVal, llvm::PointerType::get(llvm::Type::getInt8Ty(*context), 0));
}
llvm::Function* lenFn = module->getFunction("sun_array_length");
lastValue = builder->CreateCall(lenFn, {arrVal}, "len");
lastClassName = ""; // Returns int
return;
}
// Handle "print" specially or as a normal function // Handle "print" specially or as a normal function
if (node.callee == "print") { if (node.callee == "print") {
if (node.args.size() != 1) { if (node.args.size() != 1) {
@ -731,6 +797,9 @@ void CodeGen::visit(IndexExpr& node) {
if (arrayType == "StringArray") { if (arrayType == "StringArray") {
lastValue = valPtr; // Already i8* lastValue = valPtr; // Already i8*
lastClassName = "String"; lastClassName = "String";
} else if (arrayType == "CSVArray") {
lastValue = valPtr; // It's a void* (pointer to array)
lastClassName = "StringArray";
} else { } else {
// Assume IntArray, cast back to i32 // Assume IntArray, cast back to i32
lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt"); lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt");

View File

@ -47,7 +47,7 @@ typedef struct {
void* sun_array_create(int size) { void* sun_array_create(int size) {
Array* arr = (Array*)malloc(sizeof(Array)); Array* arr = (Array*)malloc(sizeof(Array));
arr->size = size; arr->size = size;
arr->data = (void**)malloc(sizeof(void*) * size); arr->data = (void**)calloc(size, sizeof(void*));
return (void*)arr; return (void*)arr;
} }
@ -77,15 +77,120 @@ int sun_array_length(void* arrPtr) {
return arr->size; return arr->size;
} }
char* sun_strdup(const char* s) {
char* d = (char*)malloc(strlen(s) + 1);
if (d == NULL) return NULL;
strcpy(d, s);
return d;
}
void* sun_read_csv(char* filename, char* separator, char* quote) {
FILE* fp = fopen(filename, "r");
if (!fp) {
printf("Error: Could not open file %s\n", filename);
exit(1);
}
// Count lines
int lines = 0;
char ch;
char lastChar = 0;
int empty = 1;
while ((ch = fgetc(fp)) != EOF) {
empty = 0;
if (ch == '\n') lines++;
lastChar = ch;
}
if (!empty && lastChar != '\n') lines++;
rewind(fp);
void* mainArr = sun_array_create(lines);
char lineBuffer[4096]; // Max line length
int lineIdx = 0;
char sep = separator[0];
char q = quote[0];
while (fgets(lineBuffer, sizeof(lineBuffer), fp)) {
// Remove newline
lineBuffer[strcspn(lineBuffer, "\n")] = 0;
// Count fields
int fields = 1;
char* ptr = lineBuffer;
int inQuote = 0;
while (*ptr) {
if (*ptr == q) inQuote = !inQuote;
else if (*ptr == sep && !inQuote) fields++;
ptr++;
}
void* rowArr = sun_array_create(fields);
// Parse fields
ptr = lineBuffer;
int fieldIdx = 0;
char fieldBuffer[4096];
int fbIdx = 0;
inQuote = 0;
while (*ptr) {
if (*ptr == q) {
inQuote = !inQuote;
}
else if (*ptr == sep && !inQuote) {
fieldBuffer[fbIdx] = 0;
sun_array_set(rowArr, fieldIdx, sun_strdup(fieldBuffer));
fieldIdx++;
fbIdx = 0;
}
else {
fieldBuffer[fbIdx++] = *ptr;
}
ptr++;
}
// Last field
fieldBuffer[fbIdx] = 0;
sun_array_set(rowArr, fieldIdx, sun_strdup(fieldBuffer));
sun_array_set(mainArr, lineIdx, rowArr);
lineIdx++;
}
fclose(fp);
return mainArr;
}
} }
)"; )";
void printUsage() {
std::cout << "Sun Language Compiler v0.1.0" << std::endl;
std::cout << "Usage: sun <filename> [options]" << std::endl;
std::cout << "Options:" << std::endl;
std::cout << " -o <file> Specify output executable name" << std::endl;
std::cout << " -v, --version Show version information" << std::endl;
std::cout << " -h, --help Show this help message" << std::endl;
}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
if (argc < 2) { if (argc < 2) {
std::cerr << "Usage: sun <filename> [-o output]" << std::endl; printUsage();
return 1; return 1;
} }
std::string arg1 = argv[1];
if (arg1 == "-v" || arg1 == "--version") {
std::cout << "Sun Language Compiler v0.1.0" << std::endl;
return 0;
}
if (arg1 == "-h" || arg1 == "--help") {
printUsage();
return 0;
}
std::string filename = argv[1]; std::string filename = argv[1];
std::string outputExe = "a.out"; std::string outputExe = "a.out";
bool runImmediately = true; bool runImmediately = true;

View File

@ -35,7 +35,7 @@ typedef struct {
void* sun_array_create(int size) { void* sun_array_create(int size) {
Array* arr = (Array*)malloc(sizeof(Array)); Array* arr = (Array*)malloc(sizeof(Array));
arr->size = size; arr->size = size;
arr->data = (void**)malloc(sizeof(void*) * size); arr->data = (void**)calloc(size, sizeof(void*)); // Use calloc to init to NULL
return (void*)arr; return (void*)arr;
} }
@ -65,4 +65,90 @@ int sun_array_length(void* arrPtr) {
return arr->size; return arr->size;
} }
char* sun_strdup(const char* s) {
char* d = (char*)malloc(strlen(s) + 1);
if (d == NULL) return NULL;
strcpy(d, s);
return d;
}
void* sun_read_csv(char* filename, char* separator, char* quote) {
FILE* fp = fopen(filename, "r");
if (!fp) {
printf("Error: Could not open file %s\n", filename);
exit(1);
}
// Count lines
int lines = 0;
char ch;
char lastChar = 0;
int empty = 1;
while ((ch = fgetc(fp)) != EOF) {
empty = 0;
if (ch == '\n') lines++;
lastChar = ch;
}
if (!empty && lastChar != '\n') lines++;
rewind(fp);
void* mainArr = sun_array_create(lines);
char lineBuffer[4096]; // Max line length
int lineIdx = 0;
char sep = separator[0];
char q = quote[0];
while (fgets(lineBuffer, sizeof(lineBuffer), fp)) {
// Remove newline
lineBuffer[strcspn(lineBuffer, "\n")] = 0;
// Count fields
int fields = 1;
char* ptr = lineBuffer;
int inQuote = 0;
while (*ptr) {
if (*ptr == q) inQuote = !inQuote;
else if (*ptr == sep && !inQuote) fields++;
ptr++;
}
void* rowArr = sun_array_create(fields);
// Parse fields
ptr = lineBuffer;
int fieldIdx = 0;
char fieldBuffer[4096];
int fbIdx = 0;
inQuote = 0;
while (*ptr) {
if (*ptr == q) {
inQuote = !inQuote;
}
else if (*ptr == sep && !inQuote) {
fieldBuffer[fbIdx] = 0;
sun_array_set(rowArr, fieldIdx, sun_strdup(fieldBuffer));
fieldIdx++;
fbIdx = 0;
}
else {
fieldBuffer[fbIdx++] = *ptr;
}
ptr++;
}
// Last field
fieldBuffer[fbIdx] = 0;
sun_array_set(rowArr, fieldIdx, sun_strdup(fieldBuffer));
sun_array_set(mainArr, lineIdx, rowArr);
lineIdx++;
}
fclose(fp);
return mainArr;
}
} }

BIN
sun Executable file

Binary file not shown.