mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 00:00:10 +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
|
for (var i = 1; i < 40; i++) do
|
||||||
print("The fib number of " .. i .. " is " .. fib(i))
|
print("The fib number of " .. i .. " is " .. fib(i))
|
||||||
end
|
end
|
@ -15,6 +15,20 @@ proto Vector
|
|||||||
function __index(self, key)
|
function __index(self, key)
|
||||||
return self.vector[key]
|
return self.vector[key]
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
var vector = Vector()
|
var vector = Vector()
|
||||||
@ -23,6 +37,6 @@ for (var i = 0; i < 100000; i++) do
|
|||||||
vector.push(i)
|
vector.push(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
for (var i = 0; i < 100000; i++) do
|
for i in vector do
|
||||||
print(vector.pop() .. " : " .. vector[i])
|
print(i)
|
||||||
end
|
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);
|
CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT);
|
||||||
obj->proto = state->protoObj;
|
obj->proto = state->protoObj;
|
||||||
obj->istringFlags = 0;
|
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
|
cosmoV_pushValue(state, cosmoV_newObj(obj)); // so our GC can keep track of it
|
||||||
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
|
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
|
||||||
cosmoV_pop(state);
|
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) {
|
void cosmoO_setUserP(CState *state, CObjObject *object, void *p) {
|
||||||
object->user = p;
|
object->userP = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *cosmoO_getUserData(CState *state, CObjObject *object) {
|
void *cosmoO_getUserP(CState *state, CObjObject *object) {
|
||||||
return object->user;
|
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) {
|
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
|
CommonHeader; // "is a" CObj
|
||||||
cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.)
|
cosmo_Flag istringFlags; // enables us to have a much faster lookup for reserved IStrings (like __init, __index, etc.)
|
||||||
CTable tbl;
|
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
|
struct CObjObject *proto; // protoobject, describes the behavior of the object
|
||||||
} CObjObject;
|
} 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_indexObject(CState *state, CObjObject *object, CValue key, CValue *val);
|
||||||
bool cosmoO_newIndexObject(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_setUserP(CState *state, CObjObject *object, void *p);
|
||||||
void *cosmoO_getUserData(CState *state, CObjObject *object);
|
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
|
// internal string
|
||||||
bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val);
|
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_ITER] = cosmoO_copyString(state, "__iter", 6);
|
||||||
state->iStrings[ISTRING_NEXT] = cosmoO_copyString(state, "__next", 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
|
// set the IString flags
|
||||||
for (int i = 0; i < ISTRING_MAX; i++)
|
for (int i = 0; i < ISTRING_MAX; i++)
|
||||||
state->iStrings[i]->isIString = true;
|
state->iStrings[i]->isIString = true;
|
||||||
|
@ -20,6 +20,7 @@ typedef enum IStringEnum {
|
|||||||
ISTRING_SETTER, // __setter
|
ISTRING_SETTER, // __setter
|
||||||
ISTRING_ITER, // __iter
|
ISTRING_ITER, // __iter
|
||||||
ISTRING_NEXT, // __next
|
ISTRING_NEXT, // __next
|
||||||
|
ISTRING_RESERVED, // __reserved
|
||||||
ISTRING_MAX
|
ISTRING_MAX
|
||||||
} IStringEnum;
|
} 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
|
state->top = savedBase + offset; // set stack
|
||||||
|
|
||||||
// push the return value back onto the 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
|
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
|
// 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);
|
popCallFrame(state, offset);
|
||||||
|
|
||||||
// push the return value back onto the 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
|
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
|
// 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) {
|
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 (cosmoO_getObject(state, object, key, val)) {
|
||||||
if (IS_OBJ(*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
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cosmoV_pop(state);
|
||||||
return false;
|
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) \
|
#define NUMBEROP(typeConst, op) \
|
||||||
StkPtr valA = cosmoV_getTop(state, 1); \
|
StkPtr valA = cosmoV_getTop(state, 1); \
|
||||||
StkPtr valB = cosmoV_getTop(state, 0); \
|
StkPtr valB = cosmoV_getTop(state, 0); \
|
||||||
@ -564,14 +606,29 @@ int cosmoV_execute(CState *state) {
|
|||||||
|
|
||||||
switch (cosmoV_readObj(*temp)->type) {
|
switch (cosmoV_readObj(*temp)->type) {
|
||||||
case COBJ_DICT: {
|
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_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key
|
||||||
cosmoV_error(state, "unimpl. mass ping cpunch!!!!");
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case COBJ_OBJECT: {
|
case COBJ_OBJECT: {
|
||||||
CObjObject *obj = (CObjObject*)cosmoV_readObj(*temp);
|
CObjObject *obj = cosmoV_readObject(*temp);
|
||||||
CValue val;
|
CValue val;
|
||||||
|
|
||||||
// grab __iter & call it
|
// grab __iter & call it
|
||||||
|
Loading…
Reference in New Issue
Block a user