From 025ede86a45ee1cfd4d0b7b63f8bc054444614bf Mon Sep 17 00:00:00 2001 From: Thakee Nathees Date: Sat, 3 Jul 2021 21:54:36 +0530 Subject: [PATCH] Fix: Main function of native modules were NULL (#161) This is handled and the crash were fixed --- src/pk_compiler.c | 8 ++++++-- src/pk_core.c | 14 +++++++------- src/pk_var.c | 25 ++++++++++++++----------- src/pk_var.h | 12 +++++++++++- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/pk_compiler.c b/src/pk_compiler.c index ad1c2e8..e278432 100644 --- a/src/pk_compiler.c +++ b/src/pk_compiler.c @@ -2766,7 +2766,7 @@ static void compileTopLevelStatement(Compiler* compiler) { } PkResult compile(PKVM* vm, Script* script, const char* source, - const PkCompileOptions* options) { + const PkCompileOptions* options) { // Skip utf8 BOM if there is any. if (strncmp(source, "\xEF\xBB\xBF", 3) == 0) source += 3; @@ -2781,10 +2781,14 @@ PkResult compile(PKVM* vm, Script* script, const char* source, compiler->next_compiler = vm->compiler; vm->compiler = compiler; + // If the script doesn't has a body by default, it's probably was created by + // the native api function (pkNewModule() that'll return a module without a + // main function) so just create and add the function here. + if (script->body == NULL) scriptAddMain(vm, script); + // If we're compiling for a script that was already compiled (when running // REPL or evaluating an expression) we don't need the old main anymore. // just use the globals and functions of the script and use a new body func. - ASSERT(script->body != NULL, OOPS); pkByteBufferClear(&script->body->fn->opcodes, vm); // Remember the count of the globals, functions and types, If the compilation diff --git a/src/pk_core.c b/src/pk_core.c index 347d9fe..97c4cf7 100644 --- a/src/pk_core.c +++ b/src/pk_core.c @@ -38,7 +38,7 @@ // Create a new module with the given [name] and returns as a Script* for // internal. Which will be wrapped by pkNewModule to return a pkHandle*. -static Script* newModuleInternal(PKVM* vm, const char* name, bool is_core); +static Script* newModuleInternal(PKVM* vm, const char* name); // The internal function to add global value to a module. static void moduleAddGlobalInternal(PKVM* vm, Script* script, @@ -51,7 +51,7 @@ static void moduleAddFunctionInternal(PKVM* vm, Script* script, // pkNewModule implementation (see pocketlang.h for description). PkHandle* pkNewModule(PKVM* vm, const char* name) { - Script* module = newModuleInternal(vm, name, false); + Script* module = newModuleInternal(vm, name); return vmNewHandle(vm, VAR_OBJ(module)); } @@ -743,7 +743,7 @@ DEF(coreMapRemove, /*****************************************************************************/ // Create a module and add it to the vm's core modules, returns the script. -static Script* newModuleInternal(PKVM* vm, const char* name, bool is_core) { +static Script* newModuleInternal(PKVM* vm, const char* name) { // Create a new Script for the module. String* _name = newString(vm, name); @@ -757,7 +757,7 @@ static Script* newModuleInternal(PKVM* vm, const char* name, bool is_core) { "A module named '$' already exists", name)->data); } - Script* scr = newScript(vm, _name, is_core); + Script* scr = newScript(vm, _name, true); vmPopTempRef(vm); // _name // Add the script to core_libs. @@ -1182,7 +1182,7 @@ void initializeCore(PKVM* vm) { // Core Modules ///////////////////////////////////////////////////////////// - Script* lang = newModuleInternal(vm, "lang", true); + Script* lang = newModuleInternal(vm, "lang"); MODULE_ADD_FN(lang, "clock", stdLangClock, 0); MODULE_ADD_FN(lang, "gc", stdLangGC, 0); MODULE_ADD_FN(lang, "disas", stdLangDisas, 1); @@ -1191,7 +1191,7 @@ void initializeCore(PKVM* vm) { MODULE_ADD_FN(lang, "debug_break", stdLangDebugBreak, 0); #endif - Script* math = newModuleInternal(vm, "math", true); + Script* math = newModuleInternal(vm, "math"); MODULE_ADD_FN(math, "floor", stdMathFloor, 1); MODULE_ADD_FN(math, "ceil", stdMathCeil, 1); MODULE_ADD_FN(math, "pow", stdMathPow, 2); @@ -1218,7 +1218,7 @@ void initializeCore(PKVM* vm) { // attribute of a core module and we can throw an error. moduleAddGlobalInternal(vm, math, "PI", VAR_NUM(M_PI)); - Script* fiber = newModuleInternal(vm, "Fiber", true); + Script* fiber = newModuleInternal(vm, "Fiber"); MODULE_ADD_FN(fiber, "new", stdFiberNew, 1); MODULE_ADD_FN(fiber, "run", stdFiberRun, -1); MODULE_ADD_FN(fiber, "resume", stdFiberResume, -1); diff --git a/src/pk_var.c b/src/pk_var.c index c4dc5db..7972ed1 100644 --- a/src/pk_var.c +++ b/src/pk_var.c @@ -375,15 +375,11 @@ Script* newScript(PKVM* vm, String* name, bool is_core) { script->path = name; script->module = NULL; - script->initialized = false; + script->initialized = is_core; script->body = NULL; - // Core modules has its name as the module name, and since they don't have a - // main function, they doesn't need an initialization. - if (is_core) { - script->module = name; - script->initialized = true; - } + // Core modules has its name as the module name. + if (is_core) script->module = name; pkVarBufferInit(&script->globals); pkUintBufferInit(&script->global_names); @@ -396,10 +392,7 @@ Script* newScript(PKVM* vm, String* name, bool is_core) { // if it's not a core module. if (!is_core) { vmPushTempRef(vm, &script->_super); - const char* fn_name = PK_IMPLICIT_MAIN_NAME; - script->body = newFunction(vm, fn_name, (int)strlen(fn_name), - script, false, NULL/*TODO*/); - script->body->arity = 0; + scriptAddMain(vm, script); // Add '__file__' variable with it's path as value. If the path starts with // '$' It's a special file ($(REPL) or $(TRY)) and don't define __file__. @@ -1159,6 +1152,16 @@ uint32_t scriptAddGlobal(PKVM* vm, Script* script, return script->globals.count - 1; } +void scriptAddMain(PKVM* vm, Script* script) { + ASSERT(script->body == NULL, OOPS); + + const char* fn_name = PK_IMPLICIT_MAIN_NAME; + script->body = newFunction(vm, fn_name, (int)strlen(fn_name), + script, false, NULL/*TODO*/); + script->body->arity = 0; + script->initialized = false; +} + bool instGetAttrib(PKVM* vm, Instance* inst, String* attrib, Var* value) { ASSERT(inst != NULL, OOPS); ASSERT(attrib != NULL, OOPS); diff --git a/src/pk_var.h b/src/pk_var.h index 0b86074..a45daf5 100644 --- a/src/pk_var.h +++ b/src/pk_var.h @@ -295,7 +295,11 @@ struct Script { pkVarBuffer literals; //< Script literal constant values. Function* body; //< Script body is an anonymous function. - bool initialized; //< Set to true just before the body executed. + + // When a script has globals, it's body need to be executed to initialize the + // global values, this will be false if the module isn't initialized yet and + // we need to execute the script's body whe we're importing it. + bool initialized; }; // Script function pointer. @@ -588,6 +592,12 @@ uint32_t scriptAddGlobal(PKVM* vm, Script* script, const char* name, uint32_t length, Var value); +// This will allocate a new implicit main function for the script and assign to +// the script's body attribute. And the attribute initialized will be set to +// false for the new function. Note that the body of the script should be NULL +// before calling this function. +void scriptAddMain(PKVM* vm, Script* script); + // Get the attribut from the instance and set it [value]. On success return // true, if the attribute not exists it'll return false but won't set an error. bool instGetAttrib(PKVM* vm, Instance* inst, String* attrib, Var* value);