Keep source file descriptors stable for the lifetime of the VM and execute included fragments in the enclosing method and closure context
Build / AerScript (push) Successful in 40s
Build / AerScript (push) Successful in 40s
This commit is contained in:
+141
-6
@@ -237,6 +237,7 @@ static sxi32 GenStateFixGoto(ph7_gen_state *pGen, sxu32 nOfft)
|
|||||||
pInstr = PH7_VmGetInstr(pGen->pVm, pJump->nInstrIdx);
|
pInstr = PH7_VmGetInstr(pGen->pVm, pJump->nInstrIdx);
|
||||||
if(pInstr) {
|
if(pInstr) {
|
||||||
pInstr->iP2 = pLabel->nJumpDest;
|
pInstr->iP2 = pLabel->nJumpDest;
|
||||||
|
pInstr->iP1 = pLabel->bExternal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
@@ -1127,7 +1128,8 @@ static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen) {
|
|||||||
if(pObj == 0) {
|
if(pObj == 0) {
|
||||||
PH7_GenCompileError(pGen, E_ERROR, pToken->nLine, "PH7 engine is running out-of-memory");
|
PH7_GenCompileError(pGen, E_ERROR, pToken->nLine, "PH7 engine is running out-of-memory");
|
||||||
}
|
}
|
||||||
SyString *pFile = (SyString *)SySetPeek(&pGen->pVm->aFiles);
|
SyString **ppFile = (SyString **)SySetPeek(&pGen->pVm->aFiles);
|
||||||
|
SyString *pFile = ppFile ? *ppFile : 0;
|
||||||
if(pFile == 0) {
|
if(pFile == 0) {
|
||||||
SyString pMemory;
|
SyString pMemory;
|
||||||
SyStringInitFromBuf(&pMemory, "[MEMORY]", (int)sizeof("[MEMORY]") - 1);
|
SyStringInitFromBuf(&pMemory, "[MEMORY]", (int)sizeof("[MEMORY]") - 1);
|
||||||
@@ -1380,6 +1382,10 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) {
|
|||||||
PH7_GenCompileError(pGen, E_ERROR, nLine, "A 'continue' statement may only be used within a loop");
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "A 'continue' statement may only be used within a loop");
|
||||||
} else {
|
} else {
|
||||||
sxu32 nInstrIdx = 0;
|
sxu32 nInstrIdx = 0;
|
||||||
|
if(pLoop->iFlags & GEN_BLOCK_INCLUDE) {
|
||||||
|
ph7_include *pInclude = (ph7_include *)pLoop->pUserData;
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 1, pInclude->nContinue, 0, 0);
|
||||||
|
} else {
|
||||||
if(!pLoop->bPostContinue) {
|
if(!pLoop->bPostContinue) {
|
||||||
/* Emit the OP_LF_STOP instruction to leave the loop frame */
|
/* Emit the OP_LF_STOP instruction to leave the loop frame */
|
||||||
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
|
||||||
@@ -1393,6 +1399,7 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) {
|
|||||||
SySetPut(&pLoop->aPostContFix, (const void *)&sJumpFix);
|
SySetPut(&pLoop->aPostContFix, (const void *)&sJumpFix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI) == 0) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI) == 0) {
|
||||||
/* Not so fatal, emit a warning only */
|
/* Not so fatal, emit a warning only */
|
||||||
PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, "Expected semi-colon ';' after 'continue' statement");
|
PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, "Expected semi-colon ';' after 'continue' statement");
|
||||||
@@ -1421,6 +1428,10 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) {
|
|||||||
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "A 'break' statement may only be used within a loop or switch");
|
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "A 'break' statement may only be used within a loop or switch");
|
||||||
} else {
|
} else {
|
||||||
sxu32 nInstrIdx;
|
sxu32 nInstrIdx;
|
||||||
|
if(pLoop->iFlags & GEN_BLOCK_INCLUDE) {
|
||||||
|
ph7_include *pInclude = (ph7_include *)pLoop->pUserData;
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 1, pInclude->nBreak, 0, 0);
|
||||||
|
} else {
|
||||||
if((pLoop->iFlags & GEN_BLOCK_SWITCH) == 0) {
|
if((pLoop->iFlags & GEN_BLOCK_SWITCH) == 0) {
|
||||||
/* Emit the OP_LF_STOP instruction to leave the loop frame */
|
/* Emit the OP_LF_STOP instruction to leave the loop frame */
|
||||||
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
|
||||||
@@ -1431,6 +1442,7 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) {
|
|||||||
PH7_GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx);
|
PH7_GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI) == 0) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI) == 0) {
|
||||||
/* Not so fatal,emit a warning only */
|
/* Not so fatal,emit a warning only */
|
||||||
PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, "Expected semi-colon ';' after 'break' statement");
|
PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, "Expected semi-colon ';' after 'break' statement");
|
||||||
@@ -1469,6 +1481,7 @@ static sxi32 PH7_CompileLabel(ph7_gen_state *pGen)
|
|||||||
}
|
}
|
||||||
SyStringInitFromBuf(&sLabel.sName, zDup, pTarget->nByte);
|
SyStringInitFromBuf(&sLabel.sName, zDup, pTarget->nByte);
|
||||||
sLabel.bRef = FALSE;
|
sLabel.bRef = FALSE;
|
||||||
|
sLabel.bExternal = FALSE;
|
||||||
sLabel.nLine = pGen->pIn->nLine;
|
sLabel.nLine = pGen->pIn->nLine;
|
||||||
pBlock = pGen->pCurrent;
|
pBlock = pGen->pCurrent;
|
||||||
while(pBlock) {
|
while(pBlock) {
|
||||||
@@ -2315,10 +2328,9 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) {
|
|||||||
* of the current function, and returns its argument as the value of the function call.
|
* of the current function, and returns its argument as the value of the function call.
|
||||||
* return() will also end the execution of an eval() statement or script file.
|
* return() will also end the execution of an eval() statement or script file.
|
||||||
* If called from the global scope, then execution of the current script file is ended.
|
* If called from the global scope, then execution of the current script file is ended.
|
||||||
* If the current script file was include()ed or require()ed, then control is passed back
|
* An included method/closure chunk shares its caller's return boundary. A required
|
||||||
* to the calling file. Furthermore, if the current script file was include()ed, then the value
|
* global script retains its own execution boundary. If return() is called from
|
||||||
* given to return() will be returned as the value of the include() call. If return() is called
|
* within the main script file, then script execution ends.
|
||||||
* from within the main script file, then script execution end.
|
|
||||||
* Note that since return() is a language construct and not a function, the parentheses
|
* Note that since return() is a language construct and not a function, the parentheses
|
||||||
* surrounding its arguments are not required. It is common to leave them out, and you actually
|
* surrounding its arguments are not required. It is common to leave them out, and you actually
|
||||||
* should do so as Aer has less work to do in this case.
|
* should do so as Aer has less work to do in this case.
|
||||||
@@ -2670,6 +2682,30 @@ static sxi32 PH7_CompileImport(ph7_gen_state *pGen) {
|
|||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Resolve include-to-owner gotos only after the owner's labels are known.
|
||||||
|
* Bridges also let nested includes forward a transfer one bytecode at a time. */
|
||||||
|
static void GenStateFixIncludeLabels(ph7_gen_state *pGen) {
|
||||||
|
sxu32 n, j, nCount = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
for(n = 0; n < nCount; n++) {
|
||||||
|
VmInstr *pInstr = PH7_VmGetInstr(pGen->pVm, n);
|
||||||
|
if(pInstr->iOp == PH7_OP_INCLUDE && !pInstr->iP1 && pInstr->iP2) {
|
||||||
|
ph7_include *pInclude = (ph7_include *)pInstr->p3;
|
||||||
|
sxu32 nSkip;
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_JMP, 0, 0, 0, &nSkip);
|
||||||
|
for(j = 0; j < SySetUsed(&pGen->aLabel); j++) {
|
||||||
|
Label sLabel = *(Label *)SySetAt(&pGen->aLabel, j);
|
||||||
|
if(sLabel.pFunc == pInclude->pFunc) {
|
||||||
|
sxu32 nDest = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_JMP, sLabel.bExternal, sLabel.nJumpDest, 0, 0);
|
||||||
|
sLabel.nJumpDest = nDest;
|
||||||
|
sLabel.bExternal = TRUE;
|
||||||
|
SySetPut(&pInclude->aLabel, &sLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PH7_VmGetInstr(pGen->pVm, nSkip)->iP2 = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Compile the 'include' and 'require' statements
|
* Compile the 'include' and 'require' statements
|
||||||
*/
|
*/
|
||||||
@@ -2678,8 +2714,13 @@ static sxi32 PH7_CompileInclude(ph7_gen_state *pGen) {
|
|||||||
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData));
|
||||||
sxu32 nLine = pGen->pIn->nLine;
|
sxu32 nLine = pGen->pIn->nLine;
|
||||||
sxi32 iP1 = (nKey == PH7_KEYWORD_REQUIRE) ? 1 : 0;
|
sxi32 iP1 = (nKey == PH7_KEYWORD_REQUIRE) ? 1 : 0;
|
||||||
|
sxi32 bParen = FALSE;
|
||||||
/* Jump the 'include' or 'require' keyword */
|
/* Jump the 'include' or 'require' keyword */
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
|
if(!iP1 && pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_LPAREN)) {
|
||||||
|
bParen = TRUE;
|
||||||
|
pGen->pIn++;
|
||||||
|
}
|
||||||
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_SSTR | PH7_TK_DSTR)) == 0) {
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_SSTR | PH7_TK_DSTR)) == 0) {
|
||||||
if(pGen->pIn >= pGen->pEnd) {
|
if(pGen->pIn >= pGen->pEnd) {
|
||||||
pGen->pIn--;
|
pGen->pIn--;
|
||||||
@@ -2689,12 +2730,60 @@ static sxi32 PH7_CompileInclude(ph7_gen_state *pGen) {
|
|||||||
}
|
}
|
||||||
zFile = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
|
zFile = SyMemBackendStrDup(&pGen->pVm->sAllocator, pGen->pIn->sData.zString, pGen->pIn->sData.nByte);
|
||||||
pGen->pIn++;
|
pGen->pIn++;
|
||||||
|
if(bParen) {
|
||||||
|
if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_RPAREN) == 0) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "Include: expecting ')'");
|
||||||
|
}
|
||||||
|
pGen->pIn++;
|
||||||
|
}
|
||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI/*';'*/) == 0) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI/*';'*/) == 0) {
|
||||||
/* Unexpected token */
|
/* Unexpected token */
|
||||||
PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Include: Unexpected token '%z', expecting ';'",
|
PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Include: Unexpected token '%z', expecting ';'",
|
||||||
&pGen->pIn->sData);
|
&pGen->pIn->sData);
|
||||||
}
|
}
|
||||||
|
if(iP1) {
|
||||||
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_INCLUDE, iP1, 0, zFile, 0);
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_INCLUDE, iP1, 0, zFile, 0);
|
||||||
|
} else {
|
||||||
|
ph7_include *pInclude = (ph7_include *)SyMemBackendAlloc(&pGen->pVm->sAllocator, sizeof(ph7_include));
|
||||||
|
GenBlock *pBlock = pGen->pCurrent;
|
||||||
|
GenBlock *pLoop = PH7_GenStateFetchBlock(pBlock, GEN_BLOCK_LOOP, 0);
|
||||||
|
sxu32 nSkip;
|
||||||
|
if(pInclude == 0) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, nLine, "PH7 is running out-of-memory");
|
||||||
|
}
|
||||||
|
SyZero(pInclude, sizeof(*pInclude));
|
||||||
|
pInclude->zPath = zFile;
|
||||||
|
pInclude->nBreak = pInclude->nContinue = SXU32_HIGH;
|
||||||
|
SySetInit(&pInclude->aLabel, &pGen->pVm->sAllocator, sizeof(Label));
|
||||||
|
while(pBlock && (pBlock->iFlags & GEN_BLOCK_FUNC) == 0) {
|
||||||
|
if(pBlock->iFlags & GEN_BLOCK_EXCEPTION) {
|
||||||
|
pInclude->bException = TRUE;
|
||||||
|
}
|
||||||
|
pBlock = pBlock->pParent;
|
||||||
|
}
|
||||||
|
pInclude->pFunc = pBlock ? (ph7_vm_func *)pBlock->pUserData : 0;
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_INCLUDE, 0, 1, pInclude, 0);
|
||||||
|
if(pLoop) {
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_JMP, 0, 0, 0, &nSkip);
|
||||||
|
pInclude->nBreak = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
/* Reuse the ordinary compiler's loop cleanup and forward fixups. */
|
||||||
|
SyToken sToken;
|
||||||
|
SyToken *pSavedIn = pGen->pIn, *pSavedEnd = pGen->pEnd;
|
||||||
|
SyZero(&sToken, sizeof(sToken));
|
||||||
|
sToken.nLine = nLine;
|
||||||
|
pGen->pIn = &sToken;
|
||||||
|
pGen->pEnd = &sToken + 1;
|
||||||
|
PH7_CompileBreak(pGen);
|
||||||
|
if((pLoop->iFlags & GEN_BLOCK_SWITCH) == 0) {
|
||||||
|
pInclude->nContinue = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
pGen->pIn = &sToken;
|
||||||
|
PH7_CompileContinue(pGen);
|
||||||
|
}
|
||||||
|
pGen->pIn = pSavedIn;
|
||||||
|
pGen->pEnd = pSavedEnd;
|
||||||
|
PH7_VmGetInstr(pGen->pVm, nSkip)->iP2 = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
}
|
||||||
|
}
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -3013,6 +3102,7 @@ static sxi32 PH7_GenStateCompileFuncBody(
|
|||||||
if(SXERR_ABORT == GenStateFixGoto(&(*pGen), nGotoOfft)) {
|
if(SXERR_ABORT == GenStateFixGoto(&(*pGen), nGotoOfft)) {
|
||||||
rc = SXERR_ABORT;
|
rc = SXERR_ABORT;
|
||||||
}
|
}
|
||||||
|
GenStateFixIncludeLabels(pGen);
|
||||||
SySetTruncate(&pGen->aGoto,nGotoOfft);
|
SySetTruncate(&pGen->aGoto,nGotoOfft);
|
||||||
/* Restore the default container */
|
/* Restore the default container */
|
||||||
PH7_VmSetByteCodeContainer(pGen->pVm, pInstrContainer);
|
PH7_VmSetByteCodeContainer(pGen->pVm, pInstrContainer);
|
||||||
@@ -5224,6 +5314,7 @@ static sxi32 PH7_CompileScript(
|
|||||||
if(SXERR_ABORT == GenStateFixGoto(&(*pGen), 0)) {
|
if(SXERR_ABORT == GenStateFixGoto(&(*pGen), 0)) {
|
||||||
rc = SXERR_ABORT;
|
rc = SXERR_ABORT;
|
||||||
}
|
}
|
||||||
|
GenStateFixIncludeLabels(pGen);
|
||||||
/* Reset container */
|
/* Reset container */
|
||||||
SySetReset(&pGen->aGoto);
|
SySetReset(&pGen->aGoto);
|
||||||
SySetReset(&pGen->aLabel);
|
SySetReset(&pGen->aLabel);
|
||||||
@@ -5282,6 +5373,48 @@ PH7_PRIVATE sxi32 PH7_CompileAerScript(
|
|||||||
SySetRelease(&aAerToken);
|
SySetRelease(&aAerToken);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
/* Compile an include without resetting a suspended run-time compilation. */
|
||||||
|
PH7_PRIVATE sxi32 PH7_CompileIncludedChunk(ph7_vm *pVm, SyString *pScript, ph7_vm_func *pFunc, ph7_include *pInclude) {
|
||||||
|
ph7_gen_state sSaved = pVm->sCodeGen;
|
||||||
|
ph7_gen_state *pGen = &pVm->sCodeGen;
|
||||||
|
ph7_class_info sClass;
|
||||||
|
sxi32 rc;
|
||||||
|
PH7_InitCodeGenerator(pVm, pVm->pEngine->xConf.xErr, pVm->pEngine->xConf.pErrData);
|
||||||
|
if(pFunc) {
|
||||||
|
if(pFunc->pClass) {
|
||||||
|
SyZero(&sClass, sizeof(sClass));
|
||||||
|
sClass.sName = pFunc->pClass->sName;
|
||||||
|
PH7_GenStateEnterBlock(pGen, GEN_BLOCK_CLASS, 0, &sClass, 0);
|
||||||
|
}
|
||||||
|
PH7_GenStateEnterBlock(pGen, GEN_BLOCK_PROTECTED | GEN_BLOCK_FUNC, 0, pFunc, 0);
|
||||||
|
}
|
||||||
|
if(pInclude) {
|
||||||
|
sxu32 n;
|
||||||
|
for(n = 0; n < SySetUsed(&pInclude->aLabel); n++) {
|
||||||
|
Label sLabel = *(Label *)SySetAt(&pInclude->aLabel, n);
|
||||||
|
/* A using closure executes a clone, but its labels belong to the
|
||||||
|
* compiled template. Rebind only this compilation's borrowed copy. */
|
||||||
|
sLabel.pFunc = pFunc;
|
||||||
|
SySetPut(&pGen->aLabel, &sLabel);
|
||||||
|
}
|
||||||
|
if(pInclude->bException) {
|
||||||
|
PH7_GenStateEnterBlock(pGen, GEN_BLOCK_EXCEPTION, 0, 0, 0);
|
||||||
|
}
|
||||||
|
if(pInclude->nBreak != SXU32_HIGH) {
|
||||||
|
PH7_GenStateEnterBlock(pGen, GEN_BLOCK_LOOP | GEN_BLOCK_INCLUDE |
|
||||||
|
(pInclude->nContinue == SXU32_HIGH ? GEN_BLOCK_SWITCH : 0), 0, pInclude, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rc = PH7_CompileAerScript(pVm, pScript, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_FILE);
|
||||||
|
PH7_ResetCodeGenerator(pVm, sSaved.xErr, sSaved.pErrData);
|
||||||
|
PH7_GenStateReleaseBlock(&pGen->sGlobal);
|
||||||
|
SySetRelease(&pGen->aLabel);
|
||||||
|
SySetRelease(&pGen->aGoto);
|
||||||
|
SyHashRelease(&pGen->hLiteral);
|
||||||
|
SyHashRelease(&pGen->hVar);
|
||||||
|
pVm->sCodeGen = sSaved;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Utility routines.Initialize the code generator.
|
* Utility routines.Initialize the code generator.
|
||||||
*/
|
*/
|
||||||
@@ -5350,12 +5483,14 @@ PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32
|
|||||||
SyBlob *pWorker = &pGen->sErrBuf;
|
SyBlob *pWorker = &pGen->sErrBuf;
|
||||||
const char *zErr;
|
const char *zErr;
|
||||||
SyString *pFile;
|
SyString *pFile;
|
||||||
|
SyString **ppFile;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
/* Reset the working buffer */
|
/* Reset the working buffer */
|
||||||
SyBlobReset(pWorker);
|
SyBlobReset(pWorker);
|
||||||
/* Peek the processed file path if available */
|
/* Peek the processed file path if available */
|
||||||
pFile = (SyString *)SySetPeek(&pGen->pVm->aFiles);
|
ppFile = (SyString **)SySetPeek(&pGen->pVm->aFiles);
|
||||||
|
pFile = ppFile ? *ppFile : 0;
|
||||||
if(pGen->xErr == 0) {
|
if(pGen->xErr == 0) {
|
||||||
/* No available error consumer, return immediately */
|
/* No available error consumer, return immediately */
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
|
|||||||
+1
-1
@@ -1197,7 +1197,7 @@ PH7_PRIVATE sxi32 PH7_HashmapCreateSuper(ph7_vm *pVm) {
|
|||||||
ph7_release_value(&(*pVm), pSuper);
|
ph7_release_value(&(*pVm), pSuper);
|
||||||
}
|
}
|
||||||
/* Set some $_SERVER entries */
|
/* Set some $_SERVER entries */
|
||||||
pFile = (SyString *)SySetPeek(&pVm->aFiles);
|
pFile = SySetUsed(&pVm->aFiles) ? *(SyString **)SySetPeek(&pVm->aFiles) : 0;
|
||||||
/*
|
/*
|
||||||
* 'SCRIPT_FILENAME'
|
* 'SCRIPT_FILENAME'
|
||||||
* The absolute pathname of the currently executing script.
|
* The absolute pathname of the currently executing script.
|
||||||
|
|||||||
+186
-38
@@ -302,7 +302,8 @@ PH7_PRIVATE sxi32 PH7_VmEmitInstr(
|
|||||||
VmInstr sInstr;
|
VmInstr sInstr;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
/* Extract the processed script */
|
/* Extract the processed script */
|
||||||
SyString *pFile = (SyString *)SySetPeek(&pVm->aFiles);
|
SyString **ppFile = (SyString **)SySetPeek(&pVm->aFiles);
|
||||||
|
SyString *pFile = ppFile ? *ppFile : 0;
|
||||||
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
||||||
if(pFile == 0) {
|
if(pFile == 0) {
|
||||||
pFile = (SyString *)&sFileName;
|
pFile = (SyString *)&sFileName;
|
||||||
@@ -807,7 +808,11 @@ static sxi32 VmOverloadDominates(const sxi32 *aFirst, const sxi32 *aSecond, sxu3
|
|||||||
return nFirstDefaults < nSecondDefaults;
|
return nFirstDefaults < nSecondDefaults;
|
||||||
}
|
}
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
static sxi32 VmExecIncludedFile(ph7_vm *pVm, SyString *pPath, int iFlags);
|
#define VM_EXEC_INCLUDE 2
|
||||||
|
#define VM_INCLUDE_RETURN 3
|
||||||
|
#define VM_INCLUDE_JUMP 4
|
||||||
|
#define VM_INCLUDE_EXCEPTION 5
|
||||||
|
static sxi32 VmExecIncludedFile(ph7_vm *pVm, SyString *pPath, int iFlags, ph7_value *pResult, ph7_include *pInclude);
|
||||||
static sxi32 VmLocalExec(ph7_vm *pVm, SySet *pByteCode, ph7_value *pResult);
|
static sxi32 VmLocalExec(ph7_vm *pVm, SySet *pByteCode, ph7_value *pResult);
|
||||||
static sxi32 VmClassMemberAccess(ph7_vm *pVm, ph7_class *pClass, sxi32 iProtection);
|
static sxi32 VmClassMemberAccess(ph7_vm *pVm, ph7_class *pClass, sxi32 iProtection);
|
||||||
static ph7_class *VmMethodClass(ph7_vm *pVm);
|
static ph7_class *VmMethodClass(ph7_vm *pVm);
|
||||||
@@ -1335,7 +1340,7 @@ PH7_PRIVATE ph7_value *VmReserveMemObj(ph7_vm *pVm, sxu32 *pIndex) {
|
|||||||
return pObj;
|
return pObj;
|
||||||
}
|
}
|
||||||
/* Forward declaration */
|
/* Forward declaration */
|
||||||
static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags);
|
static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags, ph7_value *pResult, ph7_include *pInclude);
|
||||||
/*
|
/*
|
||||||
* Built-in classes/interfaces and some functions that cannot be implemented
|
* Built-in classes/interfaces and some functions that cannot be implemented
|
||||||
* directly as foreign functions.
|
* directly as foreign functions.
|
||||||
@@ -1504,7 +1509,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
|
|||||||
/* Configuration containers */
|
/* Configuration containers */
|
||||||
SySetInit(&pVm->aModules, &pVm->sAllocator, sizeof(VmModule));
|
SySetInit(&pVm->aModules, &pVm->sAllocator, sizeof(VmModule));
|
||||||
SySetInit(&pVm->aModuleHandles, &pVm->sAllocator, sizeof(VmModule));
|
SySetInit(&pVm->aModuleHandles, &pVm->sAllocator, sizeof(VmModule));
|
||||||
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString));
|
SySetInit(&pVm->aFiles, &pVm->sAllocator, sizeof(SyString *));
|
||||||
SySetInit(&pVm->aPaths, &pVm->sAllocator, sizeof(SyString));
|
SySetInit(&pVm->aPaths, &pVm->sAllocator, sizeof(SyString));
|
||||||
SySetInit(&pVm->aIncluded, &pVm->sAllocator, sizeof(SyString));
|
SySetInit(&pVm->aIncluded, &pVm->sAllocator, sizeof(SyString));
|
||||||
rc = SyHashInit(&pVm->hRequired, &pVm->sAllocator, SyStrHash, (int (*)(const void *, const void *, sxu32))SyMemcmp);
|
rc = SyHashInit(&pVm->hRequired, &pVm->sAllocator, SyStrHash, (int (*)(const void *, const void *, sxu32))SyMemcmp);
|
||||||
@@ -1558,7 +1563,7 @@ PH7_PRIVATE sxi32 PH7_VmInit(
|
|||||||
pVm->nMagic = PH7_VM_INIT;
|
pVm->nMagic = PH7_VM_INIT;
|
||||||
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
|
SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1);
|
||||||
/* Precompile the built-in library */
|
/* Precompile the built-in library */
|
||||||
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE);
|
VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE, 0, 0);
|
||||||
if(bDebug) {
|
if(bDebug) {
|
||||||
/* Enable debugging */
|
/* Enable debugging */
|
||||||
pVm->bDebug = TRUE;
|
pVm->bDebug = TRUE;
|
||||||
@@ -2449,13 +2454,15 @@ static sxi32 VmByteCodeExec(
|
|||||||
int nTos, /* Top entry in the operand stack (usually -1) */
|
int nTos, /* Top entry in the operand stack (usually -1) */
|
||||||
ph7_value *pResult, /* Store program return value here. NULL otherwise */
|
ph7_value *pResult, /* Store program return value here. NULL otherwise */
|
||||||
sxu32 *pLastRef, /* Last referenced ph7_value index */
|
sxu32 *pLastRef, /* Last referenced ph7_value index */
|
||||||
int is_callback /* TRUE if we are executing a callback */
|
int iExecFlags /* Callback (1) or included statements (VM_EXEC_INCLUDE) */
|
||||||
) {
|
) {
|
||||||
VmInstr *pInstr;
|
VmInstr *pInstr;
|
||||||
ph7_value *pTos;
|
ph7_value *pTos;
|
||||||
SySet aArg;
|
SySet aArg;
|
||||||
sxi32 pc;
|
sxi32 pc;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
|
sxi32 bReturning = FALSE;
|
||||||
|
VmFrame *pEntryFrame = pVm->pFrame;
|
||||||
/* Argument container */
|
/* Argument container */
|
||||||
SySetInit(&aArg, &pVm->sAllocator, sizeof(ph7_value *));
|
SySetInit(&aArg, &pVm->sAllocator, sizeof(ph7_value *));
|
||||||
if(nTos < 0) {
|
if(nTos < 0) {
|
||||||
@@ -2465,6 +2472,7 @@ static sxi32 VmByteCodeExec(
|
|||||||
}
|
}
|
||||||
pc = 0;
|
pc = 0;
|
||||||
/* Execute as much as we can */
|
/* Execute as much as we can */
|
||||||
|
Resume:
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if(!pVm->bDebug) {
|
if(!pVm->bDebug) {
|
||||||
/* Reset instructions set container */
|
/* Reset instructions set container */
|
||||||
@@ -2491,6 +2499,11 @@ static sxi32 VmByteCodeExec(
|
|||||||
* and return immediately.
|
* and return immediately.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_DONE:
|
case PH7_OP_DONE:
|
||||||
|
bReturning = pInstr->p3 != 0;
|
||||||
|
if(bReturning && !pInstr->iP1 && (iExecFlags & VM_EXEC_INCLUDE) && pResult) {
|
||||||
|
PH7_MemObjRelease(pResult);
|
||||||
|
MemObjSetType(pResult, MEMOBJ_NULL);
|
||||||
|
}
|
||||||
if(pInstr->iP1) {
|
if(pInstr->iP1) {
|
||||||
if(pTos < pStack) {
|
if(pTos < pStack) {
|
||||||
goto Abort;
|
goto Abort;
|
||||||
@@ -2500,11 +2513,11 @@ static sxi32 VmByteCodeExec(
|
|||||||
}
|
}
|
||||||
/* Unwind local loops, but let VmExecExceptionBlock() release
|
/* Unwind local loops, but let VmExecExceptionBlock() release
|
||||||
* the handler without freeing its borrowed owner frames. */
|
* the handler without freeing its borrowed owner frames. */
|
||||||
if(pInstr->p3) { /* Called from a return statement */
|
if(pInstr->p3 && (iExecFlags & VM_EXEC_INCLUDE) == 0) { /* Called from a return statement */
|
||||||
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
|
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
}
|
}
|
||||||
} else if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
|
} else if(!pInstr->p3 && (iExecFlags & VM_EXEC_INCLUDE) == 0 && (pVm->pFrame->iFlags & VM_FRAME_LOOP)) {
|
||||||
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
|
while(pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
}
|
}
|
||||||
@@ -2512,8 +2525,14 @@ static sxi32 VmByteCodeExec(
|
|||||||
if(pResult) {
|
if(pResult) {
|
||||||
/* Execution result */
|
/* Execution result */
|
||||||
PH7_MemObjStore(pTos, pResult);
|
PH7_MemObjStore(pTos, pResult);
|
||||||
if(!pInstr->iP2 && pVm->pFrame->iFlags & VM_FRAME_ACTIVE) {
|
VmFrame *pOwner = pVm->pFrame;
|
||||||
ph7_vm_func *pFunc = (ph7_vm_func *)pVm->pFrame->pUserData;
|
if(iExecFlags & VM_EXEC_INCLUDE) {
|
||||||
|
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
|
||||||
|
pOwner = pOwner->pParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!pInstr->iP2 && (pOwner->iFlags & VM_FRAME_ACTIVE)) {
|
||||||
|
ph7_vm_func *pFunc = (ph7_vm_func *)pOwner->pUserData;
|
||||||
if(pFunc->nType) {
|
if(pFunc->nType) {
|
||||||
if((pFunc->nType & MEMOBJ_MIXED) == 0) {
|
if((pFunc->nType & MEMOBJ_MIXED) == 0) {
|
||||||
if(pFunc->nType & MEMOBJ_VOID) {
|
if(pFunc->nType & MEMOBJ_VOID) {
|
||||||
@@ -2539,6 +2558,9 @@ static sxi32 VmByteCodeExec(
|
|||||||
/* Nothing referenced */
|
/* Nothing referenced */
|
||||||
*pLastRef = SXU32_HIGH;
|
*pLastRef = SXU32_HIGH;
|
||||||
}
|
}
|
||||||
|
if(bReturning && (iExecFlags & VM_EXEC_INCLUDE)) {
|
||||||
|
goto IncludeReturn;
|
||||||
|
}
|
||||||
goto Done;
|
goto Done;
|
||||||
/*
|
/*
|
||||||
* HALT: P1 * *
|
* HALT: P1 * *
|
||||||
@@ -2572,12 +2594,22 @@ static sxi32 VmByteCodeExec(
|
|||||||
}
|
}
|
||||||
goto Abort;
|
goto Abort;
|
||||||
/*
|
/*
|
||||||
* JMP: * P2 *
|
* JMP: P1 P2 *
|
||||||
*
|
*
|
||||||
* Unconditional jump: The next instruction executed will be
|
* Unconditional jump: The next instruction executed will be
|
||||||
* the one at index P2 from the beginning of the program.
|
* the one at index P2 from the beginning of the program.
|
||||||
|
* P1 marks an include-to-owner transfer rather than a local jump.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_JMP:
|
case PH7_OP_JMP:
|
||||||
|
if(pInstr->iP1 && (iExecFlags & VM_EXEC_INCLUDE)) {
|
||||||
|
if(pResult) {
|
||||||
|
PH7_MemObjRelease(pResult);
|
||||||
|
pResult->x.iVal = pInstr->iP2;
|
||||||
|
MemObjSetType(pResult, MEMOBJ_INT);
|
||||||
|
}
|
||||||
|
SySetRelease(&aArg);
|
||||||
|
return VM_INCLUDE_JUMP;
|
||||||
|
}
|
||||||
pc = pInstr->iP2 - 1;
|
pc = pInstr->iP2 - 1;
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
@@ -4434,6 +4466,9 @@ static sxi32 VmByteCodeExec(
|
|||||||
pException->pFrame = 0;
|
pException->pFrame = 0;
|
||||||
/* Leave the exception frame */
|
/* Leave the exception frame */
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
|
if(bReturning) {
|
||||||
|
goto IncludeReturn;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -4483,6 +4518,9 @@ static sxi32 VmByteCodeExec(
|
|||||||
}
|
}
|
||||||
/* Pop the top entry */
|
/* Pop the top entry */
|
||||||
VmPopOperand(&pTos, 1);
|
VmPopOperand(&pTos, 1);
|
||||||
|
if(iExecFlags & VM_EXEC_INCLUDE) {
|
||||||
|
goto IncludeException;
|
||||||
|
}
|
||||||
/* Perform an unconditional jump */
|
/* Perform an unconditional jump */
|
||||||
pc = nJump - 1;
|
pc = nJump - 1;
|
||||||
break;
|
break;
|
||||||
@@ -4568,20 +4606,50 @@ static sxi32 VmByteCodeExec(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* OP_INCLUDE P1 * P3
|
* OP_INCLUDE P1 P2 P3
|
||||||
* Include another source file. If P1 is zero, 'include' statement was used, otherwise it was 'require'.
|
* Include another source file. If P1 is zero, 'include' statement was used, otherwise it was 'require'.
|
||||||
* P3 contains a path to the source file.
|
* P3 contains a path, or lexical include metadata when P2 is set.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_INCLUDE:
|
case PH7_OP_INCLUDE:
|
||||||
{
|
{
|
||||||
char *zFile = (char *) pInstr->p3;
|
ph7_include *pInclude = !pInstr->iP1 && pInstr->iP2 ? (ph7_include *)pInstr->p3 : 0;
|
||||||
|
char *zFile = pInclude ? pInclude->zPath : (char *)pInstr->p3;
|
||||||
|
ph7_value sIncludeResult;
|
||||||
int iFlags = pInstr->iP1 ? PH7_AERSCRIPT_CODE : PH7_AERSCRIPT_CHNK;
|
int iFlags = pInstr->iP1 ? PH7_AERSCRIPT_CODE : PH7_AERSCRIPT_CHNK;
|
||||||
SyString sFile;
|
SyString sFile;
|
||||||
if(SyStrlen(zFile) < 1) {
|
if(SyStrlen(zFile) < 1) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
SyStringInitFromBuf(&sFile, zFile, SyStrlen(zFile));
|
SyStringInitFromBuf(&sFile, zFile, SyStrlen(zFile));
|
||||||
rc = VmExecIncludedFile(&(*pVm), &sFile, iFlags | PH7_AERSCRIPT_FILE);
|
PH7_MemObjInit(pVm, &sIncludeResult);
|
||||||
|
rc = VmExecIncludedFile(&(*pVm), &sFile, iFlags | PH7_AERSCRIPT_FILE, &sIncludeResult, pInclude);
|
||||||
|
if(rc == VM_INCLUDE_JUMP) {
|
||||||
|
pc = (sxi32)sIncludeResult.x.iVal - 1;
|
||||||
|
PH7_MemObjRelease(&sIncludeResult);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!pInstr->iP1 && rc == VM_INCLUDE_RETURN) {
|
||||||
|
if(pResult) {
|
||||||
|
PH7_MemObjStore(&sIncludeResult, pResult);
|
||||||
|
}
|
||||||
|
PH7_MemObjRelease(&sIncludeResult);
|
||||||
|
bReturning = TRUE;
|
||||||
|
goto IncludeReturn;
|
||||||
|
}
|
||||||
|
PH7_MemObjRelease(&sIncludeResult);
|
||||||
|
if(rc == VM_INCLUDE_EXCEPTION) {
|
||||||
|
goto IncludeException;
|
||||||
|
}
|
||||||
|
if(!pInstr->iP1 && rc == SXERR_NOTFOUND) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_WARNING, "IO error while including file: '%z'", &sFile);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!pInstr->iP1 && rc == PH7_ABORT) {
|
||||||
|
goto Abort;
|
||||||
|
}
|
||||||
|
if(!pInstr->iP1 && rc == PH7_EXCEPTION) {
|
||||||
|
goto Exception;
|
||||||
|
}
|
||||||
if(rc != SXRET_OK && rc != SXERR_EXISTS) {
|
if(rc != SXRET_OK && rc != SXERR_EXISTS) {
|
||||||
PH7_VmThrowError(pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "IO error while including file: '%z'", &sFile);
|
||||||
}
|
}
|
||||||
@@ -5541,12 +5609,12 @@ static sxi32 VmByteCodeExec(
|
|||||||
if(rc != PH7_ABORT && ((pFrame->iFlags & VM_FRAME_THROW) || rc == PH7_EXCEPTION)) {
|
if(rc != PH7_ABORT && ((pFrame->iFlags & VM_FRAME_THROW) || rc == PH7_EXCEPTION)) {
|
||||||
/* An exception was throw in this frame */
|
/* An exception was throw in this frame */
|
||||||
pFrame = pFrame->pParent;
|
pFrame = pFrame->pParent;
|
||||||
if(!is_callback && pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) && pFrame->iExceptionJump > 0) {
|
if((iExecFlags & 1) == 0 && pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) && pFrame->iExceptionJump > 0) {
|
||||||
/* Pop the result */
|
/* Pop the result */
|
||||||
VmPopOperand(&pTos, 1);
|
VmPopOperand(&pTos, 1);
|
||||||
/* Jump to this destination */
|
/* Jump to this destination */
|
||||||
pc = pFrame->iExceptionJump - 1;
|
pc = pFrame->iExceptionJump - 1;
|
||||||
rc = PH7_OK;
|
rc = (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_EXCEPTION : PH7_OK;
|
||||||
} else {
|
} else {
|
||||||
if(pFrame->pParent) {
|
if(pFrame->pParent) {
|
||||||
rc = PH7_EXCEPTION;
|
rc = PH7_EXCEPTION;
|
||||||
@@ -5560,6 +5628,9 @@ static sxi32 VmByteCodeExec(
|
|||||||
SyMemBackendFree(&pVm->sAllocator, pFrameStack);
|
SyMemBackendFree(&pVm->sAllocator, pFrameStack);
|
||||||
/* Leave the frame */
|
/* Leave the frame */
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
|
if(rc == VM_INCLUDE_EXCEPTION) {
|
||||||
|
goto IncludeException;
|
||||||
|
}
|
||||||
if(rc == PH7_ABORT) {
|
if(rc == PH7_ABORT) {
|
||||||
/* Abort processing immediately */
|
/* Abort processing immediately */
|
||||||
goto Abort;
|
goto Abort;
|
||||||
@@ -5637,9 +5708,50 @@ static sxi32 VmByteCodeExec(
|
|||||||
} /* Switch() */
|
} /* Switch() */
|
||||||
pc++; /* Next instruction in the stream */
|
pc++; /* Next instruction in the stream */
|
||||||
} /* For(;;) */
|
} /* For(;;) */
|
||||||
|
IncludeException:
|
||||||
|
/* The catch has already run. Transfer to its owning bytecode's epilogue,
|
||||||
|
* forwarding across included chunks without throwing/catching again. */
|
||||||
|
{
|
||||||
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
|
while(pFrame->pParent) {
|
||||||
|
if((iExecFlags & VM_EXEC_INCLUDE) && pFrame == pEntryFrame) {
|
||||||
|
SySetRelease(&aArg);
|
||||||
|
while(pTos >= pStack) {
|
||||||
|
PH7_MemObjRelease(pTos);
|
||||||
|
pTos--;
|
||||||
|
}
|
||||||
|
return VM_INCLUDE_EXCEPTION;
|
||||||
|
}
|
||||||
|
if(pFrame->iFlags & VM_FRAME_EXCEPTION) {
|
||||||
|
while(pVm->pFrame != pFrame) {
|
||||||
|
VmLeaveFrame(pVm);
|
||||||
|
}
|
||||||
|
pc = pFrame->iExceptionJump;
|
||||||
|
goto Resume;
|
||||||
|
}
|
||||||
|
if(pFrame == pEntryFrame) {
|
||||||
|
/* A called method still has its own execution boundary. */
|
||||||
|
goto Exception;
|
||||||
|
}
|
||||||
|
pFrame = pFrame->pParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto Exception;
|
||||||
|
IncludeReturn:
|
||||||
|
/* The include has no return boundary. Let the owner's existing exception
|
||||||
|
* epilogue run finally before completing the pending return. */
|
||||||
|
if((iExecFlags & VM_EXEC_INCLUDE) == 0 || pVm->pFrame != pEntryFrame) {
|
||||||
|
while(pVm->pFrame->pParent && pVm->pFrame != pEntryFrame && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY | VM_FRAME_EXCEPTION)) == 0) {
|
||||||
|
VmLeaveFrame(pVm);
|
||||||
|
}
|
||||||
|
if(((iExecFlags & VM_EXEC_INCLUDE) == 0 || pVm->pFrame != pEntryFrame) && (pVm->pFrame->iFlags & VM_FRAME_EXCEPTION) && pVm->pFrame->iExceptionJump > 0) {
|
||||||
|
pc = pVm->pFrame->iExceptionJump;
|
||||||
|
goto Resume;
|
||||||
|
}
|
||||||
|
}
|
||||||
Done:
|
Done:
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
return SXRET_OK;
|
return bReturning && (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_RETURN : SXRET_OK;
|
||||||
Abort:
|
Abort:
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
while(pTos >= pStack) {
|
while(pTos >= pStack) {
|
||||||
@@ -8251,7 +8363,7 @@ static int vm_builtin_assert(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||||||
SyString sChunk;
|
SyString sChunk;
|
||||||
SyStringInitFromBuf(&sChunk, SyBlobData(&pAssert->sBlob), SyBlobLength(&pAssert->sBlob));
|
SyStringInitFromBuf(&sChunk, SyBlobData(&pAssert->sBlob), SyBlobLength(&pAssert->sBlob));
|
||||||
if(sChunk.nByte > 0) {
|
if(sChunk.nByte > 0) {
|
||||||
VmEvalChunk(pVm, pCtx, &sChunk, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_EXPR);
|
VmEvalChunk(pVm, pCtx, &sChunk, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_EXPR, 0, 0);
|
||||||
/* Extract evaluation result */
|
/* Extract evaluation result */
|
||||||
iResult = ph7_value_to_bool(pCtx->pRet);
|
iResult = ph7_value_to_bool(pCtx->pRet);
|
||||||
} else {
|
} else {
|
||||||
@@ -8268,8 +8380,10 @@ static int vm_builtin_assert(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||||||
ph7_value sFile, sLine;
|
ph7_value sFile, sLine;
|
||||||
ph7_value *apCbArg[3];
|
ph7_value *apCbArg[3];
|
||||||
SyString *pFile;
|
SyString *pFile;
|
||||||
|
SyString **ppFile;
|
||||||
/* Extract the processed script */
|
/* Extract the processed script */
|
||||||
pFile = (SyString *)SySetPeek(&pVm->aFiles);
|
ppFile = (SyString **)SySetPeek(&pVm->aFiles);
|
||||||
|
pFile = ppFile ? *ppFile : 0;
|
||||||
if(pFile == 0) {
|
if(pFile == 0) {
|
||||||
pFile = (SyString *)&sFileName;
|
pFile = (SyString *)&sFileName;
|
||||||
}
|
}
|
||||||
@@ -9332,12 +9446,15 @@ static sxi32 VmEvalChunk(
|
|||||||
ph7_vm *pVm, /* Underlying Virtual Machine */
|
ph7_vm *pVm, /* Underlying Virtual Machine */
|
||||||
ph7_context *pCtx, /* Call Context */
|
ph7_context *pCtx, /* Call Context */
|
||||||
SyString *pChunk, /* PHP chunk to evaluate */
|
SyString *pChunk, /* PHP chunk to evaluate */
|
||||||
int iFlags /* Code evaluation flag */
|
int iFlags, /* Code evaluation flag */
|
||||||
|
ph7_value *pResult, /* Enclosing method/closure return value for include */
|
||||||
|
ph7_include *pInclude /* Lexical control-flow bridges */
|
||||||
) {
|
) {
|
||||||
SySet *pByteCode, aByteCode;
|
SySet *pByteCode, aByteCode;
|
||||||
sxi32 rc = SXRET_OK;
|
sxi32 rc = SXRET_OK;
|
||||||
sxi32 bRequire = (iFlags & (PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE)) ==
|
sxi32 bRequire = (iFlags & (PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE)) ==
|
||||||
(PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE);
|
(PH7_AERSCRIPT_CODE | PH7_AERSCRIPT_FILE);
|
||||||
|
sxi32 bInclude = (iFlags & PH7_AERSCRIPT_FILE) && !bRequire;
|
||||||
ProcConsumer xErr = 0;
|
ProcConsumer xErr = 0;
|
||||||
void *pErrData = 0;
|
void *pErrData = 0;
|
||||||
/* Initialize bytecode container */
|
/* Initialize bytecode container */
|
||||||
@@ -9349,7 +9466,9 @@ static sxi32 VmEvalChunk(
|
|||||||
/* Log compile-time errors */
|
/* Log compile-time errors */
|
||||||
xErr = pVm->pEngine->xConf.xErr;
|
xErr = pVm->pEngine->xConf.xErr;
|
||||||
pErrData = pVm->pEngine->xConf.pErrData;
|
pErrData = pVm->pEngine->xConf.pErrData;
|
||||||
|
if(!bInclude) {
|
||||||
PH7_ResetCodeGenerator(pVm, xErr, pErrData);
|
PH7_ResetCodeGenerator(pVm, xErr, pErrData);
|
||||||
|
}
|
||||||
/* Swap bytecode container */
|
/* Swap bytecode container */
|
||||||
pByteCode = pVm->pByteContainer;
|
pByteCode = pVm->pByteContainer;
|
||||||
pVm->pByteContainer = &aByteCode;
|
pVm->pByteContainer = &aByteCode;
|
||||||
@@ -9358,8 +9477,16 @@ static sxi32 VmEvalChunk(
|
|||||||
PH7_VmPushFilePath(pVm, "[MEMORY]", -1, TRUE, 0);
|
PH7_VmPushFilePath(pVm, "[MEMORY]", -1, TRUE, 0);
|
||||||
}
|
}
|
||||||
/* Compile the chunk */
|
/* Compile the chunk */
|
||||||
|
if(bInclude) {
|
||||||
|
VmFrame *pOwner = pVm->pFrame;
|
||||||
|
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
|
||||||
|
pOwner = pOwner->pParent;
|
||||||
|
}
|
||||||
|
rc = PH7_CompileIncludedChunk(pVm, pChunk, (ph7_vm_func *)pOwner->pUserData, pInclude);
|
||||||
|
} else {
|
||||||
rc = PH7_CompileAerScript(pVm, pChunk, iFlags);
|
rc = PH7_CompileAerScript(pVm, pChunk, iFlags);
|
||||||
if(rc != SXRET_OK && bRequire) {
|
}
|
||||||
|
if(rc != SXRET_OK && (bRequire || bInclude)) {
|
||||||
goto Cleanup;
|
goto Cleanup;
|
||||||
}
|
}
|
||||||
ph7_value sResult; /* Return value */
|
ph7_value sResult; /* Return value */
|
||||||
@@ -9386,7 +9513,21 @@ static sxi32 VmEvalChunk(
|
|||||||
/* Assume a boolean true return value */
|
/* Assume a boolean true return value */
|
||||||
PH7_MemObjInitFromBool(pVm, &sResult, 1);
|
PH7_MemObjInitFromBool(pVm, &sResult, 1);
|
||||||
/* Execute the compiled chunk */
|
/* Execute the compiled chunk */
|
||||||
|
if(bInclude) {
|
||||||
|
ph7_value *pStack = VmNewOperandStack(pVm, SySetUsed(&aByteCode));
|
||||||
|
if(pStack == 0) {
|
||||||
|
rc = SXERR_MEM;
|
||||||
|
} else {
|
||||||
|
rc = VmByteCodeExec(pVm, (VmInstr *)SySetBasePtr(&aByteCode), pStack, -1,
|
||||||
|
&sResult, 0, VM_EXEC_INCLUDE);
|
||||||
|
SyMemBackendFree(&pVm->sAllocator, pStack);
|
||||||
|
if((rc == VM_INCLUDE_RETURN || rc == VM_INCLUDE_JUMP) && pResult) {
|
||||||
|
PH7_MemObjStore(&sResult, pResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
rc = VmLocalExec(pVm, &aByteCode, &sResult);
|
rc = VmLocalExec(pVm, &aByteCode, &sResult);
|
||||||
|
}
|
||||||
if(pCtx) {
|
if(pCtx) {
|
||||||
/* Set the execution result */
|
/* Set the execution result */
|
||||||
ph7_result_value(pCtx, &sResult);
|
ph7_result_value(pCtx, &sResult);
|
||||||
@@ -9396,7 +9537,7 @@ Cleanup:
|
|||||||
/* Cleanup the mess left behind */
|
/* Cleanup the mess left behind */
|
||||||
pVm->pByteContainer = pByteCode;
|
pVm->pByteContainer = pByteCode;
|
||||||
SySetRelease(&aByteCode);
|
SySetRelease(&aByteCode);
|
||||||
return bRequire ? rc : SXRET_OK;
|
return bRequire || bInclude ? rc : SXRET_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* value eval(string $code)
|
* value eval(string $code)
|
||||||
@@ -9423,7 +9564,7 @@ static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) {
|
|||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
/* Eval the chunk */
|
/* Eval the chunk */
|
||||||
VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK);
|
VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK, 0, 0);
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -9446,7 +9587,7 @@ static int VmIsIncludedFile(ph7_vm *pVm, SyString *pFile) {
|
|||||||
* Push a file path in the appropriate VM container.
|
* Push a file path in the appropriate VM container.
|
||||||
*/
|
*/
|
||||||
PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, sxu8 bMain, sxi32 *pNew) {
|
PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, sxu8 bMain, sxi32 *pNew) {
|
||||||
SyString sPath;
|
SyString *pPath;
|
||||||
char *zDup;
|
char *zDup;
|
||||||
#ifdef __WINNT__
|
#ifdef __WINNT__
|
||||||
char *zCur;
|
char *zCur;
|
||||||
@@ -9455,11 +9596,16 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
|
|||||||
if(nLen < 0) {
|
if(nLen < 0) {
|
||||||
nLen = SyStrlen(zPath);
|
nLen = SyStrlen(zPath);
|
||||||
}
|
}
|
||||||
/* Duplicate the file path first */
|
/* Instructions borrow the descriptor, not an element of the growable
|
||||||
zDup = SyMemBackendStrDup(&pVm->sAllocator, zPath, nLen);
|
* file list. Keep it and its bytes stable until the VM allocator releases
|
||||||
if(zDup == 0) {
|
* them, including after nested include/require compilation. */
|
||||||
|
pPath = (SyString *)SyMemBackendAlloc(&pVm->sAllocator, sizeof(SyString) + nLen + 1);
|
||||||
|
if(pPath == 0) {
|
||||||
return SXERR_MEM;
|
return SXERR_MEM;
|
||||||
}
|
}
|
||||||
|
zDup = (char *)(pPath + 1);
|
||||||
|
SyMemcpy(zPath, zDup, nLen);
|
||||||
|
zDup[nLen] = 0;
|
||||||
#ifdef __WINNT__
|
#ifdef __WINNT__
|
||||||
/* Normalize path on windows
|
/* Normalize path on windows
|
||||||
* Example:
|
* Example:
|
||||||
@@ -9479,27 +9625,27 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Install the file path */
|
/* Install the file path */
|
||||||
SyStringInitFromBuf(&sPath, zDup, nLen);
|
SyStringInitFromBuf(pPath, zDup, nLen);
|
||||||
if(!bMain) {
|
if(!bMain) {
|
||||||
if(VmIsIncludedFile(&(*pVm), &sPath)) {
|
if(VmIsIncludedFile(&(*pVm), pPath)) {
|
||||||
/* Already included */
|
/* Already included */
|
||||||
*pNew = 0;
|
*pNew = 0;
|
||||||
} else {
|
} else {
|
||||||
/* Insert in the corresponding container */
|
/* Insert in the corresponding container */
|
||||||
rc = SySetPut(&pVm->aIncluded, (const void *)&sPath);
|
rc = SySetPut(&pVm->aIncluded, (const void *)pPath);
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
SyMemBackendFree(&pVm->sAllocator, zDup);
|
SyMemBackendFree(&pVm->sAllocator, pPath);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
*pNew = 1;
|
*pNew = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rc = SySetPut(&pVm->aFiles, (const void *)&sPath);
|
rc = SySetPut(&pVm->aFiles, (const void *)&pPath);
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
if(!bMain && *pNew) {
|
if(!bMain && *pNew) {
|
||||||
SySetPop(&pVm->aIncluded);
|
SySetPop(&pVm->aIncluded);
|
||||||
}
|
}
|
||||||
SyMemBackendFree(&pVm->sAllocator, zDup);
|
SyMemBackendFree(&pVm->sAllocator, pPath);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
@@ -9517,7 +9663,9 @@ PH7_PRIVATE sxi32 PH7_VmPushFilePath(ph7_vm *pVm, const char *zPath, int nLen, s
|
|||||||
static sxi32 VmExecIncludedFile(
|
static sxi32 VmExecIncludedFile(
|
||||||
ph7_vm *pVm, /* Underlying Virtual Machine */
|
ph7_vm *pVm, /* Underlying Virtual Machine */
|
||||||
SyString *pPath, /* Script path or URL*/
|
SyString *pPath, /* Script path or URL*/
|
||||||
int iFlags /* Code evaluation flag */
|
int iFlags, /* Code evaluation flag */
|
||||||
|
ph7_value *pResult, /* Enclosing method/closure return value */
|
||||||
|
ph7_include *pInclude /* Lexical control-flow bridges */
|
||||||
) {
|
) {
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
const ph7_io_stream *pStream;
|
const ph7_io_stream *pStream;
|
||||||
@@ -9537,13 +9685,13 @@ static sxi32 VmExecIncludedFile(
|
|||||||
*/
|
*/
|
||||||
pHandle = PH7_StreamOpenHandle(pVm, pStream, pPath->zString, PH7_IO_OPEN_RDONLY, TRUE, 0, TRUE, &isNew);
|
pHandle = PH7_StreamOpenHandle(pVm, pStream, pPath->zString, PH7_IO_OPEN_RDONLY, TRUE, 0, TRUE, &isNew);
|
||||||
if(pHandle == 0) {
|
if(pHandle == 0) {
|
||||||
return SXERR_IO;
|
return (iFlags & PH7_AERSCRIPT_CODE) ? SXERR_IO : SXERR_NOTFOUND;
|
||||||
}
|
}
|
||||||
rc = SXRET_OK; /* Stupid cc warning */
|
rc = SXRET_OK; /* Stupid cc warning */
|
||||||
if(iFlags & PH7_AERSCRIPT_CODE) {
|
if(iFlags & PH7_AERSCRIPT_CODE) {
|
||||||
/* The loader owns these bytes until VM release. Do not use the spelling
|
/* The loader owns these bytes until VM release. Do not use the spelling
|
||||||
* from the statement, or the independent include history, as the key. */
|
* from the statement, or the independent include history, as the key. */
|
||||||
sRequired = *(SyString *)SySetPeek(&pVm->aFiles);
|
sRequired = **(SyString **)SySetPeek(&pVm->aFiles);
|
||||||
pRequired = SyHashGet(&pVm->hRequired, sRequired.zString, sRequired.nByte);
|
pRequired = SyHashGet(&pVm->hRequired, sRequired.zString, sRequired.nByte);
|
||||||
if(pRequired) {
|
if(pRequired) {
|
||||||
PH7_VmThrowError(pVm, PH7_CTX_WARNING, pRequired->pUserData ?
|
PH7_VmThrowError(pVm, PH7_CTX_WARNING, pRequired->pUserData ?
|
||||||
@@ -9567,7 +9715,7 @@ static sxi32 VmExecIncludedFile(
|
|||||||
/* Compile and execute the script */
|
/* Compile and execute the script */
|
||||||
SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents));
|
SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents));
|
||||||
pVm->nMagic = PH7_VM_INCL;
|
pVm->nMagic = PH7_VM_INCL;
|
||||||
rc = VmEvalChunk(pVm, 0, &sScript, iFlags);
|
rc = VmEvalChunk(pVm, 0, &sScript, iFlags, pResult, pInclude);
|
||||||
pVm->nMagic = (iFlags & PH7_AERSCRIPT_CODE) ? nMagic : PH7_VM_EXEC;
|
pVm->nMagic = (iFlags & PH7_AERSCRIPT_CODE) ? nMagic : PH7_VM_EXEC;
|
||||||
}
|
}
|
||||||
if(pRequired) {
|
if(pRequired) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ typedef struct Label Label;
|
|||||||
#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */
|
#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */
|
||||||
#define GEN_BLOCK_CLASS 0x400 /* Class definition */
|
#define GEN_BLOCK_CLASS 0x400 /* Class definition */
|
||||||
#define GEN_BLOCK_NAMESPACE 0x800 /* Namespace body */
|
#define GEN_BLOCK_NAMESPACE 0x800 /* Namespace body */
|
||||||
|
#define GEN_BLOCK_INCLUDE 0x1000 /* Borrowed enclosing loop targets */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Each label seen in the input is recorded in an instance
|
* Each label seen in the input is recorded in an instance
|
||||||
@@ -34,6 +35,7 @@ struct Label {
|
|||||||
SyString sName; /* Label name */
|
SyString sName; /* Label name */
|
||||||
sxu32 nLine; /* Line number this label occurs */
|
sxu32 nLine; /* Line number this label occurs */
|
||||||
sxu8 bRef; /* True if the label was referenced */
|
sxu8 bRef; /* True if the label was referenced */
|
||||||
|
sxu8 bExternal; /* Target is in the including bytecode */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
+12
-1
@@ -902,6 +902,16 @@ typedef struct ph7_vm_func_static_var ph7_vm_func_static_var;
|
|||||||
typedef struct ph7_vm_func_arg ph7_vm_func_arg;
|
typedef struct ph7_vm_func_arg ph7_vm_func_arg;
|
||||||
typedef struct ph7_vm_func ph7_vm_func;
|
typedef struct ph7_vm_func ph7_vm_func;
|
||||||
typedef struct VmFrame VmFrame;
|
typedef struct VmFrame VmFrame;
|
||||||
|
/* Lexical exit bridges in the bytecode containing an include statement. */
|
||||||
|
typedef struct ph7_include ph7_include;
|
||||||
|
struct ph7_include {
|
||||||
|
char *zPath;
|
||||||
|
sxu32 nBreak;
|
||||||
|
sxu32 nContinue;
|
||||||
|
SySet aLabel;
|
||||||
|
ph7_vm_func *pFunc;
|
||||||
|
sxbool bException;
|
||||||
|
};
|
||||||
/*
|
/*
|
||||||
* Each collected function argument is recorded in an instance
|
* Each collected function argument is recorded in an instance
|
||||||
* of the following structure.
|
* of the following structure.
|
||||||
@@ -1205,7 +1215,7 @@ struct ph7_vm {
|
|||||||
SyBlob sArgv; /* $argv[] collector [refer to the [getopt()] implementation for more information] */
|
SyBlob sArgv; /* $argv[] collector [refer to the [getopt()] implementation for more information] */
|
||||||
SySet aModules; /* Set of loaded modules */
|
SySet aModules; /* Set of loaded modules */
|
||||||
SySet aModuleHandles; /* Libraries retained after initialization attempts */
|
SySet aModuleHandles; /* Libraries retained after initialization attempts */
|
||||||
SySet aFiles; /* Stack of processed files */
|
SySet aFiles; /* SyString pointers, VM-owned until release */
|
||||||
SySet aPaths; /* Set of import paths */
|
SySet aPaths; /* Set of import paths */
|
||||||
SySet aIncluded; /* Set of included files */
|
SySet aIncluded; /* Set of included files */
|
||||||
SyHash hRequired; /* Resolved require paths, including pending evaluations */
|
SyHash hRequired; /* Resolved require paths, including pending evaluations */
|
||||||
@@ -1730,6 +1740,7 @@ PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pE
|
|||||||
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData);
|
||||||
PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...);
|
PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...);
|
||||||
PH7_PRIVATE sxi32 PH7_CompileAerScript(ph7_vm *pVm, SyString *pScript, sxi32 iFlags);
|
PH7_PRIVATE sxi32 PH7_CompileAerScript(ph7_vm *pVm, SyString *pScript, sxi32 iFlags);
|
||||||
|
PH7_PRIVATE sxi32 PH7_CompileIncludedChunk(ph7_vm *pVm, SyString *pScript, ph7_vm_func *pFunc, ph7_include *pInclude);
|
||||||
/* constant.c function prototypes */
|
/* constant.c function prototypes */
|
||||||
PH7_PRIVATE void PH7_RegisterBuiltInConstant(ph7_vm *pVm);
|
PH7_PRIVATE void PH7_RegisterBuiltInConstant(ph7_vm *pVm);
|
||||||
/* builtin.c function prototypes */
|
/* builtin.c function prototypes */
|
||||||
|
|||||||
Reference in New Issue
Block a user