static HRESULT EvaluateRpnExpression()

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);
}