Browse Source

Reimplement 'parent' construct as variable $parent.

This commit also adds new controls to variables, which prevents from re-assigning a value when set. Thanks to that, both $this and $parent cannot be overwritten by using OP_STORE instruction. Other instructions still need some
work.
release/v0.1
Rafal Kupiec 1 year ago
parent
commit
07bd3ceec3
Signed by: belliash GPG Key ID: 4E829243E0CFE6B4
3 changed files with 26 additions and 18 deletions
  1. +1
    -1
      engine/memobj.c
  2. +22
    -17
      engine/vm.c
  3. +3
    -0
      include/ph7int.h

+ 1
- 1
engine/memobj.c View File

@ -401,7 +401,7 @@ PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType) {
* destination are of the compatible data types.
*/
PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
if(pDest->iFlags == 0 || pDest->iFlags == pSrc->iFlags) {
if(pDest->iFlags == 0 || ((pDest->iFlags | MEMOBJ_FIXEDVAL | MEMOBJ_PARENTOBJ) == (pSrc->iFlags | MEMOBJ_FIXEDVAL | MEMOBJ_PARENTOBJ))) {
PH7_MemObjStore(pSrc, pDest);
} else if(pDest->iFlags & MEMOBJ_MIXED) {
if(pDest->iFlags & MEMOBJ_HASHMAP) {


+ 22
- 17
engine/vm.c View File

@ -2765,6 +2765,8 @@ static sxi32 VmByteCodeExec(
if(pObj == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
"Variable '$%z' undeclared (first use in this method/closure)", &sName);
} else if(pObj->iFlags & MEMOBJ_FIXEDVAL) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot re-assign a value of '$%z' statement", &sName);
}
if(!pInstr->p3) {
PH7_MemObjRelease(&pTos[1]);
@ -4152,6 +4154,13 @@ static sxi32 VmByteCodeExec(
pThis = (ph7_class_instance *)pNos->x.pOther;
/* Point to the instantiated class */
pClass = pThis->pClass;
if(pNos->iFlags & MEMOBJ_PARENTOBJ) {
if(pClass->pBase == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
"Attempt to call parent class from non-inheritance instance of class '%z'", &pClass->sName);
}
pClass = pClass->pBase;
}
/* Extract attribute name first */
SyStringInitFromBuf(&sName, (const char *)SyBlobData(&pTos->sBlob), SyBlobLength(&pTos->sBlob));
if(pInstr->iP2) {
@ -4552,7 +4561,7 @@ static sxi32 VmByteCodeExec(
if(pTarget->iFlags & MEMOBJ_OBJ) {
/* Instance already loaded */
pThis = (ph7_class_instance *)pTarget->x.pOther;
pThis->iRef++;
pThis->iRef += 2;
pSelf = pThis->pClass;
}
if(pSelf == 0) {
@ -4565,20 +4574,6 @@ static sxi32 VmByteCodeExec(
pSelf = (ph7_class *)pVmFunc->pUserData;
}
}
if(pThis == 0) {
VmFrame *pFrame = pVm->pFrame;
while(pFrame->pParent && (pFrame->iFlags & VM_FRAME_EXCEPTION)) {
/* Safely ignore the exception frame */
pFrame = pFrame->pParent;
}
if(pFrame->pParent) {
/* TICKET-1433-52: Make sure the '$this' variable is available to the current scope */
pThis = pFrame->pThis;
if(pThis) {
pThis->iRef++;
}
}
}
VmPopOperand(&pTos, 1);
PH7_MemObjRelease(pTos);
/* Synchronize pointers */
@ -4633,14 +4628,24 @@ static sxi32 VmByteCodeExec(
/* Raise exception: Out of memory */
PH7_VmMemoryError(&(*pVm));
}
if((pVmFunc->iFlags & VM_FUNC_CLASS_METHOD) && pThis) {
if(pVmFunc->iFlags & VM_FUNC_CLASS_METHOD) {
/* Install the '$parent' variable */
static const SyString sParent = { "parent", sizeof("parent") - 1 };
pObj = VmCreateMemObj(&(*pVm), &sParent, TRUE);
if(pObj) {
/* Reflect the change */
pObj->x.pOther = pThis;
MemObjSetType(pObj, MEMOBJ_OBJ);
pObj->iFlags |= MEMOBJ_FIXEDVAL | MEMOBJ_PARENTOBJ;
}
/* Install the '$this' variable */
static const SyString sThis = { "this", sizeof("this") - 1 };
pObj = VmCreateMemObj(&(*pVm), &sThis, FALSE);
pObj = VmCreateMemObj(&(*pVm), &sThis, TRUE);
if(pObj) {
/* Reflect the change */
pObj->x.pOther = pThis;
MemObjSetType(pObj, MEMOBJ_OBJ);
pObj->iFlags |= MEMOBJ_FIXEDVAL;
}
}
if(SySetUsed(&pVmFunc->aStatic) > 0) {


+ 3
- 0
include/ph7int.h View File

@ -643,6 +643,9 @@ struct ph7_value {
#define MEMOBJ_MIXED 0x0200 /* Memory value is mixed */
#define MEMOBJ_HASHMAP 0x0400 /* Memory value is a hashmap aka 'array' in the PHP jargon */
#define MEMOBJ_NULL 0x0800 /* Memory value is NULL */
/* Special purpose */
#define MEMOBJ_FIXEDVAL 0x1000 /* Memory value is fixed and cannot be modified */
#define MEMOBJ_PARENTOBJ 0x2000 /* Memory value is a parent object */
/* Mask of all known types */
#define MEMOBJ_ALL (MEMOBJ_STRING|MEMOBJ_INT|MEMOBJ_REAL|MEMOBJ_BOOL|MEMOBJ_NULL|MEMOBJ_HASHMAP|MEMOBJ_OBJ|MEMOBJ_RES|MEMOBJ_CALL|MEMOBJ_CHAR|MEMOBJ_VOID)
/* Scalar variables


Loading…
Cancel
Save