This commit is contained in:
+39
-2
@@ -1595,6 +1595,35 @@ static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen) {
|
|||||||
pGen->pRawIn++;
|
pGen->pRawIn++;
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
|
/* Attach lexical ancestry after compilation, so nested bytecode containers
|
||||||
|
* (closures, initializers and handlers) never inherit the caller's scopes. */
|
||||||
|
static void GenStateCloseScope(ph7_gen_state *pGen, sxu32 nFirst) {
|
||||||
|
VmScopeInfo *pScope;
|
||||||
|
VmInstr *pInstr;
|
||||||
|
sxu32 n, nEnd = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
pScope = (VmScopeInfo *)SyMemBackendAlloc(&pGen->pVm->sAllocator, sizeof(VmScopeInfo));
|
||||||
|
if(pScope == 0) {
|
||||||
|
PH7_VmMemoryError(pGen->pVm);
|
||||||
|
}
|
||||||
|
pScope->pParent = 0;
|
||||||
|
for(n = nFirst; n < nEnd; n++) {
|
||||||
|
VmScopeInfo *pChild;
|
||||||
|
pInstr = PH7_VmGetInstr(pGen->pVm, n);
|
||||||
|
if(pInstr->pScope == 0) {
|
||||||
|
pInstr->pScope = pScope;
|
||||||
|
} else {
|
||||||
|
pChild = pInstr->pScope;
|
||||||
|
while(pChild->pParent && pChild->pParent != pScope) {
|
||||||
|
pChild = pChild->pParent;
|
||||||
|
}
|
||||||
|
if(pChild != pScope) {
|
||||||
|
pChild->pParent = pScope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* A real target outside the scope, including for empty blocks. */
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_NOOP, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Compile an AerScript block.
|
* Compile an AerScript block.
|
||||||
* A block is simply one or more Aer statements and expressions to compile
|
* A block is simply one or more Aer statements and expressions to compile
|
||||||
@@ -1609,6 +1638,8 @@ static sxi32 PH7_CompileBlock(
|
|||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
if(pGen->pIn->nType & PH7_TK_OCB /* '{' */) {
|
if(pGen->pIn->nType & PH7_TK_OCB /* '{' */) {
|
||||||
sxu32 nLine = pGen->pIn->nLine;
|
sxu32 nLine = pGen->pIn->nLine;
|
||||||
|
sxu32 nScope = PH7_VmInstrLength(pGen->pVm);
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_NOOP, 0, 0, 0, 0);
|
||||||
rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_STD, PH7_VmInstrLength(pGen->pVm), 0, 0);
|
rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_STD, PH7_VmInstrLength(pGen->pVm), 0, 0);
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
return SXERR_ABORT;
|
return SXERR_ABORT;
|
||||||
@@ -1637,6 +1668,7 @@ static sxi32 PH7_CompileBlock(
|
|||||||
return SXERR_ABORT;
|
return SXERR_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
GenStateCloseScope(pGen, nScope);
|
||||||
PH7_GenStateLeaveBlock(&(*pGen), 0);
|
PH7_GenStateLeaveBlock(&(*pGen), 0);
|
||||||
} else {
|
} else {
|
||||||
/* Compile a single statement */
|
/* Compile a single statement */
|
||||||
@@ -1867,6 +1899,7 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) {
|
|||||||
* of using the for truth expression.
|
* of using the for truth expression.
|
||||||
*/
|
*/
|
||||||
static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
||||||
|
sxu32 nScope = PH7_VmInstrLength(pGen->pVm);
|
||||||
SyToken *pTmp, *pPostStart, *pEnd = 0;
|
SyToken *pTmp, *pPostStart, *pEnd = 0;
|
||||||
GenBlock *pForBlock = 0;
|
GenBlock *pForBlock = 0;
|
||||||
sxu32 nFalseJump;
|
sxu32 nFalseJump;
|
||||||
@@ -1993,6 +2026,7 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
|||||||
PH7_GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
PH7_GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
||||||
/* Release the loop block */
|
/* Release the loop block */
|
||||||
PH7_GenStateLeaveBlock(pGen, 0);
|
PH7_GenStateLeaveBlock(pGen, 0);
|
||||||
|
GenStateCloseScope(pGen, nScope);
|
||||||
/* Statement successfully compiled */
|
/* Statement successfully compiled */
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
@@ -2028,6 +2062,7 @@ static sxi32 GenStateForEachNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pR
|
|||||||
* first element of the array. This means that you do not need to call reset() before a foreach loop.
|
* first element of the array. This means that you do not need to call reset() before a foreach loop.
|
||||||
*/
|
*/
|
||||||
static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
||||||
|
sxu32 nScope = PH7_VmInstrLength(pGen->pVm);
|
||||||
SyToken *pCur, *pTmp, *pEnd = 0;
|
SyToken *pCur, *pTmp, *pEnd = 0;
|
||||||
GenBlock *pForeachBlock = 0;
|
GenBlock *pForeachBlock = 0;
|
||||||
ph7_foreach_info *pInfo;
|
ph7_foreach_info *pInfo;
|
||||||
@@ -2193,6 +2228,7 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
|||||||
PH7_GenStateFixJumps(pForeachBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
PH7_GenStateFixJumps(pForeachBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
||||||
/* Release the loop block */
|
/* Release the loop block */
|
||||||
PH7_GenStateLeaveBlock(pGen, 0);
|
PH7_GenStateLeaveBlock(pGen, 0);
|
||||||
|
GenStateCloseScope(pGen, nScope);
|
||||||
/* Statement successfully compiled */
|
/* Statement successfully compiled */
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
@@ -2450,8 +2486,6 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) {
|
|||||||
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_COMMA/*','*/ | PH7_TK_SEMI/*';'*/ | PH7_TK_EQUAL/*'='*/)) == 0) {
|
if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_COMMA/*','*/ | PH7_TK_SEMI/*';'*/ | PH7_TK_EQUAL/*'='*/)) == 0) {
|
||||||
PH7_GenCompileError(&(*pGen), E_ERROR, pGen->pIn->nLine, "Unexpected token '%z'", &pGen->pIn->sData);
|
PH7_GenCompileError(&(*pGen), E_ERROR, pGen->pIn->nLine, "Unexpected token '%z'", &pGen->pIn->sData);
|
||||||
}
|
}
|
||||||
/* TODO: Check if static variable exists to avoid redeclaration */
|
|
||||||
|
|
||||||
/* Initialize the structure describing the static variable */
|
/* Initialize the structure describing the static variable */
|
||||||
SySetInit(&sStatic.aByteCode, &pGen->pVm->sAllocator, sizeof(VmInstr));
|
SySetInit(&sStatic.aByteCode, &pGen->pVm->sAllocator, sizeof(VmInstr));
|
||||||
sStatic.nIdx = SXU32_HIGH; /* Not yet created */
|
sStatic.nIdx = SXU32_HIGH; /* Not yet created */
|
||||||
@@ -2488,6 +2522,9 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) {
|
|||||||
sStatic.iFlags = nType;
|
sStatic.iFlags = nType;
|
||||||
/* Finally save the compiled static variable in the appropriate container */
|
/* Finally save the compiled static variable in the appropriate container */
|
||||||
SySetPut(&pFunc->aStatic, (const void *)&sStatic);
|
SySetPut(&pFunc->aStatic, (const void *)&sStatic);
|
||||||
|
/* Storage belongs to the declaration; visibility starts here. */
|
||||||
|
PH7_VmEmitInstr(pGen->pVm, pGen->pIn->nLine, PH7_OP_DECLARE, 2,
|
||||||
|
SySetUsed(&pFunc->aStatic) - 1, pFunc, 0);
|
||||||
} else {
|
} else {
|
||||||
zDup = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte);
|
zDup = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte);
|
||||||
if(zDup == 0) {
|
if(zDup == 0) {
|
||||||
|
|||||||
+224
-48
@@ -54,6 +54,7 @@ struct SyhttpHeader {
|
|||||||
#define HTTP_PROTO_10 1 /* HTTP/1.0 */
|
#define HTTP_PROTO_10 1 /* HTTP/1.0 */
|
||||||
#define HTTP_PROTO_11 2 /* HTTP/1.1 */
|
#define HTTP_PROTO_11 2 /* HTTP/1.1 */
|
||||||
#define HTTP_PROTO_20 3 /* HTTP/2.0 */
|
#define HTTP_PROTO_20 3 /* HTTP/2.0 */
|
||||||
|
static void VmScopeRecord(ph7_vm *pVm, const SyString *pName, sxi32 bConst);
|
||||||
/*
|
/*
|
||||||
* Register a constant and it's associated expansion callback so that
|
* Register a constant and it's associated expansion callback so that
|
||||||
* it can be expanded from the target PHP program.
|
* it can be expanded from the target PHP program.
|
||||||
@@ -82,7 +83,11 @@ PH7_PRIVATE sxi32 PH7_VmRegisterConstant(
|
|||||||
if(bGlobal) {
|
if(bGlobal) {
|
||||||
pCollection = &pVm->hConstant;
|
pCollection = &pVm->hConstant;
|
||||||
} else {
|
} else {
|
||||||
pCollection = &pVm->pFrame->hConst;
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
|
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
|
||||||
|
pFrame = pFrame->pParent;
|
||||||
|
}
|
||||||
|
pCollection = &pFrame->hConst;
|
||||||
}
|
}
|
||||||
pEntry = SyHashGet(pCollection, (const void *)pName->zString, pName->nByte);
|
pEntry = SyHashGet(pCollection, (const void *)pName->zString, pName->nByte);
|
||||||
if(pEntry) {
|
if(pEntry) {
|
||||||
@@ -107,6 +112,9 @@ PH7_PRIVATE sxi32 PH7_VmRegisterConstant(
|
|||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
PH7_VmMemoryError(&(*pVm));
|
PH7_VmMemoryError(&(*pVm));
|
||||||
}
|
}
|
||||||
|
if(!bGlobal) {
|
||||||
|
VmScopeRecord(pVm, &pCons->sName, TRUE);
|
||||||
|
}
|
||||||
/* All done,constant can be invoked from PHP code */
|
/* All done,constant can be invoked from PHP code */
|
||||||
return SXRET_OK;
|
return SXRET_OK;
|
||||||
}
|
}
|
||||||
@@ -310,6 +318,7 @@ PH7_PRIVATE sxi32 PH7_VmEmitInstr(
|
|||||||
}
|
}
|
||||||
/* Fill the VM instruction */
|
/* Fill the VM instruction */
|
||||||
sInstr.iOp = (sxu8)iOp;
|
sInstr.iOp = (sxu8)iOp;
|
||||||
|
sInstr.pScope = 0;
|
||||||
sInstr.iP1 = iP1;
|
sInstr.iP1 = iP1;
|
||||||
sInstr.iP2 = iP2;
|
sInstr.iP2 = iP2;
|
||||||
sInstr.p3 = p3;
|
sInstr.p3 = p3;
|
||||||
@@ -386,6 +395,103 @@ PH7_PRIVATE VmInstr *PH7_VmPeekNextInstr(ph7_vm *pVm) {
|
|||||||
aInstr = (VmInstr *)SySetBasePtr(pVm->pByteContainer);
|
aInstr = (VmInstr *)SySetBasePtr(pVm->pByteContainer);
|
||||||
return &aInstr[n - 2];
|
return &aInstr[n - 2];
|
||||||
}
|
}
|
||||||
|
/* Names belong to lexical scopes, storage and references to their existing
|
||||||
|
* owner frame. The execution tag keeps borrowed include/handler frames from
|
||||||
|
* turning nested bytecode execution into a new variable-visibility boundary. */
|
||||||
|
typedef struct VmScopeBinding VmScopeBinding;
|
||||||
|
struct VmScopeBinding {
|
||||||
|
SyString sName;
|
||||||
|
sxi32 bConst;
|
||||||
|
};
|
||||||
|
struct VmScope {
|
||||||
|
VmScope *pParent;
|
||||||
|
VmScopeInfo *pInfo;
|
||||||
|
VmFrame *pFrame;
|
||||||
|
void *pExec; /* Execution boundary: includes and handlers borrow their owner */
|
||||||
|
SySet aBinding;
|
||||||
|
};
|
||||||
|
static void VmScopeRecord(ph7_vm *pVm, const SyString *pName, sxi32 bConst) {
|
||||||
|
VmScope *pScope;
|
||||||
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
|
VmScopeBinding sBinding;
|
||||||
|
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
|
||||||
|
pFrame = pFrame->pParent;
|
||||||
|
}
|
||||||
|
for(pScope = pVm->pScope; pScope; pScope = pScope->pParent) {
|
||||||
|
if(pScope->pFrame == pFrame) {
|
||||||
|
sBinding.sName = *pName;
|
||||||
|
sBinding.bConst = bConst;
|
||||||
|
if(SySetPut(&pScope->aBinding, &sBinding) != SXRET_OK) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static void VmScopeLeave(ph7_vm *pVm) {
|
||||||
|
VmScope *pScope = pVm->pScope;
|
||||||
|
VmScopeBinding *aBinding = (VmScopeBinding *)SySetBasePtr(&pScope->aBinding);
|
||||||
|
sxu32 n;
|
||||||
|
for(n = 0; n < SySetUsed(&pScope->aBinding); n++) {
|
||||||
|
VmScopeBinding *pBinding = &aBinding[n];
|
||||||
|
SyHash *pHash = pBinding->bConst ? &pScope->pFrame->hConst : &pScope->pFrame->hVar;
|
||||||
|
SyHashEntry *pEntry = SyHashGet(pHash, pBinding->sName.zString, pBinding->sName.nByte);
|
||||||
|
if(pEntry) {
|
||||||
|
if(!pBinding->bConst) {
|
||||||
|
sxu32 nIdx = (sxu32)SX_PTR_TO_INT(pEntry->pUserData);
|
||||||
|
VmSlot *aRef = (VmSlot *)SySetBasePtr(&pScope->pFrame->sRef);
|
||||||
|
sxu32 i;
|
||||||
|
PH7_VmRefObjRemove(pVm, nIdx, pEntry, 0);
|
||||||
|
for(i = 0; i < SySetUsed(&pScope->pFrame->sRef); i++) {
|
||||||
|
if(aRef[i].pUserData == pEntry) {
|
||||||
|
aRef[i].pUserData = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SyHashDeleteEntry2(pEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Values stay in sLocal until frame cleanup. Escaping references and closure
|
||||||
|
* copies must not be recycled just because their names became invisible. */
|
||||||
|
pVm->pScope = pScope->pParent;
|
||||||
|
SySetRelease(&pScope->aBinding);
|
||||||
|
SyMemBackendPoolFree(&pVm->sAllocator, pScope);
|
||||||
|
}
|
||||||
|
static sxi32 VmScopeContains(VmScopeInfo *pScope, VmScopeInfo *pTarget) {
|
||||||
|
while(pTarget) {
|
||||||
|
if(pTarget == pScope) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
pTarget = pTarget->pParent;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
static void VmScopeEnter(ph7_vm *pVm, VmScopeInfo *pInfo, void *pExec) {
|
||||||
|
VmScope *pScope;
|
||||||
|
if(pInfo == 0 || (pVm->pScope && pVm->pScope->pExec == pExec && pVm->pScope->pInfo == pInfo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VmScopeEnter(pVm, pInfo->pParent, pExec);
|
||||||
|
pScope = (VmScope *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(VmScope));
|
||||||
|
if(pScope == 0) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
|
pScope->pParent = pVm->pScope;
|
||||||
|
pScope->pInfo = pInfo;
|
||||||
|
pScope->pFrame = pVm->pFrame;
|
||||||
|
while(pScope->pFrame->pParent && (pScope->pFrame->iFlags & VM_FRAME_EXCEPTION)) {
|
||||||
|
pScope->pFrame = pScope->pFrame->pParent;
|
||||||
|
}
|
||||||
|
pScope->pExec = pExec;
|
||||||
|
SySetInit(&pScope->aBinding, &pVm->sAllocator, sizeof(VmScopeBinding));
|
||||||
|
pVm->pScope = pScope;
|
||||||
|
}
|
||||||
|
static void VmScopeSync(ph7_vm *pVm, VmScopeInfo *pTarget, void *pExec) {
|
||||||
|
while(pVm->pScope && pVm->pScope->pExec == pExec && !VmScopeContains(pVm->pScope->pInfo, pTarget)) {
|
||||||
|
VmScopeLeave(pVm);
|
||||||
|
}
|
||||||
|
VmScopeEnter(pVm, pTarget, pExec);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Allocate a new virtual machine frame.
|
* Allocate a new virtual machine frame.
|
||||||
*/
|
*/
|
||||||
@@ -411,6 +517,7 @@ static VmFrame *VmNewFrame(
|
|||||||
SySetInit(&pFrame->sArg, &pVm->sAllocator, sizeof(VmSlot));
|
SySetInit(&pFrame->sArg, &pVm->sAllocator, sizeof(VmSlot));
|
||||||
SySetInit(&pFrame->sLocal, &pVm->sAllocator, sizeof(VmSlot));
|
SySetInit(&pFrame->sLocal, &pVm->sAllocator, sizeof(VmSlot));
|
||||||
SySetInit(&pFrame->sRef, &pVm->sAllocator, sizeof(VmSlot));
|
SySetInit(&pFrame->sRef, &pVm->sAllocator, sizeof(VmSlot));
|
||||||
|
SySetInit(&pFrame->sConstDecl, &pVm->sAllocator, sizeof(void *));
|
||||||
return pFrame;
|
return pFrame;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -443,6 +550,9 @@ static sxi32 VmEnterFrame(
|
|||||||
static void VmLeaveFrame(ph7_vm *pVm) {
|
static void VmLeaveFrame(ph7_vm *pVm) {
|
||||||
VmFrame *pFrame = pVm->pFrame;
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
if(pFrame) {
|
if(pFrame) {
|
||||||
|
while(pVm->pScope && pVm->pScope->pFrame == pFrame) {
|
||||||
|
VmScopeLeave(pVm);
|
||||||
|
}
|
||||||
/* Unlink from the list of active VM frame */
|
/* Unlink from the list of active VM frame */
|
||||||
pVm->pFrame = pFrame->pParent;
|
pVm->pFrame = pFrame->pParent;
|
||||||
if(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) == 0) {
|
if(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION) == 0) {
|
||||||
@@ -466,6 +576,7 @@ static void VmLeaveFrame(ph7_vm *pVm) {
|
|||||||
SySetRelease(&pFrame->sArg);
|
SySetRelease(&pFrame->sArg);
|
||||||
SySetRelease(&pFrame->sLocal);
|
SySetRelease(&pFrame->sLocal);
|
||||||
SySetRelease(&pFrame->sRef);
|
SySetRelease(&pFrame->sRef);
|
||||||
|
SySetRelease(&pFrame->sConstDecl);
|
||||||
/* Release the whole structure */
|
/* Release the whole structure */
|
||||||
SyMemBackendPoolFree(&pVm->sAllocator, pFrame);
|
SyMemBackendPoolFree(&pVm->sAllocator, pFrame);
|
||||||
}
|
}
|
||||||
@@ -1888,8 +1999,12 @@ static ph7_value *VmCreateMemObj(
|
|||||||
sxu32 nIdx;
|
sxu32 nIdx;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
SyHashEntry *pEntry;
|
SyHashEntry *pEntry;
|
||||||
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
|
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
|
||||||
|
pFrame = pFrame->pParent;
|
||||||
|
}
|
||||||
/* Query the top active frame */
|
/* Query the top active frame */
|
||||||
pEntry = SyHashGet(&pVm->pFrame->hVar, (const void *)pName->zString, pName->nByte);
|
pEntry = SyHashGet(&pFrame->hVar, (const void *)pName->zString, pName->nByte);
|
||||||
if(pEntry) {
|
if(pEntry) {
|
||||||
/* Variable already exists */
|
/* Variable already exists */
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1911,15 +2026,16 @@ static ph7_value *VmCreateMemObj(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Link to the top active VM frame */
|
/* Link to the top active VM frame */
|
||||||
rc = SyHashInsert(&pVm->pFrame->hVar, zName, pName->nByte, SX_INT_TO_PTR(nIdx));
|
rc = SyHashInsert(&pFrame->hVar, zName, pName->nByte, SX_INT_TO_PTR(nIdx));
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
PH7_VmMemoryError(&(*pVm));
|
PH7_VmMemoryError(&(*pVm));
|
||||||
}
|
}
|
||||||
/* Register local variable */
|
/* Register local variable */
|
||||||
sLocal.nIdx = nIdx;
|
sLocal.nIdx = nIdx;
|
||||||
SySetPut(&pVm->pFrame->sLocal, (const void *)&sLocal);
|
SySetPut(&pFrame->sLocal, (const void *)&sLocal);
|
||||||
/* Install in the reference table */
|
/* Install in the reference table */
|
||||||
PH7_VmRefObjInstall(&(*pVm), nIdx, SyHashLastEntry(&pVm->pFrame->hVar), 0, 0);
|
PH7_VmRefObjInstall(&(*pVm), nIdx, SyHashLastEntry(&pFrame->hVar), 0, 0);
|
||||||
|
VmScopeRecord(pVm, pName, FALSE);
|
||||||
/* Save object index */
|
/* Save object index */
|
||||||
pObj->nIdx = nIdx;
|
pObj->nIdx = nIdx;
|
||||||
return pObj;
|
return pObj;
|
||||||
@@ -2462,6 +2578,7 @@ static sxi32 VmByteCodeExec(
|
|||||||
sxi32 pc;
|
sxi32 pc;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
sxi32 bReturning = FALSE;
|
sxi32 bReturning = FALSE;
|
||||||
|
sxbool bScopeStopped = FALSE;
|
||||||
VmFrame *pEntryFrame = pVm->pFrame;
|
VmFrame *pEntryFrame = pVm->pFrame;
|
||||||
/* Argument container */
|
/* Argument container */
|
||||||
SySetInit(&aArg, &pVm->sAllocator, sizeof(ph7_value *));
|
SySetInit(&aArg, &pVm->sAllocator, sizeof(ph7_value *));
|
||||||
@@ -2480,6 +2597,13 @@ Resume:
|
|||||||
}
|
}
|
||||||
/* Fetch the instruction to execute */
|
/* Fetch the instruction to execute */
|
||||||
pInstr = &aInstr[pc];
|
pInstr = &aInstr[pc];
|
||||||
|
/* LF_STOP's following transfer must not recreate the released iteration
|
||||||
|
* scope. Other jumps also reconcile their source, including jump chains
|
||||||
|
* that leave and immediately reenter a block without executing its end. */
|
||||||
|
if(pInstr->iOp != PH7_OP_LF_STOP && !(bScopeStopped && pInstr->iOp == PH7_OP_JMP)) {
|
||||||
|
VmScopeSync(pVm, pInstr->pScope, &aArg);
|
||||||
|
}
|
||||||
|
bScopeStopped = FALSE;
|
||||||
pInstr->bExec = TRUE;
|
pInstr->bExec = TRUE;
|
||||||
/* Record executed instruction in global container */
|
/* Record executed instruction in global container */
|
||||||
SySetPut(&pVm->aInstrSet, (void *)pInstr);
|
SySetPut(&pVm->aInstrSet, (void *)pInstr);
|
||||||
@@ -2518,7 +2642,8 @@ Resume:
|
|||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
}
|
}
|
||||||
} else if(!pInstr->p3 && (iExecFlags & VM_EXEC_INCLUDE) == 0 && (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) {
|
/* An initializer can borrow an existing iteration frame. */
|
||||||
|
while(pVm->pFrame != pEntryFrame && pVm->pFrame->pParent && (pVm->pFrame->iFlags & (VM_FRAME_ACTIVE | VM_FRAME_CATCH | VM_FRAME_FINALLY)) == 0) {
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2607,6 +2732,7 @@ Resume:
|
|||||||
pResult->x.iVal = pInstr->iP2;
|
pResult->x.iVal = pInstr->iP2;
|
||||||
MemObjSetType(pResult, MEMOBJ_INT);
|
MemObjSetType(pResult, MEMOBJ_INT);
|
||||||
}
|
}
|
||||||
|
VmScopeSync(pVm, 0, &aArg);
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
return VM_INCLUDE_JUMP;
|
return VM_INCLUDE_JUMP;
|
||||||
}
|
}
|
||||||
@@ -2688,6 +2814,7 @@ Resume:
|
|||||||
/* Leave the jump loop frame */
|
/* Leave the jump loop frame */
|
||||||
if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
|
if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
|
||||||
VmLeaveFrame(&(*pVm));
|
VmLeaveFrame(&(*pVm));
|
||||||
|
bScopeStopped = TRUE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2889,13 +3016,75 @@ Resume:
|
|||||||
/*
|
/*
|
||||||
* DECLARE: P1 P2 P3
|
* DECLARE: P1 P2 P3
|
||||||
*
|
*
|
||||||
* Create a constant if P1 is set, or variable otherwise. It takes the constant/variable name
|
* P1=0 declares a variable named by P3, with type P2; P1=1 declares
|
||||||
* from the the P3 operand. P2 operand is used to provide a variable type.
|
* a constant described by P3. P1=2 binds the static declaration P2
|
||||||
|
* in the function pointed to by P3.
|
||||||
*/
|
*/
|
||||||
case PH7_OP_DECLARE: {
|
case PH7_OP_DECLARE: {
|
||||||
if(pInstr->iP1) {
|
if(pInstr->iP1 == 2) {
|
||||||
|
ph7_vm_func *pFunc = (ph7_vm_func *)pInstr->p3;
|
||||||
|
ph7_vm_func_static_var *pStatic = (ph7_vm_func_static_var *)SySetAt(&pFunc->aStatic, pInstr->iP2);
|
||||||
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
|
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
|
||||||
|
pFrame = pFrame->pParent;
|
||||||
|
}
|
||||||
|
if(SyHashGet(&pFrame->hVar, pStatic->sName.zString, pStatic->sName.nByte)) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Redeclaration of ‘$%z’ variable", &pStatic->sName);
|
||||||
|
}
|
||||||
|
if(pStatic->nIdx == SXU32_HIGH) {
|
||||||
|
ph7_value *pObj = VmReserveMemObj(pVm, &pStatic->nIdx);
|
||||||
|
ph7_value sValue;
|
||||||
|
if(pObj == 0) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
|
MemObjSetType(pObj, pStatic->iFlags);
|
||||||
|
if(SySetUsed(&pStatic->aByteCode) > 0) {
|
||||||
|
PH7_MemObjInit(pVm, &sValue);
|
||||||
|
rc = VmLocalExec(pVm, &pStatic->aByteCode, &sValue);
|
||||||
|
pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pStatic->nIdx);
|
||||||
|
if(rc == SXRET_OK) {
|
||||||
|
rc = PH7_MemObjSafeStore(&sValue, pObj);
|
||||||
|
if(rc != SXRET_OK) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Cannot assign a value of incompatible type to variable '$%z'", &pStatic->sName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PH7_MemObjRelease(&sValue);
|
||||||
|
if(rc == PH7_ABORT) {
|
||||||
|
goto Abort;
|
||||||
|
} else if(rc == PH7_EXCEPTION) {
|
||||||
|
goto Exception;
|
||||||
|
}
|
||||||
|
} else if(pObj->nType & MEMOBJ_HASHMAP) {
|
||||||
|
pObj->x.pOther = PH7_NewHashmap(pVm, 0, 0);
|
||||||
|
if(pObj->x.pOther == 0) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pObj->nIdx = pStatic->nIdx;
|
||||||
|
}
|
||||||
|
if(SyHashInsert(&pFrame->hVar, pStatic->sName.zString, pStatic->sName.nByte,
|
||||||
|
SX_INT_TO_PTR(pStatic->nIdx)) != SXRET_OK) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
|
VmScopeRecord(pVm, &pStatic->sName, FALSE);
|
||||||
|
} else if(pInstr->iP1) {
|
||||||
/* Constant declaration */
|
/* Constant declaration */
|
||||||
ph7_constant_info *pConstInfo = (ph7_constant_info *) pInstr->p3;
|
ph7_constant_info *pConstInfo = (ph7_constant_info *) pInstr->p3;
|
||||||
|
VmFrame *pOwner = pVm->pFrame;
|
||||||
|
void **apDecl;
|
||||||
|
sxu32 n;
|
||||||
|
while(pOwner->pParent && (pOwner->iFlags & VM_FRAME_ACTIVE) == 0) {
|
||||||
|
pOwner = pOwner->pParent;
|
||||||
|
}
|
||||||
|
apDecl = (void **)SySetBasePtr(&pOwner->sConstDecl);
|
||||||
|
for(n = 0; n < SySetUsed(&pOwner->sConstDecl); n++) {
|
||||||
|
if(apDecl[n] == pConstInfo) {
|
||||||
|
PH7_VmThrowError(pVm, PH7_CTX_ERR, "Redeclaration of ‘%z’ constant", &pConstInfo->pName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(SySetPut(&pOwner->sConstDecl, &pConstInfo) != SXRET_OK) {
|
||||||
|
PH7_VmMemoryError(pVm);
|
||||||
|
}
|
||||||
rc = PH7_VmRegisterConstant(&(*pVm), &pConstInfo->pName, PH7_VmExpandConstantValue, pConstInfo->pConsCode, FALSE);
|
rc = PH7_VmRegisterConstant(&(*pVm), &pConstInfo->pName, PH7_VmExpandConstantValue, pConstInfo->pConsCode, FALSE);
|
||||||
if(rc == SXERR_EXISTS) {
|
if(rc == SXERR_EXISTS) {
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
|
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
|
||||||
@@ -4425,6 +4614,8 @@ Resume:
|
|||||||
ph7_exception *pException = (ph7_exception *)pInstr->p3;
|
ph7_exception *pException = (ph7_exception *)pInstr->p3;
|
||||||
VmFrame *pFrame = 0;
|
VmFrame *pFrame = 0;
|
||||||
SySetPut(&pVm->aException, (const void *)&pException);
|
SySetPut(&pVm->aException, (const void *)&pException);
|
||||||
|
pException->pScope = pVm->pScope ? pVm->pScope->pInfo : 0;
|
||||||
|
pException->pScopeExec = pVm->pScope ? pVm->pScope->pExec : 0;
|
||||||
/* Create the exception frame */
|
/* Create the exception frame */
|
||||||
rc = VmEnterFrame(&(*pVm), 0, 0, &pFrame);
|
rc = VmEnterFrame(&(*pVm), 0, 0, &pFrame);
|
||||||
if(rc != SXRET_OK) {
|
if(rc != SXRET_OK) {
|
||||||
@@ -5220,9 +5411,9 @@ Resume:
|
|||||||
ph7_value *pArg = &pTos[-pInstr->iP1];
|
ph7_value *pArg = &pTos[-pInstr->iP1];
|
||||||
SyHashEntry *pEntry;
|
SyHashEntry *pEntry;
|
||||||
SyString sName;
|
SyString sName;
|
||||||
VmInstr *bInstr = &aInstr[pc - 1];
|
|
||||||
/* Extract function name */
|
/* Extract function name */
|
||||||
if(pTos->nType & MEMOBJ_STRING && bInstr->iOp == PH7_OP_LOADV) {
|
/* Synthetic calls have no preceding instruction at pc == 0. */
|
||||||
|
if(pTos->nType & MEMOBJ_STRING && pc > 0 && aInstr[pc - 1].iOp == PH7_OP_LOADV) {
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Calling a non-callable object");
|
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Calling a non-callable object");
|
||||||
} else if((pTos->nType & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
|
} else if((pTos->nType & (MEMOBJ_CALL | MEMOBJ_STRING)) == 0) {
|
||||||
if(pTos->nType & MEMOBJ_HASHMAP) {
|
if(pTos->nType & MEMOBJ_HASHMAP) {
|
||||||
@@ -5357,43 +5548,6 @@ Resume:
|
|||||||
MemObjSetType(pObj, MEMOBJ_OBJ);
|
MemObjSetType(pObj, MEMOBJ_OBJ);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(SySetUsed(&pVmFunc->aStatic) > 0) {
|
|
||||||
ph7_vm_func_static_var *pStatic, *aStatic;
|
|
||||||
/* Install static variables */
|
|
||||||
aStatic = (ph7_vm_func_static_var *)SySetBasePtr(&pVmFunc->aStatic);
|
|
||||||
for(n = 0 ; n < SySetUsed(&pVmFunc->aStatic) ; ++n) {
|
|
||||||
pStatic = &aStatic[n];
|
|
||||||
if(pStatic->nIdx == SXU32_HIGH) {
|
|
||||||
ph7_value *pVal;
|
|
||||||
/* Initialize the static variables */
|
|
||||||
pObj = VmReserveMemObj(&(*pVm), &pStatic->nIdx);
|
|
||||||
pVal = PH7_ReserveMemObj(&(*pVm));
|
|
||||||
if(pObj == 0 || pVal == 0) {
|
|
||||||
PH7_VmMemoryError(&(*pVm));
|
|
||||||
}
|
|
||||||
MemObjSetType(pObj, pStatic->iFlags);
|
|
||||||
if(SySetUsed(&pStatic->aByteCode) > 0) {
|
|
||||||
/* Evaluate initialization expression (Any complex expression) */
|
|
||||||
VmLocalExec(&(*pVm), &pStatic->aByteCode, pVal);
|
|
||||||
rc = PH7_MemObjSafeStore(pVal, pObj);
|
|
||||||
if(rc != SXRET_OK) {
|
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot assign a value of incompatible type to variable '$%z'", &pStatic->sName);
|
|
||||||
}
|
|
||||||
} else if(pObj->nType & MEMOBJ_HASHMAP) {
|
|
||||||
ph7_hashmap *pMap;
|
|
||||||
pMap = PH7_NewHashmap(&(*pVm), 0, 0);
|
|
||||||
if(pMap == 0) {
|
|
||||||
PH7_VmMemoryError(&(*pVm));
|
|
||||||
}
|
|
||||||
pObj->x.pOther = pMap;
|
|
||||||
}
|
|
||||||
pObj->nIdx = pStatic->nIdx;
|
|
||||||
}
|
|
||||||
/* Install in the current frame */
|
|
||||||
SyHashInsert(&pFrame->hVar, SyStringData(&pStatic->sName), SyStringLength(&pStatic->sName),
|
|
||||||
SX_INT_TO_PTR(pStatic->nIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Push arguments in the local frame */
|
/* Push arguments in the local frame */
|
||||||
n = 0;
|
n = 0;
|
||||||
while(pArg < pTos) {
|
while(pArg < pTos) {
|
||||||
@@ -5715,6 +5869,7 @@ IncludeException:
|
|||||||
VmFrame *pFrame = pVm->pFrame;
|
VmFrame *pFrame = pVm->pFrame;
|
||||||
while(pFrame->pParent) {
|
while(pFrame->pParent) {
|
||||||
if((iExecFlags & VM_EXEC_INCLUDE) && pFrame == pEntryFrame) {
|
if((iExecFlags & VM_EXEC_INCLUDE) && pFrame == pEntryFrame) {
|
||||||
|
VmScopeSync(pVm, 0, &aArg);
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
while(pTos >= pStack) {
|
while(pTos >= pStack) {
|
||||||
PH7_MemObjRelease(pTos);
|
PH7_MemObjRelease(pTos);
|
||||||
@@ -5750,9 +5905,11 @@ IncludeReturn:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Done:
|
Done:
|
||||||
|
VmScopeSync(pVm, 0, &aArg);
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
return bReturning && (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_RETURN : SXRET_OK;
|
return bReturning && (iExecFlags & VM_EXEC_INCLUDE) ? VM_INCLUDE_RETURN : SXRET_OK;
|
||||||
Abort:
|
Abort:
|
||||||
|
VmScopeSync(pVm, 0, &aArg);
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
while(pTos >= pStack) {
|
while(pTos >= pStack) {
|
||||||
PH7_MemObjRelease(pTos);
|
PH7_MemObjRelease(pTos);
|
||||||
@@ -5760,6 +5917,7 @@ Abort:
|
|||||||
}
|
}
|
||||||
return PH7_ABORT;
|
return PH7_ABORT;
|
||||||
Exception:
|
Exception:
|
||||||
|
VmScopeSync(pVm, 0, &aArg);
|
||||||
SySetRelease(&aArg);
|
SySetRelease(&aArg);
|
||||||
while(pTos >= pStack) {
|
while(pTos >= pStack) {
|
||||||
PH7_MemObjRelease(pTos);
|
PH7_MemObjRelease(pTos);
|
||||||
@@ -7007,6 +7165,7 @@ static sxi32 VmCallClassMethod(
|
|||||||
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
||||||
/* Emit the CALL instruction */
|
/* Emit the CALL instruction */
|
||||||
aInstr[0].iOp = PH7_OP_CALL;
|
aInstr[0].iOp = PH7_OP_CALL;
|
||||||
|
aInstr[0].pScope = 0;
|
||||||
aInstr[0].iP1 = nArg; /* Total number of given arguments */
|
aInstr[0].iP1 = nArg; /* Total number of given arguments */
|
||||||
aInstr[0].iP2 = iEntry;
|
aInstr[0].iP2 = iEntry;
|
||||||
aInstr[0].p3 = 0;
|
aInstr[0].p3 = 0;
|
||||||
@@ -7015,6 +7174,7 @@ static sxi32 VmCallClassMethod(
|
|||||||
aInstr[0].pFile = (SyString *)&sFileName;
|
aInstr[0].pFile = (SyString *)&sFileName;
|
||||||
/* Emit the DONE instruction */
|
/* Emit the DONE instruction */
|
||||||
aInstr[1].iOp = PH7_OP_DONE;
|
aInstr[1].iOp = PH7_OP_DONE;
|
||||||
|
aInstr[1].pScope = 0;
|
||||||
aInstr[1].iP1 = 1; /* Extract method return value */
|
aInstr[1].iP1 = 1; /* Extract method return value */
|
||||||
aInstr[1].iP2 = 1;
|
aInstr[1].iP2 = 1;
|
||||||
aInstr[1].p3 = 0;
|
aInstr[1].p3 = 0;
|
||||||
@@ -7077,6 +7237,7 @@ PH7_PRIVATE sxi32 PH7_VmCallUserFunction(
|
|||||||
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
static const SyString sFileName = { "[MEMORY]", sizeof("[MEMORY]") - 1};
|
||||||
/* Emit the CALL instruction */
|
/* Emit the CALL instruction */
|
||||||
aInstr[0].iOp = PH7_OP_CALL;
|
aInstr[0].iOp = PH7_OP_CALL;
|
||||||
|
aInstr[0].pScope = 0;
|
||||||
aInstr[0].iP1 = nArg; /* Total number of given arguments */
|
aInstr[0].iP1 = nArg; /* Total number of given arguments */
|
||||||
aInstr[0].iP2 = 0;
|
aInstr[0].iP2 = 0;
|
||||||
aInstr[0].p3 = 0;
|
aInstr[0].p3 = 0;
|
||||||
@@ -7085,6 +7246,7 @@ PH7_PRIVATE sxi32 PH7_VmCallUserFunction(
|
|||||||
aInstr[0].pFile = (SyString *)&sFileName;
|
aInstr[0].pFile = (SyString *)&sFileName;
|
||||||
/* Emit the DONE instruction */
|
/* Emit the DONE instruction */
|
||||||
aInstr[1].iOp = PH7_OP_DONE;
|
aInstr[1].iOp = PH7_OP_DONE;
|
||||||
|
aInstr[1].pScope = 0;
|
||||||
aInstr[1].iP1 = 1; /* Extract function return value if available */
|
aInstr[1].iP1 = 1; /* Extract function return value if available */
|
||||||
aInstr[1].iP2 = 1;
|
aInstr[1].iP2 = 1;
|
||||||
aInstr[1].p3 = 0;
|
aInstr[1].p3 = 0;
|
||||||
@@ -8581,6 +8743,7 @@ static sxi32 VmExecExceptionBlock(ph7_vm *pVm, ph7_exception *pException,
|
|||||||
VmFrame *pSavedFrame = pVm->pFrame;
|
VmFrame *pSavedFrame = pVm->pFrame;
|
||||||
VmFrame *pOwner = pException->pFrame;
|
VmFrame *pOwner = pException->pFrame;
|
||||||
VmFrame *pFrame;
|
VmFrame *pFrame;
|
||||||
|
VmScope *pScope;
|
||||||
SySet sSelf, sSavedSelf;
|
SySet sSelf, sSavedSelf;
|
||||||
sxu32 nSelf = SySetUsed(&pVm->aSelf), i;
|
sxu32 nSelf = SySetUsed(&pVm->aSelf), i;
|
||||||
sxi32 rc;
|
sxi32 rc;
|
||||||
@@ -8599,6 +8762,19 @@ static sxi32 VmExecExceptionBlock(ph7_vm *pVm, ph7_exception *pException,
|
|||||||
}
|
}
|
||||||
sSavedSelf = pVm->aSelf;
|
sSavedSelf = pVm->aSelf;
|
||||||
pVm->aSelf = sSelf;
|
pVm->aSelf = sSelf;
|
||||||
|
/* Handlers run before the throwing bytecode resumes its unwind. Remove
|
||||||
|
* exited names now, without releasing owner values or enclosing scopes.
|
||||||
|
* A context already unwound by an earlier exit must not be recreated. */
|
||||||
|
for(pScope = pVm->pScope; pScope; pScope = pScope->pParent) {
|
||||||
|
if(pScope->pInfo == pException->pScope && pScope->pExec == pException->pScopeExec) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pScope || pException->pScope == 0) {
|
||||||
|
while(pVm->pScope != pScope) {
|
||||||
|
VmScopeLeave(pVm);
|
||||||
|
}
|
||||||
|
}
|
||||||
pVm->pFrame = pOwner;
|
pVm->pFrame = pOwner;
|
||||||
rc = VmEnterFrame(pVm, 0, 0, &pFrame);
|
rc = VmEnterFrame(pVm, 0, 0, &pFrame);
|
||||||
if(rc == SXRET_OK) {
|
if(rc == SXRET_OK) {
|
||||||
|
|||||||
@@ -1121,7 +1121,13 @@ struct ph7_class_instance {
|
|||||||
* is stored in an instance of the following structure.
|
* is stored in an instance of the following structure.
|
||||||
*/
|
*/
|
||||||
typedef struct VmInstr VmInstr;
|
typedef struct VmInstr VmInstr;
|
||||||
|
typedef struct VmScopeInfo VmScopeInfo;
|
||||||
|
typedef struct VmScope VmScope;
|
||||||
|
struct VmScopeInfo {
|
||||||
|
VmScopeInfo *pParent; /* Lexical parent in the same bytecode container */
|
||||||
|
};
|
||||||
struct VmInstr {
|
struct VmInstr {
|
||||||
|
VmScopeInfo *pScope; /* Lexical scope at this instruction */
|
||||||
sxu8 iOp; /* Operation to preform */
|
sxu8 iOp; /* Operation to preform */
|
||||||
sxi32 iP1; /* First operand */
|
sxi32 iP1; /* First operand */
|
||||||
sxu32 iP2; /* Second operand (Often the jump destination) */
|
sxu32 iP2; /* Second operand (Often the jump destination) */
|
||||||
@@ -1161,6 +1167,8 @@ struct ph7_exception {
|
|||||||
*/
|
*/
|
||||||
SySet sFinally; /* Compiled 'finally' instructions block (VmInstr) */
|
SySet sFinally; /* Compiled 'finally' instructions block (VmInstr) */
|
||||||
VmFrame *pFrame; /* Frame that trigger the exception */
|
VmFrame *pFrame; /* Frame that trigger the exception */
|
||||||
|
VmScopeInfo *pScope; /* Enclosing lexical context at try entry */
|
||||||
|
void *pScopeExec; /* Execution owning that context */
|
||||||
};
|
};
|
||||||
/* Forward reference */
|
/* Forward reference */
|
||||||
typedef struct ph7_case_expr ph7_case_expr;
|
typedef struct ph7_case_expr ph7_case_expr;
|
||||||
@@ -1244,6 +1252,7 @@ struct ph7_vm {
|
|||||||
SySet aSelf; /* 'self' stack used for static member access [i.e: self::MyConstant] */
|
SySet aSelf; /* 'self' stack used for static member access [i.e: self::MyConstant] */
|
||||||
sxi32 iExitStatus; /* Script exit status */
|
sxi32 iExitStatus; /* Script exit status */
|
||||||
ph7_gen_state sCodeGen; /* Code generator module */
|
ph7_gen_state sCodeGen; /* Code generator module */
|
||||||
|
VmScope *pScope; /* Active lexical scopes (not call frames) */
|
||||||
ph7_vm *pNext, *pPrev; /* List of active VMs */
|
ph7_vm *pNext, *pPrev; /* List of active VMs */
|
||||||
sxu32 nMagic; /* Sanity check against misuse */
|
sxu32 nMagic; /* Sanity check against misuse */
|
||||||
};
|
};
|
||||||
@@ -1261,6 +1270,7 @@ struct VmFrame {
|
|||||||
SyHash hVar; /* Variable hashtable for fast lookup */
|
SyHash hVar; /* Variable hashtable for fast lookup */
|
||||||
SySet sArg; /* Function arguments container */
|
SySet sArg; /* Function arguments container */
|
||||||
SySet sRef; /* Local reference table (VmSlot instance) */
|
SySet sRef; /* Local reference table (VmSlot instance) */
|
||||||
|
SySet sConstDecl; /* Constants already declared during this invocation */
|
||||||
sxi32 iFlags; /* Frame configuration flags (See below) */
|
sxi32 iFlags; /* Frame configuration flags (See below) */
|
||||||
sxu32 iExceptionJump; /* Exception jump destination */
|
sxu32 iExceptionJump; /* Exception jump destination */
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ class Base32 {
|
|||||||
if(!$input) return '';
|
if(!$input) return '';
|
||||||
char[] $aInput = str_split($input);
|
char[] $aInput = str_split($input);
|
||||||
string $binaryString = '';
|
string $binaryString = '';
|
||||||
for(int $i = 0; $i < sizeof($aInput); $i++) {
|
int $i;
|
||||||
|
for($i = 0; $i < sizeof($aInput); $i++) {
|
||||||
$binaryString += str_pad(base_convert(ord($aInput[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
|
$binaryString += str_pad(base_convert(ord($aInput[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
|
||||||
}
|
}
|
||||||
string[] $fiveBitBinaryArray = str_split($binaryString, 5);
|
string[] $fiveBitBinaryArray = str_split($binaryString, 5);
|
||||||
@@ -43,7 +44,8 @@ class Base32 {
|
|||||||
int $paddingCharCount = substr_count($input, Base32::$map[32]);
|
int $paddingCharCount = substr_count($input, Base32::$map[32]);
|
||||||
int[] $allowedValues = {6, 4, 3, 1, 0};
|
int[] $allowedValues = {6, 4, 3, 1, 0};
|
||||||
if(!in_array($paddingCharCount, $allowedValues)) return '';
|
if(!in_array($paddingCharCount, $allowedValues)) return '';
|
||||||
for(int $i = 0; $i < 4; $i++) {
|
int $i;
|
||||||
|
for($i = 0; $i < 4; $i++) {
|
||||||
if($paddingCharCount == $allowedValues[$i] && substr($input, -($allowedValues[$i])) != str_repeat(Base32::$map[32], $allowedValues[$i]))
|
if($paddingCharCount == $allowedValues[$i] && substr($input, -($allowedValues[$i])) != str_repeat(Base32::$map[32], $allowedValues[$i]))
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user