Implement a NULL-coalescing '??' operator.
The build was successful. Details

This commit is contained in:
Rafal Kupiec 2019-06-21 00:34:41 +02:00
parent 6d964d6113
commit dcf37af75e
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
3 changed files with 42 additions and 1 deletions

View File

@ -86,6 +86,8 @@ static const ph7_expr_op aOpTable[] = {
{ {"^^", sizeof(char) * 2}, EXPR_OP_LXOR, 16, EXPR_OP_ASSOC_LEFT, PH7_OP_LXOR},
/* Precedence 17,left-associative */
{ {"||", sizeof(char) * 2}, EXPR_OP_LOR, 17, EXPR_OP_ASSOC_LEFT, PH7_OP_LOR},
/* Precedence 18,right-associative */
{ {"??", sizeof(char) * 2}, EXPR_OP_NULLC, 18, EXPR_OP_ASSOC_RIGHT, PH7_OP_NULLC},
/* Ternary operator */
/* Precedence 19,left-associative */
{ {"?", sizeof(char)}, EXPR_OP_QUESTY, 19, EXPR_OP_ASSOC_LEFT, 0},
@ -1074,6 +1076,30 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
iLeft = iCur;
}
}
/* Process right-associative operators with precedence 18 */
iRight = -1;
for(iCur = nToken - 1 ; iCur >= 0 ; iCur--) {
if(apNode[iCur] == 0) {
continue;
}
pNode = apNode[iCur];
if(pNode->pOp && pNode->pOp->iPrec == 18 && 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 (Reverse) */
pNode->pLeft = apNode[iRight];
pNode->pRight = apNode[iLeft];
apNode[iLeft] = apNode[iRight] = 0;
}
iRight = iCur;
}
/* Handle the ternary operator. (expr1) ? (expr2) : (expr3)
* Note that we do not need a precedence loop here since
* we are dealing with a single operator.
@ -1139,7 +1165,7 @@ static sxi32 ExprMakeTree(ph7_gen_state *pGen, ph7_expr_node **apNode, sxi32 nTo
iLeft = iCur;
}
/* Process right associative binary operators [i.e: '=','+=','/=']
* Note: All right associative binary operators have precedence 18
* Note: All right associative binary operators have precedence 20
* so there is no need for a precedence loop here.
*/
iRight = -1;

View File

@ -3879,6 +3879,16 @@ static sxi32 VmByteCodeExec(
}
break;
}
case PH7_OP_NULLC: {
ph7_value *pNos = &pTos[-1];
int rc;
rc = PH7_MemObjIsNull(pTos);
if(!rc) {
PH7_MemObjStore(pTos, pNos);
}
VmPopOperand(&pTos, 1);
break;
}
/*
* OP_LOAD_EXCEPTION * P2 P3
* Push an exception in the corresponding container so that
@ -5381,6 +5391,9 @@ static const char *VmInstrToString(sxi32 nOp) {
case PH7_OP_NEQ:
zOp = "NEQ";
break;
case PH7_OP_NULLC:
zOp = "NULLC";
break;
case PH7_OP_BAND:
zOp = "BITAND";
break;

View File

@ -1433,6 +1433,7 @@ enum ph7_vm_op {
PH7_OP_LAND, /* Logical and '&&' */
PH7_OP_LOR, /* Logical or '||' */
PH7_OP_LXOR, /* Logical xor '^^' */
PH7_OP_NULLC, /* NULL-coalescing '??' */
PH7_OP_STORE, /* Store Object */
PH7_OP_STORE_IDX, /* Store indexed object */
PH7_OP_STORE_IDX_REF,/* Store indexed object by reference */
@ -1510,6 +1511,7 @@ enum ph7_expr_id {
EXPR_OP_LAND, /* Logical and '&&' */
EXPR_OP_LOR, /* Logical or '||' */
EXPR_OP_LXOR, /* Logical xor '^^' */
EXPR_OP_NULLC, /* NULL-coalescing '??' */
EXPR_OP_QUESTY, /* Ternary operator '?' */
EXPR_OP_ASSIGN, /* Assignment '=' */
EXPR_OP_ADD_ASSIGN, /* Combined operator: += */