diff --git a/src/cbaselib.c b/src/cbaselib.c index 65e02db..3a78301 100644 --- a/src/cbaselib.c +++ b/src/cbaselib.c @@ -75,7 +75,7 @@ int cosmoB_tostring(CState *state, int nargs, CValue *args) { return 0; } - cosmoV_pushValue(state, cosmoV_newObj(cosmoV_toString(state, args[0]))); + cosmoV_pushObj(state, (CObj*)cosmoV_toString(state, args[0])); return 1; } @@ -303,11 +303,10 @@ void cosmoB_loadStrLib(CState *state) { cosmoV_pushString(state, identifiers[i]); cosmoV_pushCFunction(state, strLib[i]); } - cosmoV_makeObject(state, i); - // grab the object from the stack and set the base protoObject - StkPtr obj = cosmoV_getTop(state, 0); - state->protoObjects[COBJ_STRING] = cosmoV_readObject(*obj); + // make the object and set the protoobject for all strings + CObjObject *obj = cosmoV_makeObject(state, i); + cosmoV_registerProtoObject(state, COBJ_STRING, obj); // register "string" to the global table cosmoV_register(state, 1); @@ -322,7 +321,7 @@ int cosmoB_dsetProto(CState *state, int nargs, CValue *args) { obj->proto = proto; // boom done } else { - cosmoV_error(state, "Expected 2 parameters, got %d!", nargs); + cosmoV_error(state, "Expected 2 arguments, got %d!", nargs); } 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) { if (nargs != 1) { 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 } +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", "", "%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", ", , ", "%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) { // make __getter object for debug proto cosmoV_pushString(state, "__getter"); @@ -357,8 +406,28 @@ void cosmoB_loadDebug(CState *state) { cosmoV_makeTable(state, 1); // 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 - 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!"); } diff --git a/src/cbaselib.h b/src/cbaselib.h index 07a6aa3..b10c1af 100644 --- a/src/cbaselib.h +++ b/src/cbaselib.h @@ -5,15 +5,30 @@ /* loads all of the base library, including: - 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); + +/* 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); + +/* 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 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, ...) \ cosmoV_error(state, name " expected (" expectedTypes "), got (" formatStr ")!", __VA_ARGS__); diff --git a/src/cobj.c b/src/cobj.c index b499438..2b13261 100644 --- a/src/cobj.c +++ b/src/cobj.c @@ -114,7 +114,7 @@ CObjObject *cosmoO_newObject(CState *state) { CObjObject *obj = (CObjObject*)cosmoO_allocateBase(state, sizeof(CObjObject), COBJ_OBJECT); obj->istringFlags = 0; 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); cosmoV_pop(state); @@ -125,7 +125,7 @@ CObjTable *cosmoO_newTable(CState *state) { CObjTable *obj = (CObjTable*)cosmoO_allocateBase(state, sizeof(CObjTable), COBJ_TABLE); // 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); cosmoV_pop(state); @@ -236,7 +236,7 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin 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) - cosmoV_pushValue(state, cosmoV_newObj(strObj)); + cosmoV_pushObj(state, (CObj*)strObj); cosmoT_insert(state, &state->strings, cosmoV_newObj((CObj*)strObj)); 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 (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, 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 return false; *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 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, cosmoV_newObj(obj)); // push object + cosmoV_pushObj(state, (CObj*)obj); // push object cosmoV_pushValue(state, val); // push new value cosmoV_call(state, 2, 0); 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) { if (cosmoO_getIString(state, object, ISTRING_INDEX, val)) { 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 if (cosmoV_call(state, 2, 1) != COSMOVM_OK) // call the function with the 2 arguments return false; @@ -396,7 +396,7 @@ bool cosmoO_newIndexObject(CState *state, CObjObject *object, CValue key, CValue if (cosmoO_getIString(state, object, ISTRING_NEWINDEX, &ret)) { 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, val); return cosmoV_call(state, 3, 0) == COSMOVM_OK; @@ -414,7 +414,7 @@ CObjString *cosmoO_toString(CState *state, CObj *obj) { // use user-defined __tostring if (protoObject != NULL && cosmoO_getIString(state, protoObject, ISTRING_TOSTRING, &res)) { cosmoV_pushValue(state, res); - cosmoV_pushValue(state, cosmoV_newObj(obj)); + cosmoV_pushObj(state, (CObj*)obj); if (cosmoV_call(state, 1, 1) != COSMOVM_OK) return cosmoO_copyString(state, "", 5); @@ -467,7 +467,7 @@ cosmo_Number cosmoO_toNumber(CState *state, CObj *obj) { if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_TONUMBER, &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 return 0; @@ -498,7 +498,7 @@ int cosmoO_count(CState *state, CObj *obj) { if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_COUNT, &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 return 0; diff --git a/src/cobj.h b/src/cobj.h index 3cfe3ce..22ee177 100644 --- a/src/cobj.h +++ b/src/cobj.h @@ -3,7 +3,7 @@ #include "cosmo.h" -typedef enum { +typedef enum CObjType { COBJ_STRING, COBJ_OBJECT, COBJ_TABLE, diff --git a/src/cparse.c b/src/cparse.c index 61f10c9..dc20fb5 100644 --- a/src/cparse.c +++ b/src/cparse.c @@ -1630,7 +1630,7 @@ CObjFunction* cosmoP_compileString(CState *state, const char *source, const char freeParseState(&parser); // 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); cosmoV_pop(state); return resFunc; diff --git a/src/cvm.c b/src/cvm.c index f37212e..667b746 100644 --- a/src/cvm.c +++ b/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); #endif // 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)); return true; } // fail state->panic = false; - cosmoV_pushValue(state, cosmoV_newObj(state->error)); + cosmoV_pushObj(state, (CObj*)state->error); return false; } @@ -173,9 +173,9 @@ void cosmoV_concat(CState *state, int vals) { CObjString *result = cosmoV_toString(state, *start); 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); - 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 size_t sz = result->length + otherStr->length; @@ -190,7 +190,7 @@ void cosmoV_concat(CState *state, int vals) { } state->top = start; - cosmoV_pushValue(state, cosmoV_newObj(result)); + cosmoV_pushObj(state, (CObj*)result); } 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); 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); newObj->_obj.proto = protoObj; cosmoV_pop(state); // pop proto @@ -340,7 +340,7 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset) } if (nresults > 0) { - cosmoV_pushValue(state, cosmoV_newObj(newObj)); + cosmoV_pushObj(state, (CObj*)newObj); // 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 @@ -374,7 +374,7 @@ COSMOVMRESULT cosmoV_pcall(CState *state, int args, int nresults) { state->panic = false; if (nresults > 0) { - cosmoV_pushValue(state, cosmoV_newObj(state->error)); + cosmoV_pushObj(state, (CObj*)state->error); // push other expected results onto the stack 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)); } -COSMO_API void cosmoV_makeObject(CState *state, int pairs) { +COSMO_API CObjObject* cosmoV_makeObject(CState *state, int pairs) { StkPtr key, val; 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++) { 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 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) { StkPtr key, val; 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++) { 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 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) { @@ -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 - cosmoV_pushValue(state, cosmoV_newObj(object)); + cosmoV_pushObj(state, (CObj*)object); if (cosmoO_getRawObject(state, object, key, val, _obj)) { // *val now equals the response, pop the object 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 (IS_CALLABLE(*val)) { // 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); cosmoV_pop(state); // pop the object *val = cosmoV_newObj(method); @@ -643,7 +650,7 @@ int cosmoV_execute(CState *state) { uint16_t index = READUINT(); CObjFunction *func = cosmoV_readFunction(constants[index]); 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++) { uint8_t encoding = READBYTE(); @@ -673,7 +680,7 @@ int cosmoV_execute(CState *state) { uint16_t pairs = READUINT(); StkPtr val; 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++) { 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 cosmoV_setTop(state, pairs + 1); // + 1 for our table - cosmoV_pushValue(state, cosmoV_newObj(newObj)); + cosmoV_pushObj(state, (CObj*)newObj); continue; } case OP_INDEX: { @@ -851,7 +858,7 @@ int cosmoV_execute(CState *state) { if (cosmoO_getIString(state, proto, ISTRING_ITER, &val)) { cosmoV_pop(state); // pop the object from the stack 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 return -1; @@ -871,23 +878,21 @@ int cosmoV_execute(CState *state) { } else if (obj->type == COBJ_TABLE) { CObjTable *tbl = (CObjTable*)obj; - cosmoV_pushValue(state, cosmoV_newObj(state->iStrings[ISTRING_RESERVED])); // key - cosmoV_pushValue(state, cosmoV_newObj(tbl)); // value + cosmoV_pushObj(state, (CObj*)state->iStrings[ISTRING_RESERVED]); // key + cosmoV_pushObj(state, (CObj*)tbl); // value cosmoV_pushString(state, "__next"); // key 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_readObject(*(cosmoV_getTop(state, 0))); + CObjObject *obj = cosmoV_makeObject(state, 2); // pushes the new object to the stack cosmoO_setUserI(state, obj, 0); // increment for iterator // make our CObjMethod for OP_NEXT to call CObjMethod *method = cosmoO_newMethod(state, cosmoV_newObj(tbl_next), (CObj*)obj); 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 { cosmoV_error(state, "No proto defined! Couldn't get from type %s", cosmoO_typeStr(obj)); return -1; diff --git a/src/cvm.h b/src/cvm.h index 8e676e4..70847c7 100644 --- a/src/cvm.h +++ b/src/cvm.h @@ -17,7 +17,9 @@ typedef enum { // args = # of pass parameters, nresults = # of expected results COSMO_API COSMOVMRESULT cosmoV_call(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_concat(CState *state, int vals); 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 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 , if successful, will be pushed onto the stack otherwise the will be pushed. @@ -90,13 +95,17 @@ static inline void cosmoV_pushBoolean(CState *state, bool 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 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) { - 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 @@ -104,4 +113,8 @@ static inline void cosmoV_pushString(CState *state, const char *str) { cosmoV_pushLString(state, str, strlen(str)); } +static inline void cosmoV_pushNil(CState *state) { + cosmoV_pushValue(state, cosmoV_newNil()); +} + #endif diff --git a/src/main.c b/src/main.c index c7d5586..ecc1284 100644 --- a/src/main.c +++ b/src/main.c @@ -26,7 +26,7 @@ int cosmoB_input(CState *state, int nargs, CValue *args) { char line[1024]; 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 }