Implement exponentiation (**) operator
All checks were successful
Build / AerScript (push) Successful in 40s
All checks were successful
Build / AerScript (push) Successful in 40s
This commit is contained in:
58
engine/vm.c
58
engine/vm.c
@@ -7,6 +7,7 @@
|
||||
* Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
* David Carlier <devnexen@gmail.com>
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "ph7int.h"
|
||||
|
||||
/*
|
||||
@@ -2979,6 +2980,63 @@ static sxi32 VmByteCodeExec(
|
||||
VmPopOperand(&pTos, 1);
|
||||
break;
|
||||
}
|
||||
/* OP_POW * * *
|
||||
* OP_POW_STORE * * *
|
||||
*
|
||||
* Pop the top two elements from the stack, perform an exponentiation,
|
||||
* and push the result back onto the stack.
|
||||
*/
|
||||
case PH7_OP_POW:
|
||||
case PH7_OP_POW_STORE: {
|
||||
SyString sName;
|
||||
ph7_value *pNos = &pTos[-1];
|
||||
/* Force the operand to be numeric */
|
||||
if(pNos < pStack) {
|
||||
goto Abort;
|
||||
}
|
||||
PH7_MemObjToNumeric(pTos);
|
||||
PH7_MemObjToNumeric(pNos);
|
||||
/* Perform the requested operation */
|
||||
if(MEMOBJ_REAL & (pTos->nType | pNos->nType)) {
|
||||
/* Floating point arithmetic */
|
||||
ph7_real a, b, r;
|
||||
if((pTos->nType & MEMOBJ_REAL) == 0) {
|
||||
PH7_MemObjToReal(pTos);
|
||||
}
|
||||
if((pNos->nType & MEMOBJ_REAL) == 0) {
|
||||
PH7_MemObjToReal(pNos);
|
||||
}
|
||||
a = pNos->x.rVal;
|
||||
b = pTos->x.rVal;
|
||||
r = pow(b, a);
|
||||
/* Push the result */
|
||||
pNos->x.rVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_REAL);
|
||||
} else {
|
||||
/* Integer arithmetic */
|
||||
sxi64 a, b, r;
|
||||
a = pNos->x.iVal;
|
||||
b = pTos->x.iVal;
|
||||
r = (sxi64)pow((double)b, (double)a);
|
||||
/* Push the result */
|
||||
pNos->x.iVal = r;
|
||||
MemObjSetType(pNos, MEMOBJ_INT);
|
||||
}
|
||||
if(pInstr->iOp == PH7_OP_POW_STORE) {
|
||||
ph7_value *pObj;
|
||||
if(pTos->nIdx == SXU32_HIGH) {
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot perform assignment on a constant class attribute");
|
||||
} else if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) {
|
||||
if(pNos->nType != pObj->nType && PH7_CheckVarCompat(pNos, pObj->nType) != SXRET_OK) {
|
||||
SyStringInitFromBuf(&sName, pInstr->p3, SyStrlen((const char *)pInstr->p3));
|
||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Cannot assign a value of incompatible type to variable '$%z'", &sName);
|
||||
};
|
||||
PH7_MemObjStore(pNos, pObj);
|
||||
}
|
||||
}
|
||||
VmPopOperand(&pTos, 1);
|
||||
break;
|
||||
}
|
||||
/* OP_ADD P1 P2 *
|
||||
*
|
||||
* Pop the top two elements from the stack, add them together,
|
||||
|
Reference in New Issue
Block a user