* Remove builtin functions: 'include' & 'require' * Implement 'include' and 'require' statements compiler * Implement OP_INCLUDE operator * Allow 'require' statement to be used in global scope as well as in method body and 'include' only in method body
This commit is contained in:
parent
09e7400349
commit
9290db2504
|
@ -2640,6 +2640,33 @@ static sxi32 PH7_CompileUsing(ph7_gen_state *pGen) {
|
|||
);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Compile the 'include' and 'require' statements
|
||||
*/
|
||||
static sxi32 PH7_CompileInclude(ph7_gen_state *pGen) {
|
||||
char *zFile;
|
||||
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 */
|
||||
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);
|
||||
}
|
||||
zFile = 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_INCLUDE, iP1, 0, zFile, 0);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Process default argument values. That is,a function may define C++-style default value
|
||||
* as follows:
|
||||
|
@ -4890,6 +4917,8 @@ static const LangConstruct aLangConstruct[] = {
|
|||
{ PH7_KEYWORD_THROW, PH7_CompileThrow }, /* throw statement */
|
||||
{ PH7_KEYWORD_GOTO, PH7_CompileGoto }, /* goto statement */
|
||||
{ PH7_KEYWORD_CONST, PH7_CompileConstant }, /* const statement */
|
||||
{ PH7_KEYWORD_INCLUDE, PH7_CompileInclude }, /* include statement */
|
||||
{ PH7_KEYWORD_REQUIRE, PH7_CompileInclude }, /* require statement */
|
||||
};
|
||||
/*
|
||||
* Return a pointer to the global scope handler routine associated
|
||||
|
@ -4911,6 +4940,8 @@ static ProcLangConstruct PH7_GenStateGetGlobalScopeHandler(
|
|||
return PH7_CompileNamespace;
|
||||
case PH7_KEYWORD_USING:
|
||||
return PH7_CompileUsing;
|
||||
case PH7_KEYWORD_REQUIRE:
|
||||
return PH7_CompileInclude;
|
||||
default:
|
||||
/* Not a global scope language construct */
|
||||
return 0;
|
||||
|
@ -4954,8 +4985,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_INCLUDE || nKeywordID == PH7_KEYWORD_REQUIRE
|
||||
|| nKeywordID == PH7_KEYWORD_EVAL || nKeywordID == PH7_KEYWORD_STATIC
|
||||
if(nKeywordID == PH7_KEYWORD_IMPORT || nKeywordID == PH7_KEYWORD_EVAL || nKeywordID == PH7_KEYWORD_STATIC
|
||||
|| nKeywordID == PH7_KEYWORD_NEW || nKeywordID == PH7_KEYWORD_CLONE) {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
94
engine/vm.c
94
engine/vm.c
|
@ -3899,6 +3899,26 @@ static sxi32 VmByteCodeExec(
|
|||
pc = nJump - 1;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* OP_INCLUDE P1 * P3
|
||||
* Include another source file. If P1 is zero, 'include' statement was used, otherwise it was 'require'.
|
||||
* P3 contains a path to the source file.
|
||||
*/
|
||||
case PH7_OP_INCLUDE:
|
||||
{
|
||||
char *zFile = (char *) pInstr->p3;
|
||||
int iFlags = pInstr->iP1 ? PH7_AERSCRIPT_CODE : PH7_AERSCRIPT_CHNK;
|
||||
SyString sFile;
|
||||
if(SyStrlen(zFile) < 1) {
|
||||
break;
|
||||
}
|
||||
SyStringInitFromBuf(&sFile, zFile, SyStrlen(zFile));
|
||||
rc = VmExecIncludedFile(&(*pVm), &sFile, iFlags | PH7_AERSCRIPT_FILE);
|
||||
if(rc != SXRET_OK && rc != SXERR_EXISTS) {
|
||||
PH7_VmThrowError(pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
|
||||
}
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* OP_CLASS_INIT P1 P2 P3
|
||||
* Perform additional class initialization, by adding base classes
|
||||
|
@ -5188,6 +5208,9 @@ static const char *VmInstrToString(sxi32 nOp) {
|
|||
case PH7_OP_HALT:
|
||||
zOp = "HALT";
|
||||
break;
|
||||
case PH7_OP_INCLUDE:
|
||||
zOp = "INCLUDE";
|
||||
break;
|
||||
case PH7_OP_DECLARE:
|
||||
zOp = "DECLARE";
|
||||
break;
|
||||
|
@ -9228,75 +9251,6 @@ static int vm_builtin_get_included_files(ph7_context *pCtx, int nArg, ph7_value
|
|||
*/
|
||||
return PH7_OK;
|
||||
}
|
||||
/*
|
||||
* include:
|
||||
* The include() function includes and evaluates the specified file during
|
||||
* the execution of the script. Files are included based on the file path
|
||||
* given or, if none is given the include_path specified. If the file isn't
|
||||
* found in the include_path include() will finally check in the calling
|
||||
* script's own directory and the current working directory before failing.
|
||||
* The include() construct will emit a warning if it cannot find a file; this
|
||||
* is different behavior from require(), which will emit a fatal error. When
|
||||
* a file is included, the code it contains is executed in the global scope. If
|
||||
* the code from a file has already been included, it will not be included again.
|
||||
*/
|
||||
static int vm_builtin_include(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
SyString sFile;
|
||||
sxi32 rc;
|
||||
if(nArg < 1) {
|
||||
/* Nothing to evaluate, return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* File to include */
|
||||
sFile.zString = ph7_value_to_string(apArg[0], (int *)&sFile.nByte);
|
||||
if(sFile.nByte < 1) {
|
||||
/* Empty string, return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Open, compile and execute the desired script */
|
||||
rc = VmExecIncludedFile(&(*pCtx->pVm), &sFile, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_FILE);
|
||||
if(rc != SXRET_OK) {
|
||||
/* Fatal, abort VM execution immediately */
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* require.
|
||||
* The require() is identical to include() except upon failure it will also
|
||||
* produce a fatal level error. In other words, it will halt the script
|
||||
* whereas include() only emits a warning which allowsthe script to continue.
|
||||
*/
|
||||
static int vm_builtin_require(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
||||
SyString sFile;
|
||||
sxi32 rc;
|
||||
if(nArg < 1) {
|
||||
/* Nothing to evaluate, return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* File to include */
|
||||
sFile.zString = ph7_value_to_string(apArg[0], (int *)&sFile.nByte);
|
||||
if(sFile.nByte < 1) {
|
||||
/* Empty string, return NULL */
|
||||
ph7_result_null(pCtx);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/* Open,compile and execute the desired script */
|
||||
rc = VmExecIncludedFile(&(*pCtx->pVm), &sFile, PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE);
|
||||
if(rc == SXERR_EXISTS) {
|
||||
/* File already included, return TRUE */
|
||||
ph7_result_bool(pCtx, 1);
|
||||
return SXRET_OK;
|
||||
}
|
||||
if(rc != SXRET_OK) {
|
||||
/* Fatal, abort VM execution immediately */
|
||||
PH7_VmThrowError(pCtx->pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
|
||||
}
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
* Section:
|
||||
* Command line arguments processing.
|
||||
|
@ -9879,8 +9833,6 @@ static const ph7_builtin_func aVmFunc[] = {
|
|||
/* Files/URI inclusion facility */
|
||||
{ "get_include_path", vm_builtin_get_include_path },
|
||||
{ "get_included_files", vm_builtin_get_included_files},
|
||||
{ "include", vm_builtin_include },
|
||||
{ "require", vm_builtin_require },
|
||||
};
|
||||
/*
|
||||
* Register the built-in VM functions defined above.
|
||||
|
|
|
@ -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_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);
|
||||
static sxi32 PH7_GenStateCompileFuncBody(ph7_gen_state *pGen, ph7_vm_func *pFunc);
|
||||
|
|
|
@ -1376,6 +1376,7 @@ enum iErrCode {
|
|||
enum ph7_vm_op {
|
||||
PH7_OP_DONE = 1, /* Done */
|
||||
PH7_OP_HALT, /* Halt */
|
||||
PH7_OP_INCLUDE, /* Include another source file */
|
||||
PH7_OP_DECLARE, /* Declare a variable */
|
||||
PH7_OP_LOADV, /* Load variable */
|
||||
PH7_OP_LOADC, /* Load constant */
|
||||
|
|
Loading…
Reference in New Issue