add support to reading csv files
This commit is contained in:
parent
f8695b14e3
commit
d345186370
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -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");
|
||||||
|
|
|
||||||
109
src/main.cpp
109
src/main.cpp
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue