From 0ad0df5fbadc154137a8ac1bfa98fd97e7c40846 Mon Sep 17 00:00:00 2001 From: CPunch Date: Sat, 23 Jan 2021 15:30:30 -0600 Subject: [PATCH] Added '__tonumber' metamethod --- docs/objects.md | 1 + src/cobj.c | 22 +++++++++++++++++++++- src/cstate.c | 5 +++-- src/cstate.h | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/objects.md b/docs/objects.md index 7f4e4d5..d830152 100644 --- a/docs/objects.md +++ b/docs/objects.md @@ -95,6 +95,7 @@ that are called on special operators. | __newindex | `(, key, newValue)` | Called on new index using the '[] = ' operator | | __index | `(, key)` -> `value` | Called on index using the '[]' operator | | __tostring | `()` -> `` | Called when tostring() is called on an object | +| __tonumber | `()` -> `` | Called when tonumber() is called on an object | | __count | `()` -> `` | Called when object is used with the '#' count operator | | __iter | `()` -> `` | Called when used in a for-each loop with the 'in' operator | | __next | `()` -> `...` | Called on each iteration in a for-each loop, return values are passed as parameters in the loop | diff --git a/src/cobj.c b/src/cobj.c index 446b183..b499438 100644 --- a/src/cobj.c +++ b/src/cobj.c @@ -462,6 +462,26 @@ CObjString *cosmoO_toString(CState *state, CObj *obj) { } cosmo_Number cosmoO_toNumber(CState *state, CObj *obj) { + CObjObject *proto = cosmoO_grabProto(obj); + CValue res; + + if (proto != NULL && cosmoO_getIString(state, proto, ISTRING_TONUMBER, &res)) { + cosmoV_pushValue(state, res); + cosmoV_pushValue(state, cosmoV_newObj(obj)); + if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, expect 1 return val of + return 0; + + StkPtr temp = cosmoV_getTop(state, 0); + if (!IS_NUMBER(*temp)) { + cosmoV_error(state, "__tonumber expected to return , got %s!", cosmoV_typeStr(*temp)); + return 0; + } + + // return number + cosmoV_pop(state); + return cosmoV_readNumber(*temp); + } + switch (obj->type) { case COBJ_STRING: { CObjString *str = (CObjString*)obj; @@ -479,7 +499,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)); - if (!cosmoV_call(state, 1, 1) != COSMOVM_OK) // call ret, we expect 1 return value of type + if (cosmoV_call(state, 1, 1) != COSMOVM_OK) // call res, we expect 1 return value of type return 0; StkPtr ret = cosmoV_getTop(state, 0); diff --git a/src/cstate.c b/src/cstate.c index 40367a5..47697b2 100644 --- a/src/cstate.c +++ b/src/cstate.c @@ -24,7 +24,7 @@ CState *cosmoV_newState() { state->grayStack.count = 0; state->grayStack.capacity = 2; state->grayStack.array = NULL; - state->allocatedBytes = 0; + state->allocatedBytes = sizeof(CState); state->nextGC = 1024 * 8; // threshhold starts at 8kb // init stack @@ -42,12 +42,13 @@ CState *cosmoV_newState() { for (int i = 0; i < ISTRING_MAX; i++) state->iStrings[i] = NULL; - cosmoT_initTable(state, &state->strings, 8); // init string table + cosmoT_initTable(state, &state->strings, 16); // init string table cosmoT_initTable(state, &state->globals, 8); // init global table // setup all strings used by the VM state->iStrings[ISTRING_INIT] = cosmoO_copyString(state, "__init", 6); state->iStrings[ISTRING_TOSTRING] = cosmoO_copyString(state, "__tostring", 10); + state->iStrings[ISTRING_TONUMBER] = cosmoO_copyString(state, "__tonumber", 10); state->iStrings[ISTRING_INDEX] = cosmoO_copyString(state, "__index", 7); state->iStrings[ISTRING_NEWINDEX] = cosmoO_copyString(state, "__newindex", 10); state->iStrings[ISTRING_COUNT] = cosmoO_copyString(state, "__count", 7); diff --git a/src/cstate.h b/src/cstate.h index 82f1797..d3df773 100644 --- a/src/cstate.h +++ b/src/cstate.h @@ -15,6 +15,7 @@ typedef struct CCallFrame { typedef enum IStringEnum { ISTRING_INIT, // __init ISTRING_TOSTRING, // __tostring + ISTRING_TONUMBER, // __tonumber ISTRING_INDEX, // __index ISTRING_NEWINDEX, // __newindex ISTRING_COUNT, // __count