Fix value comparison and sorting semantics
Build / AerScript (push) Successful in 31s

This commit is contained in:
2026-11-05 22:26:00 +01:00
parent 3c3c15281a
commit d98f6a8e91
10 changed files with 1956 additions and 681 deletions
+9 -135
View File
@@ -1193,143 +1193,17 @@ PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
}
}
/*
* Compare two class instances [i.e: Objects in the PHP jargon]
* Note on objects comparison:
* According to the PHP langauge reference manual
* When using the comparison operator (==), object variables are compared in a simple manner
* namely: Two object instances are equal if they have the same attributes and values, and are
* instances of the same class.
* On the other hand, when using the identity operator (===), object variables are identical
* if and only if they refer to the same instance of the same class.
* An example will clarify these rules.
* Example #1 Example of object comparison
* <?php
* function bool2str($bool)
* {
* if ($bool === false) {
* return 'FALSE';
* } else {
* return 'TRUE';
* }
* }
* function compareObjects(&$o1, &$o2)
* {
* echo 'o1 == o2 : ' . bool2str($o1 == $o2) . "\n";
* echo 'o1 != o2 : ' . bool2str($o1 != $o2) . "\n";
* echo 'o1 === o2 : ' . bool2str($o1 === $o2) . "\n";
* echo 'o1 !== o2 : ' . bool2str($o1 !== $o2) . "\n";
* }
* class Flag
* {
* public $flag;
*
* function Flag($flag = true) {
* $this->flag = $flag;
* }
* }
*
* class OtherFlag
* {
* public $flag;
*
* function OtherFlag($flag = true) {
* $this->flag = $flag;
* }
* }
*
* $o = new Flag();
* $p = new Flag();
* $q = $o;
* $r = new OtherFlag();
*
* echo "Two instances of the same class\n";
* compareObjects($o, $p);
* echo "\nTwo references to the same instance\n";
* compareObjects($o, $q);
* echo "\nInstances of two different classes\n";
* compareObjects($o, $r);
* ?>
* The above example will output:
* Two instances of the same class
* o1 == o2 : TRUE
* o1 != o2 : FALSE
* o1 === o2 : FALSE
* o1 !== o2 : TRUE
* Two references to the same instance
* o1 == o2 : TRUE
* o1 != o2 : FALSE
* o1 === o2 : TRUE
* o1 !== o2 : FALSE
* Instances of two different classes
* o1 == o2 : FALSE
* o1 != o2 : TRUE
* o1 === o2 : FALSE
* o1 !== o2 : TRUE
*
* This function return 0 if the objects are equals according to the comprison rules defined above.
* Any other return values indicates difference.
* Compare two class instances [i.e: Objects in the PHP jargon].
* Under the typed comparison contract object comparison is IDENTITY-ONLY:
* two values are equal if and only if they reference the same instance
* [or both are empty references, i.e: x.pOther == 0]. There is no
* attribute comparison and no ordering; bStrict yields the same result.
*/
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_instance *pRight, int bStrict, int iNest) {
SyHashEntry *pEntry, *pEntry2;
ph7_value sV1, sV2;
sxi32 rc;
if(iNest > 31) {
/* Nesting limit reached */
PH7_VmThrowError(pLeft->pVm, PH7_CTX_ERR, "Nesting limit reached, probably infinite recursion");
}
/* Comparison is performed only if the objects are instance of the same class */
if(pLeft->pClass != pRight->pClass) {
return 1;
}
if(bStrict) {
/*
* According to the PHP language reference manual:
* when using the identity operator (===), object variables
* are identical if and only if they refer to the same instance
* of the same class.
*/
return pLeft != pRight;
}
/*
* Attribute comparison.
* According to the PHP reference manual:
* When using the comparison operator (==), object variables are compared
* in a simple manner, namely: Two object instances are equal if they have
* the same attributes and values, and are instances of the same class.
*/
if(pLeft == pRight) {
/* Same instance,don't bother processing,object are equals */
return 0;
}
SyHashResetLoopCursor(&pLeft->hAttr);
SyHashResetLoopCursor(&pRight->hAttr);
PH7_MemObjInit(pLeft->pVm, &sV1);
PH7_MemObjInit(pLeft->pVm, &sV2);
sV1.nIdx = sV2.nIdx = SXU32_HIGH;
while((pEntry = SyHashGetNextEntry(&pLeft->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pRight->hAttr)) != 0) {
VmClassAttr *p1 = (VmClassAttr *)pEntry->pUserData;
VmClassAttr *p2 = (VmClassAttr *)pEntry2->pUserData;
/* Compare only non-static attribute */
if((p1->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
ph7_value *pL, *pR;
pL = ExtractClassAttrValue(pLeft->pVm, p1);
pR = ExtractClassAttrValue(pRight->pVm, p2);
if(pL && pR) {
PH7_MemObjLoad(pL, &sV1);
PH7_MemObjLoad(pR, &sV2);
/* Compare the two values now */
rc = PH7_MemObjCmp(&sV1, &sV2, bStrict, iNest + 1);
PH7_MemObjRelease(&sV1);
PH7_MemObjRelease(&sV2);
if(rc != 0) {
/* Not equals */
return rc;
}
}
}
}
/* Object are equals */
return 0;
SXUNUSED(bStrict); /* cc warning */
SXUNUSED(iNest); /* cc warning */
/* Identity comparison */
return pLeft == pRight ? 0 : 1;
}
/*
* Dump a class instance and the store the dump in the BLOB given