Implement nominal class and interface types across declarations and calls
Build / AerScript (push) Successful in 37s
Build / AerScript (push) Successful in 37s
This commit is contained in:
+80
-3
@@ -394,6 +394,40 @@ PH7_PRIVATE sxi32 PH7_CheckVarCompat(ph7_value *pObj, int nType) {
|
||||
}
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
/* Apply only to owned storage. Array copies are made before this walk, so a
|
||||
* wider destination never weakens the source array's leaf contracts. */
|
||||
PH7_PRIVATE void PH7_MemObjSetDeclaredType(ph7_value *pValue, sxu32 nType) {
|
||||
ph7_hashmap_node *pNode;
|
||||
ph7_hashmap *pMap;
|
||||
if(nType & MEMOBJ_NAMED) {
|
||||
PH7_VmTypeClass(pValue->pVm, nType, TRUE);
|
||||
} else {
|
||||
nType = 0;
|
||||
}
|
||||
pValue->nDeclaredType = nType;
|
||||
if(nType) {
|
||||
pValue->iFlags = MEMOBJ_VARIABLE;
|
||||
}
|
||||
if(nType && MemObjIsNullReference(pValue)) {
|
||||
pValue->nType = nType & MEMOBJ_TYPEMASK;
|
||||
pValue->x.pOther = 0;
|
||||
if(nType & MEMOBJ_HASHMAP) {
|
||||
pValue->x.pOther = PH7_NewHashmap(pValue->pVm, 0, 0);
|
||||
if(pValue->x.pOther == 0) {
|
||||
PH7_VmMemoryError(pValue->pVm);
|
||||
}
|
||||
}
|
||||
}
|
||||
if((pValue->nType & MEMOBJ_HASHMAP) == 0 || pValue->x.pOther == 0) {
|
||||
return;
|
||||
}
|
||||
pMap = (ph7_hashmap *)pValue->x.pOther;
|
||||
pMap->nDeclaredType = nType & ~MEMOBJ_HASHMAP;
|
||||
for(pNode = pMap->pFirst; pNode; pNode = pNode->pPrev) {
|
||||
ph7_value *pLeaf = (ph7_value *)SySetAt(&pValue->pVm->aMemObj, pNode->nValIdx);
|
||||
PH7_MemObjSetDeclaredType(pLeaf, nType ? pMap->nDeclaredType | (pLeaf->nType & MEMOBJ_HASHMAP) : 0);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Duplicate safely the contents of a ph7_value if source and
|
||||
* destination are of the compatible data types.
|
||||
@@ -403,6 +437,38 @@ PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
ph7_vm *pVm = (pSrc->nType & MEMOBJ_HASHMAP) ? pDest->pVm : 0;
|
||||
sxu32 nDest = pVm ? pDest->nIdx : SXU32_HIGH;
|
||||
sxi32 bArena = pVm && SySetAt(&pVm->aMemObj, nDest) == pDest;
|
||||
if(pDest->nDeclaredType & MEMOBJ_NAMED) {
|
||||
sxu32 nDeclared = pDest->nDeclaredType;
|
||||
sxi32 iFlags = pDest->iFlags;
|
||||
ph7_value sValue, sPrevious;
|
||||
sxi32 rc;
|
||||
if(PH7_VmTypeCheck(pSrc, nDeclared) != SXRET_OK) {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
/* Retain both payloads until storage has its contract again. Releasing
|
||||
* the old object/map may invoke a destructor which writes through an
|
||||
* alias of this binding. The source can also be the destination itself. */
|
||||
PH7_MemObjInit(pDest->pVm, &sValue);
|
||||
PH7_MemObjInit(pDest->pVm, &sPrevious);
|
||||
PH7_MemObjLoad(pSrc, &sValue);
|
||||
PH7_MemObjLoad(pDest, &sPrevious);
|
||||
PH7_MemObjRelease(pDest);
|
||||
pDest->x.pOther = 0;
|
||||
if(MemObjIsNullReference(&sValue)) {
|
||||
rc = SXRET_OK;
|
||||
} else {
|
||||
rc = PH7_MemObjStore(&sValue, pDest);
|
||||
if(bArena) {
|
||||
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||
}
|
||||
pDest->nType = nDeclared & MEMOBJ_TYPEMASK;
|
||||
}
|
||||
PH7_MemObjSetDeclaredType(pDest, nDeclared);
|
||||
pDest->iFlags = iFlags;
|
||||
PH7_MemObjRelease(&sValue);
|
||||
PH7_MemObjRelease(&sPrevious);
|
||||
return rc;
|
||||
}
|
||||
if(pDest->nType == 0 || pDest->nType == MEMOBJ_NULL || pDest->nType == pSrc->nType) {
|
||||
sxu32 nType = pSrc->nType;
|
||||
PH7_MemObjStore(pSrc, pDest);
|
||||
@@ -465,6 +531,10 @@ PH7_PRIVATE sxi32 PH7_MemObjSafeStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
} else {
|
||||
return SXERR_NOMATCH;
|
||||
}
|
||||
if(bArena) {
|
||||
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||
}
|
||||
PH7_MemObjSetDeclaredType(pDest, 0);
|
||||
return SXRET_OK;
|
||||
}
|
||||
/*
|
||||
@@ -957,7 +1027,10 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
if((pDest->nType & (MEMOBJ_OBJ | MEMOBJ_HASHMAP)) == MEMOBJ_OBJ) {
|
||||
pObj = (ph7_class_instance *)pDest->x.pOther;
|
||||
}
|
||||
SyMemcpy((const void *) & (*pSrc), &(*pDest), sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||
pDest->x = pSrc->x;
|
||||
pDest->iFlags = pSrc->iFlags;
|
||||
pDest->nType = pSrc->nType;
|
||||
pDest->nDeclaredType = pSrc->nDeclaredType;
|
||||
rc = SXRET_OK;
|
||||
if(SyBlobLength(&pSrc->sBlob) > 0) {
|
||||
SyBlobReset(&pDest->sBlob);
|
||||
@@ -976,6 +1049,7 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
* Stack destinations have no arena slot and must not be rebound. */
|
||||
pMap = PH7_NewHashmap(pVm, 0, 0);
|
||||
PH7_HashmapDup(pSrcMap, pMap);
|
||||
pMap->nDeclaredType = pSrcMap->nDeclaredType;
|
||||
if(bArena) {
|
||||
pDest = (ph7_value *)SySetAt(&pVm->aMemObj, nDest);
|
||||
}
|
||||
@@ -991,8 +1065,10 @@ PH7_PRIVATE sxi32 PH7_MemObjStore(ph7_value *pSrc, ph7_value *pDest) {
|
||||
* buffer contents,simply point to it.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjLoad(ph7_value *pSrc, ph7_value *pDest) {
|
||||
SyMemcpy((const void *) & (*pSrc), &(*pDest),
|
||||
sizeof(ph7_value) - (sizeof(ph7_vm *) + sizeof(SyBlob) + sizeof(sxu32)));
|
||||
pDest->x = pSrc->x;
|
||||
pDest->iFlags = pSrc->iFlags;
|
||||
pDest->nType = pSrc->nType;
|
||||
pDest->nDeclaredType = pSrc->nDeclaredType;
|
||||
if(pSrc->x.pOther) {
|
||||
if(pSrc->nType & MEMOBJ_HASHMAP) {
|
||||
/* Increment reference count */
|
||||
@@ -1014,6 +1090,7 @@ PH7_PRIVATE sxi32 PH7_MemObjLoad(ph7_value *pSrc, ph7_value *pDest) {
|
||||
* Invalidate any prior representation of a given ph7_value.
|
||||
*/
|
||||
PH7_PRIVATE sxi32 PH7_MemObjRelease(ph7_value *pObj) {
|
||||
pObj->nDeclaredType = 0;
|
||||
if((pObj->nType & MEMOBJ_NULL) == 0) {
|
||||
if(pObj->x.pOther) {
|
||||
if(pObj->nType & MEMOBJ_HASHMAP) {
|
||||
|
||||
Reference in New Issue
Block a user