Compare commits

...

6 Commits

8 changed files with 106 additions and 51 deletions

View File

@ -1,8 +1,8 @@
# make clean && make && ./bin/cosmo # make clean && make && ./bin/cosmo
CC=clang CC=clang
CFLAGS=-fPIE -Wall -O3 -Isrc -std=c99 CFLAGS=-fPIE -Wall -O0 -Isrc -std=c99 -g
LDFLAGS=-lm #-fsanitize=address LDFLAGS=-lm -fsanitize=address
OUT=bin/cosmo OUT=bin/cosmo
CHDR=\ CHDR=\
@ -19,6 +19,8 @@ CHDR=\
src/cvm.h\ src/cvm.h\
src/cobj.h\ src/cobj.h\
src/cbaselib.h\ src/cbaselib.h\
src/cdump.h\
src/cundump.h\
CSRC=\ CSRC=\
src/cchunk.c\ src/cchunk.c\
@ -33,6 +35,8 @@ CSRC=\
src/cvm.c\ src/cvm.c\
src/cobj.c\ src/cobj.c\
src/cbaselib.c\ src/cbaselib.c\
src/cdump.c\
src/cundump.c\
main.c\ main.c\
COBJ=$(CSRC:.c=.o) COBJ=$(CSRC:.c=.o)

View File

@ -1,5 +1,6 @@
#include "cdump.h" #include "cdump.h"
#include "cdebug.h"
#include "cmem.h" #include "cmem.h"
#include "cobj.h" #include "cobj.h"
#include "cvalue.h" #include "cvalue.h"
@ -45,10 +46,10 @@ static void writeSize(DumpState *dstate, size_t d)
writeBlock(dstate, &d, sizeof(size_t)); 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); writeSize(dstate, count);
writeBlock(dstate, data, size); writeBlock(dstate, data, size * count);
} }
static void writeHeader(DumpState *dstate) static void writeHeader(DumpState *dstate)
@ -86,10 +87,10 @@ static void writeCObjFunction(DumpState *dstate, CObjFunction *obj)
writeu8(dstate, obj->variadic); writeu8(dstate, obj->variadic);
/* write chunk info */ /* 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 */ /* 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 */ /* write constants */
writeSize(dstate, obj->chunk.constants.count); writeSize(dstate, obj->chunk.constants.count);

View File

@ -9,8 +9,6 @@
#define COSMO_MAGIC "COS\x12" #define COSMO_MAGIC "COS\x12"
#define COSMO_MAGIC_LEN 4 #define COSMO_MAGIC_LEN 4
typedef int (*cosmo_Writer)(CState *state, const void *data, size_t size, const void *ud);
bool cosmoD_isBigEndian(); bool cosmoD_isBigEndian();
/* returns non-zero on error */ /* returns non-zero on error */

View File

@ -45,6 +45,9 @@ typedef struct CObjClosure CObjClosure;
typedef uint8_t INSTRUCTION; 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 COSMOMAX_UPVALS 80
#define FRAME_MAX 64 #define FRAME_MAX 64
#define STACK_MAX (256 * FRAME_MAX) #define STACK_MAX (256 * FRAME_MAX)

View File

