diff --git a/repl/hal_file.h b/hal/hal_file.h similarity index 91% rename from repl/hal_file.h rename to hal/hal_file.h index 4fd89cd..1b3d160 100644 --- a/repl/hal_file.h +++ b/hal/hal_file.h @@ -10,6 +10,8 @@ typedef enum hal_file_code { HAL_ERROR_READ, // Error while reading from a file HAL_ERROR_WRITE, // Error while writing to a file HAL_ERROR_CLOSE, // Error while closing a file + HAL_ERROR_RENAME, // Error while renaming a file + HAL_ERROR_REMOVE, // Error while removing (deleting) a file HAL_ERROR_TEARDOWN, // Error during teardown HAL_ERROR_MAX, // Maximum error code value (used for range checking) } hal_file_code; @@ -44,6 +46,12 @@ typedef struct hal_file_operations { // Returns: HAL_SUCCESS on successful close, or appropriate error code on failure. hal_file_code (*close)(hal_file* file); + + hal_file_code (*rename)(const char* oldname, const char* newname); + + + hal_file_code (*remove)(const char* filename); + // Function: teardown // Perform necessary cleanup and teardown operations for the file handling system. // Returns: HAL_SUCCESS on successful teardown, or appropriate error code on failure. diff --git a/hal/makefile b/hal/makefile new file mode 100644 index 0000000..37613d3 --- /dev/null +++ b/hal/makefile @@ -0,0 +1,25 @@ +CC = gcc +CFLAGS = -Wall -Wextra -pedantic + +# Library name and source files +LIB_NAME = hal.a +SRC_FILES = ports/hal_file.c +BUILD_DIR = bin + +# Object files derived from source files +OBJ_FILES = $(SRC_FILES:.c=.o) + +# Target: build the library +all: $(BUILD_DIR)/$(LIB_NAME) + +# Build the library from object files +$(LIB_NAME): $(OBJ_FILES) + ar rcs $@ $^ + +# Compile from object files +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean up generated files +clean: + rm -f $(LIB_NAME) $(OBJ_FILES) \ No newline at end of file diff --git a/repl/hal_file.c b/hal/ports/hal_file.c similarity index 77% rename from repl/hal_file.c rename to hal/ports/hal_file.c index c65e87d..f399043 100644 --- a/repl/hal_file.c +++ b/hal/ports/hal_file.c @@ -36,6 +36,8 @@ hal_file_code read(hal_file* file, char* buffer, const int size) { return HAL_ERROR_INPUT; } + scanf() + if (fgets(buffer, size, file->fp) == NULL) { return HAL_ERROR_READ; } @@ -68,6 +70,31 @@ hal_file_code close(hal_file* file) { return HAL_SUCCESS; } +hal_file_code crename(const char* oldname, const char* newname) { + if (!oldname || !newname) { + return HAL_ERROR_INPUT; + + } + + if (rename(oldname, newname) != 0) { + return HAL_ERROR_RENAME; + } + + return HAL_SUCCESS; +} + +hal_file_code cremove(const char* filename) { + if (!filename) { + return HAL_ERROR_INPUT; + } + + if (remove(filename) != 0) { + return HAL_ERROR_REMOVE; + } + + return HAL_SUCCESS; +} + // deletion logic, if needed hal_file_code teardown() { return HAL_SUCCESS; @@ -80,6 +107,8 @@ hal_file_operations hal_file_manager = { .read = read, .write = write, .close = close, + .rename = crename, + .remove = cremove, .teardown = teardown }; diff --git a/repl/lib_fileio.c b/repl/lib_fileio.c index 8de32e3..37f5a1f 100644 --- a/repl/lib_fileio.c +++ b/repl/lib_fileio.c @@ -1,12 +1,12 @@ #include "lib_fileio.h" #include "toy_memory.h" -#include "hal_file.h" +#include "../hal/hal_file.h" typedef struct Toy_File { hal_file* fp; - int error; + hal_file_code error; int size; } Toy_File; @@ -46,19 +46,16 @@ static int nativeOpen(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) const char* filename = Toy_toCString(TOY_AS_STRING(filenameLiteral)); const char* mode = Toy_toCString(TOY_AS_STRING(modeLiteral)); - static int tag = 0; - bool error = false; - hal_file* fp = NULL; + // build file object + Toy_File* file = TOY_ALLOCATE(Toy_File, 1); + file->error = HAL_SUCCESS; + file->fp = NULL; + file->size = 0; // attempt to open file - hal_file_code code = hal_file_manager.open(&fp, filename, mode); - if (code != HAL_SUCCESS) { - error = true; - } + file->error = hal_file_manager.open(&file->fp, filename, mode); // set size - int size = 0; - // if (!error) { // fseek(fp, 0, SEEK_END); @@ -69,42 +66,15 @@ static int nativeOpen(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) // } // result - Toy_LiteralDictionary* result = TOY_ALLOCATE(Toy_LiteralDictionary, 1); - Toy_initLiteralDictionary(result); + Toy_Literal fileLiteral = TOY_TO_OPAQUE_LITERAL(file, 900); - Toy_Literal fileKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("_file")); - Toy_Literal fileLiteral = TOY_TO_OPAQUE_LITERAL(fp, tag); - - Toy_Literal errorKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("error")); - Toy_Literal errorLiteral = TOY_TO_BOOLEAN_LITERAL(error); - - Toy_Literal sizeKeyLiteral = TOY_TO_STRING_LITERAL(Toy_createRefString("size")); - Toy_Literal sizeLiteral = TOY_TO_INTEGER_LITERAL(size); - - Toy_setLiteralDictionary(result, fileKeyLiteral, fileLiteral); - Toy_setLiteralDictionary(result, errorKeyLiteral, errorLiteral); - Toy_setLiteralDictionary(result, sizeKeyLiteral, sizeLiteral); - - Toy_Literal name = TOY_TO_STRING_LITERAL(Toy_createRefString("File")); - Toy_Literal resultLiteral = TOY_TO_DICTIONARY_LITERAL(result); - - Toy_Literal type = TOY_TO_TYPE_LITERAL(TOY_LITERAL_DICTIONARY, true); - Toy_Literal stringType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_STRING, true); - Toy_Literal anyType = TOY_TO_TYPE_LITERAL(TOY_LITERAL_ANY, true); - TOY_TYPE_PUSH_SUBTYPE(&type, stringType); - TOY_TYPE_PUSH_SUBTYPE(&type, anyType); - - - Toy_pushLiteralArray(&interpreter->stack, resultLiteral); + Toy_pushLiteralArray(&interpreter->stack, fileLiteral); // cleanup - Toy_freeLiteral(type); - Toy_freeLiteral(resultLiteral); + Toy_freeLiteral(fileLiteral); Toy_freeLiteral(filenameLiteral); Toy_freeLiteral(modeLiteral); - tag++; - return 1; } @@ -135,6 +105,61 @@ static int nativeClose(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments return 1; } +static int nativeRead(Toy_Interpreter* interpreter, Toy_LiteralArray* arguments) { + if (arguments->count != 2) { + interpreter->errorOutput("Incorrect number of arguments to read\n"); + return -1; + } + + Toy_Literal valueLiteral = Toy_popLiteralArray(arguments); + Toy_Literal selfLiteral = Toy_popLiteralArray(arguments); + + // parse the value (if it's an identifier) + Toy_Literal valueLiteralIdn = valueLiteral; + if (TOY_IS_IDENTIFIER(valueLiteral) && Toy_parseIdentifierToValue(interpreter, &valueLiteral)) { + Toy_freeLiteral(valueLiteralIdn); + } + + // check the value type + if (!TOY_IS_TYPE(valueLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to read\n"); + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(valueLiteral); + + return -1; + } + + // parse the self (if it's an identifier) + Toy_Literal selfLiteralIdn = selfLiteral; + if (TOY_IS_IDENTIFIER(selfLiteral) && Toy_parseIdentifierToValue(interpreter, &selfLiteral)) { + Toy_freeLiteral(selfLiteralIdn); + } + + // check self type + if (!TOY_IS_OPAQUE(selfLiteral)) { + interpreter->errorOutput("Incorrect argument type passed to read\n"); + Toy_freeLiteral(selfLiteral); + Toy_freeLiteral(valueLiteral); + + return -1; + } + + Toy_File* file = (Toy_File*)TOY_AS_OPAQUE(selfLiteral); + + char buffer[256] = {0}; + + hal_file_manager.read(file->fp, buffer, 256); + + Toy_RefString* result = Toy_createRefStringLength(buffer, 256); + + Toy_pushLiteralArray(&interpreter->stack, TOY_TO_STRING_LITERAL(result)); + + Toy_freeLiteral(valueLiteral); + Toy_freeLiteral(selfLiteral); + + return 1; +} + //call the hook typedef struct Natives { char* name; @@ -196,11 +221,24 @@ int Toy_hookFileIO(Toy_Interpreter* interpreter, Toy_Literal identifier, Toy_Lit {"open", nativeOpen}, {"close", nativeClose}, + // + {"read", nativeRead}, {NULL, NULL} }; + // store the library in an aliased dictionary + if (!TOY_IS_NULL(alias)) { + // make sure the name isn't taken + if (Toy_isDeclaredScopeVariable(interpreter->scope, alias)) { + interpreter->errorOutput("Can't override an existing variable\n"); + Toy_freeLiteral(alias); + return -1; + } - //default + // TODO + } + + // default for (int i = 0; natives[i].name; i++) { Toy_injectNativeFn(interpreter, natives[i].name, natives[i].fn); } diff --git a/test/scripts/lib/fileio.toy b/test/scripts/lib/fileio.toy index c59cbd3..7962f39 100644 --- a/test/scripts/lib/fileio.toy +++ b/test/scripts/lib/fileio.toy @@ -11,10 +11,17 @@ import fileio; // test open { - var file = open("doesNotExist.txt", "r"); - - assert file["error"] == true, "error failed"; - assert file["size"] == 0, "size failed"; + var file = open("does", "r"); + file.read(string); + + // TODO: + // file.write(12, ",", 12); + // file.size(); + // file.isOpened(); + // file.error(); + // file.position(); + // file.mode(); + // close(file); } \ No newline at end of file