mirror of
https://github.com/CPunch/Cosmo.git
synced 2024-11-22 07:20:05 +00:00
Added cosmoV_pushFString(), and cosmoO_pushVFString().
cosmoV_error now pushes the error string onto the stack, as well as uses cosmoO_VFString to format strings. cosmoV_concat is now entirely self contained, and is now stack based. Push the CValues you want to concat into strings onto the stack and call cosmoV_concat with the # of values you pushed.
This commit is contained in:
parent
de3a89ad4f
commit
31a852a127
40
src/cobj.c
40
src/cobj.c
@ -224,6 +224,46 @@ CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uin
|
|||||||
return strObj;
|
return strObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CObjString *cosmoO_pushVFString(CState *state, const char *format, va_list args) {
|
||||||
|
StkPtr start = state->top;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const char *end = strchr(format, '%'); // grab the next occurrence of '%'
|
||||||
|
if (end == NULL) // the end, no '%' found
|
||||||
|
break;
|
||||||
|
|
||||||
|
// push the string before '%'
|
||||||
|
cosmoV_pushLString(state, format, (end - format));
|
||||||
|
char c = *(end+1); // the character right after '%'
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'd': { // int
|
||||||
|
cosmoV_pushNumber(state, va_arg(args, int));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'f': { // double
|
||||||
|
cosmoV_pushNumber(state, va_arg(args, double));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 's': { // const char *
|
||||||
|
cosmoV_pushString(state, va_arg(args, char *));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
char temp[2];
|
||||||
|
temp[0] = '%';
|
||||||
|
temp[1] = c;
|
||||||
|
cosmoV_pushLString(state, temp, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format = end + 2; // + 2 because of % and the following character
|
||||||
|
}
|
||||||
|
|
||||||
|
cosmoV_pushString(state, format); // push the rest of the string
|
||||||
|
cosmoV_concat(state, state->top - start); // use cosmoV_concat to concat all the strings on the stack
|
||||||
|
return cosmoV_readString(*start); // start should be state->top - 1
|
||||||
|
}
|
||||||
|
|
||||||
bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val) {
|
bool cosmoO_getObject(CState *state, CObjObject *object, CValue key, CValue *val) {
|
||||||
if (!cosmoT_get(&object->tbl, key, val)) { // if the field doesn't exist in the object, check the proto
|
if (!cosmoT_get(&object->tbl, key, val)) { // if the field doesn't exist in the object, check the proto
|
||||||
if (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getObject(state, cosmoV_readObject(*val), key, val)) {
|
if (cosmoO_getIString(state, object, ISTRING_GETTER, val) && IS_OBJECT(*val) && cosmoO_getObject(state, cosmoV_readObject(*val), key, val)) {
|
||||||
|
@ -154,6 +154,15 @@ CObjString *cosmoO_takeString(CState *state, char *str, size_t sz);
|
|||||||
// allocates a CObjStruct pointing directly to *str
|
// allocates a CObjStruct pointing directly to *str
|
||||||
CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uint32_t hash);
|
CObjString *cosmoO_allocateString(CState *state, const char *str, size_t sz, uint32_t hash);
|
||||||
|
|
||||||
|
/*
|
||||||
|
formats strings to push onto the VM stack, formatting supported:
|
||||||
|
|
||||||
|
'%d' - decimal numbers [int]
|
||||||
|
'%f' - floating point [double]
|
||||||
|
'%s' - strings [const char*]
|
||||||
|
*/
|
||||||
|
CObjString *cosmoO_pushVFString(CState *state, const char *format, va_list args);
|
||||||
|
|
||||||
COSMO_API void printObject(CObj *o);
|
COSMO_API void printObject(CObj *o);
|
||||||
const char *cosmoO_typeStr(CObj* obj);
|
const char *cosmoO_typeStr(CObj* obj);
|
||||||
|
|
||||||
|
56
src/cvm.c
56
src/cvm.c
@ -6,6 +6,13 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
cosmoO_pushVFString(state, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
void cosmoV_error(CState *state, const char *format, ...) {
|
void cosmoV_error(CState *state, const char *format, ...) {
|
||||||
if (state->panic)
|
if (state->panic)
|
||||||
return;
|
return;
|
||||||
@ -37,14 +44,12 @@ void cosmoV_error(CState *state, const char *format, ...) {
|
|||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
vfprintf(stderr, format, args);
|
CObjString *errString = cosmoO_pushVFString(state, format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
fputs("\n", stderr);
|
|
||||||
|
|
||||||
// TODO: push error onto the stack :P
|
|
||||||
state->panic = true;
|
|
||||||
|
|
||||||
|
printf("%.*s\n", errString->length, errString->str);
|
||||||
cosmoV_printStack(state);
|
cosmoV_printStack(state);
|
||||||
|
state->panic = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjUpval *captureUpvalue(CState *state, CValue *local) {
|
CObjUpval *captureUpvalue(CState *state, CValue *local) {
|
||||||
@ -97,15 +102,30 @@ void popCallFrame(CState *state, int offset) {
|
|||||||
state->frameCount--;
|
state->frameCount--;
|
||||||
}
|
}
|
||||||
|
|
||||||
CObjString *cosmoV_concat(CState *state, CObjString *strA, CObjString *strB) {
|
void cosmoV_concat(CState *state, int vals) {
|
||||||
size_t sz = strA->length + strB->length;
|
StkPtr start = state->top - vals;
|
||||||
|
StkPtr end = cosmoV_getTop(state, 0);
|
||||||
|
|
||||||
|
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
|
||||||
|
CObjString *otherStr = cosmoV_toString(state, *current);
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(otherStr)); // also so our GC won't free otherStr
|
||||||
|
|
||||||
|
// concat the two strings together
|
||||||
|
size_t sz = result->length + otherStr->length;
|
||||||
char *buf = cosmoM_xmalloc(state, sz + 1); // +1 for null terminator
|
char *buf = cosmoM_xmalloc(state, sz + 1); // +1 for null terminator
|
||||||
|
|
||||||
memcpy(buf, strA->str, strA->length);
|
memcpy(buf, result->str, result->length);
|
||||||
memcpy(buf + strA->length, strB->str, strB->length);
|
memcpy(buf + result->length, otherStr->str, otherStr->length);
|
||||||
buf[sz] = '\0';
|
buf[sz] = '\0';
|
||||||
|
result = cosmoO_takeString(state, buf, sz);
|
||||||
|
|
||||||
return cosmoO_takeString(state, buf, sz);
|
cosmoV_setTop(state, 2); // pop result & otherStr off the stack
|
||||||
|
}
|
||||||
|
|
||||||
|
state->top = start;
|
||||||
|
cosmoV_pushValue(state, cosmoV_newObj(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
int cosmoV_execute(CState *state);
|
int cosmoV_execute(CState *state);
|
||||||
@ -726,21 +746,7 @@ int cosmoV_execute(CState *state) {
|
|||||||
}
|
}
|
||||||
case OP_CONCAT: {
|
case OP_CONCAT: {
|
||||||
uint8_t vals = READBYTE();
|
uint8_t vals = READBYTE();
|
||||||
StkPtr start = state->top - vals;
|
cosmoV_concat(state, vals);
|
||||||
StkPtr end = cosmoV_getTop(state, 0);
|
|
||||||
|
|
||||||
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
|
|
||||||
CObjString *otherStr = cosmoV_toString(state, *current);
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(otherStr)); // also so our GC won't free otherStr
|
|
||||||
result = cosmoV_concat(state, result, otherStr);
|
|
||||||
|
|
||||||
cosmoV_setTop(state, 2); // pop result & otherStr off the stack
|
|
||||||
}
|
|
||||||
|
|
||||||
state->top = start;
|
|
||||||
cosmoV_pushValue(state, cosmoV_newObj(result));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OP_INCLOCAL: { // this leaves the value on the stack
|
case OP_INCLOCAL: { // this leaves the value on the stack
|
||||||
|
@ -17,6 +17,8 @@ COSMO_API COSMOVMRESULT cosmoV_call(CState *state, int args, int nresults);
|
|||||||
COSMO_API void cosmoV_makeObject(CState *state, int pairs);
|
COSMO_API void cosmoV_makeObject(CState *state, int pairs);
|
||||||
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs);
|
COSMO_API void cosmoV_makeDictionary(CState *state, int pairs);
|
||||||
COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, CValue *val);
|
COSMO_API bool cosmoV_getObject(CState *state, CObjObject *object, CValue key, CValue *val);
|
||||||
|
COSMO_API void cosmoV_concat(CState *state, int vals);
|
||||||
|
COSMO_API void cosmoV_pushFString(CState *state, const char *format, ...);
|
||||||
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
COSMO_API void cosmoV_error(CState *state, const char *format, ...);
|
||||||
|
|
||||||
// nice to have wrappers
|
// nice to have wrappers
|
||||||
|
@ -52,6 +52,7 @@ static void repl() {
|
|||||||
cosmoB_loadLibrary(state);
|
cosmoB_loadLibrary(state);
|
||||||
cosmoB_loadDebug(state);
|
cosmoB_loadDebug(state);
|
||||||
|
|
||||||
|
// add our custom REPL functions
|
||||||
cosmoV_pushString(state, "quit");
|
cosmoV_pushString(state, "quit");
|
||||||
cosmoV_pushCFunction(state, cosmoB_quitRepl);
|
cosmoV_pushCFunction(state, cosmoB_quitRepl);
|
||||||
|
|
||||||
@ -111,6 +112,12 @@ static void runFile(const char* fileName) {
|
|||||||
CState *state = cosmoV_newState();
|
CState *state = cosmoV_newState();
|
||||||
cosmoB_loadLibrary(state);
|
cosmoB_loadLibrary(state);
|
||||||
|
|
||||||
|
// add our input() function to the global table
|
||||||
|
cosmoV_pushString(state, "input");
|
||||||
|
cosmoV_pushCFunction(state, cosmoB_input);
|
||||||
|
|
||||||
|
cosmoV_register(state, 1);
|
||||||
|
|
||||||
interpret(state, script, fileName);
|
interpret(state, script, fileName);
|
||||||
|
|
||||||
cosmoV_freeState(state);
|
cosmoV_freeState(state);
|
||||||
|
Loading…
Reference in New Issue
Block a user