diff --git a/Makefile b/Makefile index 11bbf78..f3bb83b 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # make clean && make && ./bin/cosmo CC=clang -CFLAGS=-fPIE -Wall -O0 -Isrc -std=c99 -g -LDFLAGS=-lm -fsanitize=address +CFLAGS=-fPIE -Wall -O3 -Isrc -std=c99 +LDFLAGS=-lm #-fsanitize=address OUT=bin/cosmo CHDR=\ diff --git a/main.c b/main.c index 51f45b5..f096427 100644 --- a/main.c +++ b/main.c @@ -1,21 +1,29 @@ -#include "cosmo.h" +#include "cbaselib.h" #include "cchunk.h" #include "cdebug.h" -#include "cvm.h" -#include "cparse.h" -#include "cbaselib.h" - +#include "cdump.h" #include "cmem.h" +#include "cosmo.h" +#include "cparse.h" +#include "cundump.h" +#include "cvm.h" + +#include +#include +#include +#include static bool _ACTIVE = false; -int cosmoB_quitRepl(CState *state, int nargs, CValue *args) { +int cosmoB_quitRepl(CState *state, int nargs, CValue *args) +{ _ACTIVE = false; return 0; // we don't return anything } -int cosmoB_input(CState *state, int nargs, CValue *args) { +int cosmoB_input(CState *state, int nargs, CValue *args) +{ // input() accepts the same params as print()! for (int i = 0; i < nargs; i++) { CObjString *str = cosmoV_toString(state, args[i]); @@ -26,16 +34,18 @@ int cosmoB_input(CState *state, int nargs, CValue *args) { char line[1024]; fgets(line, sizeof(line), stdin); - cosmoV_pushRef(state, (CObj*)cosmoO_copyString(state, line, strlen(line)-1)); // -1 for the \n + cosmoV_pushRef(state, + (CObj *)cosmoO_copyString(state, line, strlen(line) - 1)); // -1 for the \n return 1; // 1 return value } -static bool interpret(CState *state, const char *script, const char *mod) { +static bool interpret(CState *state, const char *script, const char *mod) +{ bool ret; // cosmoV_compileString pushes the result onto the stack (COBJ_ERROR or COBJ_CLOSURE) - if (cosmoV_compileString(state, script, mod)) { + if (cosmoV_compileString(state, script, mod)) { COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected if (res == COSMOVM_RUNTIME_ERR) @@ -50,15 +60,11 @@ static bool interpret(CState *state, const char *script, const char *mod) { return !ret; } -static void repl() { +static void repl(CState *state) +{ char line[1024]; _ACTIVE = true; - CState *state = cosmoV_newState(); - cosmoB_loadLibrary(state); - cosmoB_loadOSLib(state); - cosmoB_loadVM(state); - // add our custom REPL functions cosmoV_pushString(state, "quit"); cosmoV_pushCFunction(state, cosmoB_quitRepl); @@ -78,12 +84,11 @@ static void repl() { interpret(state, line, "REPL"); } - - cosmoV_freeState(state); } -static char *readFile(const char* path) { - FILE* file = fopen(path, "rb"); +static char *readFile(const char *path) +{ + FILE *file = fopen(path, "rb"); if (file == NULL) { fprintf(stderr, "Could not open file \"%s\".\n", path); exit(74); @@ -94,7 +99,7 @@ static char *readFile(const char* path) { size_t fileSize = ftell(file); rewind(file); - char *buffer = (char*)malloc(fileSize + 1); // make room for the null byte + char *buffer = (char *)malloc(fileSize + 1); // make room for the null byte if (buffer == NULL) { fprintf(stderr, "failed to allocate!"); exit(1); @@ -106,7 +111,7 @@ static char *readFile(const char* path) { printf("failed to read file \"%s\"!\n", path); exit(74); } - + buffer[bytesRead] = '\0'; // place our null terminator // close the file handler and return the script buffer @@ -114,12 +119,10 @@ static char *readFile(const char* path) { return buffer; } -static bool runFile(const char* fileName) { +static bool runFile(CState *state, const char *fileName) +{ bool ret; - char* script = readFile(fileName); - CState *state = cosmoV_newState(); - cosmoB_loadLibrary(state); - cosmoB_loadOSLib(state); + char *script = readFile(fileName); // add our input() function to the global table cosmoV_pushString(state, "input"); @@ -129,21 +132,119 @@ static bool runFile(const char* fileName) { ret = interpret(state, script, fileName); - cosmoV_freeState(state); free(script); return ret; // let the caller know if the script failed } -int main(int argc, const char *argv[]) { - if (argc == 1) { - repl(); - } else if (argc >= 2) { // they passed a file (or more lol) - for (int i = 1; i < argc; i++) { - if (!runFile(argv[i])) { +int fileWriter(CState *state, const void *data, size_t size, const void *ud) +{ + return !fwrite(data, size, 1, (FILE *)ud); +} + +int fileReader(CState *state, void *data, size_t size, const void *ud) +{ + return fread(data, size, 1, (FILE *)ud) != 1; +} + +void compileScript(CState *state, const char *in, const char *out) +{ + char *script = readFile(in); + + FILE *fout = fopen(out, "wb"); + + if (cosmoV_compileString(state, script, in)) { + CObjFunction *func = cosmoV_readClosure(*cosmoV_getTop(state, 0))->function; + cosmoD_dump(state, func, fileWriter, (void *)fout); + } else { + cosmoV_pop(state); // pop the error off the stack + cosmoV_printError(state, state->error); + } + + free(script); + fclose(fout); + + printf("[!] compiled %s to %s successfully!\n", in, out); +} + +void loadScript(CState *state, const char *in) +{ + FILE *file; + + file = fopen(in, "rb"); + if (!cosmoV_undump(state, fileReader, file)) { + cosmoV_pop(state); // pop the error off the stack + cosmoV_printError(state, state->error); + return; + }; + + printf("[!] loaded %s!\n", in); + COSMOVMRESULT res = cosmoV_call(state, 0, 0); // 0 args being passed, 0 results expected + + if (res == COSMOVM_RUNTIME_ERR) + cosmoV_printError(state, state->error); + + fclose(file); +} + +void printUsage(const char *name) +{ + printf("Usage: %s [-clsr] [args]\n\n", name); + printf("available options are:\n" + "-c \tcompile and dump to \n" + "-l \t\tload dump from \n" + "-s \t\tcompile and run script(s)\n" + "-r\t\t\tstart the repl\n\n"); +} + +int main(int argc, char *const argv[]) +{ + CState *state = cosmoV_newState(); + cosmoB_loadLibrary(state); + cosmoB_loadOSLib(state); + cosmoB_loadVM(state); + + int opt; + bool isValid = false; + while ((opt = getopt(argc, argv, "clsr")) != -1) { + switch (opt) { + case 'c': + if (optind >= argc - 1) { + printf("Usage: %s -c \n", argv[0]); exit(EXIT_FAILURE); + } else { + compileScript(state, argv[optind], argv[optind + 1]); } + isValid = true; + break; + case 'l': + if (optind >= argc) { + printf("Usage: %s -l \n", argv[0]); + exit(EXIT_FAILURE); + } else { + loadScript(state, argv[optind]); + } + isValid = true; + break; + case 's': + for (int i = optind; i < argc; i++) { + if (!runFile(state, argv[i])) { + printf("failed to run %s!\n", argv[i]); + exit(EXIT_FAILURE); + } + } + isValid = true; + break; + case 'r': + repl(state); + isValid = true; + break; } } + if (!isValid) { + printUsage(argv[0]); + } + + cosmoV_freeState(state); return 0; } diff --git a/src/cbaselib.c b/src/cbaselib.c index 069a944..0a2e769 100644 --- a/src/cbaselib.c +++ b/src/cbaselib.c @@ -980,6 +980,4 @@ void cosmoB_loadVM(CState *state) // register "vm" to the global table cosmoV_register(state, 1); - - printf("[WARNING] the vm.* library has been loaded!\n"); }