This commit is contained in:
+55
-10
@@ -3283,8 +3283,16 @@ Resume:
|
||||
iRes = VmInstanceOf(pVm, pThis->pClass, pClass);
|
||||
}
|
||||
} else {
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0);
|
||||
iRes = rc == 0;
|
||||
/* Value comparison fallback: follows the typed comparison
|
||||
* contract. Incomparable categories yield FALSE [no match]
|
||||
* rather than a fatal error, since is is a type test with
|
||||
* a value-comparison fallback. */
|
||||
if(PH7_MemObjComparable(pNos, pTos)) {
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0, 0);
|
||||
iRes = rc == 0;
|
||||
} else {
|
||||
iRes = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Push result */
|
||||
@@ -4823,8 +4831,11 @@ Resume:
|
||||
if(pNos < pStack) {
|
||||
goto Abort;
|
||||
}
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0);
|
||||
if(pInstr->iOp == PH7_OP_EQ) {
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0, pInstr->iOp == PH7_OP_EQ ? "==" : "!=");
|
||||
if(rc == SXERR_NOMATCH) {
|
||||
/* NaN operand: == is FALSE, != is TRUE */
|
||||
rc = pInstr->iOp != PH7_OP_EQ;
|
||||
} else if(pInstr->iOp == PH7_OP_EQ) {
|
||||
rc = rc == 0;
|
||||
} else {
|
||||
rc = rc != 0;
|
||||
@@ -4870,8 +4881,19 @@ Resume:
|
||||
if(pNos < pStack) {
|
||||
goto Abort;
|
||||
}
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0);
|
||||
if(pInstr->iOp == PH7_OP_LE) {
|
||||
if(!PH7_MemObjOrderable(pNos, pTos)) {
|
||||
/* Only two numbers or two strings define an order.
|
||||
* The diagnostic is terminal: abort the execution
|
||||
* instead of falling through into a second,
|
||||
* contradictory comparison. */
|
||||
PH7_VmThrowNoOrder(pNos, pTos, pInstr->iOp == PH7_OP_LE ? "<=" : "<");
|
||||
goto Abort;
|
||||
}
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0, pInstr->iOp == PH7_OP_LE ? "<=" : "<");
|
||||
if(rc == SXERR_NOMATCH) {
|
||||
/* NaN operand: ordering is always FALSE */
|
||||
rc = 0;
|
||||
} else if(pInstr->iOp == PH7_OP_LE) {
|
||||
rc = rc < 1;
|
||||
} else {
|
||||
rc = rc < 0;
|
||||
@@ -4917,8 +4939,19 @@ Resume:
|
||||
if(pNos < pStack) {
|
||||
goto Abort;
|
||||
}
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0);
|
||||
if(pInstr->iOp == PH7_OP_GE) {
|
||||
if(!PH7_MemObjOrderable(pNos, pTos)) {
|
||||
/* Only two numbers or two strings define an order.
|
||||
* The diagnostic is terminal: abort the execution
|
||||
* instead of falling through into a second,
|
||||
* contradictory comparison. */
|
||||
PH7_VmThrowNoOrder(pNos, pTos, pInstr->iOp == PH7_OP_GE ? ">=" : ">");
|
||||
goto Abort;
|
||||
}
|
||||
rc = PH7_MemObjCmp(pNos, pTos, FALSE, 0, pInstr->iOp == PH7_OP_GE ? ">=" : ">");
|
||||
if(rc == SXERR_NOMATCH) {
|
||||
/* NaN operand: ordering is always FALSE */
|
||||
rc = 0;
|
||||
} else if(pInstr->iOp == PH7_OP_GE) {
|
||||
rc = rc >= 0;
|
||||
} else {
|
||||
rc = rc > 0;
|
||||
@@ -5750,8 +5783,20 @@ Resume:
|
||||
nTarget = pc + 1;
|
||||
goto Unwind;
|
||||
}
|
||||
/* Compare the two expression */
|
||||
rc = PH7_MemObjCmp(&sValue, &sCaseValue, FALSE, 0);
|
||||
/* Compare the two expressions.
|
||||
* Matching follows the typed comparison contract: only
|
||||
* values of the same comparison category can match;
|
||||
* incomparable case labels are skipped [no match]. */
|
||||
if(PH7_MemObjComparable(&sValue, &sCaseValue)) {
|
||||
rc = PH7_MemObjCmp(&sValue, &sCaseValue, FALSE, 0, 0);
|
||||
if(rc == SXERR_NOMATCH) {
|
||||
/* NaN operand never matches a case label */
|
||||
rc = 1;
|
||||
}
|
||||
} else {
|
||||
/* Different categories: fall through to the next case */
|
||||
rc = 1;
|
||||
}
|
||||
PH7_MemObjRelease(&sValue);
|
||||
PH7_MemObjRelease(&sCaseValue);
|
||||
if(rc == 0) {
|
||||
|
||||
Reference in New Issue
Block a user