From dc5725d1afb15b7fafde22deb534efe8d7197e68 Mon Sep 17 00:00:00 2001 From: Rafal Kupiec Date: Thu, 28 Aug 2025 18:38:28 +0200 Subject: [PATCH] Unset local for variable, fixes #62 --- engine/compiler.c | 15 +++++++++++++++ engine/vm.c | 22 ++++++++++++++++++++++ include/ph7int.h | 1 + 3 files changed, 38 insertions(+) diff --git a/engine/compiler.c b/engine/compiler.c index 17f5b87..a5d7a72 100644 --- a/engine/compiler.c +++ b/engine/compiler.c @@ -1860,6 +1860,9 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { sxu32 nLine; sxi32 rc; nLine = pGen->pIn->nLine; + SyString *pName = NULL; + char *zName = NULL; + /* Jump the 'for' keyword */ pGen->pIn++; if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_LPAREN) == 0) { @@ -1879,6 +1882,13 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { pGen->pEnd = pEnd; sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pGen->pIn->pUserData)); if(nKey & (PH7_KEYWORD_AUTO | PH7_KEYWORD_TYPEDEF)) { + /* Local for variable, store its name */ + pName = &pGen->pIn[2].sData; + zName = SyMemBackendStrDup(&pGen->pVm->sAllocator, pName->zString, pName->nByte); + if(zName == 0) { + PH7_GenCompileError(pGen, E_ERROR, nLine, "PH7 engine is running out-of-memory"); + } + /* Compile variable */ PH7_CompileVar(&(*pGen)); } /* Compile initialization expressions if available */ @@ -1976,6 +1986,11 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForBlock->nFirstInstr, 0, 0); /* Fix all jumps now the destination is resolved */ PH7_GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm)); + /* If local for loop variable, unset it */ + if(zName != NULL) { + /* Emit instruction to unset the variable after its initialization */ + PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_UNSET, 0, 0, (void*)zName, 0); + } /* Release the loop block */ PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ diff --git a/engine/vm.c b/engine/vm.c index 80777f5..45046da 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -2292,6 +2292,28 @@ static sxi32 VmByteCodeExec( } break; } + /* + * UNSET: * * P3 + * + * Unset a variable. It takes the variable name indexed at P3 operand. + */ + case PH7_OP_UNSET: { + SyString sName; + VmFrame *pFrame = pVm->pFrame; + SyHashEntry *pEntry; + sxu32 nIdx; + SyStringInitFromBuf(&sName, pInstr->p3, SyStrlen((const char *)pInstr->p3)); + /* Find variable in local frame */ + pEntry = SyHashGet(&pFrame->hVar, (const void *)sName.zString, sName.nByte); + if(pEntry) { + nIdx = (sxu32)SX_PTR_TO_INT(pEntry->pUserData); + /* Delete variable from local frame */ + SyHashDeleteEntry(&pFrame->hVar, (const void *)sName.zString, sName.nByte, 0); + /* Call PH7_VmUnsetMemObj to release the variable */ + PH7_VmUnsetMemObj(&(*pVm), nIdx, FALSE); + } + break; + } /* * LOADC P1 P2 * * diff --git a/include/ph7int.h b/include/ph7int.h index becbb94..c43317f 100644 --- a/include/ph7int.h +++ b/include/ph7int.h @@ -1379,6 +1379,7 @@ enum ph7_vm_op { PH7_OP_IMPORT, /* Import AerScript module */ PH7_OP_INCLUDE, /* Include another source file */ PH7_OP_DECLARE, /* Declare a variable */ + PH7_OP_UNSET, /* Unset variable */ PH7_OP_LOADV, /* Load variable */ PH7_OP_LOADC, /* Load constant */ PH7_OP_LOAD_IDX, /* Load array entry */