Added dictionary support to OP_ITER

ISTRING_RESERVED was added to iStrings
call & callCFunction now use memmove instead of memcpy
Additionally, added cosmoO_setUserP, cosmoO_getUserP, cosmoO_setUserI and cosmoO_getUserI to the C API.
This commit is contained in:
CPunch 2020-12-17 19:44:04 -06:00
parent b2c1f73e01
commit 0beeee0fdf
7 changed files with 105 additions and 17 deletions

View File

@ -8,4 +8,4 @@ end
for (var i = 1; i < 40; i++) do
print("The fib number of " .. i .. " is " .. fib(i))
end
end

View File

@ -15,6 +15,20 @@ proto Vector
function __index(self, key)
return self.vector[key]
end
function __iter(self)
self.iterIndex = 0
return self
end
function __next(self)
if self.iterIndex > self.x then
return nil
end
return vector[self.iterIndex++]
end
end
var vector = Vector()
@ -23,6 +37,6 @@ for (var i = 0; i < 100000; i++) do
vector.push(i)
end
for (var i = 0; i < 100000; i++) do
print(vector.pop() .. " : " .. vector[i])
for i in vector do
print(i)
end

View File

@ -105,7 +105,7 @@ CObjObject *cosmoO_newObject(CState *state) {
CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT);
obj->proto = state->protoObj;
obj->istringFlags = 0;
obj->user = NULL; // reserved for C API
obj->userP = NULL; // reserved for C API
cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of it
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
cosmoV_pop(state);
@ -266,12 +266,20 @@ void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val)
}
}
void cosmoO_setUserData(CState *state, CObjObject *object, void *p) {
object->user = p;
void cosmoO_setUserP(CState *state, CObjObject *object, void *p) {
object->userP = p;
}
void *cosmoO_getUserData(CState *state, CObjObject *object) {
return object->user;
void *cosmoO_getUserP(CState *state, CObjObject *object) {
return object->userP;
}
void cosmoO_setUserI(CState *state, CObjObject *object, int i) {
object->userI = i;
}
int cosmoO_getUserI(CState *state, CObjObject *object) {
return object->userI;
}
bool rawgetIString(CState *state, CObjObject *object, int flag, CValue *val) {

View File

@ -47,7 +47,10 @@ typedef struct CObjObject {
CommonHeader; // "is a" CObj
cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.)
CTable tbl;
void *user; // userdata (NULL by default)
union { // userdata (NULL by default)
void *userP;
int userI;
};
struct CObjObject *proto; // protoobject, describes the behavior of the object
} CObjObject;
@ -136,8 +139,10 @@ void cosmoO_setObject(CState *state, CObjObject *object, CValue key, CValue val)
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue val);
void cosmoO_setUserData(CState *state, CObjObject *object, void *p);
void *cosmoO_getUserData(CState *state, CObjObject *object);
void cosmoO_setUserP(CState *state, CObjObject *object, void *p);
void *cosmoO_getUserP(CState *state, CObjObject *object);
void cosmoO_setUserI(CState *state, CObjObject *object, int i);
int cosmoO_getUserI(CState *state, CObjObject *object);
// internal string
bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val);

View File

