Added string.split() & string.find()

This commit is contained in:
CPunch 2021-01-17 14:07:30 -06:00
parent 2864c7be53
commit 3c19079262
3 changed files with 97 additions and 6 deletions

View File

@ -142,6 +142,85 @@ int cosmoB_sSub(CState *state, int nargs, CValue *args) {
return 1; 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()", "<string>, <string>", "%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()", "<string>, <string>, <number>", "%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()", "<string>, <string>", "%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) { void cosmoB_loadLibrary(CState *state) {
const char *identifiers[] = { const char *identifiers[] = {
"print", "print",
@ -179,7 +258,15 @@ void cosmoB_loadLibrary(CState *state) {
cosmoV_pushString(state, "sub"); cosmoV_pushString(state, "sub");
cosmoV_pushCFunction(state, cosmoB_sSub); cosmoV_pushCFunction(state, cosmoB_sSub);
cosmoV_makeObject(state, 1); // find
cosmoV_pushString(state, "find");
cosmoV_pushCFunction(state, cosmoB_sFind);
// split
cosmoV_pushString(state, "split");
cosmoV_pushCFunction(state, cosmoB_sSplit);
cosmoV_makeObject(state, 3);
// string.* // string.*
// grab the object from the stack and set the base protoObject // grab the object from the stack and set the base protoObject

View File

@ -5,7 +5,7 @@
#include "cstate.h" #include "cstate.h"
#define GC_STRESS //#define GC_STRESS
//#define GC_DEBUG //#define GC_DEBUG
// arrays will grow by a factor of 2 // arrays will grow by a factor of 2
#define GROW_FACTOR 2 #define GROW_FACTOR 2

View File

@ -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 case COBJ_OBJECT: { // object is being instantiated, making another object
CObjObject *protoObj = (CObjObject*)cosmoV_readObj(func); 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); CObjObject *newObj = cosmoO_newObject(state);
newObj->_obj.proto = protoObj; newObj->_obj.proto = protoObj;
CValue ret; cosmoV_pop(state); // pop proto
// check if they defined an initializer (we accept 0 return values) // check if they defined an initializer (we accept 0 return values)
if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) { if (cosmoO_getIString(state, protoObj, ISTRING_INIT, &ret)) {
@ -577,6 +580,7 @@ int cosmoV_execute(CState *state) {
} }
case OP_SETLOCAL: { case OP_SETLOCAL: {
uint8_t indx = READBYTE(); uint8_t indx = READBYTE();
// set base to top of stack & pop
frame->base[indx] = *cosmoV_pop(state); frame->base[indx] = *cosmoV_pop(state);
continue; 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 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); StkPtr temp = cosmoV_getTop(state, 0);
if (!IS_OBJ(*temp) || cosmoV_readObj(*temp)->type != COBJ_TABLE) { if (!IS_TABLE(*temp)) {
cosmoV_error(state, "Expected object, got %s!", cosmoV_typeStr(*temp)); cosmoV_error(state, "Expected table, got %s!", cosmoV_typeStr(*temp));
return -1; return -1;
} }