diff --git a/src/cbaselib.c b/src/cbaselib.c index c029fc5..ff643cc 100644 --- a/src/cbaselib.c +++ b/src/cbaselib.c @@ -142,6 +142,85 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args) { return 1; } +// string.find +int cosmoB_sFind(CState *state, int nargs, CValue *args) { + if (nargs == 2) { + if (!IS_STRING(args[0]) || !IS_STRING(args[1])) { + cosmoV_typeError(state, "string.find()", ", ", "%s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1])); + return 0; + } + + CObjString *str = cosmoV_readString(args[0]); + CObjString *ptrn = cosmoV_readString(args[1]); + + char *indx = strstr(str->str, ptrn->str); + + // failed, we have nothing to return + if (indx == NULL) + return 0; + + // success! push the index + cosmoV_pushNumber(state, indx - str->str); + } else if (nargs == 3) { + if (!IS_STRING(args[0]) || !IS_STRING(args[1]) || !IS_NUMBER(args[2])) { + cosmoV_typeError(state, "string.find()", ", , ", "%s, %s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1]), cosmoV_typeStr(args[2])); + return 0; + } + + CObjString *str = cosmoV_readString(args[0]); + CObjString *ptrn = cosmoV_readString(args[1]); + int startIndx = (int)cosmoV_readNumber(args[2]); + + char *indx = strstr(str->str + startIndx, ptrn->str); + + // failed, we have nothing to return + if (indx == NULL) + return 0; + + // success! push the index + cosmoV_pushNumber(state, indx - str->str); + } else { + cosmoV_error(state, "Expected 2 or 3 arguments, got %d!", nargs); + return 0; + } + + return 1; +} + +// string.split +int cosmoB_sSplit(CState *state, int nargs, CValue *args) { + if (nargs != 2) { + cosmoV_error(state, "Expected 2 arguments, got %d!", nargs); + return 0; + } + + if (!IS_STRING(args[0]) || !IS_STRING(args[1])) { + cosmoV_typeError(state, "string.split()", ", ", "%s, %s", cosmoV_typeStr(args[0]), cosmoV_typeStr(args[1])); + return 0; + } + + CObjString *str = cosmoV_readString(args[0]); + CObjString *ptrn = cosmoV_readString(args[1]); + + int nEntries = 0; + char *indx = str->str; + char *nIndx; + + // while there are still patterns to match in the string, push the split strings onto the stack + do { + nIndx = strstr(indx, ptrn->str); + + cosmoV_pushNumber(state, nEntries++); + cosmoV_pushLString(state, indx, nIndx == NULL ? strlen(indx) : nIndx - indx); + + indx = nIndx + ptrn->length; + } while (nIndx != NULL); + + // finally, make a table out of the pushed entries + cosmoV_makeTable(state, nEntries); + return 1; +} + void cosmoB_loadLibrary(CState *state) { const char *identifiers[] = { "print", @@ -178,8 +257,16 @@ void cosmoB_loadLibrary(CState *state) { // sub cosmoV_pushString(state, "sub"); cosmoV_pushCFunction(state, cosmoB_sSub); + + // find + cosmoV_pushString(state, "find"); + cosmoV_pushCFunction(state, cosmoB_sFind); + + // split + cosmoV_pushString(state, "split"); + cosmoV_pushCFunction(state, cosmoB_sSplit); - cosmoV_makeObject(state, 1); + cosmoV_makeObject(state, 3); // string.* // grab the object from the stack and set the base protoObject diff --git a/src/cmem.h b/src/cmem.h index ca0eb0e..7e65b94 100644 --- a/src/cmem.h +++ b/src/cmem.h @@ -5,7 +5,7 @@ #include "cstate.h" -#define GC_STRESS +//#define GC_STRESS //#define GC_DEBUG // arrays will grow by a factor of 2 #define GROW_FACTOR 2 diff --git a/src/cvm.c b/src/cvm.c index 56c4ed3..bf212cb 100644 --- a/src/cvm.c +++ b/src/cvm.c @@ -281,7 +281,7 @@ static bool rawCall(CState *state, CObjClosure *closure, int args, int nresults, // pop the callframe and return results :) popCallFrame(state, offset); - + if (state->panic) // panic state return false; @@ -320,9 +320,12 @@ bool callCValue(CState *state, CValue func, int args, int nresults, int offset) } case COBJ_OBJECT: { // object is being instantiated, making another object CObjObject *protoObj = (CObjObject*)cosmoV_readObj(func); + CValue ret; + + cosmoV_pushValue(state, cosmoV_newObj(protoObj)); // push proto to stack for GC to find CObjObject *newObj = cosmoO_newObject(state); newObj->_obj.proto = protoObj; - CValue ret; + cosmoV_pop(state); // pop proto // check if they defined an initializer (we accept 0 return values) if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) { @@ -577,6 +580,7 @@ int cosmoV_execute(CState *state) { } case OP_SETLOCAL: { uint8_t indx = READBYTE(); + // set base to top of stack & pop frame->base[indx] = *cosmoV_pop(state); continue; } @@ -978,8 +982,8 @@ int cosmoV_execute(CState *state) { case OP_COUNT: { // pop 1 value off the stack & if it's a table return the amount of active entries it has StkPtr temp = cosmoV_getTop(state, 0); - if (!IS_OBJ(*temp) || cosmoV_readObj(*temp)->type != COBJ_TABLE) { - cosmoV_error(state, "Expected object, got %s!", cosmoV_typeStr(*temp)); + if (!IS_TABLE(*temp)) { + cosmoV_error(state, "Expected table, got %s!", cosmoV_typeStr(*temp)); return -1; }