diff --git a/engine/memobj.c b/engine/memobj.c index a368d17..2c3a0ef 100644 --- a/engine/memobj.c +++ b/engine/memobj.c @@ -363,7 +363,7 @@ static ph7_real MemObjCharValue(ph7_value *pObj) { * Checks a ph7_value variable compatibility with nType data type. */ PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType) { - if(((nType & MEMOBJ_HASHMAP) && (pObj->iFlags & MEMOBJ_HASHMAP)) || (((nType & MEMOBJ_HASHMAP) == 0) && ((pObj->iFlags & MEMOBJ_HASHMAP) == 0))) { + if(((nType & MEMOBJ_HASHMAP) == 0) && ((pObj->iFlags & MEMOBJ_HASHMAP) == 0)) { if((nType & MEMOBJ_REAL) && (pObj->iFlags & MEMOBJ_INT)) { return SXRET_OK; } else if((nType & MEMOBJ_CHAR) && (pObj->iFlags & MEMOBJ_INT)) { @@ -586,8 +586,6 @@ PH7_PRIVATE ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags) { return PH7_MemObjToBool; } else if(iFlags & MEMOBJ_CHAR) { return PH7_MemObjToChar; - } else if(iFlags & MEMOBJ_HASHMAP) { - return PH7_MemObjToHashmap; } else if(iFlags & MEMOBJ_OBJ) { return PH7_MemObjToObject; } else if(iFlags & MEMOBJ_CALL) { diff --git a/engine/vm.c b/engine/vm.c index 9ea4357..27fc93d 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -2028,8 +2028,17 @@ static sxi32 VmByteCodeExec( if((pFunc->nType & MEMOBJ_MIXED) == 0) { if(pFunc->nType & MEMOBJ_VOID) { PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Return with a value in closure/method returning void"); - } else if(pFunc->nType != pResult->iFlags && PH7_CheckVarCompat(pTos, pFunc->nType) != SXRET_OK) { - PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Incompatible type when returning data by closure/method"); + } else if(pFunc->nType != pResult->iFlags) { + if(PH7_CheckVarCompat(pResult, pFunc->nType) == SXRET_OK) { + ProcMemObjCast xCast = PH7_MemObjCastMethod(pFunc->nType); + xCast(pResult); + } else if((pFunc->iFlags & MEMOBJ_HASHMAP) && (pResult->iFlags & MEMOBJ_HASHMAP)) { + if(PH7_HashmapCast(pResult, pFunc->iFlags ^ MEMOBJ_HASHMAP) != SXRET_OK) { + PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Incompatible type when returning data by closure/method"); + } + } else { + PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Incompatible type when returning data by closure/method"); + } } } } @@ -2736,6 +2745,12 @@ static sxi32 VmByteCodeExec( ProcMemObjCast xCast = PH7_MemObjCastMethod(pObj->iFlags); xCast(pTos); PH7_MemObjStore(pTos, pObj); + } else if((pObj->iFlags & MEMOBJ_HASHMAP) && (pTos->iFlags & MEMOBJ_HASHMAP)) { + if(PH7_HashmapCast(pTos, pObj->iFlags ^ MEMOBJ_HASHMAP) != SXRET_OK) { + PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, + "Cannot assign a value of incompatible type to variable '$%z'", &sName); + } + PH7_MemObjStore(pTos, pObj); } else { PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot assign a value of incompatible type to variable '$%z'", &sName); @@ -5003,6 +5018,11 @@ static sxi32 VmByteCodeExec( /* Silently typecast compatible value to expected data type */ ProcMemObjCast xCast = PH7_MemObjCastMethod(aFormalArg[n].nType); xCast(pArg); + } else if((aFormalArg[n].nType & MEMOBJ_HASHMAP) && (pArg->iFlags & MEMOBJ_HASHMAP)) { + if(PH7_HashmapCast(pArg, aFormalArg[n].nType ^ MEMOBJ_HASHMAP) != SXRET_OK) { + PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, + "Argument %u of '%z()' does not match the data type", n + 1, &pVmFunc->sName); + } } else { PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Argument %u of '%z()' does not match the data type", n + 1, &pVmFunc->sName);