diff --git a/include/jstar/jstar.h b/include/jstar/jstar.h index f74e5e00..68b40240 100644 --- a/include/jstar/jstar.h +++ b/include/jstar/jstar.h @@ -176,7 +176,11 @@ JSTAR_API void jsrPushTuple(JStarVM* vm, size_t size); JSTAR_API void jsrPushTable(JStarVM* vm); JSTAR_API void jsrPushValue(JStarVM* vm, int slot); JSTAR_API void* jsrPushUserdata(JStarVM* vm, size_t size, void (*finalize)(void*)); -JSTAR_API void jsrPushNative(JStarVM* vm, const char* module, const char* name, JStarNative nat, + +// Push a native function to the top of the stack. +// Returns true on success, leaving the native function on top of the stack. +// Retruns false if the module could not be found, leaving an exception on top of the stack. +JSTAR_API bool jsrPushNative(JStarVM* vm, const char* module, const char* name, JStarNative nat, uint8_t argc); #define jsrDup(vm) jsrPushValue(vm, -1) @@ -334,14 +338,14 @@ JSTAR_API size_t jsrGetLength(JStarVM* vm, int slot); // INSTANCE API // ----------------------------------------------------------------------------- -// Set the field `name` of the value at `slot` with the value on top of the stack -// The value is not popped -// Returns true in case of success -// Returns false otherwise leaving an exception on top of the stack +// Set the field `name` of the value at `slot` with the value on top of the stack. +// The value is not popped. +// Returns true in case of success. +// Returns false otherwise leaving an exception on top of the stack. JSTAR_API bool jsrSetField(JStarVM* vm, int slot, const char* name); -// Get the field `name` of the value at `slot` -// Returns true in case of success leaving the result on top of the stack +// Get the field `name` of the value at `slot`. +// Returns true in case of success leaving the result on top of the stack. // Returns false otherwise leaving an exception on top of the stack. JSTAR_API bool jsrGetField(JStarVM* vm, int slot, const char* name); @@ -349,15 +353,18 @@ JSTAR_API bool jsrGetField(JStarVM* vm, int slot, const char* name); // MODULE API // ----------------------------------------------------------------------------- -// Set the global `name` of the module `module` with the value on top of the stack -// The value is not popped -// If calling inside a native "module" can be NULL, and the used module will be the current one -JSTAR_API void jsrSetGlobal(JStarVM* vm, const char* module, const char* name); +// Set the global `name` of the module `module` with the value on top of the stack. +// The value is not popped. +// If calling inside a native "module" can be NULL, and the used module will be the current one. +// Returns true in case of success, false if the module could not be found, leaving an exception +// on top of the stack. +JSTAR_API bool jsrSetGlobal(JStarVM* vm, const char* module, const char* name); -// Get the global `name` of the module `module` -// Returns true in case of success leaving the result on the top of the stack -// Returns false otherwise leaving an exception on top of the stack -// If calling inside a native "module" can be NULL, and the used module will be the current one +// Get the global `name` of the module `module`. +// Returns true in case of success leaving the result on the top of the stack. +// Returns false if the module could not be found or the name could not be found in the module, +// leaving an exception on top of the stack. +// If calling inside a native "module" can be NULL, and the used module will be the current one. JSTAR_API bool jsrGetGlobal(JStarVM* vm, const char* module, const char* name); // ----------------------------------------------------------------------------- diff --git a/src/jstar.c b/src/jstar.c index 2c92fd21..b0885803 100644 --- a/src/jstar.c +++ b/src/jstar.c @@ -54,6 +54,19 @@ static Value apiStackSlot(const JStarVM* vm, int slot) { return vm->apiStack[slot]; } +static ObjModule* getModuleOrRaise(JStarVM* vm, const char* module) { + ObjModule* mod = module ? getModule(vm, copyString(vm, module, strlen(module))) : vm->module; + if(!mod) { + if(module) + jsrRaise(vm, "ImportException", "Module '%s' not found.", module); + else + jsrRaise(vm, "ImportException", + "No current module loaded, pass an explicit module name."); + return NULL; + } + return mod; +} + void jsrPrintErrorCB(JStarVM* vm, JStarResult err, const char* file, int line, const char* error) { if(line >= 0) { fprintf(stderr, "File %s [line:%d]:\n", file, line); @@ -510,11 +523,11 @@ void* jsrPushUserdata(JStarVM* vm, size_t size, void (*finalize)(void*)) { return (void*)udata->data; } -void jsrPushNative(JStarVM* vm, const char* module, const char* name, JStarNative nat, +bool jsrPushNative(JStarVM* vm, const char* module, const char* name, JStarNative nat, uint8_t argc) { checkStack(vm); - ObjModule* mod = getModule(vm, copyString(vm, module, strlen(module))); - JSR_ASSERT(mod, "Cannot find module"); + ObjModule* mod = getModuleOrRaise(vm, module); + if(!mod) return false; ObjString* nativeName = copyString(vm, name, strlen(name)); push(vm, OBJ_VAL(nativeName)); @@ -524,6 +537,7 @@ void jsrPushNative(JStarVM* vm, const char* module, const char* name, JStarNativ pop(vm); push(vm, OBJ_VAL(native)); + return true; } void jsrPop(JStarVM* vm) { @@ -542,10 +556,11 @@ int jsrTop(const JStarVM* vm) { return apiStackIndex(vm, -1); } -void jsrSetGlobal(JStarVM* vm, const char* module, const char* name) { - ObjModule* mod = module ? getModule(vm, copyString(vm, module, strlen(module))) : vm->module; - JSR_ASSERT(mod, "Module doesn't exist"); +bool jsrSetGlobal(JStarVM* vm, const char* module, const char* name) { + ObjModule* mod = getModuleOrRaise(vm, module); + if(!mod) return false; hashTablePut(&mod->globals, copyString(vm, name, strlen(name)), peek(vm)); + return true; } bool jsrIter(JStarVM* vm, int iterable, int res, bool* err) { @@ -661,8 +676,8 @@ bool jsrGetField(JStarVM* vm, int slot, const char* name) { } bool jsrGetGlobal(JStarVM* vm, const char* module, const char* name) { - ObjModule* mod = module ? getModule(vm, copyString(vm, module, strlen(module))) : vm->module; - JSR_ASSERT(mod, "Module doesn't exist"); + ObjModule* mod = getModuleOrRaise(vm, module); + if(!mod) return false; Value res; ObjString* nameStr = copyString(vm, name, strlen(name));