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:
parent
8ac9b148d1
commit
d73eb9b5b2
@ -4742,6 +4742,13 @@ static sxi32 PH7_GenStateEmitExprCode(
|
||||
(void)PH7_VmPopInstr(pGen->pVm);
|
||||
}
|
||||
}
|
||||
} else if(pNode->pOp->iPrec == 20 && pNode->pOp->iOp != EXPR_OP_ASSIGN) {
|
||||
pInstr = PH7_VmPeekInstr(pGen->pVm);
|
||||
if(pInstr) {
|
||||
if(pInstr->iOp != PH7_OP_LOAD_IDX) {
|
||||
p3 = pInstr->p3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(iVmOp > 0) {
|
||||
|
@ -52,8 +52,10 @@ static const ph7_expr_op aOpTable[] = {
|
||||
{ {"(resource)", sizeof("(resource)") - 1}, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_RES},
|
||||
{ {"(void)", sizeof("(void)") - 1 }, EXPR_OP_TYPECAST, 4, EXPR_OP_ASSOC_RIGHT, PH7_OP_CVT_VOID },
|
||||
/* Binary operators */
|
||||
/* Precedence 6,non-associative */
|
||||
{ {"is", sizeof("is") - 1}, EXPR_OP_IS, 6, EXPR_OP_NON_ASSOC, PH7_OP_IS},
|
||||
/* Precedence 5,non-associative */
|
||||
{ {"is", sizeof("is") - 1}, EXPR_OP_IS, 5, EXPR_OP_NON_ASSOC, PH7_OP_IS},
|
||||
/* Precedence 6, right-associative */
|
||||
{ {"**", sizeof(char) * 2}, EXPR_OP_POW, 6, EXPR_OP_ASSOC_RIGHT, PH7_OP_POW},
|
||||
/* Precedence 7,left-associative */
|
||||
{ {"*", sizeof(char)}, EXPR_OP_MUL, 7, EXPR_OP_ASSOC_LEFT, PH7_OP_MUL},
|
||||
{ {"/", sizeof(char)}, EXPR_OP_DIV, 7, EXPR_OP_ASSOC_LEFT, PH7_OP_DIV},
|
||||
@ -97,6 +99,7 @@ static const ph7_expr_op aOpTable[] = {
|
||||
{ {"+=", sizeof(char) * 2}, EXPR_OP_ADD_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_ADD_STORE },
|
||||
{ {"-=", sizeof(char) * 2}, EXPR_OP_SUB_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_SUB_STORE },
|
||||
{ {"*=", sizeof(char) * 2}, EXPR_OP_MUL_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_MUL_STORE },
|
||||
{ {"**=", sizeof(char) * 3}, EXPR_OP_POW_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_POW_STORE },
|
||||
{ {"/=", sizeof(char) * 2}, EXPR_OP_DIV_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_DIV_STORE },
|
||||
{ {"%=", sizeof(char) * 2}, EXPR_OP_MOD_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_MOD_STORE },
|
||||
{ {"&=", sizeof(char) * 2}, EXPR_OP_AND_ASSIGN, 20, EXPR_OP_ASSOC_RIGHT, PH7_OP_BAND_STORE },
|
||||
@ -1020,8 +1023,32 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
|
||||
iLeft = iCur;
|
||||
}
|
||||
}
|
||||
/* Handle right associative binary operators with precedence 6 */
|
||||
iRight = -1;
|
||||
for(iCur = nToken - 1; iCur >= 0; iCur--) {
|
||||
if(apNode[iCur] == 0) {
|
||||
continue;
|
||||
}
|
||||
pNode = apNode[iCur];
|
||||
if(pNode->pOp && pNode->pOp->iPrec == 6 && pNode->pLeft == 0) {
|
||||
/* Get the left node */
|
||||
iLeft = iCur - 1;
|
||||
while(iLeft >= 0 && apNode[iLeft] == 0) {
|
||||
iLeft--;
|
||||
}
|
||||
if(iLeft < 0 || iRight < 0 || !NODE_ISTERM(iRight) || !NODE_ISTERM(iLeft)) {
|
||||
/* Syntax error */
|
||||
PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine, "'%z': Missing/Invalid operand", &pNode->pOp->sOp);
|
||||
}
|
||||
/* Link the node to the tree */
|
||||
pNode->pLeft = apNode[iRight];
|
||||
pNode->pRight = apNode[iLeft];
|
||||
apNode[iLeft] = apNode[iRight] = 0;
|
||||
}
|
||||
iRight = iCur;
|
||||
}
|
||||
/* Process left and non-associative binary operators [i.e: *,/,&&,||...]*/
|
||||
for(i = 6 ; i < 18 ; i++) {
|
||||
for(i = 5 ; i < 18 ; i++) {
|
||||
iLeft = -1;
|
||||
for(iCur = 0 ; iCur < nToken ; ++iCur) {
|
||||
if(apNode[iCur] == 0) {
|
||||
|
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,
|
||||
|
@ -1403,6 +1403,7 @@ enum ph7_vm_op {
|
||||
PH7_OP_BITNOT, /* Bitwise not '~' */
|
||||
PH7_OP_LNOT, /* Logical not '!' */
|
||||
PH7_OP_MUL, /* Multiplication '*' */
|
||||
PH7_OP_POW, /* POW '**' */
|
||||
PH7_OP_DIV, /* Division '/' */
|
||||
PH7_OP_MOD, /* Modulus '%' */
|
||||
PH7_OP_ADD, /* Add '+' */
|
||||
@ -1437,6 +1438,7 @@ enum ph7_vm_op {
|
||||
PH7_OP_ADD_STORE, /* Add and store '+=' */
|
||||
PH7_OP_SUB_STORE, /* Sub and store '-=' */
|
||||
PH7_OP_MUL_STORE, /* Mul and store '*=' */
|
||||
PH7_OP_POW_STORE, /* Pow and store '**=' */
|
||||
PH7_OP_DIV_STORE, /* Div and store '/=' */
|
||||
PH7_OP_MOD_STORE, /* Mod and store '%=' */
|
||||
PH7_OP_SHL_STORE, /* Shift left and store '>>=' */
|
||||
@ -1479,6 +1481,7 @@ enum ph7_expr_id {
|
||||
EXPR_OP_TYPECAST, /* Type cast [i.e: (int),(float),(string)...] */
|
||||
EXPR_OP_IS, /* is */
|
||||
EXPR_OP_LOGNOT, /* logical not ! */
|
||||
EXPR_OP_POW, /* Exponentiation '**' */
|
||||
EXPR_OP_MUL, /* Multiplication */
|
||||
EXPR_OP_DIV, /* division */
|
||||
EXPR_OP_MOD, /* Modulus */
|
||||
@ -1505,6 +1508,7 @@ enum ph7_expr_id {
|
||||
EXPR_OP_ADD_ASSIGN, /* Combined operator: += */
|
||||
EXPR_OP_SUB_ASSIGN, /* Combined operator: -= */
|
||||
EXPR_OP_MUL_ASSIGN, /* Combined operator: *= */
|
||||
EXPR_OP_POW_ASSIGN, /* Combined operator: **= */
|
||||
EXPR_OP_DIV_ASSIGN, /* Combined operator: /= */
|
||||
EXPR_OP_MOD_ASSIGN, /* Combined operator: %= */
|
||||
EXPR_OP_AND_ASSIGN, /* Combined operator: &= */
|
||||
|
Loading…
x
Reference in New Issue
Block a user