@ -53,6 +53,9 @@ CState *cosmoV_newState() {
state->iStrings[ISTRING_ITER] = cosmoO_copyString(state, "__iter", 6);
state->iStrings[ISTRING_NEXT] = cosmoO_copyString(state, "__next", 6);
// for reserved members for objects
state->iStrings[ISTRING_RESERVED] = cosmoO_copyString(state, "__reserved", 10);
// set the IString flags
for (int i = 0; i < ISTRING_MAX; i++)
state->iStrings[i]->isIString = true;

View File

@ -20,6 +20,7 @@ typedef enum IStringEnum {
ISTRING_SETTER, // __setter
ISTRING_ITER, // __iter
ISTRING_NEXT, // __next
ISTRING_RESERVED, // __reserved
ISTRING_MAX
} IStringEnum;

View File

@ -126,7 +126,7 @@ static inline void callCFunction(CState *state, CosmoCFunction cfunc, int args,
state->top = savedBase + offset; // set stack
// push the return value back onto the stack
memcpy(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
memmove(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
state->top += nres; // and make sure to move state->top to match
// now, if the caller function expected more return values, push nils onto the stack
@ -159,7 +159,7 @@ bool call(CState *state, CObjClosure *closure, int args, int nresults, int offse
popCallFrame(state, offset);
// push the return value back onto the stack
memcpy(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
memmove(state->top, results, sizeof(CValue) * nres); // copies the return values to the top of the stack
state->top += nres; // and make sure to move state->top to match
// now, if the caller function expected more return values, push nils onto the stack
@ -285,6 +285,7 @@ COSMO_API void cosmoV_makeDictionary(CState *state, int pairs) {
}
COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, CValue *val) {
cosmoV_pushValue(state, cosmoV_newObj(object));
if (cosmoO_getObject(state, object, key, val)) {
if (IS_OBJ(*val)) {
if (cosmoV_readObj(*val)->type == COBJ_CLOSURE) { // is it a function? if so, make it a method to the current object
@ -296,12 +297,53 @@ COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, C
}
}
cosmoV_pop(state);
return true;
}
cosmoV_pop(state);
return false;
}
int _dict__next(CState *state, int nargs, CValue *args) {
if (nargs != 1) {
cosmoV_error(state, "Expected 1 parameter, %d received!", nargs);
return 0;
}
if (!IS_OBJECT(args[0])) {
cosmoV_error(state, "Expected iterable object, %s received!", cosmoV_typeStr(args[0]));
return 0;
}
CObjObject *obj = cosmoV_readObject(args[0]);
int index = cosmoO_getUserI(state, obj); // we store the index in the userdata
CValue val;
cosmoO_getIString(state, obj, ISTRING_RESERVED, &val);
if (!IS_DICT(val)) {
return 0; // someone set the __reserved member to something else. this will exit the iterator loop
}
CObjDict *dict = (CObjDict*)cosmoV_readObj(val);
// while the entry is invalid, go to the next entry
CTableEntry *entry;
do {
entry = &dict->tbl.table[index++];
} while (IS_NIL(entry->key) && index < dict->tbl.capacity);
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
cosmoV_pushValue(state, entry->key);
cosmoV_pushValue(state, entry->val);
return 2; // we pushed 2 values onto the stack for the return values
} else {
return 0; // we have nothing to return, this should exit the iterator loop
}
}
#define NUMBEROP(typeConst, op) \
StkPtr valA = cosmoV_getTop(state, 1); \
StkPtr valB = cosmoV_getTop(state, 0); \
@ -564,14 +606,29 @@ int cosmoV_execute(CState *state) {
switch (cosmoV_readObj(*temp)->type) {
case COBJ_DICT: {
//CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
CObjDict *dict = (CObjDict*)cosmoV_readObj(*temp);
// TODO: add cosmoV_makeIter, which will make a dummy iterable object for dictionaries
cosmoV_error(state, "unimpl. mass ping cpunch!!!!");
cosmoV_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key
cosmoV_pushValue(state, cosmoV_newObj(dict)); // value
cosmoV_pushLString(state, "__next", 6); // key
CObjCFunction *dict_next = cosmoO_newCFunction(state, _dict__next);
cosmoV_pushValue(state, cosmoV_newObj(dict_next)); // value
cosmoV_makeObject(state, 2); // pushes the new object to the stack
CObjObject *obj = cosmoV_readObject(*(cosmoV_getTop(state, 0)));
cosmoO_setUserI(state, obj, 0); // increment for iterator
// make our CObjMethod for OP_NEXT to call
CObjMethod *method = cosmoO_newCMethod(state, dict_next, obj);
cosmoV_setTop(state, 2); // pops the object & the dict
cosmoV_pushValue(state, cosmoV_newObj(method)); // pushes the method for OP_NEXT
break;
}
case COBJ_OBJECT: {
CObjObject *obj = (CObjObject*)cosmoV_readObj(*temp);
CObjObject *obj = cosmoV_readObject(*temp);
CValue val;
// grab __iter & call it