Implement deterministic int64 wrapping arithmetic
This commit is contained in:
+1
-1
@@ -1259,7 +1259,7 @@ PH7_PRIVATE sxi32 PH7_MemObjAdd(ph7_value *pObj1, ph7_value *pObj2, int bAddStor
|
||||
sxi64 a, b;
|
||||
a = pObj1->x.iVal;
|
||||
b = pObj2->x.iVal;
|
||||
pObj1->x.iVal = a + b;
|
||||
pObj1->x.iVal = PH7_Int64Add(a, b);
|
||||
MemObjSetType(pObj1, MEMOBJ_INT);
|
||||
}
|
||||
} else {
|
||||
|
||||
+38
-22
@@ -3775,7 +3775,7 @@ Resume:
|
||||
if(pObj->nType & MEMOBJ_REAL) {
|
||||
pObj->x.rVal++;
|
||||
} else {
|
||||
pObj->x.iVal++;
|
||||
pObj->x.iVal = PH7_Int64Add(pObj->x.iVal, 1);
|
||||
}
|
||||
if(pInstr->iP1) {
|
||||
/* Pre-increment */
|
||||
@@ -3788,7 +3788,7 @@ Resume:
|
||||
if(pTos->nType & MEMOBJ_REAL) {
|
||||
pTos->x.rVal++;
|
||||
} else {
|
||||
pTos->x.iVal++;
|
||||
pTos->x.iVal = PH7_Int64Add(pTos->x.iVal, 1);
|
||||
MemObjSetType(pTos, MEMOBJ_INT);
|
||||
}
|
||||
}
|
||||
@@ -3816,7 +3816,7 @@ Resume:
|
||||
if(pObj->nType & MEMOBJ_REAL) {
|
||||
pObj->x.rVal--;
|
||||
} else {
|
||||
pObj->x.iVal--;
|
||||
pObj->x.iVal = PH7_Int64Sub(pObj->x.iVal, 1);
|
||||
}
|
||||
if(pInstr->iP1) {
|
||||
/* Pre-decrement */
|
||||
@@ -3829,7 +3829,7 @@ Resume:
|
||||
if(pTos->nType & MEMOBJ_REAL) {
|
||||
pTos->x.rVal--;
|
||||
} else {
|
||||
pTos->x.iVal--;
|
||||
pTos->x.iVal = PH7_Int64Sub(pTos->x.iVal, 1);
|
||||
MemObjSetType(pTos, MEMOBJ_INT);
|
||||
}
|
||||
}
|
||||
@@ -3854,7 +3854,7 @@ Resume:
|
||||
pTos->x.rVal = -pTos->x.rVal;
|
||||
}
|
||||
if(pTos->nType & MEMOBJ_INT) {
|
||||
pTos->x.iVal = -pTos->x.iVal;
|
||||
pTos->x.iVal = PH7_Int64Neg(pTos->x.iVal);
|
||||
}
|
||||
break;
|
||||
/*
|
||||
@@ -3905,7 +3905,7 @@ Resume:
|
||||
if((pTos->nType & MEMOBJ_INT) == 0) {
|
||||
PH7_MemObjToInteger(pTos);
|
||||
}
|
||||
pTos->x.iVal = ~pTos->x.iVal;
|
||||
pTos->x.iVal = PH7_Int64FromUnsigned(~(sxu64)pTos->x.iVal);
|
||||
break;
|
||||
/* OP_MUL * * *
|
||||
* OP_MUL_STORE * * *
|
||||
@@ -3944,7 +3944,7 @@ Resume:
|
||||
sxi64 a, b, r;
|
||||
a = pNos->x.iVal;
|
||||
b = pTos->x.iVal;
|
||||
r = a * b;
|
||||
r = PH7_Int64Mul(a, b);
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_INT);
|
||||
@@ -4000,7 +4000,23 @@ Resume:
|
||||
sxi64 a, b, r;
|
||||
a = pNos->x.iVal;
|
||||
b = pTos->x.iVal;
|
||||
r = (sxi64)pow((double)b, (double)a);
|
||||
/* The parser emits the exponent before the base. */
|
||||
if(a < 0) {
|
||||
if(b == 0) {
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero");
|
||||
}
|
||||
r = b == 1 ? 1 : b == -1 ? ((sxu64)a & 1 ? -1 : 1) : 0;
|
||||
} else {
|
||||
sxu64 base = (sxu64)b, exponent = (sxu64)a, result = 1;
|
||||
while(exponent != 0) {
|
||||
if(exponent & 1) {
|
||||
result *= base;
|
||||
}
|
||||
base *= base;
|
||||
exponent >>= 1;
|
||||
}
|
||||
r = PH7_Int64FromUnsigned(result);
|
||||
}
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_INT);
|
||||
@@ -4131,7 +4147,7 @@ Resume:
|
||||
sxi64 a, b, r;
|
||||
a = pNos->x.iVal;
|
||||
b = pTos->x.iVal;
|
||||
r = a - b;
|
||||
r = PH7_Int64Sub(a, b);
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_INT);
|
||||
@@ -4172,7 +4188,7 @@ Resume:
|
||||
sxi64 a, b, r;
|
||||
a = pTos->x.iVal;
|
||||
b = pNos->x.iVal;
|
||||
r = a - b;
|
||||
r = PH7_Int64Sub(a, b);
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_INT);
|
||||
@@ -4217,7 +4233,7 @@ Resume:
|
||||
if(b == 0) {
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero %qd%%0", a);
|
||||
} else {
|
||||
r = a % b;
|
||||
r = b == -1 ? 0 : a % b;
|
||||
}
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
@@ -4256,7 +4272,7 @@ Resume:
|
||||
if(b == 0) {
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero %qd%%0", a);
|
||||
} else {
|
||||
r = a % b;
|
||||
r = b == -1 ? 0 : a % b;
|
||||
}
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
@@ -4392,16 +4408,16 @@ Resume:
|
||||
switch(pInstr->iOp) {
|
||||
case PH7_OP_BOR_STORE:
|
||||
case PH7_OP_BOR:
|
||||
r = a | b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a | (sxu64)b);
|
||||
break;
|
||||
case PH7_OP_BXOR_STORE:
|
||||
case PH7_OP_BXOR:
|
||||
r = a ^ b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a ^ (sxu64)b);
|
||||
break;
|
||||
case PH7_OP_BAND_STORE:
|
||||
case PH7_OP_BAND:
|
||||
default:
|
||||
r = a & b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a & (sxu64)b);
|
||||
break;
|
||||
}
|
||||
/* Push the result */
|
||||
@@ -4450,16 +4466,16 @@ Resume:
|
||||
switch(pInstr->iOp) {
|
||||
case PH7_OP_BOR_STORE:
|
||||
case PH7_OP_BOR:
|
||||
r = a | b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a | (sxu64)b);
|
||||
break;
|
||||
case PH7_OP_BXOR_STORE:
|
||||
case PH7_OP_BXOR:
|
||||
r = a ^ b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a ^ (sxu64)b);
|
||||
break;
|
||||
case PH7_OP_BAND_STORE:
|
||||
case PH7_OP_BAND:
|
||||
default:
|
||||
r = a & b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a & (sxu64)b);
|
||||
break;
|
||||
}
|
||||
/* Push the result */
|
||||
@@ -4506,9 +4522,9 @@ Resume:
|
||||
a = pNos->x.iVal;
|
||||
b = (sxi32)pTos->x.iVal;
|
||||
if(pInstr->iOp == PH7_OP_SHL) {
|
||||
r = a << b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a << b);
|
||||
} else {
|
||||
r = a >> b;
|
||||
r = PH7_Int64ShiftRight(a, b);
|
||||
}
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
@@ -4550,9 +4566,9 @@ Resume:
|
||||
a = pTos->x.iVal;
|
||||
b = (sxi32)pNos->x.iVal;
|
||||
if(pInstr->iOp == PH7_OP_SHL_STORE) {
|
||||
r = a << b;
|
||||
r = PH7_Int64FromUnsigned((sxu64)a << b);
|
||||
} else {
|
||||
r = a >> b;
|
||||
r = PH7_Int64ShiftRight(a, b);
|
||||
}
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
|
||||
@@ -1642,6 +1642,28 @@ enum json_err_code {
|
||||
JSON_ERROR_SYNTAX, /* Syntax error. */
|
||||
JSON_ERROR_UTF8 /* Malformed UTF-8 characters */
|
||||
};
|
||||
/* Integer operators retain the low 64 bits, interpreted as two's complement.
|
||||
* Convert only representable unsigned values to signed; arithmetic wraps unsigned.
|
||||
*/
|
||||
static inline sxi64 PH7_Int64FromUnsigned(sxu64 u) {
|
||||
return u <= (sxu64)SXI64_HIGH ? (sxi64)u : -1 - (sxi64)~u;
|
||||
}
|
||||
static inline sxi64 PH7_Int64Add(sxi64 a, sxi64 b) {
|
||||
return PH7_Int64FromUnsigned((sxu64)a + (sxu64)b);
|
||||
}
|
||||
static inline sxi64 PH7_Int64Sub(sxi64 a, sxi64 b) {
|
||||
return PH7_Int64FromUnsigned((sxu64)a - (sxu64)b);
|
||||
}
|
||||
static inline sxi64 PH7_Int64Mul(sxi64 a, sxi64 b) {
|
||||
return PH7_Int64FromUnsigned((sxu64)a * (sxu64)b);
|
||||
}
|
||||
static inline sxi64 PH7_Int64Neg(sxi64 a) {
|
||||
return PH7_Int64FromUnsigned((sxu64)0 - (sxu64)a);
|
||||
}
|
||||
/* The caller supplies a valid shift count (0..63). Avoid signed right shift. */
|
||||
static inline sxi64 PH7_Int64ShiftRight(sxi64 a, sxi32 b) {
|
||||
return a < 0 ? -1 - (sxi64)((~(sxu64)a) >> b) : (sxi64)((sxu64)a >> b);
|
||||
}
|
||||
/* memobj.c function prototypes */
|
||||
PH7_PRIVATE sxi32 PH7_MemObjDump(SyBlob *pOut, ph7_value *pObj, int ShowType, int nTab, int nDepth);
|
||||
PH7_PRIVATE const char *PH7_MemObjTypeDump(ph7_value *pVal);
|
||||
|
||||
+715
-256
File diff suppressed because it is too large
Load Diff
+3
-1
@@ -22,7 +22,7 @@
|
||||
#define JSON_HEX_QUOT 0x08 /* All " are converted to \u0022. */
|
||||
#define JSON_FORCE_OBJECT 0x10 /* Outputs an object rather than an array */
|
||||
#define JSON_NUMERIC_CHECK 0x20 /* Encodes numeric strings as numbers. */
|
||||
#define JSON_BIGINT_AS_STRING 0x40 /* Not used */
|
||||
#define JSON_BIGINT_AS_STRING 0x40 /* Decode big integers as strings. */
|
||||
#define JSON_PRETTY_PRINT 0x80 /* Use whitespace in returned data to format it.*/
|
||||
#define JSON_UNESCAPED_SLASHES 0x100 /* Don't escape '/' */
|
||||
#define JSON_UNESCAPED_UNICODE 0x200 /* Not used */
|
||||
@@ -54,6 +54,8 @@ struct json_private_data {
|
||||
int isFirst; /* True if first encoded entry */
|
||||
int iFlags; /* JSON encoding flags */
|
||||
int nRecCount; /* Recursion count */
|
||||
sxi32 bObject; /* True if the current container is encoded as an object */
|
||||
sxi32 bAbort; /* True if the encoding process was aborted */
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user