diff --git a/rock.json b/rock.json index af93c57..a1dd2fc 100644 --- a/rock.json +++ b/rock.json @@ -2,7 +2,7 @@ "configVersion": 1, "rock": { "name": "io", - "version": "0.0.2", + "version": "0.1.0", "gccArgs": [], "description": "Input / Output", "dependencies": {} diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..6c12214 --- /dev/null +++ b/src/file.c @@ -0,0 +1,228 @@ +#include "file.h" +#include +#include +#include + +ResultType(int64_t, objectPtr) impl_File_INIT(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + + cometSetField(fileObj, 0, args[1]); // self.path = path + + char* path = cometArgString(args[1]); + char* mode = cometArgString(args[2]); + + FILE* f = fopen(path, mode); + if (!f) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Failed to open \"%s\": %s", path, strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + + cometSetField(fileObj, 2, (int64_t)f); // self.ptr = f + + // seek to end + fseek(f, 0L, SEEK_END); + int64_t size = ftell(f); + rewind(f); + + cometSetField(fileObj, 3, size); // self.size = size + + return Success(int64_t, objectPtr, (int64_t)fileObj); +} + +ResultType(int64_t, objectPtr) impl_readAll(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + + FILE* f = (FILE*)fileObj->fields[2]; + int64_t length = fileObj->fields[3]; + + if (length == 0) { + return Success(int64_t, objectPtr, cometSerializeString("")); + } + + char* content = calloc(length + 1, 1); + if (!content) { + return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for file content. (impl_readAll)"); + } + + fread(content, length, 1, f); + + // serialize string + return Success(int64_t, objectPtr, cometSerializeString(content)); +} + +ResultType(int64_t, objectPtr) impl_read(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[1]; + + int64_t amountToRead = cometArgBig(args[0]); + + FILE* f = (FILE*)fileObj->fields[2]; + + char* content = calloc(amountToRead + 1, 1); + if (!content) { + return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for file content. (impl_read)"); + } + + size_t bytesRead = fread(content, amountToRead, 1, f); + if (bytesRead != amountToRead) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Error while reading file: %s", strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + + // serialize string + return Success(int64_t, objectPtr, cometSerializeString(content)); +} + +ResultType(int64_t, objectPtr) impl_readLine(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + + FILE* f = (FILE*)fileObj->fields[2]; + + if (feof(f)) { + return Success(int64_t, objectPtr, cometSerializeString("")); + } + + char* line = NULL; + size_t len = 0; + ssize_t read = getline(&line, &len, f); + + if (read == -1) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Error while reading line: %s", strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + + if (read > 0 && line[read - 1] == '\n') { + line[read - 1] = 0; + } + + // serialize string + return Success(int64_t, objectPtr, cometSerializeString(line)); +} + +ResultType(int64_t, objectPtr) impl_isEOF(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + + FILE* f = (FILE*)fileObj->fields[2]; + + return Success(int64_t, objectPtr, feof(f)); +} + +ResultType(int64_t, objectPtr) impl_write(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[1]; + + FILE* f = (FILE*)fileObj->fields[2]; + + char* strToWrite = cometArgString(args[0]); + size_t numBytes = strlen(strToWrite); + + size_t written = fwrite(strToWrite, numBytes, 1, f); + if (written < numBytes) { + if (ferror(f)) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Error while writing to file: %s", strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + } + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_writeln(int64_t* args, CometVM* vm) { + char* strToWrite = cometArgString(args[0]); + + size_t ogStrLen = strlen(strToWrite); + + char* fullString = malloc( ogStrLen + 2); // 1 byte for \n, 1 byte for null + memcpy(fullString, strToWrite, ogStrLen); + fullString[ogStrLen] = '\n'; + fullString[ogStrLen+1] = 0; + + size_t fullStringLen = ogStrLen + 1; + + CometObject* fileObj = (CometObject*)args[1]; + FILE* f = (FILE*)fileObj->fields[2]; + + size_t written = fwrite(fullString, fullStringLen, 1, f); + if (written < fullStringLen) { + if (ferror(f)) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Error while writing to file: %s", strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + } + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_seek(int64_t* args, CometVM* vm) { + int64_t seekPos = cometArgBig(args[0]); + + CometObject* fileObj = (CometObject*)args[1]; + FILE* f = (FILE*)fileObj->fields[2]; + + fseek(f, seekPos, SEEK_SET); + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_tell(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + FILE* f = (FILE*)fileObj->fields[2]; + + int64_t tellTo = ftell(f); + if (tellTo == -1) { + if (ferror(f)) { + char* buffer = malloc(128); + snprintf(buffer, 128, "Error while telling file: %s", strerror(errno)); + return cometError(vm, "IOFail", buffer); + } + } + + return Success(int64_t, objectPtr, tellTo); +} + +ResultType(int64_t, objectPtr) impl_flush(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + FILE* f = (FILE*)fileObj->fields[2]; + + fflush(f); + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_close(int64_t* args, CometVM* vm) { + CometObject* fileObj = (CometObject*)args[0]; + FILE* f = (FILE*)fileObj->fields[2]; + + fclose(f); + + return Success(int64_t, objectPtr, 0); +} + + +void createFileStruct(CometEnvironment* env) { + CometStruct* fileStruct = cometDefineStruct(env, "File", NULL); + + List(StructField) fields = newList(StructField); + append(fields, cometCreateField("path", cometTypeString)); + append(fields, cometCreateField("mode", cometTypeString)); + append(fields, cometCreateField("ptr", cometTypeBig)); + append(fields, cometCreateField("size", cometTypeBig)); + + List(cometFuncPtr) methods = newList(cometFuncPtr); + append(methods, cometDefineMethod(env, "readAll", fileStruct, cometTypeString, 0, false)); + append(methods, cometDefineMethod(env, "read", fileStruct, cometTypeString, 1, false, cometTypeBig)); + append(methods, cometDefineMethod(env, "readLine", fileStruct, cometTypeString, 0, false)); + append(methods, cometDefineMethod(env, "isEOF", fileStruct, cometTypeBool, 0, false)); + append(methods, cometDefineMethod(env, "write", fileStruct, cometTypeVoid, 1, false, cometTypeString)); + append(methods, cometDefineMethod(env, "writeln", fileStruct, cometTypeVoid, 1, false, cometTypeString)); + append(methods, cometDefineMethod(env, "seek", fileStruct, cometTypeVoid, 1, false, cometTypeBig)); + append(methods, cometDefineMethod(env, "tell", fileStruct, cometTypeBig, 0, false)); + append(methods, cometDefineMethod(env, "flush", fileStruct, cometTypeVoid, 0, false)); + append(methods, cometDefineMethod(env, "close", fileStruct, cometTypeVoid, 0, false)); + + cometSetStructFieldsAndMethods(fileStruct, fields, methods); + cometDefineConstructor(env, fileStruct, 2, false, cometTypeString, cometTypeString); +} \ No newline at end of file diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..4a28fc8 --- /dev/null +++ b/src/file.h @@ -0,0 +1,8 @@ +#ifndef FILE_H +#define FILE_H + +#include + +void createFileStruct(CometEnvironment* env); + +#endif \ No newline at end of file diff --git a/src/main.c b/src/main.c index c074a66..95a2470 100644 --- a/src/main.c +++ b/src/main.c @@ -1,101 +1,12 @@ #include -#include - -static CometType cometTypeString = cometTypeVoid; - -void ensureStringType() { - if (cometTypeString.typeKind == COMET_VOID) - cometTypeString = createArrayType(cometTypeSmall, 1, (bool[]){false}, (uint64_t[]){}); -} - -int64_t impl_print(int64_t* args, CometVM* vm) { - ensureStringType(); - - CometOperand formatStringArray = deserializeValue(args[0], cometTypeString); - char* formatString = (char*)cometArrayToCArray(formatStringArray, cometTypeSmall); - - size_t argIdx = 1; - - for (size_t i = 0; formatString[i] != 0; i++) { - - // look for '%' - if (formatString[i] == '%') { - switch (formatString[i+1]) { - case 'n': { - printf("%ld", deserializeValue(args[argIdx], cometTypeBig).imm.bigVal); - break; - } - case 'f': { - printf("%f", deserializeValue(args[argIdx], cometTypeDouble).imm.doubleVal); - break; - } - case 'b': { - bool boolVal = deserializeValue(args[argIdx], cometTypeBool).imm.boolVal; - printf( boolVal ? "true" : "false"); - break; - } - case 's': { - CometOperand strArr = deserializeValue(args[argIdx], cometTypeString); - char* str = (char*)cometArrayToCArray(strArr, cometTypeSmall); - printf("%s", str); - break; - } - case 'c': { - printf("%c", deserializeValue(args[argIdx], cometTypeBig).imm.smallVal); - break; - } - default: - printf("%%%c", formatString[i+1]); - break; - } - i++; - argIdx++; - } else { - putchar(formatString[i]); - } - - } - - return 0; -} - -int64_t impl_println(int64_t* args, CometVM* vm) { - int64_t returnVal = impl_print(args, vm); - putchar('\n'); - return returnVal; -} - -int64_t impl_getline(int64_t* args, CometVM* vm) { - ensureStringType(); - - char* userInput = NULL; - size_t numChars = 0; - - int64_t result = getline(&userInput, &numChars, stdin); - if (result == -1) { - if (userInput) free(userInput); - return 0; - } - - if (result > 0 && userInput[result - 1] == '\n') { - userInput[result - 1] = '\0'; - result--; - } - - CometOperand strValue = CArrayToCometArray(userInput, result, cometTypeSmall); - free(userInput); - - int64_t serializedStr = serializeValue(strValue); - - return serializedStr; -} +#include "file.h" on_import { - if (cometTypeString.typeKind == COMET_VOID) - cometTypeString = createArrayType(cometTypeSmall, 1, (bool[]){false}, (uint64_t[]){}); - cometDefineFunc(env, "print", cometTypeSmall, 1, true, cometTypeString); cometDefineFunc(env, "println", cometTypeSmall, 1, true, cometTypeString); cometDefineFunc(env, "getline", cometTypeString, 0, false); + + // define file struct + createFileStruct(env); } \ No newline at end of file diff --git a/src/printing.c b/src/printing.c new file mode 100644 index 0000000..c6fb1be --- /dev/null +++ b/src/printing.c @@ -0,0 +1,75 @@ +#include "printing.h" + +ResultType(int64_t, objectPtr) impl_print(int64_t* args, CometVM* vm) { + char* formatString = cometArgString(args[0]); + + size_t argIdx = 1; + + for (size_t i = 0; formatString[i] != 0; i++) { + + // look for '%' + if (formatString[i] == '%') { + switch (formatString[i+1]) { + case 'n': { + printf("%ld", cometArgBig(args[argIdx])); + break; + } + case 'f': { + printf("%f", cometArgDouble(args[argIdx])); + break; + } + case 'b': { + bool boolVal = cometArgBool(args[argIdx]); + printf( boolVal ? "true" : "false"); + break; + } + case 's': { + char* str = cometArgString(args[argIdx]); + printf("%s", str); + break; + } + case 'c': { + printf("%c", cometArgSmall(args[argIdx])); + break; + } + default: + printf("%%%c", formatString[i+1]); + break; + } + i++; + argIdx++; + } else { + putchar(formatString[i]); + } + + } + + return Success(int64_t, objectPtr, 0); +} + +ResultType(int64_t, objectPtr) impl_println(int64_t* args, CometVM* vm) { + ResultType(int64_t, objectPtr) returnVal = impl_print(args, vm); + putchar('\n'); + return returnVal; +} + +ResultType(int64_t, objectPtr) impl_getline(int64_t* args, CometVM* vm) { + char* userInput = NULL; + size_t numChars = 0; + + ssize_t result = getline(&userInput, &numChars, stdin); + if (result == -1) { + if (userInput) free(userInput); + return cometError(vm, "MemoryAllocFail", "Failed to allocate memory for string in io.getline!"); + } + + if (result > 0 && userInput[result - 1] == '\n') { + userInput[result - 1] = '\0'; + result--; + } + + int64_t serializedStr = cometSerializeString(userInput); + free(userInput); + + return Success(int64_t, objectPtr, serializedStr); +} \ No newline at end of file diff --git a/src/printing.h b/src/printing.h new file mode 100644 index 0000000..7625525 --- /dev/null +++ b/src/printing.h @@ -0,0 +1,10 @@ +#ifndef PRINTING_H +#define PRINTING_H + +#include + +ResultType(int64_t, objectPtr) impl_print(int64_t* args, CometVM* vm); +ResultType(int64_t, objectPtr) impl_println(int64_t* args, CometVM* vm); +ResultType(int64_t, objectPtr) impl_getline(int64_t* args, CometVM* vm); + +#endif \ No newline at end of file