mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-21 23:10:05 +00:00
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:
parent
b2c1f73e01
commit
0beeee0fdf
@ -8,4 +8,4 @@ end
|
||||
|
||||
for (var i = 1; i < 40; i++) do
|
||||
print("The fib number of " .. i .. " is " .. fib(i))
|
||||
end
|
||||
end
|
@ -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
|
18
src/cobj.c
18
src/cobj.c
@ -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) {
|
||||
|
11
src/cobj.h
11
src/cobj.h
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -20,6 +20,7 @@ typedef enum IStringEnum {
|
||||
ISTRING_SETTER, // __setter
|
||||
ISTRING_ITER, // __iter
|
||||
ISTRING_NEXT, // __next
|
||||
ISTRING_RESERVED, // __reserved
|
||||
ISTRING_MAX
|
||||
} IStringEnum;
|
||||
|
||||
|
69
src/cvm.c
69
src/cvm.c
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user