Dictionaries -> Tables

Tables are going to become a more generic form of data storage. While objects will be "stateful", tables will remain static.

'{}' now refers to an object declaration, '[]' will be reserved for tables.
This commit is contained in:
CPunch 2021-01-08 14:37:36 -06:00
parent e57c194837
commit 824c0e89b9
9 changed files with 123 additions and 92 deletions

View File

@ -126,7 +126,7 @@ void cosmoB_loadLibrary(CState *state) {
cosmoV_pushString(state, "sub"); cosmoV_pushString(state, "sub");
cosmoV_pushCFunction(state, cosmoB_sSub); cosmoV_pushCFunction(state, cosmoB_sSub);
cosmoV_makeDictionary(state, 1); cosmoV_makeTable(state, 1);
// string. // string.
// register these all to the global table // register these all to the global table
@ -177,7 +177,7 @@ void cosmoB_loadDebug(CState *state) {
cosmoV_pushString(state, "__proto"); // key cosmoV_pushString(state, "__proto"); // key
cosmoV_pushCFunction(state, cosmoB_dgetProto); // value cosmoV_pushCFunction(state, cosmoB_dgetProto); // value
cosmoV_makeDictionary(state, 1); cosmoV_makeTable(state, 1);
// make __setter object // make __setter object
cosmoV_pushString(state, "__setter"); cosmoV_pushString(state, "__setter");
@ -185,7 +185,7 @@ void cosmoB_loadDebug(CState *state) {
cosmoV_pushString(state, "__proto"); cosmoV_pushString(state, "__proto");
cosmoV_pushCFunction(state, cosmoB_dsetProto); cosmoV_pushCFunction(state, cosmoB_dsetProto);
cosmoV_makeDictionary(state, 1); cosmoV_makeTable(state, 1);
// we call makeObject leting it know there are 2 sets of key & value pairs on the stack // we call makeObject leting it know there are 2 sets of key & value pairs on the stack
cosmoV_makeObject(state, 2); cosmoV_makeObject(state, 2);

View File

@ -123,8 +123,8 @@ int disasmInstr(CChunk *chunk, int offset, int indent) {
} }
case OP_CLOSE: case OP_CLOSE:
return simpleInstruction("OP_CLOSE", offset); return simpleInstruction("OP_CLOSE", offset);
case OP_NEWDICT: case OP_NEWTABLE:
return u16OperandInstruction("OP_NEWDICT", chunk, offset); return u16OperandInstruction("OP_NEWTABLE", chunk, offset);
case OP_INDEX: case OP_INDEX:
return simpleInstruction("OP_INDEX", offset); return simpleInstruction("OP_INDEX", offset);
case OP_NEWINDEX: case OP_NEWINDEX:

View File

@ -97,9 +97,9 @@ void blackenObject(CState *state, CObj *obj) {
markTable(state, &cobj->tbl); markTable(state, &cobj->tbl);
break; break;
} }
case COBJ_DICT: { // dictionaries are just wrappers for CTable case COBJ_TABLE: { // tables are just wrappers for CTable
CObjDict *dict = (CObjDict*)obj; CObjTable *tbl = (CObjTable*)obj;
markTable(state, &dict->tbl); markTable(state, &tbl->tbl);
break; break;
} }
case COBJ_UPVALUE: { case COBJ_UPVALUE: {

View File

@ -53,10 +53,10 @@ void cosmoO_free(CState *state, CObj* obj) {
cosmoM_free(state, CObjObject, objTbl); cosmoM_free(state, CObjObject, objTbl);
break; break;
} }
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)obj; CObjTable *tbl = (CObjTable*)obj;
cosmoT_clearTable(state, &dict->tbl); cosmoT_clearTable(state, &tbl->tbl);
cosmoM_free(state, CObjDict, dict); cosmoM_free(state, CObjTable, tbl);
break; break;
} }
case COBJ_UPVALUE: { case COBJ_UPVALUE: {
@ -121,8 +121,8 @@ CObjObject *cosmoO_newObject(CState *state) {
return obj; return obj;
} }
CObjDict *cosmoO_newDictionary(CState *state) { CObjTable *cosmoO_newTable(CState *state) {
CObjDict *obj = (CObjDict*)cosmoO_allocateBase(state, sizeof(CObjDict), COBJ_DICT); CObjTable *obj = (CObjTable*)cosmoO_allocateBase(state, sizeof(CObjTable), COBJ_TABLE);
// init the table (might cause a GC event) // init the table (might cause a GC event)
cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of obj cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of obj
@ -448,9 +448,9 @@ CObjString *cosmoO_toString(CState *state, CObj *obj) {
CObjError *err = (CObjError*)obj; CObjError *err = (CObjError*)obj;
return cosmoV_toString(state, err->err); return cosmoV_toString(state, err->err);
} }
case COBJ_DICT: { case COBJ_TABLE: {
char buf[64]; char buf[64];
int sz = sprintf(buf, "<dict> %p", (void*)obj) + 1; // +1 for the null character int sz = sprintf(buf, "<tbl> %p", (void*)obj) + 1; // +1 for the null character
return cosmoO_copyString(state, buf, sz); return cosmoO_copyString(state, buf, sz);
} }
default: default:
@ -469,9 +469,9 @@ void printObject(CObj *o) {
printf("<obj> %p", (void*)o); printf("<obj> %p", (void*)o);
break; break;
} }
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)o; CObjTable *tbl = (CObjTable*)o;
printf("<dict> %p", (void*)dict); printf("<tbl> %p", (void*)tbl);
break; break;
} }
case COBJ_UPVALUE: { case COBJ_UPVALUE: {
@ -513,7 +513,7 @@ const char *cosmoO_typeStr(CObj* obj) {
switch (obj->type) { switch (obj->type) {
case COBJ_STRING: return "<string>"; case COBJ_STRING: return "<string>";
case COBJ_OBJECT: return "<object>"; case COBJ_OBJECT: return "<object>";
case COBJ_DICT: return "<dictionary>"; case COBJ_TABLE: return "<table>";
case COBJ_FUNCTION: return "<function>"; case COBJ_FUNCTION: return "<function>";
case COBJ_CFUNCTION: return "<c function>"; case COBJ_CFUNCTION: return "<c function>";
case COBJ_METHOD: return "<method>"; case COBJ_METHOD: return "<method>";

View File

@ -6,7 +6,7 @@
typedef enum { typedef enum {
COBJ_STRING, COBJ_STRING,
COBJ_OBJECT, COBJ_OBJECT,
COBJ_DICT, // dictionary COBJ_TABLE,
COBJ_FUNCTION, COBJ_FUNCTION,
COBJ_CFUNCTION, COBJ_CFUNCTION,
COBJ_ERROR, COBJ_ERROR,
@ -67,10 +67,10 @@ typedef struct CObjObject {
}; };
} CObjObject; } CObjObject;
typedef struct CObjDict { // dictionary, a wrapper for CTable typedef struct CObjTable { // table, a wrapper for CTable
CommonHeader; // "is a" CObj CommonHeader; // "is a" CObj
CTable tbl; CTable tbl;
} CObjDict; } CObjTable;
typedef struct CObjFunction { typedef struct CObjFunction {
CommonHeader; // "is a" CObj CommonHeader; // "is a" CObj
@ -111,7 +111,7 @@ typedef struct CObjUpval {
#define IS_STRING(x) isObjType(x, COBJ_STRING) #define IS_STRING(x) isObjType(x, COBJ_STRING)
#define IS_OBJECT(x) isObjType(x, COBJ_OBJECT) #define IS_OBJECT(x) isObjType(x, COBJ_OBJECT)
#define IS_DICT(x) isObjType(x, COBJ_DICT) #define IS_TABLE(x) isObjType(x, COBJ_TABLE)
#define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION) #define IS_FUNCTION(x) isObjType(x, COBJ_FUNCTION)
#define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION) #define IS_CFUNCTION(x) isObjType(x, COBJ_CFUNCTION)
#define IS_METHOD(x) isObjType(x, COBJ_METHOD) #define IS_METHOD(x) isObjType(x, COBJ_METHOD)
@ -139,7 +139,7 @@ void cosmoO_free(CState *state, CObj* obj);
bool cosmoO_equal(CObj* obj1, CObj* obj2); bool cosmoO_equal(CObj* obj1, CObj* obj2);
CObjObject *cosmoO_newObject(CState *state); CObjObject *cosmoO_newObject(CState *state);
CObjDict *cosmoO_newDictionary(CState *state); CObjTable *cosmoO_newTable(CState *state);
CObjFunction *cosmoO_newFunction(CState *state); CObjFunction *cosmoO_newFunction(CState *state);
CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func); CObjCFunction *cosmoO_newCFunction(CState *state, CosmoCFunction func);
CObjError *cosmoO_newError(CState *state, CValue err); CObjError *cosmoO_newError(CState *state, CValue err);

View File

@ -22,7 +22,7 @@ typedef enum {
OP_CALL, // calls top[-uint8_t] expecting uint8_t results OP_CALL, // calls top[-uint8_t] expecting uint8_t results
OP_CLOSURE, OP_CLOSURE,
OP_CLOSE, OP_CLOSE,
OP_NEWDICT, OP_NEWTABLE,
OP_INDEX, OP_INDEX,
OP_NEWINDEX, OP_NEWINDEX,
OP_NEWOBJECT, OP_NEWOBJECT,
@ -45,7 +45,7 @@ typedef enum {
OP_INCLOCAL, // pushes old value to stack, adds (uint8_t-128) to local[uint8_t] OP_INCLOCAL, // pushes old value to stack, adds (uint8_t-128) to local[uint8_t]
OP_INCGLOBAL, // pushes old value to stack, adds (uint8_t-128) to globals[const[uint16_t]] OP_INCGLOBAL, // pushes old value to stack, adds (uint8_t-128) to globals[const[uint16_t]]
OP_INCUPVAL, // pushes old value to stack, adds (uint8_t-128) to closure->upval[uint8_t] OP_INCUPVAL, // pushes old value to stack, adds (uint8_t-128) to closure->upval[uint8_t]
OP_INCINDEX, // pushes old value to stack, adds (uint8_t-128) to dict[pop()] OP_INCINDEX,
OP_INCOBJECT, // pushes old value to stack, adds (uint8_t-128) to obj[const[uint16_t]] OP_INCOBJECT, // pushes old value to stack, adds (uint8_t-128) to obj[const[uint16_t]]
// EQUALITY // EQUALITY

View File

@ -621,6 +621,34 @@ static void call_(CParseState *pstate, bool canAssign, Precedence prec) {
valuePushed(pstate, returnNum); valuePushed(pstate, returnNum);
} }
static void table(CParseState *pstate, bool canAssign, Precedence prec) {
// enter having already consumed '['
int entries = 0;
int tblType = 0; // 0 = we don't know yet / 1 = array-like table / 2 = dictionary-like table
if (!match(pstate, TOKEN_RIGHT_BRACKET)) {
do {
// grab value/key
expression(pstate, 1, true);
// they want to make a table with key:value
if (match(pstate, TOKEN_COLON) && tblType != 1) {
tblType = 2; // dictionary-like
// grab value
expression(pstate, 1, true);
} else if ((check(pstate, TOKEN_COMMA) || check(pstate, TOKEN_RIGHT_BRACKET)) && tblType != 2) {
tblType = 1; // array-like
} else {
error(pstate, "Can't change table description type mid-definition!");
return;
}
entries++;
} while (match(pstate, TOKEN_COMMA));
}
}
static void object(CParseState *pstate, bool canAssign, Precedence prec) { static void object(CParseState *pstate, bool canAssign, Precedence prec) {
// already consumed the beginning '{' // already consumed the beginning '{'
int entries = 0; int entries = 0;
@ -628,22 +656,25 @@ static void object(CParseState *pstate, bool canAssign, Precedence prec) {
if (!match(pstate, TOKEN_RIGHT_BRACE)) { if (!match(pstate, TOKEN_RIGHT_BRACE)) {
do { do {
// parse the key first // parse the key first
expression(pstate, 1, true); // should parse until ':' consume(pstate, TOKEN_IDENTIFIER, "Expected property identifier before '='!");
uint16_t ident = identifierConstant(pstate, &pstate->previous);
writeu8(pstate, OP_LOADCONST);
writeu16(pstate, ident);
consume(pstate, TOKEN_COLON, "Expected ':' to mark end of key and start of value!"); consume(pstate, TOKEN_EQUAL, "Expected '=' to mark the start of value!");
// now, parse the value (until comma) // now, parse the value (until comma)
expression(pstate, 1, true); expression(pstate, 1, true);
// "pop" the 2 values // "pop" the 1 value
valuePopped(pstate, 2); valuePopped(pstate, 1);
entries++; entries++;
} while (match(pstate, TOKEN_COMMA) && !pstate->hadError); } while (match(pstate, TOKEN_COMMA) && !pstate->hadError);
consume(pstate, TOKEN_RIGHT_BRACE, "Expected '}' to end object definition."); consume(pstate, TOKEN_RIGHT_BRACE, "Expected '}' to end object definition.");
} }
writeu8(pstate, OP_NEWDICT); // creates a dictionary with u16 entries writeu8(pstate, OP_NEWOBJECT); // creates a object with u16 entries
writeu16(pstate, entries); writeu16(pstate, entries);
valuePushed(pstate, 1); valuePushed(pstate, 1);
} }
@ -725,7 +756,7 @@ static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIde
break; break;
case 1: // [] case 1: // []
writeu8(pstate, OP_INDEX); // so, that was a normal index, perform that writeu8(pstate, OP_INDEX); // so, that was a normal index, perform that
valuePopped(pstate, 1); // pops the key & dict off the stack, but pushes the value valuePopped(pstate, 1); // pops the key & table off the stack, but pushes the value
break; break;
default: // no previous index default: // no previous index
break; break;
@ -750,7 +781,7 @@ static void walkIndexes(CParseState *pstate, int lastIndexType, uint16_t lastIde
case 1: // [] case 1: // []
writeu8(pstate, OP_INCINDEX); writeu8(pstate, OP_INCINDEX);
writeu8(pstate, 128 + val); writeu8(pstate, 128 + val);
valuePopped(pstate, 2); // popped the dictionary & the key off the stack, but pushes the previous value valuePopped(pstate, 2); // popped the table & the key off the stack, but pushes the previous value
break; break;
default: // no previous index default: // no previous index
break; break;
@ -766,8 +797,8 @@ static void increment(CParseState *pstate, int val) {
// walk the indexes // walk the indexes
walkIndexes(pstate, 0, ident, val); walkIndexes(pstate, 0, ident, val);
} else if (match(pstate, TOKEN_LEFT_BRACKET)) { // dictionary? } else if (match(pstate, TOKEN_LEFT_BRACKET)) { // table?
namedVariable(pstate, name, false, false, 0); // just get the dictionary namedVariable(pstate, name, false, false, 0); // just get the table
// grab key // grab key
expression(pstate, 1, true); expression(pstate, 1, true);
@ -1174,8 +1205,8 @@ static void function(CParseState *pstate, FunctionType type) {
} while (match(pstate, TOKEN_COMMA)); } while (match(pstate, TOKEN_COMMA));
} }
if (match(pstate, TOKEN_DOT_DOT_DOT)) { // marks a function as variadic, now we expect an identifer for the populated variadic dictionary if (match(pstate, TOKEN_DOT_DOT_DOT)) { // marks a function as variadic, now we expect an identifer for the populated variadic table
uint16_t vari = parseVariable(pstate, "Expected identifier for variadic dictionary!", true); uint16_t vari = parseVariable(pstate, "Expected identifier for variadic table!", true);
defineVariable(pstate, vari, true); defineVariable(pstate, vari, true);
valuePushed(pstate, 1); valuePushed(pstate, 1);
compiler.function->variadic = true; compiler.function->variadic = true;
@ -1271,7 +1302,7 @@ static void forEachLoop(CParseState *pstate) {
return; return;
} }
// after we consume the values, get the dictionary/object/whatever on the stack // after we consume the values, get the table/object/whatever on the stack
consume(pstate, TOKEN_IN, "Expected 'in' before iterator!"); consume(pstate, TOKEN_IN, "Expected 'in' before iterator!");
expression(pstate, 1, true); expression(pstate, 1, true);

104
src/cvm.c
View File

@ -225,7 +225,7 @@ static bool callCFunction(CState *state, CosmoCFunction cfunc, int args, int nre
static bool rawCall(CState *state, CObjClosure *closure, int args, int nresults, int offset) { static bool rawCall(CState *state, CObjClosure *closure, int args, int nresults, int offset) {
CObjFunction *func = closure->function; CObjFunction *func = closure->function;
// if the function is variadic and theres more args than parameters, push the args into a dictionary // if the function is variadic and theres more args than parameters, push the args into a table
if (func->variadic && args >= func->args) { if (func->variadic && args >= func->args) {
int extraArgs = args - func->args; int extraArgs = args - func->args;
StkPtr variStart = cosmoV_getTop(state, extraArgs-1); StkPtr variStart = cosmoV_getTop(state, extraArgs-1);
@ -236,8 +236,8 @@ static bool rawCall(CState *state, CObjClosure *closure, int args, int nresults,
cosmoV_pushValue(state, *(variStart + i)); cosmoV_pushValue(state, *(variStart + i));
} }
cosmoV_makeDictionary(state, extraArgs); cosmoV_makeTable(state, extraArgs);
*variStart = *cosmoV_getTop(state, 0); // move dict on the stack to the vari local *variStart = *cosmoV_getTop(state, 0); // move table on the stack to the vari local
state->top -= extraArgs; state->top -= extraArgs;
pushCallFrame(state, closure, func->args + 1); pushCallFrame(state, closure, func->args + 1);
@ -390,10 +390,10 @@ COSMO_API void cosmoV_makeObject(CState *state, int pairs) {
cosmoV_pushValue(state, cosmoV_newObj(newObj)); cosmoV_pushValue(state, cosmoV_newObj(newObj));
} }
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs) { COSMO_API void cosmoV_makeTable(CState *state, int pairs) {
StkPtr key, val; StkPtr key, val;
CObjDict *newObj = cosmoO_newDictionary(state); CObjTable *newObj = cosmoO_newTable(state);
cosmoV_pushValue(state, cosmoV_newObj(newObj)); // so our GC doesn't free our new dictionary cosmoV_pushValue(state, cosmoV_newObj(newObj)); // so our GC doesn't free our new table
for (int i = 0; i < pairs; i++) { for (int i = 0; i < pairs; i++) {
val = cosmoV_getTop(state, (i*2) + 1); val = cosmoV_getTop(state, (i*2) + 1);
@ -404,8 +404,8 @@ COSMO_API void cosmoV_makeDictionary(CState *state, int pairs) {
*newVal = *val; *newVal = *val;
} }
// once done, pop everything off the stack + push new dictionary // once done, pop everything off the stack + push new table
cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our dictionary cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our table
cosmoV_pushValue(state, cosmoV_newObj(newObj)); cosmoV_pushValue(state, cosmoV_newObj(newObj));
} }
@ -449,7 +449,7 @@ COSMO_API bool cosmoV_set(CState *state, CObj *_obj, CValue key, CValue val) {
return true; return true;
} }
int _dict__next(CState *state, int nargs, CValue *args) { int _tbl__next(CState *state, int nargs, CValue *args) {
if (nargs != 1) { if (nargs != 1) {
cosmoV_error(state, "Expected 1 parameter, %d received!", nargs); cosmoV_error(state, "Expected 1 parameter, %d received!", nargs);
return 0; return 0;
@ -466,17 +466,17 @@ int _dict__next(CState *state, int nargs, CValue *args) {
cosmoO_getIString(state, obj, ISTRING_RESERVED, &val); cosmoO_getIString(state, obj, ISTRING_RESERVED, &val);
if (!IS_DICT(val)) { if (!IS_TABLE(val)) {
return 0; // someone set the __reserved member to something else. this will exit the iterator loop return 0; // someone set the __reserved member to something else. this will exit the iterator loop
} }
CObjDict *dict = (CObjDict*)cosmoV_readObj(val); CObjTable *table = (CObjTable*)cosmoV_readObj(val);
// while the entry is invalid, go to the next entry // while the entry is invalid, go to the next entry
CTableEntry *entry; CTableEntry *entry;
do { do {
entry = &dict->tbl.table[index++]; entry = &table->tbl.table[index++];
} while (IS_NIL(entry->key) && index < dict->tbl.capacity); } while (IS_NIL(entry->key) && index < table->tbl.capacity);
cosmoO_setUserI(state, obj, index); // update the userdata cosmoO_setUserI(state, obj, index); // update the userdata
if (!IS_NIL(entry->key)) { // if the entry is valid, return it's key and value pair if (!IS_NIL(entry->key)) { // if the entry is valid, return it's key and value pair
@ -614,24 +614,24 @@ int cosmoV_execute(CState *state) {
cosmoV_pop(state); cosmoV_pop(state);
break; break;
} }
case OP_NEWDICT: { case OP_NEWTABLE: {
uint16_t pairs = READUINT(); uint16_t pairs = READUINT();
cosmoV_makeDictionary(state, pairs); cosmoV_makeTable(state, pairs);
break; break;
} }
case OP_INDEX: { case OP_INDEX: {
StkPtr key = cosmoV_getTop(state, 0); // key should be the top of the stack 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 dictionary StkPtr temp = cosmoV_getTop(state, 1); // after that should be the table
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
CValue val; // to hold our value CValue val; // to hold our value
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
cosmoT_get(&dict->tbl, *key, &val); cosmoT_get(&tbl->tbl, *key, &val);
break; break;
} }
default: { // check for __index metamethod default: { // check for __index metamethod
@ -665,9 +665,9 @@ int cosmoV_execute(CState *state) {
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { // index and set table case COBJ_TABLE: { // index and set table
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
CValue *newVal = cosmoT_insert(state, &dict->tbl, *key); CValue *newVal = cosmoT_insert(state, &tbl->tbl, *key);
*newVal = *value; // set the index *newVal = *value; // set the index
break; break;
@ -709,10 +709,10 @@ int cosmoV_execute(CState *state) {
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { // syntax sugar, makes "namespaces" possible case COBJ_TABLE: { // syntax sugar, makes "namespaces" possible
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
cosmoT_get(&dict->tbl, constants[ident], &val); cosmoT_get(&tbl->tbl, constants[ident], &val);
break; break;
} }
default: default:
@ -736,9 +736,9 @@ int cosmoV_execute(CState *state) {
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { // index and set the table case COBJ_TABLE: { // index and set the table
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
CValue *newVal = cosmoT_insert(state, &dict->tbl, constants[ident]); CValue *newVal = cosmoT_insert(state, &tbl->tbl, constants[ident]);
*newVal = *value; // set the index *newVal = *value; // set the index
break; break;
@ -757,19 +757,19 @@ int cosmoV_execute(CState *state) {
break; 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! 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!
CValue val; // to hold our value
uint8_t args = READBYTE(); uint8_t args = READBYTE();
uint8_t nres = READBYTE(); uint8_t nres = READBYTE();
uint16_t ident = READUINT(); uint16_t ident = READUINT();
StkPtr temp = cosmoV_getTop(state, args); // grabs object from stack StkPtr temp = cosmoV_getTop(state, args); // grabs object from stack
CValue val; // to hold our value
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { // again, syntax sugar ("""""namespaces""""") case COBJ_TABLE: { // again, syntax sugar ("""""namespaces""""")
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
cosmoT_get(&dict->tbl, constants[ident], &val); cosmoT_get(&tbl->tbl, constants[ident], &val);
// call closure/cfunction // call closure/cfunction
if (!callCValue(state, val, args, nres, 0)) if (!callCValue(state, val, args, nres, 0))
@ -799,7 +799,7 @@ int cosmoV_execute(CState *state) {
break; break;
} }
case OP_ITER: { case OP_ITER: {
StkPtr temp = cosmoV_getTop(state, 0); // should be the object/dictionary StkPtr temp = cosmoV_getTop(state, 0); // should be the object/table
if (!IS_OBJ(*temp)) { if (!IS_OBJ(*temp)) {
cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Couldn't iterate over non-iterator type %s!", cosmoV_typeStr(*temp));
@ -808,15 +808,15 @@ int cosmoV_execute(CState *state) {
CObj *obj = cosmoV_readObj(*temp); CObj *obj = cosmoV_readObj(*temp);
switch (obj->type) { switch (obj->type) {
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)obj; CObjTable *tbl = (CObjTable*)obj;
cosmoV_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key cosmoV_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key
cosmoV_pushValue(state, cosmoV_newObj(dict)); // value cosmoV_pushValue(state, cosmoV_newObj(tbl)); // value
cosmoV_pushString(state, "__next"); // key cosmoV_pushString(state, "__next"); // key
CObjCFunction *dict_next = cosmoO_newCFunction(state, _dict__next); CObjCFunction *tbl_next = cosmoO_newCFunction(state, _tbl__next);
cosmoV_pushValue(state, cosmoV_newObj(dict_next)); // value cosmoV_pushValue(state, cosmoV_newObj(tbl_next)); // value
cosmoV_makeObject(state, 2); // pushes the new object to the stack cosmoV_makeObject(state, 2); // pushes the new object to the stack
@ -824,9 +824,9 @@ int cosmoV_execute(CState *state) {
cosmoO_setUserI(state, obj, 0); // increment for iterator cosmoO_setUserI(state, obj, 0); // increment for iterator
// make our CObjMethod for OP_NEXT to call // make our CObjMethod for OP_NEXT to call
CObjMethod *method = cosmoO_newMethod(state, cosmoV_newObj(dict_next), (CObj*)obj); CObjMethod *method = cosmoO_newMethod(state, cosmoV_newObj(tbl_next), (CObj*)obj);
cosmoV_setTop(state, 2); // pops the object & the dict cosmoV_setTop(state, 2); // pops the object & the tbl
cosmoV_pushValue(state, cosmoV_newObj(method)); // pushes the method for OP_NEXT cosmoV_pushValue(state, cosmoV_newObj(method)); // pushes the method for OP_NEXT
break; break;
} }
@ -930,17 +930,17 @@ int cosmoV_execute(CState *state) {
} }
break; break;
} }
case OP_COUNT: { // pop 1 value off the stack & if it's a dictionary return the amount of active entries it has case OP_COUNT: { // pop 1 value off the stack & if it's a table return the amount of active entries it has
StkPtr temp = cosmoV_getTop(state, 0); StkPtr temp = cosmoV_getTop(state, 0);
if (!IS_OBJ(*temp) || cosmoV_readObj(*temp)->type != COBJ_DICT) { if (!IS_OBJ(*temp) || cosmoV_readObj(*temp)->type != COBJ_TABLE) {
cosmoV_error(state, "Expected object, got %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Expected object, got %s!", cosmoV_typeStr(*temp));
return -1; return -1;
} }
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
cosmoV_pop(state); cosmoV_pop(state);
cosmoV_pushNumber(state, cosmoT_count(&dict->tbl)); // pushes the count onto the stack cosmoV_pushNumber(state, cosmoT_count(&tbl->tbl)); // pushes the count onto the stack
break; break;
} }
case OP_CONCAT: { case OP_CONCAT: {
@ -1004,11 +1004,11 @@ int cosmoV_execute(CState *state) {
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
CValue *val = cosmoT_insert(state, &dict->tbl, *key); CValue *val = cosmoT_insert(state, &tbl->tbl, *key);
// pops dict & key from stack // pops tbl & key from stack
cosmoV_setTop(state, 2); cosmoV_setTop(state, 2);
if (IS_NUMBER(*val)) { if (IS_NUMBER(*val)) {
@ -1063,11 +1063,11 @@ int cosmoV_execute(CState *state) {
// sanity check // sanity check
if (IS_OBJ(*temp)) { if (IS_OBJ(*temp)) {
switch (cosmoV_readObj(*temp)->type) { switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: { case COBJ_TABLE: {
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp); CObjTable *tbl = (CObjTable*)cosmoV_readObj(*temp);
CValue *val = cosmoT_insert(state, &dict->tbl, ident); CValue *val = cosmoT_insert(state, &tbl->tbl, ident);
// pops dict from stack // pops tbl from stack
cosmoV_pop(state); cosmoV_pop(state);
if (IS_NUMBER(*val)) { if (IS_NUMBER(*val)) {

View File

@ -16,7 +16,7 @@ typedef enum {
COSMO_API COSMOVMRESULT cosmoV_call(CState *state, int args, int nresults); COSMO_API COSMOVMRESULT cosmoV_call(CState *state, int args, int nresults);
COSMO_API COSMOVMRESULT cosmoV_pcall(CState *state, int args, int nresults); COSMO_API COSMOVMRESULT cosmoV_pcall(CState *state, int args, int nresults);
COSMO_API void cosmoV_makeObject(CState *state, int pairs); COSMO_API void cosmoV_makeObject(CState *state, int pairs);
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs); COSMO_API void cosmoV_makeTable(CState *state, int pairs);
COSMO_API void cosmoV_concat(CState *state, int vals); COSMO_API void cosmoV_concat(CState *state, int vals);
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...); COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
COSMO_API void cosmoV_printError(CState *state, CObjError *err); COSMO_API void cosmoV_printError(CState *state, CObjError *err);