in src/foundation_library/Expression.cpp [583:769]
static HRESULT EvaluateRpnExpression(
const _TokenBaseVectorType &rpn,
_In_ IResolveTokenDelegate *pResolveDelegate,
_COM_Outptr_result_maybenull_ IPropertyValue **ppValue)
{
IFCPTR_ASSERT(pResolveDelegate);
IFCPTR_ASSERT(ppValue);
*ppValue = nullptr;
std::stack<PropertyValuePtr> st;
for(_TokenBaseVectorType::const_iterator iter = rpn.begin();
iter != rpn.end();
++iter)
{
CTokenBase *pTokenBase = (*iter);
if(pTokenBase->getType() == TokenType_value_operand)
{
PropertyValuePtr value;
pTokenBase->As<CTokenValue>()->getValue(value);
st.push(value);
}
else if(pTokenBase->getType() == TokenType_reference_operand)
{
const CHAR_t *referenceToken = pTokenBase->As<CTokenReferenceValue>()->getReferenceToken();
PropertyValuePtr value;
IFR(pResolveDelegate->Invoke(referenceToken,value.GetAddressOf()));
st.push(value);
}
else
{
_OperatorType operatorType = pTokenBase->As<CTokenOperator>()->getOperatorTypeInfo()._operatorType;
// is an operator
PropertyValuePtr operandRight = st.top();
st.pop();
PropertyValuePtr result;
if(operatorType == OperatorType_not)
{
boolean boolValue;
IFR(operandRight->GetBoolean(&boolValue));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue((bool)(boolValue ? false:true)));
}
else
{
PropertyValuePtr operandLeft = st.top();
if (!st.empty())
{
operandLeft = st.top();
st.pop();
}
else
return E_UNEXPECTED;
// evaluate operator
switch(operatorType)
{
case OperatorType_land:
{
boolean boolValueLeft,boolValueRight;
IFR(operandLeft->GetBoolean(&boolValueLeft));
IFR(operandRight->GetBoolean(&boolValueRight));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue((bool)(boolValueLeft && boolValueRight)));
}
break;
case OperatorType_lor:
{
boolean boolValueLeft,boolValueRight;
IFR(operandLeft->GetBoolean(&boolValueLeft));
IFR(operandRight->GetBoolean(&boolValueRight));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue((bool)(boolValueLeft || boolValueRight)));
}
break;
case OperatorType_iseq:
case OperatorType_gt:
case OperatorType_gte:
case OperatorType_lt:
case OperatorType_lte:
case OperatorType_ne:
{
int cmp = pv_util::CompareInspectableValues(operandLeft,operandRight);
bool cond = false;
if(operatorType == OperatorType_iseq)
{
cond = (cmp == 0);
}
else if(operatorType == OperatorType_gt)
{
cond = (cmp > 0);
}
else if(operatorType == OperatorType_gte)
{
cond = (cmp > 0) || (cmp == 0);
}
else if(operatorType == OperatorType_lt)
{
cond = (cmp < 0);
}
else if(operatorType == OperatorType_lte)
{
cond = (cmp < 0) || (cmp == 0);
}
else if(operatorType == OperatorType_ne)
{
cond = cmp != 0;
}
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue(cond));
}
break;
case OperatorType_band:
case OperatorType_bor:
case OperatorType_shl:
case OperatorType_shr:
case OperatorType_xor:
{
UINT32 left,right;
IFR(operandLeft->GetUInt32(&left));
IFR(operandRight->GetUInt32(&right));
UINT32 resultVal = 0;
if(operatorType == OperatorType_band)
{
resultVal = left & right;
}
else if(operatorType == OperatorType_bor)
{
resultVal = left | right;
}
else if(operatorType == OperatorType_shl)
{
resultVal = left << right;
}
else if(operatorType == OperatorType_shr)
{
resultVal = left >> right;
}
else if(operatorType == OperatorType_xor)
{
resultVal = left ^ right;
}
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue(resultVal));
}
break;
case OperatorType_add:
case OperatorType_sub:
case OperatorType_mul:
case OperatorType_div:
case OperatorType_idiv:
{
if(hasRealTypes(operandLeft,operandRight))
{
DOUBLE left,right;
IFR(operandLeft->GetDouble(&left));
IFR(operandRight->GetDouble(&right));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue(arithmeticOperator(operatorType,left,right)));
}
else if(operatorType==OperatorType_sub || hasSignedTypes(operandLeft,operandRight))
{
INT32 left,right;
IFR(operandLeft->GetInt32(&left));
IFR(operandRight->GetInt32(&right));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue(arithmeticOperator(operatorType,left,right)));
}
else
{
UINT32 left,right;
IFR(operandLeft->GetUInt32(&left));
IFR(operandRight->GetUInt32(&right));
result = pv_util::ToPropertyValuePtr(pv_util::CreateValue(arithmeticOperator(operatorType,left,right)));
}
}
break;
default:
return E_NOTIMPL;
}
}
// push result
st.push(result);
}
}
PropertyValuePtr result = st.top();
st.pop();
if (!st.empty())
return E_UNEXPECTED;
return result.CopyTo(ppValue);
}