diff --git a/build/ast.o b/build/ast.o new file mode 100644 index 0000000..c17c079 Binary files /dev/null and b/build/ast.o differ diff --git a/build/ast_printer.o b/build/ast_printer.o new file mode 100644 index 0000000..4181c35 Binary files /dev/null and b/build/ast_printer.o differ diff --git a/build/codegen.o b/build/codegen.o new file mode 100644 index 0000000..3fa6c7f Binary files /dev/null and b/build/codegen.o differ diff --git a/build/lexer.o b/build/lexer.o new file mode 100644 index 0000000..0569422 Binary files /dev/null and b/build/lexer.o differ diff --git a/build/main.o b/build/main.o new file mode 100644 index 0000000..ad102ab Binary files /dev/null and b/build/main.o differ diff --git a/build/parser.o b/build/parser.o new file mode 100644 index 0000000..c4bde76 Binary files /dev/null and b/build/parser.o differ diff --git a/build/runtime.o b/build/runtime.o new file mode 100644 index 0000000..8d754c5 Binary files /dev/null and b/build/runtime.o differ diff --git a/src/codegen.cpp b/src/codegen.cpp index 103eeec..33e8287 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -38,6 +38,18 @@ CodeGen::CodeGen() { // 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::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) { @@ -133,6 +145,60 @@ void CodeGen::visit(AssignExpr& 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 if (node.callee == "print") { if (node.args.size() != 1) { @@ -731,6 +797,9 @@ void CodeGen::visit(IndexExpr& node) { if (arrayType == "StringArray") { lastValue = valPtr; // Already i8* lastClassName = "String"; + } else if (arrayType == "CSVArray") { + lastValue = valPtr; // It's a void* (pointer to array) + lastClassName = "StringArray"; } else { // Assume IntArray, cast back to i32 lastValue = builder->CreatePtrToInt(valPtr, llvm::Type::getInt32Ty(*context), "elemInt"); diff --git a/src/main.cpp b/src/main.cpp index b81b27c..b8a9c3e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,7 +47,7 @@ typedef struct { void* sun_array_create(int size) { Array* arr = (Array*)malloc(sizeof(Array)); arr->size = size; - arr->data = (void**)malloc(sizeof(void*) * size); + arr->data = (void**)calloc(size, sizeof(void*)); return (void*)arr; } @@ -77,15 +77,120 @@ int sun_array_length(void* arrPtr) { 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 [options]" << std::endl; + std::cout << "Options:" << std::endl; + std::cout << " -o 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[]) { if (argc < 2) { - std::cerr << "Usage: sun [-o output]" << std::endl; + printUsage(); 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 outputExe = "a.out"; bool runImmediately = true; diff --git a/src/runtime.cpp b/src/runtime.cpp index 1f7a817..cb0c044 100644 --- a/src/runtime.cpp +++ b/src/runtime.cpp @@ -35,7 +35,7 @@ typedef struct { void* sun_array_create(int size) { Array* arr = (Array*)malloc(sizeof(Array)); 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; } @@ -65,4 +65,90 @@ int sun_array_length(void* arrPtr) { 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; +} + } diff --git a/sun b/sun new file mode 100755 index 0000000..03a2a86 Binary files /dev/null and b/sun differ