From 465f4d5e4a9ac35f768809c13605599a13512c52 Mon Sep 17 00:00:00 2001 From: CPunch Date: Thu, 25 May 2023 19:41:13 -0500 Subject: [PATCH 01/14] started cdump.c:cosmoD_dump() --- src/cdump.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/cdump.h | 18 ++++++ 2 files changed, 197 insertions(+) create mode 100644 src/cdump.c create mode 100644 src/cdump.h diff --git a/src/cdump.c b/src/cdump.c new file mode 100644 index 0000000..8e12ca8 --- /dev/null +++ b/src/cdump.c @@ -0,0 +1,179 @@ +#include "cdump.h" + +#include "cmem.h" +#include "cobj.h" +#include "cvalue.h" + +typedef struct +{ + CState *state; + const void *userData; + cosmo_Writer writer; + int writerStatus; +} DumpState; + +static void writeCValue(DumpState *dstate, CValue val); + +static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, + const void *userData) +{ + dstate->state = state; + dstate->userData = userData; + dstate->writer = writer; + dstate->writerStatus = 0; +} + +static void writeBlock(DumpState *dstate, const void *data, size_t size) +{ + if (dstate->writerStatus == 0) { + dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData); + } +} + +static void writeu8(DumpState *dstate, uint8_t d) +{ + writeBlock(dstate, &d, sizeof(uint8_t)); +} + +static void writeu32(DumpState *dstate, uint32_t d) +{ + writeBlock(dstate, &d, sizeof(uint32_t)); +} + +static void writeSize(DumpState *dstate, size_t d) +{ + writeBlock(dstate, &d, sizeof(size_t)); +} + +static void writeVector(DumpState *dstate, const void *data, size_t size) +{ + writeSize(dstate, size); + writeBlock(dstate, data, size); +} + +static void writeHeader(DumpState *dstate) +{ + writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN); + + /* after the magic, we write some platform information */ + writeu8(dstate, cosmoD_isBigEndian()); + writeu8(dstate, sizeof(cosmo_Number)); + writeu8(dstate, sizeof(size_t)); + writeu8(dstate, sizeof(int)); +} + +static void writeCObjString(DumpState *dstate, CObjString *obj) +{ + if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */ + writeu32(dstate, 0); + return; + } + + /* write string length */ + writeu32(dstate, obj->length); + + /* write string data */ + writeBlock(dstate, obj->str, obj->length); +} + +static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) +{ + writeCObjString(dstate, obj->name); + writeCObjString(dstate, obj->module); + + writeu32(dstate, obj->args); + writeu32(dstate, obj->upvals); + writeu8(dstate, obj->variadic); + + /* write chunk info */ + writeVector(dstate, obj->chunk.buf, sizeof(uint8_t) * obj->chunk.count); + + /* write line info */ + writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count); + + /* write constants */ + for (int i = 0; i < obj->chunk.constants.count; i++) { + writeCValue(dstate, obj->chunk.constants.values[i]); + } +} + +#define WRITE_VAR(dstate, type, expression) \ + { \ + type _tmp = expression; \ + writeBlock(dstate, &_tmp, sizeof(_tmp)); \ + break; \ + } + +static void writeCObj(DumpState *dstate, CObj *obj) +{ + /* + we can kind of cheat here since our parser only emits a few very limited CObjs... + CChunks will only ever have the following CObj's in their constant table: + - COBJ_STRING + - COBJ_FUNCTION + + the rest of the objects are created during runtime. yay! + */ + CObjType t = cosmoO_readType(obj); + + /* write cobj type */ + writeu8(dstate, t); + + /* write object payload/body */ + switch (t) { + case COBJ_STRING: + writeCObjString(dstate, (CObjString *)obj); + break; + case COBJ_FUNCTION: + writeCObjFunction(dstate, (CObjFunction *)obj); + break; + default: + break; + } +} + +static void writeCValue(DumpState *dstate, CValue val) +{ + CosmoType t = GET_TYPE(val); + + /* write value type */ + writeu8(dstate, t); + + /* write value payload/body */ + switch (t) { + case COSMO_TNUMBER: + WRITE_VAR(dstate, cosmo_Number, cosmoV_readNumber(val)) + case COSMO_TBOOLEAN: + WRITE_VAR(dstate, bool, cosmoV_readBoolean(val)) + case COSMO_TREF: + writeCObj(dstate, cosmoV_readRef(val)); + break; + case COSMO_TNIL: /* fallthrough, no body */ + default: + break; + } +} + +#undef WRITE_VAR + +bool cosmoD_isBigEndian() +{ + union + { + uint32_t i; + uint8_t c[4]; + } _indxint = {0xDEADB33F}; + + return _indxint.c[0] == 0xDE; +} + +int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData) +{ + DumpState dstate; + initDumpState(state, &dstate, writer, userData); + + writeHeader(&dstate); + writeCObjFunction(&dstate, func); + + return dstate.writerStatus; +} diff --git a/src/cdump.h b/src/cdump.h new file mode 100644 index 0000000..a914e0b --- /dev/null +++ b/src/cdump.h @@ -0,0 +1,18 @@ +#ifndef COSMO_DUMP_H +#define COSMO_DUMP_H + +#include "cobj.h" +#include "cosmo.h" + +#include + +#define COSMO_MAGIC "COS\x12" +#define COSMO_MAGIC_LEN 4 + +typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud); + +bool cosmoD_isBigEndian(); + +int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData); + +#endif \ No newline at end of file From f116efa02c37173efff4de3b18005bb312210eee Mon Sep 17 00:00:00 2001 From: CPunch Date: Thu, 25 May 2023 21:12:21 -0500 Subject: [PATCH 02/14] started cundump.c:cosmoD_undump(); minor fixes --- src/cdump.c | 15 ++-- src/cdump.h | 1 + src/cundump.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/cundump.h | 14 ++++ 4 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 src/cundump.c create mode 100644 src/cundump.h diff --git a/src/cdump.c b/src/cdump.c index 8e12ca8..3f37e25 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -92,18 +92,12 @@ static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count); /* write constants */ + writeSize(dstate, obj->chunk.constants.count); for (int i = 0; i < obj->chunk.constants.count; i++) { writeCValue(dstate, obj->chunk.constants.values[i]); } } -#define WRITE_VAR(dstate, type, expression) \ - { \ - type _tmp = expression; \ - writeBlock(dstate, &_tmp, sizeof(_tmp)); \ - break; \ - } - static void writeCObj(DumpState *dstate, CObj *obj) { /* @@ -132,6 +126,13 @@ static void writeCObj(DumpState *dstate, CObj *obj) } } +#define WRITE_VAR(dstate, type, expression) \ + { \ + type _tmp = expression; \ + writeBlock(dstate, &_tmp, sizeof(_tmp)); \ + break; \ + } + static void writeCValue(DumpState *dstate, CValue val) { CosmoType t = GET_TYPE(val); diff --git a/src/cdump.h b/src/cdump.h index a914e0b..43a10dc 100644 --- a/src/cdump.h +++ b/src/cdump.h @@ -13,6 +13,7 @@ typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const bool cosmoD_isBigEndian(); +/* returns non-zero on error */ int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const void *userData); #endif \ No newline at end of file diff --git a/src/cundump.c b/src/cundump.c new file mode 100644 index 0000000..33e752f --- /dev/null +++ b/src/cundump.c @@ -0,0 +1,194 @@ +#include "cdump.h" +#include "cundump.h" +#include "cvm.h" +#include "cchunk.h" + +typedef struct +{ + CState *state; + const void *userData; + cosmo_Reader reader; + int readerStatus; +} UndumpState; + +#define check(e) if (!e) return false; + +static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader, + const void *userData) +{ + udstate->state = state; + udstate->userData = userData; + udstate->reader = reader; + udstate->readerStatus = 0; +} + +static bool readBlock(UndumpState *udstate, void *data, size_t size) +{ + if (udstate->readerStatus == 0) { + udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData); + } + + return udstate->readerStatus == 0; +} + +static bool readu8(UndumpState *udstate, uint8_t *d) +{ + return readBlock(udstate, d, sizeof(uint8_t)); +} + +static bool readu16(UndumpState *udstate, uint16_t *d) +{ + return readBlock(udstate, d, sizeof(uint16_t)); +} + +static bool readSize(UndumpState *udstate, size_t *d) +{ + return readBlock(udstate, d, sizeof(size_t)); +} + +static bool readVector(UndumpState *udstate, void **data, size_t *size) +{ + check(readSize(udstate, size)); + *data = cosmoM_malloc(udstate->state, *size); + return readBlock(udstate, *data, *size); +} + +#define checku8(udstate, d, tmp) \ + check(readu8(udstate, &tmp)); \ + if (d != tmp) { \ + cosmoV_error(udstate->state, "bad header!"); \ + return false; \ + } + +static bool checkHeader(UndumpState *udstate) { + char magic[COSMO_MAGIC_LEN]; + uint8_t tmp; + + /* check header */ + readBlock(udstate, magic, COSMO_MAGIC_LEN); + if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) { + cosmoV_error(udstate->state, "bad header!"); + return false; + } + + /* after the magic, we read some platform information */ + checku8(udstate, cosmoD_isBigEndian(), tmp); + checku8(udstate, sizeof(cosmo_Number), tmp); + checku8(udstate, sizeof(size_t), tmp); + checku8(udstate, sizeof(int), tmp); + + return true; +} + +#undef checku8 + +static bool readCObjString(UndumpState *udstate, CObjString **str) +{ + size_t size; + char *data; + + check(readu32(udstate, &size)); + if (size == 0) { /* empty string */ + *str = NULL; + return true; + } + + *data = cosmoM_malloc(udstate->state, size+1); + check(readBlock(udstate, (void *)&data, size)); + data[size] = '\0'; /* add NULL-terminator */ + + *str = cosmoO_takeString(udstate->state, data, size); + return true; +} + +static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { + *func = cosmoO_newFunction(udstate->state); + + check(readCObjString(udstate, &(*func)->name)); + check(readCObjString(udstate, &(*func)->module)); + + check(readu32(udstate, &(*func)->args)); + check(readu32(udstate, &(*func)->upvals)); + check(readu8(udstate, &(*func)->variadic)); + + /* read chunk info */ + check(readVector(udstate, (void **)&(*func)->chunk.buf, &(*func)->chunk.count)); + check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, &(*func)->chunk.count)); + + /* read constants */ + size_t constants; + check(readSize(udstate, &constants)); + for (int i = 0; i < constants; i++) { + CValue val; + check(readCValue(udstate, &val)); + addConstant(udstate->state, &(*func)->chunk, val); + } + + return true; +} + +static bool readCObj(UndumpState *udstate, CObj **obj) +{ + uint8_t type; + check(readu8(udstate, &type)); + + switch (type) { + case COBJ_STRING: + return readCObjString(udstate, (CObjString **)obj); + case COBJ_FUNCTION: + return readCObjFunction(udstate, (CObjFunction **)obj); + default: + cosmoV_error(udstate->state, "unknown object type!"); + return false; + } + + return true; +} + +#define READ_VAR(udstate, val, type, creator) \ + { \ + type _tmp; \ + check(readBlock(udstate, &_tmp, sizeof(type))); \ + *val = creator(_tmp); \ + break; \ + } + +static bool readCValue(UndumpState *udstate, CValue *val) { + uint8_t type; + check(readu8(udstate, &type)); + + switch (type) { + case COSMO_TNUMBER: + READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber) + case COSMO_TBOOLEAN: + READ_VAR(udstate, val, bool, cosmoV_newBoolean) + case COSMO_TREF: { + CObj *obj; + check(readCObj(udstate, (CObj **)&obj)); + *val = cosmoV_newRef(obj); + break; + } + case COSMO_TNIL: + *val = cosmoV_newNil(); + break; + default: + break; + } + + return true; +} + +int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData) { + UndumpState udstate; + initUndumpState(state, &udstate, writer, userData); + + if (!checkHeader(&udstate)) { + return 1; + } + + if (!readCObjFunction(&udstate, &func)) { + return 1; + } + + return udstate.readerStatus; +} \ No newline at end of file diff --git a/src/cundump.h b/src/cundump.h new file mode 100644 index 0000000..282f5bc --- /dev/null +++ b/src/cundump.h @@ -0,0 +1,14 @@ +#ifndef COSMO_UNDUMP_H +#define COSMO_UNDUMP_H + +#include "cobj.h" +#include "cosmo.h" + +#include + +typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud); + +/* returns non-zero on error */ +int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData); + +#endif \ No newline at end of file From 819e76b711c400b936e394ba1fa4159789a8b51c Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 27 May 2023 23:15:12 -0500 Subject: [PATCH 03/14] cdump.c: fix instruction and line info dumping --- src/cdump.c | 11 ++++++----- src/cdump.h | 2 -- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cdump.c b/src/cdump.c index 3f37e25..a2f6258 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -3,6 +3,7 @@ #include "cmem.h" #include "cobj.h" #include "cvalue.h" +#include "cdebug.h" typedef struct { @@ -45,10 +46,10 @@ static void writeSize(DumpState *dstate, size_t d) writeBlock(dstate, &d, sizeof(size_t)); } -static void writeVector(DumpState *dstate, const void *data, size_t size) +static void writeVector(DumpState *dstate, const void *data, size_t size, size_t count) { - writeSize(dstate, size); - writeBlock(dstate, data, size); + writeSize(dstate, count); + writeBlock(dstate, data, size * count); } static void writeHeader(DumpState *dstate) @@ -86,10 +87,10 @@ static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) writeu8(dstate, obj->variadic); /* write chunk info */ - writeVector(dstate, obj->chunk.buf, sizeof(uint8_t) * obj->chunk.count); + writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count); /* write line info */ - writeVector(dstate, obj->chunk.lineInfo, sizeof(int) * obj->chunk.count); + writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count); /* write constants */ writeSize(dstate, obj->chunk.constants.count); diff --git a/src/cdump.h b/src/cdump.h index 43a10dc..15bb745 100644 --- a/src/cdump.h +++ b/src/cdump.h @@ -9,8 +9,6 @@ #define COSMO_MAGIC "COS\x12" #define COSMO_MAGIC_LEN 4 -typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud); - bool cosmoD_isBigEndian(); /* returns non-zero on error */ From 45f36e6e87cf19109c27079555b26f2b75a2850c Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 27 May 2023 23:15:58 -0500 Subject: [PATCH 04/14] cdump.c: major refactoring; various fixes --- src/cosmo.h | 3 +++ src/cundump.c | 49 ++++++++++++++++++++++++++++++------------------- src/cundump.h | 4 +--- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/cosmo.h b/src/cosmo.h index f4878e9..8134ff0 100644 --- a/src/cosmo.h +++ b/src/cosmo.h @@ -45,6 +45,9 @@ typedef struct CObjClosure CObjClosure; typedef uint8_t INSTRUCTION; +typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud); +typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud); + #define COSMOMAX_UPVALS 80 #define FRAME_MAX 64 #define STACK_MAX (256 * FRAME_MAX) diff --git a/src/cundump.c b/src/cundump.c index 33e752f..e36048a 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -2,6 +2,7 @@ #include "cundump.h" #include "cvm.h" #include "cchunk.h" +#include "cmem.h" typedef struct { @@ -11,7 +12,12 @@ typedef struct int readerStatus; } UndumpState; -#define check(e) if (!e) return false; +static bool readCValue(UndumpState *udstate, CValue *val); + +#define check(e) if (!e) { \ + printf("FAILED %d\n", __LINE__); \ + return false; \ +} static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader, const void *userData) @@ -36,9 +42,9 @@ static bool readu8(UndumpState *udstate, uint8_t *d) return readBlock(udstate, d, sizeof(uint8_t)); } -static bool readu16(UndumpState *udstate, uint16_t *d) +static bool readu32(UndumpState *udstate, uint32_t *d) { - return readBlock(udstate, d, sizeof(uint16_t)); + return readBlock(udstate, d, sizeof(uint32_t)); } static bool readSize(UndumpState *udstate, size_t *d) @@ -46,11 +52,11 @@ static bool readSize(UndumpState *udstate, size_t *d) return readBlock(udstate, d, sizeof(size_t)); } -static bool readVector(UndumpState *udstate, void **data, size_t *size) +static bool readVector(UndumpState *udstate, void **data, size_t size, size_t *count) { - check(readSize(udstate, size)); - *data = cosmoM_malloc(udstate->state, *size); - return readBlock(udstate, *data, *size); + check(readSize(udstate, count)); + *data = cosmoM_xmalloc(udstate->state, (*count)*size); + return readBlock(udstate, *data, (*count)*size); } #define checku8(udstate, d, tmp) \ @@ -84,17 +90,17 @@ static bool checkHeader(UndumpState *udstate) { static bool readCObjString(UndumpState *udstate, CObjString **str) { - size_t size; + uint32_t size; char *data; - check(readu32(udstate, &size)); + check(readu32(udstate, (uint32_t *)&size)); if (size == 0) { /* empty string */ *str = NULL; return true; } - *data = cosmoM_malloc(udstate->state, size+1); - check(readBlock(udstate, (void *)&data, size)); + data = cosmoM_xmalloc(udstate->state, size+1); + check(readBlock(udstate, (void *)data, size)); data[size] = '\0'; /* add NULL-terminator */ *str = cosmoO_takeString(udstate->state, data, size); @@ -107,13 +113,13 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { check(readCObjString(udstate, &(*func)->name)); check(readCObjString(udstate, &(*func)->module)); - check(readu32(udstate, &(*func)->args)); - check(readu32(udstate, &(*func)->upvals)); - check(readu8(udstate, &(*func)->variadic)); + check(readu32(udstate, (uint32_t *)&(*func)->args)); + check(readu32(udstate, (uint32_t *)&(*func)->upvals)); + check(readu8(udstate, (uint8_t *)&(*func)->variadic)); /* read chunk info */ - check(readVector(udstate, (void **)&(*func)->chunk.buf, &(*func)->chunk.count)); - check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, &(*func)->chunk.count)); + check(readVector(udstate, (void **)&(*func)->chunk.buf, sizeof(uint8_t), &(*func)->chunk.count)); + check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, sizeof(int), &(*func)->chunk.count)); /* read constants */ size_t constants; @@ -121,6 +127,8 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { for (int i = 0; i < constants; i++) { CValue val; check(readCValue(udstate, &val)); + // printValue(val); + // putc('\n', stdout); addConstant(udstate->state, &(*func)->chunk, val); } @@ -178,17 +186,20 @@ static bool readCValue(UndumpState *udstate, CValue *val) { return true; } -int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData) { +int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func) { UndumpState udstate; - initUndumpState(state, &udstate, writer, userData); + initUndumpState(state, &udstate, reader, userData); if (!checkHeader(&udstate)) { + cosmoV_pushNil(state); return 1; } - if (!readCObjFunction(&udstate, &func)) { + if (!readCObjFunction(&udstate, func)) { + cosmoV_pushNil(state); return 1; } + cosmoV_pushRef(state, (CObj *)*func); return udstate.readerStatus; } \ No newline at end of file diff --git a/src/cundump.h b/src/cundump.h index 282f5bc..763be70 100644 --- a/src/cundump.h +++ b/src/cundump.h @@ -6,9 +6,7 @@ #include -typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud); - /* returns non-zero on error */ -int cosmoD_undump(CState *state, CObjFunction *func, cosmo_Reader writer, const void *userData); +int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func); #endif \ No newline at end of file From 355842989ba0f2e22bbc5bbd1ca621bbc572cfe8 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 27 May 2023 23:16:47 -0500 Subject: [PATCH 05/14] cvm.c: added cosmoV_undump --- src/cvm.c | 24 +++++++++++++++++++++++- src/cvm.h | 12 +++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/cvm.c b/src/cvm.c index b3735ff..67a01bd 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -4,6 +4,7 @@ #include "cmem.h" #include "cparse.h" #include "cstate.h" +#include "cundump.h" #include #include @@ -30,6 +31,27 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val) state->top++; } +COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud) { + CObjFunction *func; + + if (cosmoD_undump(state, reader, ud, &func)) { + // fail recovery + state->panic = false; + cosmoV_pushRef(state, (CObj *)state->error); + return false; + }; + +#ifdef VM_DEBUG + disasmChunk(&func->chunk, func->name ? func->name->str : UNNAMEDCHUNK, 0); +#endif + + // push function onto the stack so it doesn't it cleaned up by the GC, at the same stack + // location put our closure + cosmoV_pushRef(state, (CObj *)func); + *(cosmoV_getTop(state, 0)) = cosmoV_newRef(cosmoO_newClosure(state, func)); + return true; +} + COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name) { CObjFunction *func; @@ -46,7 +68,7 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char * return true; } - // fail + // fail recovery state->panic = false; cosmoV_pushRef(state, (CObj *)state->error); return false; diff --git a/src/cvm.h b/src/cvm.h index 6e1fe52..6e3953c 100644 --- a/src/cvm.h +++ b/src/cvm.h @@ -38,7 +38,7 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val); COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj); /* - compiles string into a , if successful, will be pushed onto the stack + compiles string into a . if successful, will be pushed onto the stack otherwise the will be pushed. returns: @@ -47,6 +47,16 @@ COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjO */ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name); +/* + loads a from a dump. if successful, will be pushed onto the stack + otherwise the will be pushed. + + returns: + false : is at the top of the stack + true : is at the top of the stack +*/ +COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud); + /* expects object to be pushed, then the key. From 54a959438bad9f97b08ca727027be8f91ed7ed16 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 27 May 2023 23:17:17 -0500 Subject: [PATCH 06/14] added cdump.[ch] and cundump.[ch] to makefile --- Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b991ab7..11bbf78 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ # make clean && make && ./bin/cosmo CC=clang -CFLAGS=-fPIE -Wall -O3 -Isrc -std=c99 -LDFLAGS=-lm #-fsanitize=address +CFLAGS=-fPIE -Wall -O0 -Isrc -std=c99 -g +LDFLAGS=-lm -fsanitize=address OUT=bin/cosmo CHDR=\ @@ -19,6 +19,8 @@ CHDR=\ src/cvm.h\ src/cobj.h\ src/cbaselib.h\ + src/cdump.h\ + src/cundump.h\ CSRC=\ src/cchunk.c\ @@ -33,6 +35,8 @@ CSRC=\ src/cvm.c\ src/cobj.c\ src/cbaselib.c\ + src/cdump.c\ + src/cundump.c\ main.c\ COBJ=$(CSRC:.c=.o) From 89d443d7674d0a2ae1e1750c5d9ee52db311996d Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 00:03:50 -0500 Subject: [PATCH 07/14] formatting changes --- src/cdump.c | 2 +- src/cundump.c | 62 ++++++++++++++++++++++++++++----------------------- src/cvm.c | 3 ++- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/cdump.c b/src/cdump.c index a2f6258..745dcf7 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -1,9 +1,9 @@ #include "cdump.h" +#include "cdebug.h" #include "cmem.h" #include "cobj.h" #include "cvalue.h" -#include "cdebug.h" typedef struct { diff --git a/src/cundump.c b/src/cundump.c index e36048a..58f21bd 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -1,8 +1,9 @@ -#include "cdump.h" #include "cundump.h" -#include "cvm.h" + #include "cchunk.h" +#include "cdump.h" #include "cmem.h" +#include "cvm.h" typedef struct { @@ -14,10 +15,11 @@ typedef struct static bool readCValue(UndumpState *udstate, CValue *val); -#define check(e) if (!e) { \ - printf("FAILED %d\n", __LINE__); \ - return false; \ -} +#define check(e) \ + if (!e) { \ + printf("FAILED %d\n", __LINE__); \ + return false; \ + } static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader, const void *userData) @@ -55,18 +57,19 @@ static bool readSize(UndumpState *udstate, size_t *d) static bool readVector(UndumpState *udstate, void **data, size_t size, size_t *count) { check(readSize(udstate, count)); - *data = cosmoM_xmalloc(udstate->state, (*count)*size); - return readBlock(udstate, *data, (*count)*size); + *data = cosmoM_xmalloc(udstate->state, (*count) * size); + return readBlock(udstate, *data, (*count) * size); } -#define checku8(udstate, d, tmp) \ - check(readu8(udstate, &tmp)); \ - if (d != tmp) { \ - cosmoV_error(udstate->state, "bad header!"); \ - return false; \ +#define checku8(udstate, d, tmp) \ + check(readu8(udstate, &tmp)); \ + if (d != tmp) { \ + cosmoV_error(udstate->state, "bad header!"); \ + return false; \ } -static bool checkHeader(UndumpState *udstate) { +static bool checkHeader(UndumpState *udstate) +{ char magic[COSMO_MAGIC_LEN]; uint8_t tmp; @@ -99,7 +102,7 @@ static bool readCObjString(UndumpState *udstate, CObjString **str) return true; } - data = cosmoM_xmalloc(udstate->state, size+1); + data = cosmoM_xmalloc(udstate->state, size + 1); check(readBlock(udstate, (void *)data, size)); data[size] = '\0'; /* add NULL-terminator */ @@ -107,7 +110,8 @@ static bool readCObjString(UndumpState *udstate, CObjString **str) return true; } -static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { +static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) +{ *func = cosmoO_newFunction(udstate->state); check(readCObjString(udstate, &(*func)->name)); @@ -118,8 +122,10 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { check(readu8(udstate, (uint8_t *)&(*func)->variadic)); /* read chunk info */ - check(readVector(udstate, (void **)&(*func)->chunk.buf, sizeof(uint8_t), &(*func)->chunk.count)); - check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, sizeof(int), &(*func)->chunk.count)); + check( + readVector(udstate, (void **)&(*func)->chunk.buf, sizeof(uint8_t), &(*func)->chunk.count)); + check( + readVector(udstate, (void **)&(*func)->chunk.lineInfo, sizeof(int), &(*func)->chunk.count)); /* read constants */ size_t constants; @@ -127,8 +133,6 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { for (int i = 0; i < constants; i++) { CValue val; check(readCValue(udstate, &val)); - // printValue(val); - // putc('\n', stdout); addConstant(udstate->state, &(*func)->chunk, val); } @@ -153,15 +157,16 @@ static bool readCObj(UndumpState *udstate, CObj **obj) return true; } -#define READ_VAR(udstate, val, type, creator) \ - { \ - type _tmp; \ - check(readBlock(udstate, &_tmp, sizeof(type))); \ - *val = creator(_tmp); \ - break; \ +#define READ_VAR(udstate, val, type, creator) \ + { \ + type _tmp; \ + check(readBlock(udstate, &_tmp, sizeof(type))); \ + *val = creator(_tmp); \ + break; \ } -static bool readCValue(UndumpState *udstate, CValue *val) { +static bool readCValue(UndumpState *udstate, CValue *val) +{ uint8_t type; check(readu8(udstate, &type)); @@ -186,7 +191,8 @@ static bool readCValue(UndumpState *udstate, CValue *val) { return true; } -int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func) { +int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func) +{ UndumpState udstate; initUndumpState(state, &udstate, reader, userData); diff --git a/src/cvm.c b/src/cvm.c index 67a01bd..5b248b0 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -31,7 +31,8 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val) state->top++; } -COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud) { +COSMO_API bool cosmoV_undump(CState *state, cosmo_Reader reader, const void *ud) +{ CObjFunction *func; if (cosmoD_undump(state, reader, ud, &func)) { From c945c5648259765b681f1e31582dc95522e9275e Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 00:08:28 -0500 Subject: [PATCH 08/14] these values can be defined at the top of the function --- src/cundump.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cundump.c b/src/cundump.c index 58f21bd..b6007ff 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -112,6 +112,9 @@ static bool readCObjString(UndumpState *udstate, CObjString **str) static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { + size_t constants; + CValue val; + *func = cosmoO_newFunction(udstate->state); check(readCObjString(udstate, &(*func)->name)); @@ -128,10 +131,8 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) readVector(udstate, (void **)&(*func)->chunk.lineInfo, sizeof(int), &(*func)->chunk.count)); /* read constants */ - size_t constants; check(readSize(udstate, &constants)); for (int i = 0; i < constants; i++) { - CValue val; check(readCValue(udstate, &val)); addConstant(udstate->state, &(*func)->chunk, val); } From e854c5dbb3691a53f13ae07d55eed617c3163bca Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 11:55:48 -0500 Subject: [PATCH 09/14] fixed GC bug in cundump.c --- src/cundump.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/cundump.c b/src/cundump.c index b6007ff..e4956b1 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -117,6 +117,9 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) *func = cosmoO_newFunction(udstate->state); + /* make sure our GC can see that we're currently using this function (and the values it uses) */ + cosmoV_pushRef(udstate->state, (CObj *)*func); + check(readCObjString(udstate, &(*func)->name)); check(readCObjString(udstate, &(*func)->module)); @@ -137,6 +140,8 @@ static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) addConstant(udstate->state, &(*func)->chunk, val); } + /* pop function off stack */ + cosmoV_pop(udstate->state); return true; } From 4fe437ea4ed5f7831bac7bf1ea07bac9bf062d7c Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 12:03:49 -0500 Subject: [PATCH 10/14] undef macros --- src/cundump.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cundump.c b/src/cundump.c index e4956b1..18e51aa 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -17,7 +17,6 @@ static bool readCValue(UndumpState *udstate, CValue *val); #define check(e) \ if (!e) { \ - printf("FAILED %d\n", __LINE__); \ return false; \ } @@ -197,6 +196,9 @@ static bool readCValue(UndumpState *udstate, CValue *val) return true; } +#undef READ_VAR +#undef check + int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObjFunction **func) { UndumpState udstate; From be49ec5af550bd24b8fa8ea0c08935f3628c43c8 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 12:16:00 -0500 Subject: [PATCH 11/14] proper error handling for dump edgecases --- src/cdump.c | 109 ++++++++++++++++++++++++++++++-------------------- src/cundump.c | 9 +++-- 2 files changed, 71 insertions(+), 47 deletions(-) diff --git a/src/cdump.c b/src/cdump.c index 745dcf7..ebc2187 100644 --- a/src/cdump.c +++ b/src/cdump.c @@ -4,6 +4,7 @@ #include "cmem.h" #include "cobj.h" #include "cvalue.h" +#include "cvm.h" typedef struct { @@ -13,7 +14,12 @@ typedef struct int writerStatus; } DumpState; -static void writeCValue(DumpState *dstate, CValue val); +static bool writeCValue(DumpState *dstate, CValue val); + +#define check(e) \ + if (!e) { \ + return false; \ + } static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, const void *userData) @@ -24,82 +30,92 @@ static void initDumpState(CState *state, DumpState *dstate, cosmo_Writer writer, dstate->writerStatus = 0; } -static void writeBlock(DumpState *dstate, const void *data, size_t size) +static bool writeBlock(DumpState *dstate, const void *data, size_t size) { if (dstate->writerStatus == 0) { dstate->writerStatus = dstate->writer(dstate->state, data, size, dstate->userData); } + + return dstate->writerStatus == 0; } -static void writeu8(DumpState *dstate, uint8_t d) +static bool writeu8(DumpState *dstate, uint8_t d) { - writeBlock(dstate, &d, sizeof(uint8_t)); + return writeBlock(dstate, &d, sizeof(uint8_t)); } -static void writeu32(DumpState *dstate, uint32_t d) +static bool writeu32(DumpState *dstate, uint32_t d) { - writeBlock(dstate, &d, sizeof(uint32_t)); + return writeBlock(dstate, &d, sizeof(uint32_t)); } -static void writeSize(DumpState *dstate, size_t d) +static bool writeSize(DumpState *dstate, size_t d) { - writeBlock(dstate, &d, sizeof(size_t)); + return writeBlock(dstate, &d, sizeof(size_t)); } -static void writeVector(DumpState *dstate, const void *data, size_t size, size_t count) +static bool writeVector(DumpState *dstate, const void *data, size_t size, size_t count) { - writeSize(dstate, count); - writeBlock(dstate, data, size * count); + check(writeSize(dstate, count)); + check(writeBlock(dstate, data, size * count)); + + return true; } -static void writeHeader(DumpState *dstate) +static bool writeHeader(DumpState *dstate) { - writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN); + check(writeBlock(dstate, COSMO_MAGIC, COSMO_MAGIC_LEN)); /* after the magic, we write some platform information */ - writeu8(dstate, cosmoD_isBigEndian()); - writeu8(dstate, sizeof(cosmo_Number)); - writeu8(dstate, sizeof(size_t)); - writeu8(dstate, sizeof(int)); + check(writeu8(dstate, cosmoD_isBigEndian())); + check(writeu8(dstate, sizeof(cosmo_Number))); + check(writeu8(dstate, sizeof(size_t))); + check(writeu8(dstate, sizeof(int))); + + return true; } -static void writeCObjString(DumpState *dstate, CObjString *obj) +static bool writeCObjString(DumpState *dstate, CObjString *obj) { if (obj == NULL) { /* this is in case cobjfunction's name or module strings are null */ - writeu32(dstate, 0); - return; + check(writeu32(dstate, 0)); + return true; } /* write string length */ - writeu32(dstate, obj->length); + check(writeu32(dstate, obj->length)); /* write string data */ - writeBlock(dstate, obj->str, obj->length); + check(writeBlock(dstate, obj->str, obj->length)); + + return true; } -static void writeCObjFunction(DumpState *dstate, CObjFunction *obj) +static bool writeCObjFunction(DumpState *dstate, CObjFunction *obj) { - writeCObjString(dstate, obj->name); - writeCObjString(dstate, obj->module); + check(writeCObjString(dstate, obj->name)); + check(writeCObjString(dstate, obj->module)); - writeu32(dstate, obj->args); - writeu32(dstate, obj->upvals); - writeu8(dstate, obj->variadic); + check(writeu32(dstate, obj->args)); + check(writeu32(dstate, obj->upvals)); + check(writeu8(dstate, obj->variadic)); /* write chunk info */ - writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count); + check(writeVector(dstate, obj->chunk.buf, sizeof(uint8_t), obj->chunk.count)); /* write line info */ - writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count); + check(writeVector(dstate, obj->chunk.lineInfo, sizeof(int), obj->chunk.count)); /* write constants */ - writeSize(dstate, obj->chunk.constants.count); + check(writeSize(dstate, obj->chunk.constants.count)); for (int i = 0; i < obj->chunk.constants.count; i++) { - writeCValue(dstate, obj->chunk.constants.values[i]); + check(writeCValue(dstate, obj->chunk.constants.values[i])); } + + return true; } -static void writeCObj(DumpState *dstate, CObj *obj) +static bool writeCObj(DumpState *dstate, CObj *obj) { /* we can kind of cheat here since our parser only emits a few very limited CObjs... @@ -117,24 +133,27 @@ static void writeCObj(DumpState *dstate, CObj *obj) /* write object payload/body */ switch (t) { case COBJ_STRING: - writeCObjString(dstate, (CObjString *)obj); + check(writeCObjString(dstate, (CObjString *)obj)); break; case COBJ_FUNCTION: - writeCObjFunction(dstate, (CObjFunction *)obj); + check(writeCObjFunction(dstate, (CObjFunction *)obj)); break; default: - break; + cosmoV_error(dstate->state, "invalid cobj type: %d", t); + return false; } + + return true; } #define WRITE_VAR(dstate, type, expression) \ { \ type _tmp = expression; \ - writeBlock(dstate, &_tmp, sizeof(_tmp)); \ + check(writeBlock(dstate, &_tmp, sizeof(_tmp))); \ break; \ } -static void writeCValue(DumpState *dstate, CValue val) +static bool writeCValue(DumpState *dstate, CValue val) { CosmoType t = GET_TYPE(val); @@ -148,12 +167,16 @@ static void writeCValue(DumpState *dstate, CValue val) case COSMO_TBOOLEAN: WRITE_VAR(dstate, bool, cosmoV_readBoolean(val)) case COSMO_TREF: - writeCObj(dstate, cosmoV_readRef(val)); + check(writeCObj(dstate, cosmoV_readRef(val))); + break; + case COSMO_TNIL: /* no body */ break; - case COSMO_TNIL: /* fallthrough, no body */ default: - break; + cosmoV_error(dstate->state, "invalid value type: %d", t); + return false; } + + return true; } #undef WRITE_VAR @@ -174,8 +197,8 @@ int cosmoD_dump(CState *state, CObjFunction *func, cosmo_Writer writer, const vo DumpState dstate; initDumpState(state, &dstate, writer, userData); - writeHeader(&dstate); - writeCObjFunction(&dstate, func); + check(writeHeader(&dstate)); + check(writeCObjFunction(&dstate, func)); return dstate.writerStatus; } diff --git a/src/cundump.c b/src/cundump.c index 18e51aa..b92dbc1 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -172,10 +172,10 @@ static bool readCObj(UndumpState *udstate, CObj **obj) static bool readCValue(UndumpState *udstate, CValue *val) { - uint8_t type; - check(readu8(udstate, &type)); + uint8_t t; + check(readu8(udstate, &t)); - switch (type) { + switch (t) { case COSMO_TNUMBER: READ_VAR(udstate, val, cosmo_Number, cosmoV_newNumber) case COSMO_TBOOLEAN: @@ -190,7 +190,8 @@ static bool readCValue(UndumpState *udstate, CValue *val) *val = cosmoV_newNil(); break; default: - break; + cosmoV_error(udstate->state, "invalid value type: %d", t); + return false; } return true; From 93a09698a95462a0d1d972d81ce06c47630fa1ac Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 12:19:52 -0500 Subject: [PATCH 12/14] minor stack fixes --- src/cundump.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/cundump.c b/src/cundump.c index b92dbc1..3165546 100644 --- a/src/cundump.c +++ b/src/cundump.c @@ -32,6 +32,7 @@ static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader re static bool readBlock(UndumpState *udstate, void *data, size_t size) { if (udstate->readerStatus == 0) { + /* if reader returns 1, we expect an error was thrown */ udstate->readerStatus = udstate->reader(udstate->state, data, size, udstate->userData); } @@ -73,7 +74,7 @@ static bool checkHeader(UndumpState *udstate) uint8_t tmp; /* check header */ - readBlock(udstate, magic, COSMO_MAGIC_LEN); + check(readBlock(udstate, magic, COSMO_MAGIC_LEN)); if (memcmp(magic, COSMO_MAGIC, COSMO_MAGIC_LEN) != 0) { cosmoV_error(udstate->state, "bad header!"); return false; @@ -206,12 +207,10 @@ int cosmoD_undump(CState *state, cosmo_Reader reader, const void *userData, CObj initUndumpState(state, &udstate, reader, userData); if (!checkHeader(&udstate)) { - cosmoV_pushNil(state); return 1; } if (!readCObjFunction(&udstate, func)) { - cosmoV_pushNil(state); return 1; } From 8c6ba18848fc7cbff128fa5f6a37eb8726da5df6 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 20:52:12 -0500 Subject: [PATCH 13/14] major main.c refactoring - now takes command line arguments: Usage: ./bin/cosmo [-clsr] [args] available options are: -c compile and dump to -l load dump from -s compile and run script(s) -r start the repl --- Makefile | 4 +- main.c | 169 +++++++++++++++++++++++++++++++++++++++---------- src/cbaselib.c | 2 - 3 files changed, 137 insertions(+), 38 deletions(-) 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"); } From c464a768497ec09eb8794e82859b2d201228001a Mon Sep 17 00:00:00 2001 From: CPunch Date: Sun, 28 May 2023 20:57:53 -0500 Subject: [PATCH 14/14] minor usage fix --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index f096427..e216ffc 100644 --- a/main.c +++ b/main.c @@ -192,8 +192,8 @@ void printUsage(const char *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"); + "-s \tcompile and run script(s)\n" + "-r\t\tstart the repl\n\n"); } int main(int argc, char *const argv[])