@ -1,7 +1,9 @@
#include "cdump.h"
#include "cundump.h" #include "cundump.h"
#include "cvm.h"
#include "cchunk.h" #include "cchunk.h"
#include "cdump.h"
#include "cmem.h"
#include "cvm.h"
typedef struct typedef struct
{ {
@ -11,7 +13,13 @@ typedef struct
int readerStatus; int readerStatus;
} UndumpState; } 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, static void initUndumpState(CState *state, UndumpState *udstate, cosmo_Reader reader,
const void *userData) const void *userData)
@ -36,9 +44,9 @@ static bool readu8(UndumpState *udstate, uint8_t *d)
return readBlock(udstate, d, sizeof(uint8_t)); 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) static bool readSize(UndumpState *udstate, size_t *d)
@ -46,21 +54,22 @@ static bool readSize(UndumpState *udstate, size_t *d)
return readBlock(udstate, d, sizeof(size_t)); 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)); check(readSize(udstate, count));
*data = cosmoM_malloc(udstate->state, *size); *data = cosmoM_xmalloc(udstate->state, (*count) * size);
return readBlock(udstate, *data, *size); return readBlock(udstate, *data, (*count) * size);
} }
#define checku8(udstate, d, tmp) \ #define checku8(udstate, d, tmp) \
check(readu8(udstate, &tmp)); \ check(readu8(udstate, &tmp)); \
if (d != tmp) { \ if (d != tmp) { \
cosmoV_error(udstate->state, "bad header!"); \ cosmoV_error(udstate->state, "bad header!"); \
return false; \ return false; \
} }
static bool checkHeader(UndumpState *udstate) { static bool checkHeader(UndumpState *udstate)
{
char magic[COSMO_MAGIC_LEN]; char magic[COSMO_MAGIC_LEN];
uint8_t tmp; uint8_t tmp;
@ -84,42 +93,46 @@ static bool checkHeader(UndumpState *udstate) {
static bool readCObjString(UndumpState *udstate, CObjString **str) static bool readCObjString(UndumpState *udstate, CObjString **str)
{ {
size_t size; uint32_t size;
char *data; char *data;
check(readu32(udstate, &size)); check(readu32(udstate, (uint32_t *)&size));
if (size == 0) { /* empty string */ if (size == 0) { /* empty string */
*str = NULL; *str = NULL;
return true; return true;
} }
*data = cosmoM_malloc(udstate->state, size+1); data = cosmoM_xmalloc(udstate->state, size + 1);
check(readBlock(udstate, (void *)&data, size)); check(readBlock(udstate, (void *)data, size));
data[size] = '\0'; /* add NULL-terminator */ data[size] = '\0'; /* add NULL-terminator */
*str = cosmoO_takeString(udstate->state, data, size); *str = cosmoO_takeString(udstate->state, data, size);
return true; return true;
} }
static bool readCObjFunction(UndumpState *udstate, CObjFunction **func) { static bool readCObjFunction(UndumpState *udstate, CObjFunction **func)
{
size_t constants;
CValue val;
*func = cosmoO_newFunction(udstate->state); *func = cosmoO_newFunction(udstate->state);
check(readCObjString(udstate, &(*func)->name)); check(readCObjString(udstate, &(*func)->name));
check(readCObjString(udstate, &(*func)->module)); check(readCObjString(udstate, &(*func)->module));
check(readu32(udstate, &(*func)->args)); check(readu32(udstate, (uint32_t *)&(*func)->args));
check(readu32(udstate, &(*func)->upvals)); check(readu32(udstate, (uint32_t *)&(*func)->upvals));
check(readu8(udstate, &(*func)->variadic)); check(readu8(udstate, (uint8_t *)&(*func)->variadic));
/* read chunk info */ /* read chunk info */
check(readVector(udstate, (void **)&(*func)->chunk.buf, &(*func)->chunk.count)); check(
check(readVector(udstate, (void **)&(*func)->chunk.lineInfo, &(*func)->chunk.count)); 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 */ /* read constants */
size_t constants;
check(readSize(udstate, &constants)); check(readSize(udstate, &constants));
for (int i = 0; i < constants; i++) { for (int i = 0; i < constants; i++) {
CValue val;
check(readCValue(udstate, &val)); check(readCValue(udstate, &val));
addConstant(udstate->state, &(*func)->chunk, val); addConstant(udstate->state, &(*func)->chunk, val);
} }
@ -145,15 +158,16 @@ static bool readCObj(UndumpState *udstate, CObj **obj)
return true; return true;
} }
#define READ_VAR(udstate, val, type, creator) \ #define READ_VAR(udstate, val, type, creator) \
{ \ { \
type _tmp; \ type _tmp; \
check(readBlock(udstate, &_tmp, sizeof(type))); \ check(readBlock(udstate, &_tmp, sizeof(type))); \
*val = creator(_tmp); \ *val = creator(_tmp); \
break; \ break; \
} }
static bool readCValue(UndumpState *udstate, CValue *val) { static bool readCValue(UndumpState *udstate, CValue *val)
{
uint8_t type; uint8_t type;
check(readu8(udstate, &type)); check(readu8(udstate, &type));
@ -178,17 +192,21 @@ static bool readCValue(UndumpState *udstate, CValue *val) {
return true; 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; UndumpState udstate;
initUndumpState(state, &udstate, writer, userData); initUndumpState(state, &udstate, reader, userData);
if (!checkHeader(&udstate)) { if (!checkHeader(&udstate)) {
cosmoV_pushNil(state);
return 1; return 1;
} }
if (!readCObjFunction(&udstate, &func)) { if (!readCObjFunction(&udstate, func)) {
cosmoV_pushNil(state);
return 1; return 1;
} }
cosmoV_pushRef(state, (CObj *)*func);
return udstate.readerStatus; return udstate.readerStatus;
} }

View File

@ -6,9 +6,7 @@
#include <stdio.h> #include <stdio.h>
typedef int (*cosmo_Reader)(CState *state, void *data, size_t size, const void *ud);
/* returns non-zero on error */ /* 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 #endif

View File

@ -4,6 +4,7 @@
#include "cmem.h" #include "cmem.h"
#include "cparse.h" #include "cparse.h"
#include "cstate.h" #include "cstate.h"
#include "cundump.h"
#include <math.h> #include <math.h>
#include <stdarg.h> #include <stdarg.h>
@ -30,6 +31,28 @@ COSMO_API void cosmo_insert(CState *state, int indx, CValue val)
state->top++; 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) COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name)
{ {
CObjFunction *func; CObjFunction *func;
@ -46,7 +69,7 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
return true; return true;
} }
// fail // fail recovery
state->panic = false; state->panic = false;
cosmoV_pushRef(state, (CObj *)state->error); cosmoV_pushRef(state, (CObj *)state->error);
return false; return false;

View File

@ -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); COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj);
/* /*
compiles string into a <closure>, if successful, <closure> will be pushed onto the stack compiles string into a <closure>. if successful, <closure> will be pushed onto the stack
otherwise the <error> will be pushed. otherwise the <error> will be pushed.
returns: 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); COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *name);
/*
loads a <closure> from a dump. if successful, <closure> will be pushed onto the stack
otherwise the <error> will be pushed.
returns:
false : <error> is at the top of the stack
true : <closure> 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. expects object to be pushed, then the key.