This commit is contained in:
+39
-2
@@ -1595,6 +1595,35 @@ static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen) {
|
||||
pGen->pRawIn++;
|
||||
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.
|
||||
* A block is simply one or more Aer statements and expressions to compile
|
||||
@@ -1609,6 +1638,8 @@ static sxi32 PH7_CompileBlock(
|
||||
sxi32 rc;
|
||||
if(pGen->pIn->nType & PH7_TK_OCB /* '{' */) {
|
||||
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);
|
||||
if(rc != SXRET_OK) {
|
||||
return SXERR_ABORT;
|
||||
@@ -1637,6 +1668,7 @@ static sxi32 PH7_CompileBlock(
|
||||
return SXERR_ABORT;
|
||||
}
|
||||
}
|
||||
GenStateCloseScope(pGen, nScope);
|
||||
PH7_GenStateLeaveBlock(&(*pGen), 0);
|
||||
} else {
|
||||
/* Compile a single statement */
|
||||
@@ -1867,6 +1899,7 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) {
|
||||
* of using the for truth expression.
|
||||
*/
|
||||
static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
||||
sxu32 nScope = PH7_VmInstrLength(pGen->pVm);
|
||||
SyToken *pTmp, *pPostStart, *pEnd = 0;
|
||||
GenBlock *pForBlock = 0;
|
||||
sxu32 nFalseJump;
|
||||
@@ -1993,6 +2026,7 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
|
||||
PH7_GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
||||
/* Release the loop block */
|
||||
PH7_GenStateLeaveBlock(pGen, 0);
|
||||
GenStateCloseScope(pGen, nScope);
|
||||
/* Statement successfully compiled */
|
||||
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.
|
||||
*/
|
||||
static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
||||
sxu32 nScope = PH7_VmInstrLength(pGen->pVm);
|
||||
SyToken *pCur, *pTmp, *pEnd = 0;
|
||||
GenBlock *pForeachBlock = 0;
|
||||
ph7_foreach_info *pInfo;
|
||||
@@ -2193,6 +2228,7 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
|
||||
PH7_GenStateFixJumps(pForeachBlock, -1, PH7_VmInstrLength(pGen->pVm));
|
||||
/* Release the loop block */
|
||||
PH7_GenStateLeaveBlock(pGen, 0);
|
||||
GenStateCloseScope(pGen, nScope);
|
||||
/* Statement successfully compiled */
|
||||
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) {
|
||||
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 */
|
||||
SySetInit(&sStatic.aByteCode, &pGen->pVm->sAllocator, sizeof(VmInstr));
|
||||
sStatic.nIdx = SXU32_HIGH; /* Not yet created */
|
||||
@@ -2488,6 +2522,9 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) {
|
||||
sStatic.iFlags = nType;
|
||||
/* Finally save the compiled static variable in the appropriate container */
|
||||
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 {
|
||||
zDup = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte);
|
||||
if(zDup == 0) {
|
||||
|
||||
Reference in New Issue
Block a user