mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-05 08:10:05 +00:00
Minor refactor, added vm.* library
- cosmoV_pushObj() has been added - cbaselib.h has been cleaned up a bit
This commit is contained in:
parent
0be6e7dff1
commit
cd6744ab65
@ -75,7 +75,7 @@ int cosmoB_tostring(CState *state, int nargs, CValue *args) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(cosmoV_toString(state, args[0])));
|
cosmoV_pushObj(state, (CObj*)cosmoV_toString(state, args[0]));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,11 +303,10 @@ void cosmoB_loadStrLib(CState *state) {
|
|||||||
cosmoV_pushString(state, identifiers[i]);
|
cosmoV_pushString(state, identifiers[i]);
|
||||||
cosmoV_pushCFunction(state, strLib[i]);
|
cosmoV_pushCFunction(state, strLib[i]);
|
||||||
}
|
}
|
||||||
cosmoV_makeObject(state, i);
|
|
||||||
|
|
||||||
// grab the object from the stack and set the base protoObject
|
// make the object and set the protoobject for all strings
|
||||||
StkPtr obj = cosmoV_getTop(state, 0);
|
CObjObject *obj = cosmoV_makeObject(state, i);
|
||||||
state->protoObjects[COBJ_STRING] = cosmoV_readObject(*obj);
|
cosmoV_registerProtoObject(state, COBJ_STRING, obj);
|
||||||
|
|
||||||
// register "string" to the global table
|
// register "string" to the global table
|
||||||
cosmoV_register(state, 1);
|
cosmoV_register(state, 1);
|
||||||
@ -322,7 +321,7 @@ int cosmoB_dsetProto(CState *state, int nargs, CValue *args) {
|
|||||||
|
|
||||||
obj->proto = proto; // boom done
|
obj->proto = proto; // boom done
|
||||||
} else {
|
} else {
|
||||||
cosmoV_error(state, "Expected 2 parameters, got %d!", nargs);
|
cosmoV_error(state, "Expected 2 arguments, got %d!", nargs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0; // nothing
|
return 0; // nothing
|
||||||
@ -331,13 +330,63 @@ int cosmoB_dsetProto(CState *state, int nargs, CValue *args) {
|
|||||||
int cosmoB_dgetProto(CState *state, int nargs, CValue *args) {
|
int cosmoB_dgetProto(CState *state, int nargs, CValue *args) {
|
||||||
if (nargs != 1) {
|
if (nargs != 1) {
|
||||||
cosmoV_error(state, "Expected 1 argument, got %d!", nargs);
|
cosmoV_error(state, "Expected 1 argument, got %d!", nargs);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(cosmoV_readObject(args[0])->_obj.proto)); // just return the proto
|
cosmoV_pushObj(state, (CObj*)cosmoV_readObject(args[0])->_obj.proto); // just return the proto
|
||||||
|
|
||||||
return 1; // 1 result
|
return 1; // 1 result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cosmoB_vindexBProto(CState *state, int nargs, CValue *args) {
|
||||||
|
if (nargs != 2) {
|
||||||
|
cosmoV_error(state, "Expected 2 argument, got %d!", nargs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_NUMBER(args[1])) {
|
||||||
|
cosmoV_typeError(state, "baseProtos.__index", "<number>", "%s", cosmoV_typeStr(args[0]));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int indx = (int)cosmoV_readNumber(args[1]);
|
||||||
|
|
||||||
|
if (indx >= COBJ_MAX || indx < 0) {
|
||||||
|
cosmoV_error(state, "index out of range! expected 0 - %d, got %d!", COBJ_MAX - 1, indx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state->protoObjects[indx] != NULL)
|
||||||
|
cosmoV_pushObj(state, (CObj*)state->protoObjects[indx]);
|
||||||
|
else
|
||||||
|
cosmoV_pushNil(state);
|
||||||
|
|
||||||
|
return 1; // 1 value pushed, 1 value returned
|
||||||
|
}
|
||||||
|
|
||||||
|
int cosmoB_vnewindexBProto(CState *state, int nargs, CValue *args) {
|
||||||
|
if (nargs != 3) {
|
||||||
|
cosmoV_error(state, "Expected 3 arguments, got %d!", nargs);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!IS_NUMBER(args[1]) || !IS_OBJECT(args[2])) {
|
||||||
|
cosmoV_typeError(state, "baseProtos.__newindex", "<object>, <number>, <object>", "%s, %s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]), cosmoV_typeStr(args[2]));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int indx = (int)cosmoV_readNumber(args[1]);
|
||||||
|
CObjObject *proto = cosmoV_readObject(args[2]);
|
||||||
|
|
||||||
|
if (indx >= COBJ_MAX || indx < 0) {
|
||||||
|
cosmoV_error(state, "index out of range! expected 0 - %d, got %d!", COBJ_MAX, indx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_registerProtoObject(state, indx, proto);
|
||||||
|
return 0; // we don't return anything
|
||||||
|
}
|
||||||
|
|
||||||
void cosmoB_loadDebug(CState *state) {
|
void cosmoB_loadDebug(CState *state) {
|
||||||
// make __getter object for debug proto
|
// make __getter object for debug proto
|
||||||
cosmoV_pushString(state, "__getter");
|
cosmoV_pushString(state, "__getter");
|
||||||
@ -357,8 +406,28 @@ void cosmoB_loadDebug(CState *state) {
|
|||||||
cosmoV_makeTable(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);
|
CObjObject *obj = cosmoV_makeObject(state, 2);
|
||||||
|
|
||||||
// set debug protos to the debug object
|
// set debug protos to the debug object
|
||||||
state->protoObjects[COBJ_OBJECT] = cosmoV_readObject(*cosmoV_pop(state));
|
cosmoV_registerProtoObject(state, COBJ_OBJECT, obj);
|
||||||
|
|
||||||
|
// make vm.* object
|
||||||
|
cosmoV_pushString(state, "vm");
|
||||||
|
|
||||||
|
// make vm.baseProtos object
|
||||||
|
cosmoV_pushString(state, "baseProtos");
|
||||||
|
|
||||||
|
cosmoV_pushString(state, "__index");
|
||||||
|
cosmoV_pushCFunction(state, cosmoB_vindexBProto);
|
||||||
|
|
||||||
|
cosmoV_pushString(state, "__newindex");
|
||||||
|
cosmoV_pushCFunction(state, cosmoB_vnewindexBProto);
|
||||||
|
|
||||||
|
cosmoV_makeObject(state, 2); // makes the baseProtos object
|
||||||
|
cosmoV_makeObject(state, 1); // makes the vm object
|
||||||
|
|
||||||
|
// register "vm" to the global table
|
||||||
|
cosmoV_register(state, 1);
|
||||||
|
|
||||||
|
printf("[WARNING] the debug library has been loaded!");
|
||||||
}
|
}
|
||||||
|
@ -5,15 +5,30 @@
|
|||||||
|
|
||||||
/* loads all of the base library, including:
|
/* loads all of the base library, including:
|
||||||
- base library ("print", "assert", "type", "pcall", "loadstring", etc.)
|
- base library ("print", "assert", "type", "pcall", "loadstring", etc.)
|
||||||
- string library ("string.sub", "string.split", "string.find")
|
- string library ("string.sub", "string.find", "string.split", "string.charAt")
|
||||||
*/
|
*/
|
||||||
COSMO_API void cosmoB_loadLibrary(CState *state);
|
COSMO_API void cosmoB_loadLibrary(CState *state);
|
||||||
|
|
||||||
|
/* loads the base string library, including:
|
||||||
|
- string.sub
|
||||||
|
- stirng.find
|
||||||
|
- string.split
|
||||||
|
- string.charAt
|
||||||
|
|
||||||
|
The base proto object for strings is also set, allowing you to invoke the string.* api through string objects, eg.
|
||||||
|
`"hello world":split(" ")` is equivalent to `string.split("hello world", " ")`
|
||||||
|
*/
|
||||||
COSMO_API void cosmoB_loadStrLib(CState *state);
|
COSMO_API void cosmoB_loadStrLib(CState *state);
|
||||||
|
|
||||||
|
/* sets the base proto of all objects to the debug proto which allows for
|
||||||
|
- manipulation of the ProtoObject of objects through the '__proto' field
|
||||||
|
|
||||||
|
additionally, the vm.* library is loaded, including:
|
||||||
|
- manually setting/grabbing base protos of any object (vm.baseProtos)
|
||||||
|
|
||||||
|
for this reason, it is recommended to NOT load this library in production
|
||||||
|
*/
|
||||||
COSMO_API void cosmoB_loadDebug(CState *state);
|
COSMO_API void cosmoB_loadDebug(CState *state);
|
||||||
COSMO_API int cosmoB_print(CState *state, int nargs, CValue *args);
|
|
||||||
COSMO_API int cosmoB_assert(CState *state, int nargs, CValue *args);
|
|
||||||
COSMO_API int cosmoB_type(CState *state, int nargs, CValue *args);
|
|
||||||
COSMO_API int cosmoB_pcall(CState *state, int nargs, CValue *args);
|
|
||||||
|
|
||||||
#define cosmoV_typeError(state, name, expectedTypes, formatStr, ...) \
|
#define cosmoV_typeError(state, name, expectedTypes, formatStr, ...) \
|
||||||
cosmoV_error(state, name " expected (" expectedTypes "), got (" formatStr ")!", __VA_ARGS__);
|
cosmoV_error(state, name " expected (" expectedTypes "), got (" formatStr ")!", __VA_ARGS__);
|
||||||
|
20
src/cobj.c
20
src/cobj.c
@ -114,7 +114,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->istringFlags = 0;
|
obj->istringFlags = 0;
|
||||||
obj->userP = 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_pushObj(state, (CObj*)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);
|
||||||
|
|
||||||
@ -125,7 +125,7 @@ CObjTable *cosmoO_newTable(CState *state) {
|
|||||||
CObjTable *obj = (CObjTable*)cosmoO_allocateBase(state, sizeof(CObjTable), COBJ_TABLE);
|
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_pushObj(state, (CObj*)obj); // so our GC can keep track of obj
|
||||||
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
|
cosmoT_initTable(state, &obj->tbl, ARRAY_START);
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
|
|
||||||
@ -236,7 +236,7 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin
|
|||||||
strObj->hash = hash;
|
strObj->hash = hash;
|
||||||
|
|
||||||
// we push & pop the string so our GC can find it (we don't use freezeGC/unfreezeGC because we *want* a GC event to happen)
|
// we push & pop the string so our GC can find it (we don't use freezeGC/unfreezeGC because we *want* a GC event to happen)
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(strObj));
|
cosmoV_pushObj(state, (CObj*)strObj);
|
||||||
cosmoT_insert(state, &state->strings, cosmoV_newObj((CObj*)strObj));
|
cosmoT_insert(state, &state->strings, cosmoV_newObj((CObj*)strObj));
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
|
|
||||||
@ -294,7 +294,7 @@ bool cosmoO_getRawObject(CState *state, CObjObject *proto, CValue key, CValue *v
|
|||||||
if (!cosmoT_get(&proto->tbl, key, val)) { // if the field doesn't exist in the object, check the proto
|
if (!cosmoT_get(&proto->tbl, key, val)) { // if the field doesn't exist in the object, check the proto
|
||||||
if (cosmoO_getIString(state, proto, ISTRING_GETTER, val) && IS_TABLE(*val) && cosmoT_get(&cosmoV_readTable(*val)->tbl, key, val)) {
|
if (cosmoO_getIString(state, proto, ISTRING_GETTER, val) && IS_TABLE(*val) && cosmoT_get(&cosmoV_readTable(*val)->tbl, key, val)) {
|
||||||
cosmoV_pushValue(state, *val); // push function
|
cosmoV_pushValue(state, *val); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj)); // push object
|
cosmoV_pushObj(state, (CObj*)obj); // push object
|
||||||
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call the function with the 1 argument
|
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call the function with the 1 argument
|
||||||
return false;
|
return false;
|
||||||
*val = *cosmoV_pop(state); // set value to the return value of __index
|
*val = *cosmoV_pop(state); // set value to the return value of __index
|
||||||
@ -317,7 +317,7 @@ void cosmoO_setRawObject(CState *state, CObjObject *proto, CValue key, CValue va
|
|||||||
// first check for __setters
|
// first check for __setters
|
||||||
if (cosmoO_getIString(state, proto, ISTRING_SETTER, &ret) && IS_TABLE(ret) && cosmoT_get(&cosmoV_readTable(ret)->tbl, key, &ret)) {
|
if (cosmoO_getIString(state, proto, ISTRING_SETTER, &ret) && IS_TABLE(ret) && cosmoT_get(&cosmoV_readTable(ret)->tbl, key, &ret)) {
|
||||||
cosmoV_pushValue(state, ret); // push function
|
cosmoV_pushValue(state, ret); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj)); // push object
|
cosmoV_pushObj(state, (CObj*)obj); // push object
|
||||||
cosmoV_pushValue(state, val); // push new value
|
cosmoV_pushValue(state, val); // push new value
|
||||||
cosmoV_call(state, 2, 0);
|
cosmoV_call(state, 2, 0);
|
||||||
return;
|
return;
|
||||||
@ -378,7 +378,7 @@ bool cosmoO_getIString(CState *state, CObjObject *object, int flag, CValue *val)
|
|||||||
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val) {
|
bool cosmoO_indexObject(CState *state, CObjObject *object, CValue key, CValue *val) {
|
||||||
if (cosmoO_getIString(state, object, ISTRING_INDEX, val)) {
|
if (cosmoO_getIString(state, object, ISTRING_INDEX, val)) {
|
||||||
cosmoV_pushValue(state, *val); // push function
|
cosmoV_pushValue(state, *val); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushObj(state, (CObj*)object); // push object
|
||||||
cosmoV_pushValue(state, key); // push key
|
cosmoV_pushValue(state, key); // push key
|
||||||
if (cosmoV_call(state, 2, 1) != COSMOVM_OK) // call the function with the 2 arguments
|
if (cosmoV_call(state, 2, 1) != COSMOVM_OK) // call the function with the 2 arguments
|
||||||
return false;
|
return false;
|
||||||
@ -396,7 +396,7 @@ bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue
|
|||||||
|
|
||||||
if (cosmoO_getIString(state, object, ISTRING_NEWINDEX, &ret)) {
|
if (cosmoO_getIString(state, object, ISTRING_NEWINDEX, &ret)) {
|
||||||
cosmoV_pushValue(state, ret); // push function
|
cosmoV_pushValue(state, ret); // push function
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object)); // push object
|
cosmoV_pushObj(state, (CObj*)object); // push object
|
||||||
cosmoV_pushValue(state, key); // push key & value pair
|
cosmoV_pushValue(state, key); // push key & value pair
|
||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
return cosmoV_call(state, 3, 0) == COSMOVM_OK;
|
return cosmoV_call(state, 3, 0) == COSMOVM_OK;
|
||||||
@ -414,7 +414,7 @@ CObjString *cosmoO_toString(CState *state, CObj *obj) {
|
|||||||
// use user-defined __tostring
|
// use user-defined __tostring
|
||||||
if (protoObject != NULL && cosmoO_getIString(state, protoObject, ISTRING_TOSTRING, &res)) {
|
if (protoObject != NULL && cosmoO_getIString(state, protoObject, ISTRING_TOSTRING, &res)) {
|
||||||
cosmoV_pushValue(state, res);
|
cosmoV_pushValue(state, res);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushObj(state, (CObj*)obj);
|
||||||
if (cosmoV_call(state, 1, 1) != COSMOVM_OK)
|
if (cosmoV_call(state, 1, 1) != COSMOVM_OK)
|
||||||
return cosmoO_copyString(state, "<err>", 5);
|
return cosmoO_copyString(state, "<err>", 5);
|
||||||
|
|
||||||
@ -467,7 +467,7 @@ cosmo_Number cosmoO_toNumber(CState *state, CObj *obj) {
|
|||||||
|
|
||||||
if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_TONUMBER, &res)) {
|
if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_TONUMBER, &res)) {
|
||||||
cosmoV_pushValue(state, res);
|
cosmoV_pushValue(state, res);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushObj(state, (CObj*)obj);
|
||||||
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, expect 1 return val of <number>
|
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, expect 1 return val of <number>
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -498,7 +498,7 @@ int cosmoO_count(CState *state, CObj *obj) {
|
|||||||
|
|
||||||
if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_COUNT, &res)) {
|
if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_COUNT, &res)) {
|
||||||
cosmoV_pushValue(state, res);
|
cosmoV_pushValue(state, res);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushObj(state, (CObj*)obj);
|
||||||
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, we expect 1 return value of type <number>
|
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, we expect 1 return value of type <number>
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "cosmo.h"
|
#include "cosmo.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum CObjType {
|
||||||
COBJ_STRING,
|
COBJ_STRING,
|
||||||
COBJ_OBJECT,
|
COBJ_OBJECT,
|
||||||
COBJ_TABLE,
|
COBJ_TABLE,
|
||||||
|
@ -1630,7 +1630,7 @@ CObjFunction* cosmoP_compileString(CState *state, const char *source, const char
|
|||||||
freeParseState(&parser);
|
freeParseState(&parser);
|
||||||
|
|
||||||
// push the funciton onto the stack so if we cause an GC event, it won't be free'd
|
// push the funciton onto the stack so if we cause an GC event, it won't be free'd
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(resFunc));
|
cosmoV_pushObj(state, (CObj*)resFunc);
|
||||||
cosmoM_unfreezeGC(state);
|
cosmoM_unfreezeGC(state);
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
return resFunc;
|
return resFunc;
|
||||||
|
57
src/cvm.c
57
src/cvm.c
@ -37,14 +37,14 @@ COSMO_API bool cosmoV_compileString(CState *state, const char *src, const char *
|
|||||||
disasmChunk(&func->chunk, func->module->str, 0);
|
disasmChunk(&func->chunk, func->module->str, 0);
|
||||||
#endif
|
#endif
|
||||||
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack location put our closure
|
// push function onto the stack so it doesn't it cleaned up by the GC, at the same stack location put our closure
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(func));
|
cosmoV_pushObj(state, (CObj*)func);
|
||||||
*(cosmoV_getTop(state, 0)) = cosmoV_newObj(cosmoO_newClosure(state, func));
|
*(cosmoV_getTop(state, 0)) = cosmoV_newObj(cosmoO_newClosure(state, func));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fail
|
// fail
|
||||||
state->panic = false;
|
state->panic = false;
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(state->error));
|
cosmoV_pushObj(state, (CObj*)state->error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,9 +173,9 @@ void cosmoV_concat(CState *state, int vals) {
|
|||||||
|
|
||||||
CObjString *result = cosmoV_toString(state, *start);
|
CObjString *result = cosmoV_toString(state, *start);
|
||||||
for (StkPtr current = start + 1; current <= end; current++) {
|
for (StkPtr current = start + 1; current <= end; current++) {
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(result)); // so our GC can find our current result string
|
cosmoV_pushObj(state, (CObj*)result); // so our GC can find our current result string
|
||||||
CObjString *otherStr = cosmoV_toString(state, *current);
|
CObjString *otherStr = cosmoV_toString(state, *current);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(otherStr)); // also so our GC won't free otherStr
|
cosmoV_pushObj(state, (CObj*)otherStr); // also so our GC won't free otherStr
|
||||||
|
|
||||||
// concat the two strings together
|
// concat the two strings together
|
||||||
size_t sz = result->length + otherStr->length;
|
size_t sz = result->length + otherStr->length;
|
||||||
@ -190,7 +190,7 @@ void cosmoV_concat(CState *state, int vals) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
state->top = start;
|
state->top = start;
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(result));
|
cosmoV_pushObj(state, (CObj*)result);
|
||||||
}
|
}
|
||||||
|
|
||||||
int cosmoV_execute(CState *state);
|
int cosmoV_execute(CState *state);
|
||||||
@ -324,7 +324,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset)
|
|||||||
CObjObject *protoObj = (CObjObject*)cosmoV_readObj(func);
|
CObjObject *protoObj = (CObjObject*)cosmoV_readObj(func);
|
||||||
CValue ret;
|
CValue ret;
|
||||||
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(protoObj)); // push proto to stack for GC to find
|
cosmoV_pushObj(state, (CObj*)protoObj); // push proto to stack for GC to find
|
||||||
CObjObject *newObj = cosmoO_newObject(state);
|
CObjObject *newObj = cosmoO_newObject(state);
|
||||||
newObj->_obj.proto = protoObj;
|
newObj->_obj.proto = protoObj;
|
||||||
cosmoV_pop(state); // pop proto
|
cosmoV_pop(state); // pop proto
|
||||||
@ -340,7 +340,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (nresults > 0) {
|
if (nresults > 0) {
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushObj(state, (CObj*)newObj);
|
||||||
|
|
||||||
// push the nils to fill up the expected return values
|
// push the nils to fill up the expected return values
|
||||||
for (int i = 0; i < nresults - 1; i++) { // -1 since the we already pushed the important value
|
for (int i = 0; i < nresults - 1; i++) { // -1 since the we already pushed the important value
|
||||||
@ -374,7 +374,7 @@ COSMOVMRESULT cosmoV_pcall(CState *state, int args, int nresults) {
|
|||||||
state->panic = false;
|
state->panic = false;
|
||||||
|
|
||||||
if (nresults > 0) {
|
if (nresults > 0) {
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(state->error));
|
cosmoV_pushObj(state, (CObj*)state->error);
|
||||||
|
|
||||||
// push other expected results onto the stack
|
// push other expected results onto the stack
|
||||||
for (int i = 0; i < nresults-1; i++)
|
for (int i = 0; i < nresults-1; i++)
|
||||||
@ -404,10 +404,10 @@ static inline bool isFalsey(StkPtr val) {
|
|||||||
return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val));
|
return IS_NIL(*val) || (IS_BOOLEAN(*val) && !cosmoV_readBoolean(*val));
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_makeObject(CState *state, int pairs) {
|
COSMO_API CObjObject* cosmoV_makeObject(CState *state, int pairs) {
|
||||||
StkPtr key, val;
|
StkPtr key, val;
|
||||||
CObjObject *newObj = cosmoO_newObject(state);
|
CObjObject *newObj = cosmoO_newObject(state);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj)); // so our GC doesn't free our new object
|
cosmoV_pushObj(state, (CObj*)newObj); // so our GC doesn't free our new object
|
||||||
|
|
||||||
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);
|
||||||
@ -420,13 +420,20 @@ COSMO_API void cosmoV_makeObject(CState *state, int pairs) {
|
|||||||
|
|
||||||
// once done, pop everything off the stack + push new object
|
// once done, pop everything off the stack + push new object
|
||||||
cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our object
|
cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our object
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushObj(state, (CObj*)newObj);
|
||||||
|
return newObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj) {
|
||||||
|
bool replaced = state->protoObjects[objType] != NULL;
|
||||||
|
state->protoObjects[objType] = obj;
|
||||||
|
return replaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API void cosmoV_makeTable(CState *state, int pairs) {
|
COSMO_API void cosmoV_makeTable(CState *state, int pairs) {
|
||||||
StkPtr key, val;
|
StkPtr key, val;
|
||||||
CObjTable *newObj = cosmoO_newTable(state);
|
CObjTable *newObj = cosmoO_newTable(state);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj)); // so our GC doesn't free our new table
|
cosmoV_pushObj(state, (CObj*)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);
|
||||||
@ -439,7 +446,7 @@ COSMO_API void cosmoV_makeTable(CState *state, int pairs) {
|
|||||||
|
|
||||||
// once done, pop everything off the stack + push new table
|
// once done, pop everything off the stack + push new table
|
||||||
cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our table
|
cosmoV_setTop(state, (pairs * 2) + 1); // + 1 for our table
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushObj(state, (CObj*)newObj);
|
||||||
}
|
}
|
||||||
|
|
||||||
COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) {
|
COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) {
|
||||||
@ -454,7 +461,7 @@ COSMO_API bool cosmoV_get(CState *state, CObj *_obj, CValue key, CValue *val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// push the object onto the stack so the GC can find it
|
// push the object onto the stack so the GC can find it
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(object));
|
cosmoV_pushObj(state, (CObj*)object);
|
||||||
if (cosmoO_getRawObject(state, object, key, val, _obj)) {
|
if (cosmoO_getRawObject(state, object, key, val, _obj)) {
|
||||||
// *val now equals the response, pop the object
|
// *val now equals the response, pop the object
|
||||||
cosmoV_pop(state);
|
cosmoV_pop(state);
|
||||||
@ -486,7 +493,7 @@ COSMO_API bool cosmoV_getMethod(CState *state, CObj *obj, CValue key, CValue *va
|
|||||||
// if the result is callable, wrap it in an method
|
// if the result is callable, wrap it in an method
|
||||||
if (IS_CALLABLE(*val)) {
|
if (IS_CALLABLE(*val)) {
|
||||||
// push object to stack so the GC can find it
|
// push object to stack so the GC can find it
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushObj(state, (CObj*)obj);
|
||||||
CObjMethod *method = cosmoO_newMethod(state, *val, obj);
|
CObjMethod *method = cosmoO_newMethod(state, *val, obj);
|
||||||
cosmoV_pop(state); // pop the object
|
cosmoV_pop(state); // pop the object
|
||||||
*val = cosmoV_newObj(method);
|
*val = cosmoV_newObj(method);
|
||||||
@ -643,7 +650,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
uint16_t index = READUINT();
|
uint16_t index = READUINT();
|
||||||
CObjFunction *func = cosmoV_readFunction(constants[index]);
|
CObjFunction *func = cosmoV_readFunction(constants[index]);
|
||||||
CObjClosure *closure = cosmoO_newClosure(state, func);
|
CObjClosure *closure = cosmoO_newClosure(state, func);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj((CObj*)closure));
|
cosmoV_pushObj(state, (CObj*)closure);
|
||||||
|
|
||||||
for (int i = 0; i < closure->upvalueCount; i++) {
|
for (int i = 0; i < closure->upvalueCount; i++) {
|
||||||
uint8_t encoding = READBYTE();
|
uint8_t encoding = READBYTE();
|
||||||
@ -673,7 +680,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
uint16_t pairs = READUINT();
|
uint16_t pairs = READUINT();
|
||||||
StkPtr val;
|
StkPtr val;
|
||||||
CObjTable *newObj = cosmoO_newTable(state);
|
CObjTable *newObj = cosmoO_newTable(state);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj)); // so our GC doesn't free our new table
|
cosmoV_pushObj(state, (CObj*)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 + 1);
|
val = cosmoV_getTop(state, i + 1);
|
||||||
@ -685,7 +692,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
|
|
||||||
// once done, pop everything off the stack + push new table
|
// once done, pop everything off the stack + push new table
|
||||||
cosmoV_setTop(state, pairs + 1); // + 1 for our table
|
cosmoV_setTop(state, pairs + 1); // + 1 for our table
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(newObj));
|
cosmoV_pushObj(state, (CObj*)newObj);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
case OP_INDEX: {
|
case OP_INDEX: {
|
||||||
@ -851,7 +858,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
if (cosmoO_getIString(state, proto, ISTRING_ITER, &val)) {
|
if (cosmoO_getIString(state, proto, ISTRING_ITER, &val)) {
|
||||||
cosmoV_pop(state); // pop the object from the stack
|
cosmoV_pop(state); // pop the object from the stack
|
||||||
cosmoV_pushValue(state, val);
|
cosmoV_pushValue(state, val);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
cosmoV_pushObj(state, (CObj*)obj);
|
||||||
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // we expect 1 return value on the stack, the iterable object
|
if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // we expect 1 return value on the stack, the iterable object
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -871,23 +878,21 @@ int cosmoV_execute(CState *state) {
|
|||||||
} else if (obj->type == COBJ_TABLE) {
|
} else if (obj->type == COBJ_TABLE) {
|
||||||
CObjTable *tbl = (CObjTable*)obj;
|
CObjTable *tbl = (CObjTable*)obj;
|
||||||
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key
|
cosmoV_pushObj(state, (CObj*)state->iStrings[ISTRING_RESERVED]); // key
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(tbl)); // value
|
cosmoV_pushObj(state, (CObj*)tbl); // value
|
||||||
|
|
||||||
cosmoV_pushString(state, "__next"); // key
|
cosmoV_pushString(state, "__next"); // key
|
||||||
CObjCFunction *tbl_next = cosmoO_newCFunction(state, _tbl__next);
|
CObjCFunction *tbl_next = cosmoO_newCFunction(state, _tbl__next);
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(tbl_next)); // value
|
cosmoV_pushObj(state, (CObj*)tbl_next); // value
|
||||||
|
|
||||||
cosmoV_makeObject(state, 2); // pushes the new object to the stack
|
CObjObject *obj = 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
|
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(tbl_next), (CObj*)obj);
|
CObjMethod *method = cosmoO_newMethod(state, cosmoV_newObj(tbl_next), (CObj*)obj);
|
||||||
|
|
||||||
cosmoV_setTop(state, 2); // pops the object & the tbl
|
cosmoV_setTop(state, 2); // pops the object & the tbl
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(method)); // pushes the method for OP_NEXT
|
cosmoV_pushObj(state, (CObj*)method); // pushes the method for OP_NEXT
|
||||||
} else {
|
} else {
|
||||||
cosmoV_error(state, "No proto defined! Couldn't get from type %s", cosmoO_typeStr(obj));
|
cosmoV_error(state, "No proto defined! Couldn't get from type %s", cosmoO_typeStr(obj));
|
||||||
return -1;
|
return -1;
|
||||||
|
19
src/cvm.h
19
src/cvm.h
@ -17,7 +17,9 @@ typedef enum {
|
|||||||
// args = # of pass parameters, nresults = # of expected results
|
// args = # of pass parameters, nresults = # of expected results
|
||||||
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);
|
|
||||||
|
// pushes new object onto the stack & returns a pointer to the new object
|
||||||
|
COSMO_API CObjObject* cosmoV_makeObject(CState *state, int pairs);
|
||||||
COSMO_API void cosmoV_makeTable(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, ...);
|
||||||
@ -26,6 +28,9 @@ COSMO_API CObjError* cosmoV_throw(CState *state);
|
|||||||
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
||||||
COSMO_API void cosmo_insert(CState *state, int indx, CValue val);
|
COSMO_API void cosmo_insert(CState *state, int indx, CValue val);
|
||||||
|
|
||||||
|
// returns true if replacing a previously registered proto object for this type
|
||||||
|
COSMO_API bool cosmoV_registerProtoObject(CState *state, CObjType objType, CObjObject *obj);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
compiles string into a <closure>, if successful, <closure> will be pushed onto the stack otherwise the <error> will be pushed.
|
compiles string into a <closure>, if successful, <closure> will be pushed onto the stack otherwise the <error> will be pushed.
|
||||||
|
|
||||||
@ -90,13 +95,17 @@ static inline void cosmoV_pushBoolean(CState *state, bool b) {
|
|||||||
cosmoV_pushValue(state, cosmoV_newBoolean(b));
|
cosmoV_pushValue(state, cosmoV_newBoolean(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cosmoV_pushObj(CState *state, CObj *obj) {
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(obj));
|
||||||
|
}
|
||||||
|
|
||||||
// pushes a C Function to the stack
|
// pushes a C Function to the stack
|
||||||
static inline void cosmoV_pushCFunction(CState *state, CosmoCFunction func) {
|
static inline void cosmoV_pushCFunction(CState *state, CosmoCFunction func) {
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_newCFunction(state, func)));
|
cosmoV_pushObj(state, (CObj*)cosmoO_newCFunction(state, func));
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cosmoV_pushLString(CState *state, const char *str, size_t len) {
|
static inline void cosmoV_pushLString(CState *state, const char *str, size_t len) {
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, str, len)));
|
cosmoV_pushObj(state, (CObj*)cosmoO_copyString(state, str, len));
|
||||||
}
|
}
|
||||||
|
|
||||||
// accepts a null terminated string and copys the buffer to the VM heap
|
// accepts a null terminated string and copys the buffer to the VM heap
|
||||||
@ -104,4 +113,8 @@ static inline void cosmoV_pushString(CState *state, const char *str) {
|
|||||||
cosmoV_pushLString(state, str, strlen(str));
|
cosmoV_pushLString(state, str, strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void cosmoV_pushNil(CState *state) {
|
||||||
|
cosmoV_pushValue(state, cosmoV_newNil());
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,7 +26,7 @@ int cosmoB_input(CState *state, int nargs, CValue *args) {
|
|||||||
char line[1024];
|
char line[1024];
|
||||||
fgets(line, sizeof(line), stdin);
|
fgets(line, sizeof(line), stdin);
|
||||||
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(cosmoO_copyString(state, line, strlen(line)-1))); // -1 for the \n
|
cosmoV_pushObj(state, (CObj*)cosmoO_copyString(state, line, strlen(line)-1)); // -1 for the \n
|
||||||
|
|
||||||
return 1; // 1 return value
|
return 1; // 1 return value
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user