Implement a NULL-coalescing '??' operator.
The build was successful.
Details
The build was successful.
Details
This commit is contained in:
parent
6d964d6113
commit
dcf37af75e
|
@ -86,6 +86,8 @@ static const ph7_expr_op aOpTable[] = {
|
||||||
{ {"^^", sizeof(char) * 2}, EXPR_OP_LXOR, 16, EXPR_OP_ASSOC_LEFT, PH7_OP_LXOR},
|
{ {"^^", sizeof(char) * 2}, EXPR_OP_LXOR, 16, EXPR_OP_ASSOC_LEFT, PH7_OP_LXOR},
|
||||||
/* Precedence 17,left-associative */
|
/* Precedence 17,left-associative */
|
||||||
{ {"||", sizeof(char) * 2}, EXPR_OP_LOR, 17, EXPR_OP_ASSOC_LEFT, PH7_OP_LOR},
|
{ {"||", 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 */
|
/* Ternary operator */
|
||||||
/* Precedence 19,left-associative */
|
/* Precedence 19,left-associative */
|
||||||
{ {"?", sizeof(char)}, EXPR_OP_QUESTY, 19, EXPR_OP_ASSOC_LEFT, 0},
|
{ {"?", 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;
|
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)
|
/* Handle the ternary operator. (expr1) ? (expr2) : (expr3)
|
||||||
* Note that we do not need a precedence loop here since
|
* Note that we do not need a precedence loop here since
|
||||||
* we are dealing with a single operator.
|
* 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;
|
iLeft = iCur;
|
||||||
}
|
}
|
||||||
/* Process right associative binary operators [i.e: '=','+=','/=']
|
/* 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.
|
* so there is no need for a precedence loop here.
|
||||||
*/
|
*/
|
||||||
iRight = -1;
|
iRight = -1;
|
||||||
|
|
13
engine/vm.c
13
engine/vm.c
|
@ -3879,6 +3879,16 @@ static sxi32 VmByteCodeExec(
|
||||||
}
|
}
|
||||||
break;
|
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
|
* OP_LOAD_EXCEPTION * P2 P3
|
||||||
* Push an exception in the corresponding container so that
|
* Push an exception in the corresponding container so that
|
||||||
|
@ -5381,6 +5391,9 @@ static const char *VmInstrToString(sxi32 nOp) {
|
||||||
case PH7_OP_NEQ:
|
case PH7_OP_NEQ:
|
||||||
zOp = "NEQ";
|
zOp = "NEQ";
|
||||||
break;
|
break;
|
||||||
|
case PH7_OP_NULLC:
|
||||||
|
zOp = "NULLC";
|
||||||
|
break;
|
||||||
case PH7_OP_BAND:
|
case PH7_OP_BAND:
|
||||||
zOp = "BITAND";
|
zOp = "BITAND";
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1433,6 +1433,7 @@ enum ph7_vm_op {
|
||||||
PH7_OP_LAND, /* Logical and '&&' */
|
PH7_OP_LAND, /* Logical and '&&' */
|
||||||
PH7_OP_LOR, /* Logical or '||' */
|
PH7_OP_LOR, /* Logical or '||' */
|
||||||
PH7_OP_LXOR, /* Logical xor '^^' */
|
PH7_OP_LXOR, /* Logical xor '^^' */
|
||||||
|
PH7_OP_NULLC, /* NULL-coalescing '??' */
|
||||||
PH7_OP_STORE, /* Store Object */
|
PH7_OP_STORE, /* Store Object */
|
||||||
PH7_OP_STORE_IDX, /* Store indexed object */
|
PH7_OP_STORE_IDX, /* Store indexed object */
|
||||||
PH7_OP_STORE_IDX_REF,/* Store indexed object by reference */
|
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_LAND, /* Logical and '&&' */
|
||||||
EXPR_OP_LOR, /* Logical or '||' */
|
EXPR_OP_LOR, /* Logical or '||' */
|
||||||
EXPR_OP_LXOR, /* Logical xor '^^' */
|
EXPR_OP_LXOR, /* Logical xor '^^' */
|
||||||
|
EXPR_OP_NULLC, /* NULL-coalescing '??' */
|
||||||
EXPR_OP_QUESTY, /* Ternary operator '?' */
|
EXPR_OP_QUESTY, /* Ternary operator '?' */
|
||||||
EXPR_OP_ASSIGN, /* Assignment '=' */
|
EXPR_OP_ASSIGN, /* Assignment '=' */
|
||||||
EXPR_OP_ADD_ASSIGN, /* Combined operator: += */
|
EXPR_OP_ADD_ASSIGN, /* Combined operator: += */
|
||||||
|
|
Loading…
Reference in New Issue