mirror of
				https://github.com/CPunch/Cosmo.git
				synced 2025-11-03 06:20:17 +00:00 
			
		
		
		
	Compare commits
	
		
			2 Commits
		
	
	
		
			861607d6a8
			...
			dcf6a09dae
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| dcf6a09dae | |||
| e0faa14b35 | 
							
								
								
									
										16
									
								
								src/cdebug.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/cdebug.c
									
									
									
									
									
								
							@@ -9,53 +9,53 @@ void printIndent(int indent)
 | 
			
		||||
        printf("\t");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int simpleInstruction(const char *name, int offset)
 | 
			
		||||
static int simpleInstruction(const char *name, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%s", name);
 | 
			
		||||
    return offset + 1; // consume opcode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int u8OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int u8OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%-16s [%03d]", name, readu8Chunk(chunk, offset + 1));
 | 
			
		||||
    return offset + 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%-16s [%05d]", name, readu16Chunk(chunk, offset + 1));
 | 
			
		||||
    return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int JumpInstruction(const char *name, CChunk *chunk, int offset, int dir)
 | 
			
		||||
static int JumpInstruction(const char *name, CChunk *chunk, int offset, int dir)
 | 
			
		||||
{
 | 
			
		||||
    int jmp = ((int)readu16Chunk(chunk, offset + 1)) * dir;
 | 
			
		||||
    printf("%-16s [%05d] - jumps to %04d", name, jmp, offset + 3 + jmp);
 | 
			
		||||
    return offset + 1 + (sizeof(uint16_t) / sizeof(INSTRUCTION));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int u8u8OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%-16s [%03d] [%03d]", name, readu8Chunk(chunk, offset + 1),
 | 
			
		||||
           readu8Chunk(chunk, offset + 2));
 | 
			
		||||
    return offset + 3; // op + u8 + u8
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int u8u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int u8u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%-16s [%03d] [%05d]", name, readu8Chunk(chunk, offset + 1),
 | 
			
		||||
           readu16Chunk(chunk, offset + 2));
 | 
			
		||||
    return offset + 4; // op + u8 + u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int u8u8u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int u8u8u16OperandInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    printf("%-16s [%03d] [%03d] [%05d]", name, readu8Chunk(chunk, offset + 1),
 | 
			
		||||
           readu8Chunk(chunk, offset + 2), readu16Chunk(chunk, offset + 3));
 | 
			
		||||
    return offset + 5; // op + u8 + u8 + u16
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int constInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
static int constInstruction(const char *name, CChunk *chunk, int offset)
 | 
			
		||||
{
 | 
			
		||||
    int index = readu16Chunk(chunk, offset + 1);
 | 
			
		||||
    printf("%-16s [%05d] - ", name, index);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										16
									
								
								src/clex.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								src/clex.c
									
									
									
									
									
								
							@@ -150,7 +150,7 @@ static bool match(CLexState *state, char expected)
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char peek(CLexState *state)
 | 
			
		||||
static char peek(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    return *state->currentChar;
 | 
			
		||||
}
 | 
			
		||||
@@ -163,7 +163,7 @@ static char peekNext(CLexState *state)
 | 
			
		||||
    return state->currentChar[1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char next(CLexState *state)
 | 
			
		||||
static char next(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    if (isEnd(state))
 | 
			
		||||
        return '\0'; // return a null terminator
 | 
			
		||||
@@ -171,12 +171,12 @@ char next(CLexState *state)
 | 
			
		||||
    return state->currentChar[-1];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool isHex(char c)
 | 
			
		||||
static bool isHex(char c)
 | 
			
		||||
{
 | 
			
		||||
    return isNumerical(c) || ('A' <= c && 'F' >= c) || ('a' <= c && 'f' >= c);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CTokenType identifierType(CLexState *state)
 | 
			
		||||
static CTokenType identifierType(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    int length = state->currentChar - state->startChar;
 | 
			
		||||
 | 
			
		||||
@@ -192,7 +192,7 @@ CTokenType identifierType(CLexState *state)
 | 
			
		||||
    return TOKEN_IDENTIFIER;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void skipWhitespace(CLexState *state)
 | 
			
		||||
static void skipWhitespace(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    while (true) {
 | 
			
		||||
        char c = peek(state);
 | 
			
		||||
@@ -235,7 +235,7 @@ void skipWhitespace(CLexState *state)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CToken parseString(CLexState *state)
 | 
			
		||||
static CToken parseString(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    makeBuffer(state); // buffer mode
 | 
			
		||||
    while (peek(state) != '"' && !isEnd(state)) {
 | 
			
		||||
@@ -341,7 +341,7 @@ CToken parseString(CLexState *state)
 | 
			
		||||
    return makeToken(state, TOKEN_STRING);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CToken parseNumber(CLexState *state)
 | 
			
		||||
static CToken parseNumber(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    switch (peek(state)) {
 | 
			
		||||
    case 'x': // hexadecimal number
 | 
			
		||||
@@ -380,7 +380,7 @@ CToken parseNumber(CLexState *state)
 | 
			
		||||
    return makeToken(state, TOKEN_NUMBER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CToken parseIdentifier(CLexState *state)
 | 
			
		||||
static CToken parseIdentifier(CLexState *state)
 | 
			
		||||
{
 | 
			
		||||
    // read literal
 | 
			
		||||
    while ((isAlpha(peek(state)) || isNumerical(peek(state))) && !isEnd(state))
 | 
			
		||||
 
 | 
			
		||||
@@ -93,7 +93,7 @@ typedef struct
 | 
			
		||||
    char *currentChar;
 | 
			
		||||
    char *startChar;
 | 
			
		||||
    char *buffer; // if non-NULL & bufCount > 0, token->start & token->length will be set to buffer
 | 
			
		||||
                  // & bufCount respectively
 | 
			
		||||
                  // & bufCount respectively. used exclusively for string literals
 | 
			
		||||
    size_t bufCount;
 | 
			
		||||
    size_t bufCap;
 | 
			
		||||
    int line;     // current line
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										24
									
								
								src/cmem.c
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								src/cmem.c
									
									
									
									
									
								
							@@ -51,10 +51,10 @@ COSMO_API bool cosmoM_checkGarbage(CState *state, size_t needed)
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markObject(CState *state, CObj *obj);
 | 
			
		||||
void markValue(CState *state, CValue val);
 | 
			
		||||
static void markObject(CState *state, CObj *obj);
 | 
			
		||||
static void markValue(CState *state, CValue val);
 | 
			
		||||
 | 
			
		||||
void markTable(CState *state, CTable *tbl)
 | 
			
		||||
static void markTable(CState *state, CTable *tbl)
 | 
			
		||||
{
 | 
			
		||||
    if (tbl->table == NULL) // table is still being initialized
 | 
			
		||||
        return;
 | 
			
		||||
@@ -68,7 +68,7 @@ void markTable(CState *state, CTable *tbl)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// frees white members from the table
 | 
			
		||||
void tableRemoveWhite(CState *state, CTable *tbl)
 | 
			
		||||
static void tableRemoveWhite(CState *state, CTable *tbl)
 | 
			
		||||
{
 | 
			
		||||
    if (tbl->table == NULL) // table is still being initialized
 | 
			
		||||
        return;
 | 
			
		||||
@@ -86,7 +86,7 @@ void tableRemoveWhite(CState *state, CTable *tbl)
 | 
			
		||||
    cosmoT_checkShrink(state, tbl); // recovers the memory we're no longer using
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markArray(CState *state, CValueArray *array)
 | 
			
		||||
static void markArray(CState *state, CValueArray *array)
 | 
			
		||||
{
 | 
			
		||||
    for (size_t i = 0; i < array->count; i++) {
 | 
			
		||||
        markValue(state, array->values[i]);
 | 
			
		||||
@@ -95,7 +95,7 @@ void markArray(CState *state, CValueArray *array)
 | 
			
		||||
 | 
			
		||||
// mark all references associated with the object
 | 
			
		||||
// black = keep, white = discard
 | 
			
		||||
void blackenObject(CState *state, CObj *obj)
 | 
			
		||||
static void blackenObject(CState *state, CObj *obj)
 | 
			
		||||
{
 | 
			
		||||
    markObject(state, (CObj *)obj->proto);
 | 
			
		||||
    switch (obj->type) {
 | 
			
		||||
@@ -161,7 +161,7 @@ void blackenObject(CState *state, CObj *obj)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markObject(CState *state, CObj *obj)
 | 
			
		||||
static void markObject(CState *state, CObj *obj)
 | 
			
		||||
{
 | 
			
		||||
    if (obj == NULL || obj->isMarked) // skip if NULL or already marked
 | 
			
		||||
        return;
 | 
			
		||||
@@ -185,14 +185,14 @@ void markObject(CState *state, CObj *obj)
 | 
			
		||||
    state->grayStack.array[state->grayStack.count++] = obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markValue(CState *state, CValue val)
 | 
			
		||||
static void markValue(CState *state, CValue val)
 | 
			
		||||
{
 | 
			
		||||
    if (IS_REF(val))
 | 
			
		||||
        markObject(state, cosmoV_readRef(val));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// trace our gray references
 | 
			
		||||
void traceGrays(CState *state)
 | 
			
		||||
static void traceGrays(CState *state)
 | 
			
		||||
{
 | 
			
		||||
    while (state->grayStack.count > 0) {
 | 
			
		||||
        CObj *obj = state->grayStack.array[--state->grayStack.count];
 | 
			
		||||
@@ -200,7 +200,7 @@ void traceGrays(CState *state)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sweep(CState *state)
 | 
			
		||||
static void sweep(CState *state)
 | 
			
		||||
{
 | 
			
		||||
    CObj *prev = NULL;
 | 
			
		||||
    CObj *object = state->objects;
 | 
			
		||||
@@ -224,7 +224,7 @@ void sweep(CState *state)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markUserRoots(CState *state)
 | 
			
		||||
static void markUserRoots(CState *state)
 | 
			
		||||
{
 | 
			
		||||
    CObj *root = state->userRoots;
 | 
			
		||||
 | 
			
		||||
@@ -235,7 +235,7 @@ void markUserRoots(CState *state)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void markRoots(CState *state)
 | 
			
		||||
static void markRoots(CState *state)
 | 
			
		||||
{
 | 
			
		||||
    // mark all values on the stack
 | 
			
		||||
    for (StkPtr value = state->stack; value < state->top; value++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ COSMO_API void cosmoM_collectGarbage(CState *state);
 | 
			
		||||
COSMO_API void cosmoM_updateThreshhold(CState *state);
 | 
			
		||||
 | 
			
		||||
// lets the VM know you are holding a reference to a CObj and to not free it
 | 
			
		||||
// NOTE: prefer to use the stack when possible
 | 
			
		||||
COSMO_API void cosmoM_addRoot(CState *state, CObj *newRoot);
 | 
			
		||||
 | 
			
		||||
// lets the VM know this root is no longer held in a reference and is able to be freed
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ typedef enum
 | 
			
		||||
    OP_FALSE,
 | 
			
		||||
    OP_NIL,
 | 
			
		||||
 | 
			
		||||
    OP_RETURN
 | 
			
		||||
    OP_RETURN,
 | 
			
		||||
} COPCODE; // there can be a max of 256 instructions
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										10
									
								
								src/cosmo.h
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/cosmo.h
									
									
									
									
									
								
							@@ -14,7 +14,15 @@
 | 
			
		||||
   performance, however this will produce undefined behavior as you reach the stack limit (and may
 | 
			
		||||
   cause a seg fault!). It is recommended to keep this enabled.
 | 
			
		||||
*/
 | 
			
		||||
#define SAFE_STACK
 | 
			
		||||
// #define SAFE_STACK
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    NAN_BOXXED:
 | 
			
		||||
        if undefined, the interpreter will use a tagged union to store values. This is the default.
 | 
			
		||||
    Note that even though the sizeof(CValue) is 8 bytes for NAN_BOXXED (as opposed to 16 bytes for
 | 
			
		||||
   the tagged union) no performance benefits were measured. I recommend keeping this undefined for
 | 
			
		||||
   now.
 | 
			
		||||
*/
 | 
			
		||||
// #define NAN_BOXXED
 | 
			
		||||
 | 
			
		||||
// forward declare *most* stuff so our headers are cleaner
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								src/ctable.c
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/ctable.c
									
									
									
									
									
								
							@@ -11,7 +11,7 @@
 | 
			
		||||
#define MIN_TABLE_CAPACITY ARRAY_START
 | 
			
		||||
 | 
			
		||||
// bit-twiddling hacks, gets the next power of 2
 | 
			
		||||
unsigned int nextPow2(unsigned int x)
 | 
			
		||||
static unsigned int nextPow2(unsigned int x)
 | 
			
		||||
{
 | 
			
		||||
    if (x <= ARRAY_START - 1)
 | 
			
		||||
        return ARRAY_START; // sanity check
 | 
			
		||||
@@ -46,13 +46,14 @@ void cosmoT_initTable(CState *state, CTable *tbl, int startCap)
 | 
			
		||||
 | 
			
		||||
void cosmoT_addTable(CState *state, CTable *from, CTable *to)
 | 
			
		||||
{
 | 
			
		||||
    CTableEntry *entry;
 | 
			
		||||
    int cap = from->capacityMask + 1;
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < cap; i++) {
 | 
			
		||||
        CTableEntry *entry = &from->table[i];
 | 
			
		||||
        entry = &from->table[i];
 | 
			
		||||
 | 
			
		||||
        if (!(IS_NIL(entry->key))) {
 | 
			
		||||
            CValue *newVal = cosmoT_insert(state, to, entry->key);
 | 
			
		||||
            *newVal = entry->val;
 | 
			
		||||
            *cosmoT_insert(state, to, entry->key) = entry->val;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -62,7 +63,7 @@ void cosmoT_clearTable(CState *state, CTable *tbl)
 | 
			
		||||
    cosmoM_freearray(state, CTableEntry, tbl->table, (tbl->capacityMask + 1));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t getObjectHash(CObj *obj)
 | 
			
		||||
static uint32_t getObjectHash(CObj *obj)
 | 
			
		||||
{
 | 
			
		||||
    switch (obj->type) {
 | 
			
		||||
    case COBJ_STRING:
 | 
			
		||||
@@ -72,7 +73,7 @@ uint32_t getObjectHash(CObj *obj)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t getValueHash(CValue *val)
 | 
			
		||||
static uint32_t getValueHash(CValue *val)
 | 
			
		||||
{
 | 
			
		||||
    switch (GET_TYPE(*val)) {
 | 
			
		||||
    case COSMO_TREF:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										391
									
								
								src/cvm.c
									
									
									
									
									
								
							
							
						
						
									
										391
									
								
								src/cvm.c
									
									
									
									
									
								
							@@ -672,15 +672,62 @@ int _tbl__next(CState *state, int nargs, CValue *args)
 | 
			
		||||
        return -1;                                                                                 \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
static inline uint8_t READBYTE(CCallFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
    return *frame->pc++;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline uint16_t READUINT(CCallFrame *frame)
 | 
			
		||||
{
 | 
			
		||||
    frame->pc += 2;
 | 
			
		||||
    return *(uint16_t *)(&frame->pc[-2]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef VM_JUMPTABLE
 | 
			
		||||
#    define DISPATCH goto *cosmoV_dispatchTable[READBYTE(frame)]
 | 
			
		||||
#    define CASE(op)                                                                               \
 | 
			
		||||
        DISPATCH;                                                                                  \
 | 
			
		||||
        JMP_##op
 | 
			
		||||
#    define JMPLABEL(op) &&JMP_##op
 | 
			
		||||
#    define SWITCH                                                                                 \
 | 
			
		||||
        static void *cosmoV_dispatchTable[] = {                                                    \
 | 
			
		||||
            JMPLABEL(OP_LOADCONST),     JMPLABEL(OP_SETGLOBAL), JMPLABEL(OP_GETGLOBAL),            \
 | 
			
		||||
            JMPLABEL(OP_SETLOCAL),      JMPLABEL(OP_GETLOCAL),  JMPLABEL(OP_GETUPVAL),             \
 | 
			
		||||
            JMPLABEL(OP_SETUPVAL),      JMPLABEL(OP_PEJMP),     JMPLABEL(OP_EJMP),                 \
 | 
			
		||||
            JMPLABEL(OP_JMP),           JMPLABEL(OP_JMPBACK),   JMPLABEL(OP_POP),                  \
 | 
			
		||||
            JMPLABEL(OP_CALL),          JMPLABEL(OP_CLOSURE),   JMPLABEL(OP_CLOSE),                \
 | 
			
		||||
            JMPLABEL(OP_NEWTABLE),      JMPLABEL(OP_NEWARRAY),  JMPLABEL(OP_INDEX),                \
 | 
			
		||||
            JMPLABEL(OP_NEWINDEX),      JMPLABEL(OP_NEWOBJECT), JMPLABEL(OP_SETOBJECT),            \
 | 
			
		||||
            JMPLABEL(OP_GETOBJECT),     JMPLABEL(OP_GETMETHOD), JMPLABEL(OP_INVOKE),               \
 | 
			
		||||
            JMPLABEL(OP_ITER),          JMPLABEL(OP_NEXT),      JMPLABEL(OP_ADD),                  \
 | 
			
		||||
            JMPLABEL(OP_SUB),           JMPLABEL(OP_MULT),      JMPLABEL(OP_DIV),                  \
 | 
			
		||||
            JMPLABEL(OP_MOD),           JMPLABEL(OP_POW),       JMPLABEL(OP_NOT),                  \
 | 
			
		||||
            JMPLABEL(OP_NEGATE),        JMPLABEL(OP_COUNT),     JMPLABEL(OP_CONCAT),               \
 | 
			
		||||
            JMPLABEL(OP_INCLOCAL),      JMPLABEL(OP_INCGLOBAL), JMPLABEL(OP_INCUPVAL),             \
 | 
			
		||||
            JMPLABEL(OP_INCINDEX),      JMPLABEL(OP_INCOBJECT), JMPLABEL(OP_EQUAL),                \
 | 
			
		||||
            JMPLABEL(OP_LESS),          JMPLABEL(OP_GREATER),   JMPLABEL(OP_LESS_EQUAL),           \
 | 
			
		||||
            JMPLABEL(OP_GREATER_EQUAL), JMPLABEL(OP_TRUE),      JMPLABEL(OP_FALSE),                \
 | 
			
		||||
            JMPLABEL(OP_NIL),           JMPLABEL(OP_RETURN),                                       \
 | 
			
		||||
        };                                                                                         \
 | 
			
		||||
        DISPATCH;
 | 
			
		||||
#    define DEFAULT DISPATCH /* no-op */
 | 
			
		||||
#else
 | 
			
		||||
#    define CASE(op)                                                                               \
 | 
			
		||||
        continue;                                                                                  \
 | 
			
		||||
    case op
 | 
			
		||||
#    define SWITCH switch (READBYTE(frame))
 | 
			
		||||
#    define DEFAULT                                                                                \
 | 
			
		||||
    default:                                                                                       \
 | 
			
		||||
        CERROR("unknown opcode!");                                                                 \
 | 
			
		||||
        exit(0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// returns -1 if panic
 | 
			
		||||
int cosmoV_execute(CState *state)
 | 
			
		||||
{
 | 
			
		||||
    CCallFrame *frame = &state->callFrame[state->frameCount - 1];         // grabs the current frame
 | 
			
		||||
    CValue *constants = frame->closure->function->chunk.constants.values; // cache the pointer :)
 | 
			
		||||
 | 
			
		||||
#define READBYTE() *frame->pc++
 | 
			
		||||
#define READUINT() (frame->pc += 2, *(uint16_t *)(&frame->pc[-2]))
 | 
			
		||||
 | 
			
		||||
    while (!state->panic) {
 | 
			
		||||
#ifdef VM_DEBUG
 | 
			
		||||
        cosmoV_printStack(state);
 | 
			
		||||
@@ -688,95 +735,98 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    frame->pc - frame->closure->function->chunk.buf, state->frameCount - 1);
 | 
			
		||||
        printf("\n");
 | 
			
		||||
#endif
 | 
			
		||||
        switch (READBYTE()) {
 | 
			
		||||
        case OP_LOADCONST: { // push const[uint] to stack
 | 
			
		||||
            uint16_t indx = READUINT();
 | 
			
		||||
        SWITCH
 | 
			
		||||
        {
 | 
			
		||||
            CASE(OP_LOADCONST) :
 | 
			
		||||
            { // push const[uint] to stack
 | 
			
		||||
                uint16_t indx = READUINT(frame);
 | 
			
		||||
                cosmoV_pushValue(state, constants[indx]);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_SETGLOBAL: {
 | 
			
		||||
            uint16_t indx = READUINT();
 | 
			
		||||
            CASE(OP_SETGLOBAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t indx = READUINT(frame);
 | 
			
		||||
                CValue ident = constants[indx]; // grabs identifier
 | 
			
		||||
                CValue *val = cosmoT_insert(state, &state->globals->tbl, ident);
 | 
			
		||||
                *val = *cosmoV_pop(state); // sets the value in the hash table
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GETGLOBAL: {
 | 
			
		||||
            uint16_t indx = READUINT();
 | 
			
		||||
            CASE(OP_GETGLOBAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t indx = READUINT(frame);
 | 
			
		||||
                CValue ident = constants[indx]; // grabs identifier
 | 
			
		||||
                CValue val;                     // to hold our value
 | 
			
		||||
                cosmoT_get(state, &state->globals->tbl, ident, &val);
 | 
			
		||||
                cosmoV_pushValue(state, val); // pushes the value to the stack
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_SETLOCAL: {
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_SETLOCAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                // set base to top of stack & pop
 | 
			
		||||
                frame->base[indx] = *cosmoV_pop(state);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GETLOCAL: {
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_GETLOCAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                cosmoV_pushValue(state, frame->base[indx]);
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GETUPVAL: {
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_GETUPVAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                cosmoV_pushValue(state, *frame->closure->upvalues[indx]->val);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_SETUPVAL: {
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_SETUPVAL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                *frame->closure->upvalues[indx]->val = *cosmoV_pop(state);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_PEJMP: { // pop equality jump
 | 
			
		||||
            uint16_t offset = READUINT();
 | 
			
		||||
            CASE(OP_PEJMP) :
 | 
			
		||||
            { // pop equality jump
 | 
			
		||||
                uint16_t offset = READUINT(frame);
 | 
			
		||||
 | 
			
		||||
                if (isFalsey(cosmoV_pop(state))) { // pop, if the condition is false, jump!
 | 
			
		||||
                    frame->pc += offset;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_EJMP: { // equality jump
 | 
			
		||||
            uint16_t offset = READUINT();
 | 
			
		||||
            CASE(OP_EJMP) :
 | 
			
		||||
            { // equality jump
 | 
			
		||||
                uint16_t offset = READUINT(frame);
 | 
			
		||||
 | 
			
		||||
                if (isFalsey(cosmoV_getTop(state, 0))) { // if the condition is false, jump!
 | 
			
		||||
                    frame->pc += offset;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_JMP: { // jump
 | 
			
		||||
            uint16_t offset = READUINT();
 | 
			
		||||
            CASE(OP_JMP) :
 | 
			
		||||
            { // jump
 | 
			
		||||
                uint16_t offset = READUINT(frame);
 | 
			
		||||
                frame->pc += offset;
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_JMPBACK: {
 | 
			
		||||
            uint16_t offset = READUINT();
 | 
			
		||||
            CASE(OP_JMPBACK) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t offset = READUINT(frame);
 | 
			
		||||
                frame->pc -= offset;
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_POP: { // pops value off the stack
 | 
			
		||||
            cosmoV_setTop(state, READBYTE());
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_POP) :
 | 
			
		||||
            { // pops value off the stack
 | 
			
		||||
                cosmoV_setTop(state, READBYTE(frame));
 | 
			
		||||
            }
 | 
			
		||||
        case OP_CALL: {
 | 
			
		||||
            uint8_t args = READBYTE();
 | 
			
		||||
            uint8_t nres = READBYTE();
 | 
			
		||||
            CASE(OP_CALL) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t args = READBYTE(frame);
 | 
			
		||||
                uint8_t nres = READBYTE(frame);
 | 
			
		||||
                if (cosmoV_call(state, args, nres) != COSMOVM_OK) {
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_CLOSURE: {
 | 
			
		||||
            uint16_t index = READUINT();
 | 
			
		||||
            CASE(OP_CLOSURE) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t index = READUINT(frame);
 | 
			
		||||
                CObjFunction *func = cosmoV_readFunction(constants[index]);
 | 
			
		||||
                CObjClosure *closure = cosmoO_newClosure(state, func);
 | 
			
		||||
                cosmoV_pushRef(state, (CObj *)closure);
 | 
			
		||||
 | 
			
		||||
                for (int i = 0; i < closure->upvalueCount; i++) {
 | 
			
		||||
                uint8_t encoding = READBYTE();
 | 
			
		||||
                uint8_t index = READBYTE();
 | 
			
		||||
                    uint8_t encoding = READBYTE(frame);
 | 
			
		||||
                    uint8_t index = READBYTE(frame);
 | 
			
		||||
                    if (encoding == OP_GETUPVAL) {
 | 
			
		||||
                        // capture upvalue from current frame's closure
 | 
			
		||||
                        closure->upvalues[i] = frame->closure->upvalues[index];
 | 
			
		||||
@@ -785,21 +835,20 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                        closure->upvalues[i] = captureUpvalue(state, frame->base + index);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_CLOSE: {
 | 
			
		||||
            CASE(OP_CLOSE) :
 | 
			
		||||
            {
 | 
			
		||||
                closeUpvalues(state, state->top - 1);
 | 
			
		||||
                cosmoV_pop(state);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEWTABLE: {
 | 
			
		||||
            uint16_t pairs = READUINT();
 | 
			
		||||
            CASE(OP_NEWTABLE) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t pairs = READUINT(frame);
 | 
			
		||||
                cosmoV_makeTable(state, pairs);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEWARRAY: {
 | 
			
		||||
            uint16_t pairs = READUINT();
 | 
			
		||||
            CASE(OP_NEWARRAY) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t pairs = READUINT(frame);
 | 
			
		||||
                StkPtr val;
 | 
			
		||||
                CObjTable *newObj = cosmoO_newTable(state);
 | 
			
		||||
                cosmoV_pushRef(state, (CObj *)newObj); // so our GC doesn't free our new table
 | 
			
		||||
@@ -816,9 +865,9 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                // once done, pop everything off the stack + push new table
 | 
			
		||||
                cosmoV_setTop(state, pairs + 1); // + 1 for our table
 | 
			
		||||
                cosmoV_pushRef(state, (CObj *)newObj);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INDEX: {
 | 
			
		||||
            CASE(OP_INDEX) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr key = cosmoV_getTop(state, 0);  // key should be the top of the stack
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 1); // after that should be the table
 | 
			
		||||
 | 
			
		||||
@@ -849,9 +898,9 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
 | 
			
		||||
                cosmoV_setTop(state, 2);      // pops the table & the key
 | 
			
		||||
                cosmoV_pushValue(state, val); // pushes the field result
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEWINDEX: {
 | 
			
		||||
            CASE(OP_NEWINDEX) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
 | 
			
		||||
                StkPtr key = cosmoV_getTop(state, 1);
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 2); // table is after the key
 | 
			
		||||
@@ -866,7 +915,8 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                CObjObject *proto = cosmoO_grabProto(obj);
 | 
			
		||||
 | 
			
		||||
                if (proto != NULL) {
 | 
			
		||||
                if (!cosmoO_newIndexObject(state, proto, *key,
 | 
			
		||||
                    if (!cosmoO_newIndexObject(
 | 
			
		||||
                            state, proto, *key,
 | 
			
		||||
                            *value)) // if it returns false, cosmoV_error was called
 | 
			
		||||
                        return -1;
 | 
			
		||||
                } else if (obj->type == COBJ_TABLE) {
 | 
			
		||||
@@ -882,17 +932,17 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
 | 
			
		||||
                // pop everything off the stack
 | 
			
		||||
                cosmoV_setTop(state, 3);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEWOBJECT: {
 | 
			
		||||
            uint16_t pairs = READUINT();
 | 
			
		||||
            CASE(OP_NEWOBJECT) :
 | 
			
		||||
            {
 | 
			
		||||
                uint16_t pairs = READUINT(frame);
 | 
			
		||||
                cosmoV_makeObject(state, pairs);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_SETOBJECT: {
 | 
			
		||||
            CASE(OP_SETOBJECT) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr value = cosmoV_getTop(state, 0); // value is at the top of the stack
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 1);  // object is after the value
 | 
			
		||||
            uint16_t ident = READUINT();            // use for the key
 | 
			
		||||
                uint16_t ident = READUINT(frame);       // use for the key
 | 
			
		||||
 | 
			
		||||
                // sanity check
 | 
			
		||||
                if (IS_REF(*temp)) {
 | 
			
		||||
@@ -907,12 +957,12 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
 | 
			
		||||
                // pop everything off the stack
 | 
			
		||||
                cosmoV_setTop(state, 2);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GETOBJECT: {
 | 
			
		||||
            CASE(OP_GETOBJECT) :
 | 
			
		||||
            {
 | 
			
		||||
                CValue val;                            // to hold our value
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
 | 
			
		||||
            uint16_t ident = READUINT();           // use for the key
 | 
			
		||||
                uint16_t ident = READUINT(frame);      // use for the key
 | 
			
		||||
 | 
			
		||||
                // sanity check
 | 
			
		||||
                if (IS_REF(*temp)) {
 | 
			
		||||
@@ -927,15 +977,15 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
 | 
			
		||||
                cosmoV_setTop(state, 1);      // pops the object
 | 
			
		||||
                cosmoV_pushValue(state, val); // pushes the field result
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GETMETHOD: {
 | 
			
		||||
            CASE(OP_GETMETHOD) :
 | 
			
		||||
            {
 | 
			
		||||
                CValue val;                            // to hold our value
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0); // that should be the object
 | 
			
		||||
            uint16_t ident = READUINT();           // use for the key
 | 
			
		||||
                uint16_t ident = READUINT(frame);      // use for the key
 | 
			
		||||
 | 
			
		||||
            // this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead of
 | 
			
		||||
            // just cosmoV_get
 | 
			
		||||
                // this is almost identical to GETOBJECT, however cosmoV_getMethod is used instead
 | 
			
		||||
                // of just cosmoV_get
 | 
			
		||||
                if (IS_REF(*temp)) {
 | 
			
		||||
                    if (!cosmoV_getMethod(state, cosmoV_readRef(*temp), constants[ident], &val))
 | 
			
		||||
                        return -1;
 | 
			
		||||
@@ -948,12 +998,12 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
 | 
			
		||||
                cosmoV_setTop(state, 1);      // pops the object
 | 
			
		||||
                cosmoV_pushValue(state, val); // pushes the field result
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INVOKE: {
 | 
			
		||||
            uint8_t args = READBYTE();
 | 
			
		||||
            uint8_t nres = READBYTE();
 | 
			
		||||
            uint16_t ident = READUINT();
 | 
			
		||||
            CASE(OP_INVOKE) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t args = READBYTE(frame);
 | 
			
		||||
                uint8_t nres = READBYTE(frame);
 | 
			
		||||
                uint16_t ident = READUINT(frame);
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, args); // grabs object from stack
 | 
			
		||||
                CValue val;                               // to hold our value
 | 
			
		||||
 | 
			
		||||
@@ -969,10 +1019,9 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Couldn't get from type %s!", cosmoV_typeStr(*temp));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_ITER: {
 | 
			
		||||
            CASE(OP_ITER) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0); // should be the object/table
 | 
			
		||||
 | 
			
		||||
                if (!IS_REF(*temp)) {
 | 
			
		||||
@@ -992,15 +1041,16 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                        cosmoV_pushValue(state, val);
 | 
			
		||||
                        cosmoV_pushRef(state, (CObj *)obj);
 | 
			
		||||
                        if (cosmoV_call(state, 1, 1) !=
 | 
			
		||||
                        COSMOVM_OK) // we expect 1 return value on the stack, the iterable object
 | 
			
		||||
                            COSMOVM_OK) // we expect 1 return value on the stack, the iterable
 | 
			
		||||
                                        // object
 | 
			
		||||
                            return -1;
 | 
			
		||||
 | 
			
		||||
                        StkPtr iObj = cosmoV_getTop(state, 0);
 | 
			
		||||
 | 
			
		||||
                        if (!IS_OBJECT(*iObj)) {
 | 
			
		||||
                        cosmoV_error(
 | 
			
		||||
                            state,
 | 
			
		||||
                            "Expected iterable object! '__iter' returned %s, expected <object>!",
 | 
			
		||||
                            cosmoV_error(state,
 | 
			
		||||
                                         "Expected iterable object! '__iter' returned %s, expected "
 | 
			
		||||
                                         "<object>!",
 | 
			
		||||
                                         cosmoV_typeStr(*iObj));
 | 
			
		||||
                            return -1;
 | 
			
		||||
                        }
 | 
			
		||||
@@ -1022,11 +1072,13 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    CObjCFunction *tbl_next = cosmoO_newCFunction(state, _tbl__next);
 | 
			
		||||
                    cosmoV_pushRef(state, (CObj *)tbl_next); // value
 | 
			
		||||
 | 
			
		||||
                CObjObject *obj = cosmoV_makeObject(state, 2); // pushes the new object to the stack
 | 
			
		||||
                    CObjObject *obj =
 | 
			
		||||
                        cosmoV_makeObject(state, 2); // pushes the new object to the stack
 | 
			
		||||
                    cosmoO_setUserI(obj, 0);         // increment for iterator
 | 
			
		||||
 | 
			
		||||
                    // make our CObjMethod for OP_NEXT to call
 | 
			
		||||
                CObjMethod *method = cosmoO_newMethod(state, cosmoV_newRef(tbl_next), (CObj *)obj);
 | 
			
		||||
                    CObjMethod *method =
 | 
			
		||||
                        cosmoO_newMethod(state, cosmoV_newRef(tbl_next), (CObj *)obj);
 | 
			
		||||
 | 
			
		||||
                    cosmoV_setTop(state, 2);               // pops the object & the tbl
 | 
			
		||||
                    cosmoV_pushRef(state, (CObj *)method); // pushes the method for OP_NEXT
 | 
			
		||||
@@ -1035,12 +1087,11 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                                 cosmoO_typeStr(obj));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEXT: {
 | 
			
		||||
            uint8_t nresults = READBYTE();
 | 
			
		||||
            uint16_t jump = READUINT();
 | 
			
		||||
            CASE(OP_NEXT) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t nresults = READBYTE(frame);
 | 
			
		||||
                uint16_t jump = READUINT(frame);
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0); // we don't actually pop this off the stack
 | 
			
		||||
 | 
			
		||||
                if (!IS_METHOD(*temp)) {
 | 
			
		||||
@@ -1058,25 +1109,29 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_setTop(state, nresults); // pop the return values
 | 
			
		||||
                    frame->pc += jump;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_ADD: { // pop 2 values off the stack & try to add them together
 | 
			
		||||
            CASE(OP_ADD) :
 | 
			
		||||
            {
 | 
			
		||||
                // pop 2 values off the stack & try to add them together
 | 
			
		||||
                NUMBEROP(cosmoV_newNumber, +);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_SUB: { // pop 2 values off the stack & try to subtracts them
 | 
			
		||||
            NUMBEROP(cosmoV_newNumber, -)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_SUB) :
 | 
			
		||||
            {
 | 
			
		||||
                // pop 2 values off the stack & try to subtracts them
 | 
			
		||||
                NUMBEROP(cosmoV_newNumber, -);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_MULT: { // pop 2 values off the stack & try to multiplies them together
 | 
			
		||||
            NUMBEROP(cosmoV_newNumber, *)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_MULT) :
 | 
			
		||||
            {
 | 
			
		||||
                // pop 2 values off the stack & try to multiplies them together
 | 
			
		||||
                NUMBEROP(cosmoV_newNumber, *);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_DIV: { // pop 2 values off the stack & try to divides them
 | 
			
		||||
            NUMBEROP(cosmoV_newNumber, /)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_DIV) :
 | 
			
		||||
            {
 | 
			
		||||
                // pop 2 values off the stack & try to divides them
 | 
			
		||||
                NUMBEROP(cosmoV_newNumber, /);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_MOD: {
 | 
			
		||||
            CASE(OP_MOD) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr valA = cosmoV_getTop(state, 1);
 | 
			
		||||
                StkPtr valB = cosmoV_getTop(state, 0);
 | 
			
		||||
                if (IS_NUMBER(*valA) && IS_NUMBER(*valB)) {
 | 
			
		||||
@@ -1088,9 +1143,9 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                                 cosmoV_typeStr(*valB));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_POW: {
 | 
			
		||||
            CASE(OP_POW) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr valA = cosmoV_getTop(state, 1);
 | 
			
		||||
                StkPtr valB = cosmoV_getTop(state, 0);
 | 
			
		||||
                if (IS_NUMBER(*valA) && IS_NUMBER(*valB)) {
 | 
			
		||||
@@ -1102,13 +1157,13 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                                 cosmoV_typeStr(*valB));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NOT: {
 | 
			
		||||
            CASE(OP_NOT) :
 | 
			
		||||
            {
 | 
			
		||||
                cosmoV_pushBoolean(state, isFalsey(cosmoV_pop(state)));
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_NEGATE: { // pop 1 value off the stack & try to negate
 | 
			
		||||
            CASE(OP_NEGATE) :
 | 
			
		||||
            { // pop 1 value off the stack & try to negate
 | 
			
		||||
                StkPtr val = cosmoV_getTop(state, 0);
 | 
			
		||||
 | 
			
		||||
                if (IS_NUMBER(*val)) {
 | 
			
		||||
@@ -1118,9 +1173,9 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_COUNT: {
 | 
			
		||||
            CASE(OP_COUNT) :
 | 
			
		||||
            {
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0);
 | 
			
		||||
 | 
			
		||||
                if (!IS_REF(*temp)) {
 | 
			
		||||
@@ -1132,16 +1187,16 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                cosmoV_pop(state);
 | 
			
		||||
 | 
			
		||||
                cosmoV_pushNumber(state, count); // pushes the count onto the stack
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_CONCAT: {
 | 
			
		||||
            uint8_t vals = READBYTE();
 | 
			
		||||
            CASE(OP_CONCAT) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t vals = READBYTE(frame);
 | 
			
		||||
                cosmoV_concat(state, vals);
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INCLOCAL: {                // this leaves the value on the stack
 | 
			
		||||
            int8_t inc = READBYTE() - 128; // amount we're incrementing by
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_INCLOCAL) :
 | 
			
		||||
            {                                       // this leaves the value on the stack
 | 
			
		||||
                int8_t inc = READBYTE(frame) - 128; // amount we're incrementing by
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                StkPtr val = &frame->base[indx];
 | 
			
		||||
 | 
			
		||||
                // check that it's a number value
 | 
			
		||||
@@ -1152,12 +1207,11 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INCGLOBAL: {
 | 
			
		||||
            int8_t inc = READBYTE() - 128; // amount we're incrementing by
 | 
			
		||||
            uint16_t indx = READUINT();
 | 
			
		||||
            CASE(OP_INCGLOBAL) :
 | 
			
		||||
            {
 | 
			
		||||
                int8_t inc = READBYTE(frame) - 128; // amount we're incrementing by
 | 
			
		||||
                uint16_t indx = READUINT(frame);
 | 
			
		||||
                CValue ident = constants[indx]; // grabs identifier
 | 
			
		||||
                CValue *val = cosmoT_insert(state, &state->globals->tbl, ident);
 | 
			
		||||
 | 
			
		||||
@@ -1169,12 +1223,11 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INCUPVAL: {
 | 
			
		||||
            int8_t inc = READBYTE() - 128; // amount we're incrementing by
 | 
			
		||||
            uint8_t indx = READBYTE();
 | 
			
		||||
            CASE(OP_INCUPVAL) :
 | 
			
		||||
            {
 | 
			
		||||
                int8_t inc = READBYTE(frame) - 128; // amount we're incrementing by
 | 
			
		||||
                uint8_t indx = READBYTE(frame);
 | 
			
		||||
                CValue *val = frame->closure->upvalues[indx]->val;
 | 
			
		||||
 | 
			
		||||
                // check that it's a number value
 | 
			
		||||
@@ -1185,16 +1238,16 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Expected number, got %s!", cosmoV_typeStr(*val));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INCINDEX: {
 | 
			
		||||
            int8_t inc = READBYTE() - 128;         // amount we're incrementing by
 | 
			
		||||
            CASE(OP_INCINDEX) :
 | 
			
		||||
            {
 | 
			
		||||
                int8_t inc = READBYTE(frame) - 128;    // amount we're incrementing by
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 1); // object should be above the key
 | 
			
		||||
                StkPtr key = cosmoV_getTop(state, 0);  // grabs key
 | 
			
		||||
 | 
			
		||||
                if (!IS_REF(*temp)) {
 | 
			
		||||
                cosmoV_error(state, "Couldn't index non-indexable type %s!", cosmoV_typeStr(*temp));
 | 
			
		||||
                    cosmoV_error(state, "Couldn't index non-indexable type %s!",
 | 
			
		||||
                                 cosmoV_typeStr(*temp));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
@@ -1236,12 +1289,11 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                                 cosmoV_typeStr(*temp));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_INCOBJECT: {
 | 
			
		||||
            int8_t inc = READBYTE() - 128; // amount we're incrementing by
 | 
			
		||||
            uint16_t indx = READUINT();
 | 
			
		||||
            CASE(OP_INCOBJECT) :
 | 
			
		||||
            {
 | 
			
		||||
                int8_t inc = READBYTE(frame) - 128; // amount we're incrementing by
 | 
			
		||||
                uint16_t indx = READUINT(frame);
 | 
			
		||||
                StkPtr temp = cosmoV_getTop(state, 0); // object should be at the top of the stack
 | 
			
		||||
                CValue ident = constants[indx];        // grabs identifier
 | 
			
		||||
 | 
			
		||||
@@ -1270,57 +1322,42 @@ int cosmoV_execute(CState *state)
 | 
			
		||||
                    cosmoV_error(state, "Couldn't set a field on type %s!", cosmoV_typeStr(*temp));
 | 
			
		||||
                    return -1;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_EQUAL: {
 | 
			
		||||
            CASE(OP_EQUAL) :
 | 
			
		||||
            {
 | 
			
		||||
                // pop vals
 | 
			
		||||
                StkPtr valB = cosmoV_pop(state);
 | 
			
		||||
                StkPtr valA = cosmoV_pop(state);
 | 
			
		||||
 | 
			
		||||
                // compare & push
 | 
			
		||||
                cosmoV_pushBoolean(state, cosmoV_equal(state, *valA, *valB));
 | 
			
		||||
            continue;
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GREATER: {
 | 
			
		||||
            NUMBEROP(cosmoV_newBoolean, >)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_GREATER) :
 | 
			
		||||
            {
 | 
			
		||||
                NUMBEROP(cosmoV_newBoolean, >);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_LESS: {
 | 
			
		||||
            NUMBEROP(cosmoV_newBoolean, <)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_LESS) :
 | 
			
		||||
            {
 | 
			
		||||
                NUMBEROP(cosmoV_newBoolean, <);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_GREATER_EQUAL: {
 | 
			
		||||
            NUMBEROP(cosmoV_newBoolean, >=)
 | 
			
		||||
            continue;
 | 
			
		||||
            CASE(OP_GREATER_EQUAL) :
 | 
			
		||||
            {
 | 
			
		||||
                NUMBEROP(cosmoV_newBoolean, >=);
 | 
			
		||||
            }
 | 
			
		||||
        case OP_LESS_EQUAL: {
 | 
			
		||||
            NUMBEROP(cosmoV_newBoolean, <=)
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        case OP_TRUE:
 | 
			
		||||
            cosmoV_pushBoolean(state, true);
 | 
			
		||||
            continue;
 | 
			
		||||
        case OP_FALSE:
 | 
			
		||||
            cosmoV_pushBoolean(state, false);
 | 
			
		||||
            continue;
 | 
			
		||||
        case OP_NIL:
 | 
			
		||||
            cosmoV_pushValue(state, cosmoV_newNil());
 | 
			
		||||
            continue;
 | 
			
		||||
        case OP_RETURN: {
 | 
			
		||||
            uint8_t res = READBYTE();
 | 
			
		||||
            CASE(OP_LESS_EQUAL)
 | 
			
		||||
                : {NUMBEROP(cosmoV_newBoolean, <=)} CASE(OP_TRUE) : cosmoV_pushBoolean(state, true);
 | 
			
		||||
            CASE(OP_FALSE) : cosmoV_pushBoolean(state, false);
 | 
			
		||||
            CASE(OP_NIL) : cosmoV_pushValue(state, cosmoV_newNil());
 | 
			
		||||
            CASE(OP_RETURN) :
 | 
			
		||||
            {
 | 
			
		||||
                uint8_t res = READBYTE(frame);
 | 
			
		||||
                return res;
 | 
			
		||||
            }
 | 
			
		||||
        default:
 | 
			
		||||
            CERROR("unknown opcode!");
 | 
			
		||||
            exit(0);
 | 
			
		||||
            DEFAULT;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#undef READBYTE
 | 
			
		||||
#undef READUINT
 | 
			
		||||
 | 
			
		||||
    // we'll only reach this is state->panic is true
 | 
			
		||||
    // we'll only reach this if state->panic is true
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								src/cvm.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/cvm.h
									
									
									
									
									
								
							@@ -8,6 +8,19 @@
 | 
			
		||||
 | 
			
		||||
// #define VM_DEBUG
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
    if we're using GNUC or clang, we can use computed gotos which speeds up
 | 
			
		||||
    cosmoV_execute by about 20% from benchmarking. of course, if you know
 | 
			
		||||
    your compiler supports computed gotos, you can define VM_JUMPTABLE
 | 
			
		||||
 | 
			
		||||
    BTW: be weary of maliciously crafted cosmo dumps!! it's very easy to crash
 | 
			
		||||
    cosmo with this enabled and reading invalid opcodes due to us just using the
 | 
			
		||||
    opcode as an index into the jump table
 | 
			
		||||
*/
 | 
			
		||||
#if defined(__GNUC__) || defined(__clang__)
 | 
			
		||||
#    define VM_JUMPTABLE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
typedef enum
 | 
			
		||||
{
 | 
			
		||||
    COSMOVM_OK,
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user