2020-10-28 05:16:30 +00:00
|
|
|
#include "cstate.h"
|
|
|
|
#include "cchunk.h"
|
|
|
|
#include "cobj.h"
|
|
|
|
#include "cvm.h"
|
2020-11-10 01:44:12 +00:00
|
|
|
#include "cmem.h"
|
2020-10-28 05:16:30 +00:00
|
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
CState *cosmoV_newState() {
|
|
|
|
// we use C's malloc because we don't want to trigger a GC with an invalid state
|
|
|
|
CState *state = malloc(sizeof(CState));
|
|
|
|
|
|
|
|
if (state == NULL) {
|
|
|
|
CERROR("failed to allocate memory!");
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
state->panic = false;
|
|
|
|
state->freezeGC = false;
|
|
|
|
|
|
|
|
// GC
|
|
|
|
state->objects = NULL;
|
2020-12-07 21:53:23 +00:00
|
|
|
state->userRoots = NULL;
|
2020-12-07 20:35:14 +00:00
|
|
|
state->grayStack.count = 0;
|
|
|
|
state->grayStack.capacity = 2;
|
|
|
|
state->grayStack.array = NULL;
|
2020-10-28 05:16:30 +00:00
|
|
|
state->allocatedBytes = 0;
|
|
|
|
state->nextGC = 1024 * 8; // threshhold starts at 8kb
|
|
|
|
|
|
|
|
// init stack
|
|
|
|
state->top = state->stack;
|
|
|
|
state->frameCount = 0;
|
|
|
|
state->openUpvalues = NULL;
|
Added CObjError, cosmoV_throw(), pcall(), and cosmoV_printError()
Errors are now handled very differently, parser errors and VM errors are now treated the same.
When cosmoV_error is called, cosmoV_throw is also called, which formats the error object and sets the panic state.
state->error now points to the latest CObjError when state->panic is true. To get a nice formatted Objection message, use
cosmoV_printError() and pass the state->error. pcall() was added to the standard base library. When called, the first argument
passed is called with the subsequent arguments given. If the call completed successfully, `true`,`nil` is returned. However
when an error occurs during the call, `false`,`<error>` is returned. Simply print the `<error>` to retrieve the error string.
2021-01-06 04:27:59 +00:00
|
|
|
|
|
|
|
state->error = NULL;
|
2021-01-10 20:38:53 +00:00
|
|
|
|
|
|
|
// set default proto objects
|
|
|
|
for (int i = 0; i < COBJ_MAX; i++)
|
|
|
|
state->protoObjects[i] = NULL;
|
2020-11-10 01:44:12 +00:00
|
|
|
|
2020-11-12 22:52:56 +00:00
|
|
|
// first, set all strings to NULL so our GC doesn't read garbage data
|
2020-11-17 01:58:16 +00:00
|
|
|
for (int i = 0; i < ISTRING_MAX; i++)
|
|
|
|
state->iStrings[i] = NULL;
|
2020-11-12 22:52:56 +00:00
|
|
|
|
2021-01-10 20:38:53 +00:00
|
|
|
cosmoT_initTable(state, &state->strings, 8); // init string table
|
|
|
|
cosmoT_initTable(state, &state->globals, 8); // init global table
|
|
|
|
|
2020-11-12 22:52:56 +00:00
|
|
|
// setup all strings used by the VM
|
2020-11-17 01:58:16 +00:00
|
|
|
state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6);
|
2021-01-03 23:33:10 +00:00
|
|
|
state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10);
|
2020-11-17 01:58:16 +00:00
|
|
|
state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7);
|
2020-11-24 21:16:37 +00:00
|
|
|
state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10);
|
|
|
|
|
2020-12-06 20:11:33 +00:00
|
|
|
// getters/setters
|
|
|
|
state->iStrings[ISTRING_GETTER] = cosmoO_copyString(state, "__getter", 8);
|
|
|
|
state->iStrings[ISTRING_SETTER] = cosmoO_copyString(state, "__setter", 8);
|
|
|
|
|
2020-12-16 03:21:51 +00:00
|
|
|
// for iterators
|
|
|
|
state->iStrings[ISTRING_ITER] = cosmoO_copyString(state, "__iter", 6);
|
|
|
|
state->iStrings[ISTRING_NEXT] = cosmoO_copyString(state, "__next", 6);
|
|
|
|
|
2020-12-18 01:44:04 +00:00
|
|
|
// for reserved members for objects
|
|
|
|
state->iStrings[ISTRING_RESERVED] = cosmoO_copyString(state, "__reserved", 10);
|
|
|
|
|
2020-12-10 02:46:20 +00:00
|
|
|
// set the IString flags
|
|
|
|
for (int i = 0; i < ISTRING_MAX; i++)
|
|
|
|
state->iStrings[i]->isIString = true;
|
|
|
|
|
2020-10-28 05:16:30 +00:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cosmoV_freeState(CState *state) {
|
2020-11-10 01:44:12 +00:00
|
|
|
#ifdef GC_DEBUG
|
2020-12-19 19:32:43 +00:00
|
|
|
printf("state %p is being freed!\n", state);
|
2020-11-10 01:44:12 +00:00
|
|
|
#endif
|
2020-10-28 05:16:30 +00:00
|
|
|
// frees all the objects
|
|
|
|
CObj *objs = state->objects;
|
|
|
|
while (objs != NULL) {
|
|
|
|
CObj *next = objs->next;
|
2020-11-06 01:53:55 +00:00
|
|
|
cosmoO_free(state, objs);
|
2020-10-28 05:16:30 +00:00
|
|
|
objs = next;
|
|
|
|
}
|
|
|
|
|
2020-11-12 22:52:56 +00:00
|
|
|
// mark our internal VM strings NULL
|
2020-11-17 01:58:16 +00:00
|
|
|
for (int i = 0; i < ISTRING_MAX; i++)
|
|
|
|
state->iStrings[i] = NULL;
|
2020-11-12 22:52:56 +00:00
|
|
|
|
|
|
|
// free our string & global table (the string table includes the internal VM strings)
|
2020-10-28 05:16:30 +00:00
|
|
|
cosmoT_clearTable(state, &state->strings);
|
|
|
|
cosmoT_clearTable(state, &state->globals);
|
2020-11-12 22:52:56 +00:00
|
|
|
|
2020-10-28 05:16:30 +00:00
|
|
|
// free our gray stack & finally free the state structure
|
2020-12-07 20:35:14 +00:00
|
|
|
free(state->grayStack.array);
|
2020-10-28 05:16:30 +00:00
|
|
|
free(state);
|
|
|
|
}
|
|
|
|
|
2020-12-20 03:15:12 +00:00
|
|
|
// expects 2*pairs values on the stack, each pair should consist of 1 key and 1 value
|
|
|
|
void cosmoV_register(CState *state, int pairs) {
|
|
|
|
for (int i = 0; i < pairs; i++) {
|
|
|
|
StkPtr key = cosmoV_getTop(state, 1);
|
|
|
|
StkPtr val = cosmoV_getTop(state, 0);
|
|
|
|
|
|
|
|
CValue *oldVal = cosmoT_insert(state, &state->globals, *key);
|
|
|
|
*oldVal = *val;
|
|
|
|
|
|
|
|
cosmoV_setTop(state, 2); // pops the 2 values off the stack
|
|
|
|
}
|
2020-10-28 05:16:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void cosmoV_printStack(CState *state) {
|
|
|
|
printf("==== [[ stack dump ]] ====\n");
|
|
|
|
for (CValue *top = state->top - 1; top >= state->stack; top--) {
|
|
|
|
printf("%d: ", (int)(top - state->stack));
|
|
|
|
printValue(*top);
|
|
|
|
printf("\n");
|
|
|
|
}
|
2021-01-02 05:06:24 +00:00
|
|
|
}
|