Fix block scope for local declarations
Build / AerScript (push) Successful in 40s

This commit is contained in:
2026-10-25 19:22:50 +01:00
parent 3e3b795626
commit 8a2d7d8bd3
4 changed files with 277 additions and 52 deletions
+39 -2
View File
@@ -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) {