diff --git a/engine/compiler.c b/engine/compiler.c index f8c1b88..95644b7 100644 --- a/engine/compiler.c +++ b/engine/compiler.c @@ -2640,6 +2640,32 @@ static sxi32 PH7_CompileUsing(ph7_gen_state *pGen) { ); return SXRET_OK; } +/* + * Compile the 'import' statement + */ +static sxi32 PH7_CompileImport(ph7_gen_state *pGen) { + char *zModule; + sxu32 nLine = pGen->pIn->nLine; + /* Jump the 'import' keyword */ + pGen->pIn++; + if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_SSTR | PH7_TK_DSTR)) == 0) { + if(pGen->pIn >= pGen->pEnd) { + pGen->pIn--; + } + /* Unexpected token */ + PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Include: Unexpected token '%z'", &pGen->pIn->sData); + } + zModule = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn->sData.zString, pGen->pIn->sData.nByte); + pGen->pIn++; + if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI/*';'*/) == 0) { + /* Unexpected token */ + PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Include: Unexpected token '%z', expecting ';'", + &pGen->pIn->sData); + } + PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_IMPORT, 0, 0, zModule, 0); + return SXRET_OK; +} + /* * Compile the 'include' and 'require' statements */ @@ -2648,7 +2674,7 @@ static sxi32 PH7_CompileInclude(ph7_gen_state *pGen) { sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData)); sxu32 nLine = pGen->pIn->nLine; sxi32 iP1 = (nKey == PH7_KEYWORD_REQUIRE) ? 1 : 0; - /* Jump the 'require' keyword */ + /* Jump the 'include' or 'require' keyword */ pGen->pIn++; if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_SSTR | PH7_TK_DSTR)) == 0) { if(pGen->pIn >= pGen->pEnd) { @@ -4940,6 +4966,8 @@ static ProcLangConstruct PH7_GenStateGetGlobalScopeHandler( return PH7_CompileNamespace; case PH7_KEYWORD_USING: return PH7_CompileUsing; + case PH7_KEYWORD_IMPORT: + return PH7_CompileImport; case PH7_KEYWORD_REQUIRE: return PH7_CompileInclude; default: @@ -4985,7 +5013,7 @@ static ProcLangConstruct PH7_GenStateGetStatementHandler( * Return TRUE if the given ID represent a language construct. FALSE otherwise. */ static int PH7_IsLangConstruct(sxu32 nKeywordID) { - if(nKeywordID == PH7_KEYWORD_IMPORT || nKeywordID == PH7_KEYWORD_EVAL || nKeywordID == PH7_KEYWORD_STATIC + if(nKeywordID == PH7_KEYWORD_EVAL || nKeywordID == PH7_KEYWORD_STATIC || nKeywordID == PH7_KEYWORD_NEW || nKeywordID == PH7_KEYWORD_CLONE) { return TRUE; } diff --git a/engine/vm.c b/engine/vm.c index f3118b1..ee3da82 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -3899,6 +3899,55 @@ static sxi32 VmByteCodeExec( pc = nJump - 1; break; } + case PH7_OP_IMPORT: + { + VmModule pModule, *pSearch; + char *zModule = (char *) pInstr->p3; + int nLen = SyStrlen(zModule); + if(nLen < 1) { + break; + } + while(SySetGetNextEntry(&pVm->aModules, (void **)&pSearch) == SXRET_OK) { + if(SyStrncmp(pSearch->sName.zString, zModule, (sxu32)(SXMAX((int) pSearch->sName.nByte, nLen))) == 0) { + SySetResetCursor(&pVm->aModules); + break; + } + } + SySetResetCursor(&pVm->aModules); + + /* Zero the module entry */ + SyZero(&pModule, sizeof(VmModule)); + SyStringInitFromBuf(&pModule.sName, zModule, nLen); + char bfile[255] = {0}; + char *file; + snprintf(bfile, sizeof(bfile) - 1, "./binary/%s%s", zModule, PH7_LIBRARY_SUFFIX); + file = bfile; + SyStringInitFromBuf(&pModule.sFile, file, nLen); +#ifdef __WINNT__ + pModule.pHandle = LoadLibrary(file); +#else + pModule.pHandle = dlopen(pModule.sFile.zString, RTLD_LAZY); +#endif + if(!pModule.pHandle) { + /* Could not load the module library file */ + PH7_VmThrowError(pVm, PH7_CTX_ERR, "ImportError: No module named '%z' found", &pModule.sName); + } + void (*init)(ph7_vm *, ph7_real *, SyString *); +#ifdef __WINNT__ + *(void**)(&init) = GetProcAddress(pModule.pHandle, "initializeModule"); +#else + *(void**)(&init) = dlsym(pModule.pHandle, "initializeModule"); +#endif + if(!init) { + PH7_VmThrowError(pVm, PH7_CTX_ERR, "ImportError: Method '%z::initializeModule()' not found", &pModule.sName); + /* Could not find the module entry point */ + } + /* Initialize the module */ + init(pVm, &pModule.fVer, &pModule.sDesc); + /* Put information about module on top of the modules stack */ + SySetPut(&pVm->aModules, (const void *)&pModule); + break; + } /* * OP_INCLUDE P1 * P3 * Include another source file. If P1 is zero, 'include' statement was used, otherwise it was 'require'. @@ -5208,6 +5257,9 @@ static const char *VmInstrToString(sxi32 nOp) { case PH7_OP_HALT: zOp = "HALT"; break; + case PH7_OP_IMPORT: + zOp = "IMPORT"; + break; case PH7_OP_INCLUDE: zOp = "INCLUDE"; break; @@ -9108,75 +9160,6 @@ static sxi32 VmExecIncludedFile( SyBlobRelease(&sContents); return rc; } -/* - * bool import(string $library) - * Loads an AerScript module library at runtime - * Parameters - * $library - * This parameter is only the module library name that should be loaded. - * Return - * Returns TRUE on success or FALSE on failure - */ -static int vm_builtin_import(ph7_context *pCtx, int nArg, ph7_value **apArg) { - const char *zStr; - VmModule pModule, *pSearch; - int nLen; - if(nArg != 1 || !ph7_value_is_string(apArg[0])) { - /* Missing/Invalid arguments, return FALSE */ - ph7_result_bool(pCtx, 0); - return PH7_OK; - } - /* Extract the given module name */ - zStr = ph7_value_to_string(apArg[0], &nLen); - if(nLen < 1) { - /* Nothing to process, return FALSE */ - ph7_result_bool(pCtx, 0); - return PH7_OK; - } - while(SySetGetNextEntry(&pCtx->pVm->aModules, (void **)&pSearch) == SXRET_OK) { - if(SyStrncmp(pSearch->sName.zString, zStr, (sxu32)(SXMAX((int) pSearch->sName.nByte, nLen))) == 0) { - SySetResetCursor(&pCtx->pVm->aModules); - ph7_result_bool(pCtx, 1); - return PH7_OK; - } - } - SySetResetCursor(&pCtx->pVm->aModules); - /* Zero the module entry */ - SyZero(&pModule, sizeof(VmModule)); - SyStringInitFromBuf(&pModule.sName, zStr, nLen); - char bfile[255] = {0}; - char *file; - snprintf(bfile, sizeof(bfile) - 1, "./binary/%s%s", zStr, PH7_LIBRARY_SUFFIX); - file = bfile; - SyStringInitFromBuf(&pModule.sFile, file, nLen); -#ifdef __WINNT__ - pModule.pHandle = LoadLibrary(file); -#else - pModule.pHandle = dlopen(pModule.sFile.zString, RTLD_LAZY); -#endif - if(!pModule.pHandle) { - /* Could not load the module library file */ - ph7_result_bool(pCtx, 0); - return PH7_OK; - } - void (*init)(ph7_vm *, ph7_real *, SyString *); -#ifdef __WINNT__ - *(void**)(&init) = GetProcAddress(pModule.pHandle, "initializeModule"); -#else - *(void**)(&init) = dlsym(pModule.pHandle, "initializeModule"); -#endif - if(!init) { - /* Could not find the module entry point */ - ph7_result_bool(pCtx, 0); - return PH7_OK; - } - /* Initialize the module */ - init(pCtx->pVm, &pModule.fVer, &pModule.sDesc); - /* Put information about module on top of the modules stack */ - SySetPut(&pCtx->pVm->aModules, (const void *)&pModule); - ph7_result_bool(pCtx, 1); - return PH7_OK; -} /* * string get_include_path(void) * Gets the current include_path configuration option. @@ -9828,8 +9811,6 @@ static const ph7_builtin_func aVmFunc[] = { {"utf8_decode", vm_builtin_utf8_decode}, /* Command line processing */ {"getopt", vm_builtin_getopt }, - /* Module loading facility */ - { "import", vm_builtin_import }, /* Files/URI inclusion facility */ { "get_include_path", vm_builtin_get_include_path }, { "get_included_files", vm_builtin_get_included_files}, diff --git a/include/compiler.h b/include/compiler.h index 6988814..6054101 100644 --- a/include/compiler.h +++ b/include/compiler.h @@ -136,6 +136,7 @@ static sxi32 PH7_CompileHalt(ph7_gen_state *pGen); static sxi32 PH7_CompileVar(ph7_gen_state *pGen); static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen); static sxi32 PH7_CompileUsing(ph7_gen_state *pGen); +static sxi32 PH7_CompileImport(ph7_gen_state *pGen); static sxi32 PH7_CompileInclude(ph7_gen_state *pGen); static sxi32 PH7_GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd); static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd); diff --git a/include/ph7int.h b/include/ph7int.h index d8ca4af..9571052 100644 --- a/include/ph7int.h +++ b/include/ph7int.h @@ -1376,6 +1376,7 @@ enum iErrCode { enum ph7_vm_op { PH7_OP_DONE = 1, /* Done */ PH7_OP_HALT, /* Halt */ + PH7_OP_IMPORT, /* Import AerScript module */ PH7_OP_INCLUDE, /* Include another source file */ PH7_OP_DECLARE, /* Declare a variable */ PH7_OP_LOADV, /* Load variable */ diff --git a/tests/int2alpha_test.aer b/tests/int2alpha_test.aer index 38e6bbe..d85ba11 100644 --- a/tests/int2alpha_test.aer +++ b/tests/int2alpha_test.aer @@ -1,3 +1,5 @@ +import 'math'; + class Program { private string num2alpha(int $n) { @@ -19,7 +21,6 @@ class Program { } public void main() { - import('math'); var_dump($this->alpha2num("Salut"), $this->num2alpha(1723), $this->num2alpha(9854), $this->alpha2num("Base64")); } diff --git a/tests/load_module.aer b/tests/load_module.aer index ecdb99a..0f88997 100644 --- a/tests/load_module.aer +++ b/tests/load_module.aer @@ -1,7 +1,7 @@ +import 'dummy'; + final class Program { public void main() { var_dump(function_exists('dummy_function')); - var_dump(import('dummy')); - var_dump(function_exists('dummy_function')); } } diff --git a/tests/load_module.exp b/tests/load_module.exp index b551b69..64cb09b 100644 --- a/tests/load_module.exp +++ b/tests/load_module.exp @@ -1,3 +1 @@ -bool(FALSE) -bool(TRUE) bool(TRUE)