Reimplement import() builtin function as a global-scope statement. This fixes #58.
All checks were successful
The build was successful.

This commit is contained in:
Rafal Kupiec 2019-12-14 23:30:38 +01:00
parent 0e757111a3
commit ad5784f81f
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
7 changed files with 88 additions and 78 deletions

View File

@ -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;
}

View File

@ -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},

View File

@ -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);

View File

@ -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 */

View File

@ -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"));
}

View File

@ -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'));
}
}

View File

@ -1,3 +1 @@
bool(FALSE)
bool(TRUE)
bool(TRUE)