diff --git a/src/cdebug.c b/src/cdebug.c index 459c602..bac9e64 100644 --- a/src/cdebug.c +++ b/src/cdebug.c @@ -127,9 +127,9 @@ int disasmInstr(CChunk *chunk, int offset, int indent) { case OP_NEWOBJECT: return u16OperandInstruction("OP_NEWOBJECT", chunk, offset); case OP_GETOBJECT: - return simpleInstruction("OP_GETOBJECT", offset); + return constInstruction("OP_GETOBJECT", chunk, offset); case OP_SETOBJECT: - return simpleInstruction("OP_SETOBJECT", offset); + return constInstruction("OP_SETOBJECT", chunk, offset); case OP_INVOKE: return u8u8OperandInstruction("OP_INVOKE", chunk, offset); case OP_ITER: diff --git a/src/cparse.c b/src/cparse.c index 100f8c7..1298c4d 100644 --- a/src/cparse.c +++ b/src/cparse.c @@ -653,11 +653,11 @@ static void dot(CParseState *pstate, bool canAssign, Precedence prec) { uint16_t name = identifierConstant(pstate, &pstate->previous); if (canAssign && match(pstate, TOKEN_EQUAL)) { - writeu8(pstate, OP_LOADCONST); - writeu16(pstate, name); expression(pstate, 1, true); + writeu8(pstate, OP_SETOBJECT); - valuePopped(pstate, 2); // pops key, value & object + writeu16(pstate, name); + valuePopped(pstate, 2); // value & object } else if (match(pstate, TOKEN_PLUS_PLUS)) { // increment the field writeu8(pstate, OP_INCOBJECT); writeu8(pstate, 128 + 1); @@ -676,9 +676,8 @@ static void dot(CParseState *pstate, bool canAssign, Precedence prec) { valuePopped(pstate, args+1); // args + function valuePushed(pstate, pstate->compiler->expectedValues); } else { - writeu8(pstate, OP_LOADCONST); - writeu16(pstate, name); writeu8(pstate, OP_GETOBJECT); + writeu16(pstate, name); // pops key & object but also pushes the field so total popped is 1 } } @@ -705,6 +704,7 @@ static void _index(CParseState *pstate, bool canAssign, Precedence prec) { } // ++test.field[1] +// this function is kind of spaghetti, feel free to rewrite (if you dare!) static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIdent, int val) { uint16_t ident = lastIdent; int indexType = lastIndexType; @@ -721,9 +721,8 @@ static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIde switch (lastIndexType) { case 0: // . - writeu8(pstate, OP_LOADCONST); // pushes ident to stack - writeu16(pstate, lastIdent); writeu8(pstate, OP_GETOBJECT); // grabs property + writeu16(pstate, lastIdent); break; case 1: // [] writeu8(pstate, OP_INDEX); // so, that was a normal index, perform that @@ -1279,7 +1278,7 @@ static void forEachLoop(CParseState *pstate) { consume(pstate, TOKEN_DO, "Expected 'do' before loop block!"); - writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and pushes the __next method onto the stack for OP_NEXT to call + writeu8(pstate, OP_ITER); // checks if stack[top] is iterable and pushes the __next metamethod onto the stack for OP_NEXT to call // start loop scope LoopState cachedLoop = pstate->compiler->loop; @@ -1434,6 +1433,7 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec parsePrecedence(pstate, prec); + // make sure we're returning with the expected values they needed on the stack if (pstate->compiler->pushedValues > saved) { writePop(pstate, pstate->compiler->pushedValues - saved); valuePopped(pstate, pstate->compiler->pushedValues - saved); @@ -1442,7 +1442,6 @@ static int expressionPrecedence(CParseState *pstate, int needed, Precedence prec } pstate->compiler->expectedValues = lastExpected; - return pstate->compiler->pushedValues - (saved - needed); } diff --git a/src/ctable.c b/src/ctable.c index 794948a..867432a 100644 --- a/src/ctable.c +++ b/src/ctable.c @@ -185,14 +185,16 @@ COSMO_API CValue* cosmoT_insert(CState *state, CTable *tbl, CValue key) { } bool cosmoT_get(CTable *tbl, CValue key, CValue *val) { + // sanity check if (tbl->count == 0) { *val = cosmoV_newNil(); - return false; // sanity check + return false; } CTableEntry *entry = findEntry(tbl->table, tbl->capacity - 1, key); *val = entry->val; + // return if get was successful return !(IS_NIL(entry->key)); } diff --git a/src/ctable.h b/src/ctable.h index 5a88b17..02857e9 100644 --- a/src/ctable.h +++ b/src/ctable.h @@ -19,11 +19,12 @@ typedef struct CTable { COSMO_API void cosmoT_initTable(CState *state, CTable *tbl, int startCap); COSMO_API void cosmoT_clearTable(CState *state, CTable *tbl); COSMO_API void cosmoT_addTable(CState *state, CTable *from, CTable *to); -COSMO_API CValue *cosmoT_insert(CState *state, CTable *tbl, CValue key); COSMO_API int cosmoT_count(CTable *tbl); -CObjString *cosmoT_lookupString(CTable *tbl, const char *str, int length, uint32_t hash); bool cosmoT_checkShrink(CState *state, CTable *tbl); + +CObjString *cosmoT_lookupString(CTable *tbl, const char *str, int length, uint32_t hash); +COSMO_API CValue *cosmoT_insert(CState *state, CTable *tbl, CValue key); bool cosmoT_get(CTable *tbl, CValue key, CValue *val); bool cosmoT_remove(CState *state, CTable *tbl, CValue key); diff --git a/src/cvm.c b/src/cvm.c index 257035b..c1cc6c2 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -680,8 +680,8 @@ int cosmoV_execute(CState *state) { } case OP_GETOBJECT: { CValue val; // to hold our value - 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 object + StkPtr temp = cosmoV_getTop(state, 0); // that should be the object + uint16_t ident = READUINT(); // use for the key // sanity check if (IS_OBJ(*temp)) { @@ -689,13 +689,13 @@ int cosmoV_execute(CState *state) { case COBJ_DICT: { // syntax sugar, makes "namespaces" possible CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); - cosmoT_get(&dict->tbl, *key, &val); + cosmoT_get(&dict->tbl, constants[ident], &val); break; } case COBJ_OBJECT: { CObjObject *object = (CObjObject*)cosmoV_readObj(*temp); - cosmoV_getObject(state, object, *key, &val); + cosmoV_getObject(state, object, constants[ident], &val); break; } default: @@ -707,21 +707,21 @@ int cosmoV_execute(CState *state) { return -1; } - cosmoV_setTop(state, 2); // pops the object & the key + cosmoV_setTop(state, 1); // pops the object cosmoV_pushValue(state, val); // pushes the field result break; } case OP_SETOBJECT: { 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); // object is after the key + StkPtr temp = cosmoV_getTop(state, 1); // object is after the value + uint16_t ident = READUINT(); // use for the key // sanity check if (IS_OBJ(*temp)) { switch (cosmoV_readObj(*temp)->type) { case COBJ_DICT: { // index and set the table CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); - CValue *newVal = cosmoT_insert(state, &dict->tbl, *key); + CValue *newVal = cosmoT_insert(state, &dict->tbl, constants[ident]); *newVal = *value; // set the index break; @@ -729,7 +729,7 @@ int cosmoV_execute(CState *state) { case COBJ_OBJECT: { CObjObject *object = (CObjObject*)cosmoV_readObj(*temp); - cosmoO_setRawObject(state, object, *key, *value); + cosmoO_setRawObject(state, object, constants[ident], *value); break; } default: @@ -742,7 +742,7 @@ int cosmoV_execute(CState *state) { } // pop everything off the stack - cosmoV_setTop(state, 3); + cosmoV_setTop(state, 2); break; } case OP_INVOKE: { // this is an optimization made by the parser, instead of allocating a CObjMethod every time we want to invoke a method, we shrink it down into one minimal instruction!