/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include #include #include #include #include #include AstExpression::AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2) : m_combOperator(c) , m_subExpr1(pExpr1) , m_subExpr2(pExpr2) { } AstExpression::AstExpression(sal_Int32 l) : m_combOperator(ExprComb::NONE) { m_exprValue.reset( new AstExprValue ); m_exprValue->et = ET_long; m_exprValue->u.lval = l; } AstExpression::AstExpression(sal_Int32 l, ExprType et) : m_combOperator(ExprComb::NONE) { m_exprValue.reset( new AstExprValue ); m_exprValue->et = et; m_exprValue->u.lval = l; } AstExpression::AstExpression(sal_Int64 h) : m_combOperator(ExprComb::NONE) { m_exprValue.reset( new AstExprValue ); m_exprValue->et = ET_hyper; m_exprValue->u.hval = h; } AstExpression::AstExpression(sal_uInt64 uh) : m_combOperator(ExprComb::NONE) { m_exprValue.reset( new AstExprValue ); m_exprValue->et = ET_uhyper; m_exprValue->u.uhval = uh; } AstExpression::AstExpression(double d) : m_combOperator(ExprComb::NONE) { m_exprValue.reset( new AstExprValue ); m_exprValue->et = ET_double; m_exprValue->u.dval = d; } AstExpression::AstExpression(OString* scopedName) : m_combOperator(ExprComb::Symbol) { if (scopedName) m_xSymbolicName = *scopedName; } AstExpression::~AstExpression() { } /* * Perform the coercion from the given AstExprValue to the requested * ExprType. Return an AstExprValue if successful, NULL if failed. * must be done for hyper, uhyper */ static bool coerce_value(AstExprValue *ev, ExprType t) { if (ev == nullptr) return false; switch (t) { case ET_short: switch (ev->et) { case ET_short: return true; case ET_ushort: { if (ev->u.usval > SAL_MAX_INT16) return false; auto tmp = static_cast(ev->u.usval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_long: { if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16) return false; auto tmp = static_cast(ev->u.lval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_ulong: { if (ev->u.ulval > SAL_MAX_INT16) return false; auto tmp = static_cast(ev->u.ulval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_hyper: { if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16) return false; auto tmp = static_cast(ev->u.hval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_uhyper: { if (ev->u.uhval > SAL_MAX_INT16) return false; auto tmp = static_cast(ev->u.uhval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_float: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT16) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT16))) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_double: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT16) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT16))) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.sval = tmp; ev->et = ET_short; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.sval = tmp; ev->et = ET_short; return true; } default: OSL_ASSERT(false); return false; } case ET_ushort: switch (ev->et) { case ET_short: { if (ev->u.sval < 0) return false; auto tmp = static_cast(ev->u.sval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } case ET_ushort: return true; case ET_long: { if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16) return false; auto tmp = static_cast(ev->u.lval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } case ET_ulong: { if (ev->u.ulval > SAL_MAX_UINT16) return false; auto tmp = static_cast(ev->u.ulval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } case ET_hyper: { if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16) return false; auto tmp = static_cast(ev->u.hval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } case ET_uhyper: { if (ev->u.uhval > SAL_MAX_UINT16) return false; auto tmp = static_cast(ev->u.uhval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.usval = tmp; ev->et = ET_short; return true; } case ET_float: { if (ev->u.fval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT16)) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.usval = tmp; ev->et = ET_short; return true; } case ET_double: { if (ev->u.dval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT16)) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.usval = tmp; ev->et = ET_short; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.usval = tmp; ev->et = ET_ushort; return true; } default: OSL_ASSERT(false); return false; } case ET_long: switch (ev->et) { case ET_short: { auto tmp = static_cast(ev->u.sval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_long: return true; case ET_ulong: { if (ev->u.ulval > SAL_MAX_INT32) return false; auto tmp = static_cast(ev->u.ulval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_hyper: { if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32) return false; auto tmp = static_cast(ev->u.hval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_uhyper: { if (ev->u.uhval > SAL_MAX_INT32) return false; auto tmp = static_cast(ev->u.uhval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_float: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT32) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT32))) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_double: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT32) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT32))) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.lval = tmp; ev->et = ET_long; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.lval = tmp; ev->et = ET_long; return true; } default: OSL_ASSERT(false); return false; } case ET_ulong: switch (ev->et) { case ET_short: { if (ev->u.sval < 0) return false; auto tmp = static_cast(ev->u.sval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_long: { if (ev->u.lval < 0) return false; auto tmp = static_cast(ev->u.lval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_ulong: return true; case ET_hyper: { if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32) return false; auto tmp = static_cast(ev->u.hval); ev->u.lval = tmp; ev->et = ET_ulong; return true; } case ET_uhyper: { if (ev->u.uhval > SAL_MAX_UINT32) return false; auto tmp = static_cast(ev->u.uhval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_float: { if (ev->u.fval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT32)) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_double: { if (ev->u.dval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT32)) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.ulval = tmp; ev->et = ET_ulong; return true; } default: OSL_ASSERT(false); return false; } case ET_hyper: switch (ev->et) { case ET_short: { auto tmp = static_cast(ev->u.sval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_long: { auto tmp = static_cast(ev->u.lval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_ulong: { auto tmp = static_cast(ev->u.ulval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_hyper: return true; case ET_uhyper: { if (ev->u.uhval > SAL_MAX_INT64) return false; auto tmp = static_cast(ev->u.uhval); ev->u.hval = tmp; ev->et = ET_long; return true; } case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_float: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT64) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_INT64))) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_double: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT64) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_INT64))) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.hval = tmp; ev->et = ET_hyper; return true; } default: OSL_ASSERT(false); return false; } case ET_uhyper: switch (ev->et) { case ET_short: { if (ev->u.sval < 0) return false; auto tmp = static_cast(ev->u.sval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_long: { if (ev->u.lval < 0) return false; auto tmp = static_cast(ev->u.lval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_ulong: { auto tmp = static_cast(ev->u.ulval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_hyper: { if (ev->u.hval < 0) return false; auto tmp = static_cast(ev->u.hval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_uhyper: return true; case ET_boolean: { auto tmp = static_cast(ev->u.bval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_float: { if (ev->u.fval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT64)) { return false; } auto tmp = static_cast(ev->u.fval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_double: { if (ev->u.dval < 0.0 || !o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT64)) { return false; } auto tmp = static_cast(ev->u.dval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.uhval = tmp; ev->et = ET_uhyper; return true; } default: OSL_ASSERT(false); return false; } case ET_boolean: switch (ev->et) { case ET_short: ev->u.bval = ev->u.sval != 0; ev->et = ET_boolean; return true; case ET_ushort: ev->u.bval = ev->u.usval != 0; ev->et = ET_boolean; return true; case ET_long: ev->u.bval = ev->u.lval != 0; ev->et = ET_boolean; return true; case ET_ulong: ev->u.bval = ev->u.ulval != 0; ev->et = ET_boolean; return true; case ET_hyper: ev->u.bval = ev->u.hval != 0; ev->et = ET_boolean; return true; case ET_uhyper: ev->u.bval = ev->u.uhval != 0; ev->et = ET_boolean; return true; case ET_boolean: return true; case ET_float: ev->u.bval = ev->u.fval != 0.0; ev->et = ET_boolean; return true; case ET_double: ev->u.bval = ev->u.dval != 0.0; ev->et = ET_boolean; return true; case ET_byte: ev->u.bval = ev->u.byval != 0; ev->et = ET_boolean; return true; default: OSL_ASSERT(false); return false; } case ET_float: switch (ev->et) { case ET_short: { auto tmp = static_cast(ev->u.sval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_long: { auto tmp = static_cast(ev->u.lval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_ulong: { auto tmp = static_cast(ev->u.ulval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_hyper: { auto tmp = static_cast(ev->u.hval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_uhyper: { if (static_cast(ev->u.ulval) > FLT_MAX) return false; auto tmp = static_cast(ev->u.ulval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_boolean: ev->u.fval = ev->u.bval ? 1.0f : 0.0f; ev->et = ET_float; return true; case ET_float: return true; case ET_double: { if (static_cast(ev->u.dval) > FLT_MAX || static_cast(ev->u.dval) < -FLT_MAX) return false; auto tmp = static_cast(ev->u.dval); ev->u.fval = tmp; ev->et = ET_float; return true; } case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.fval = tmp; ev->et = ET_float; return true; } default: OSL_ASSERT(false); return false; } case ET_double: switch (ev->et) { case ET_short: { auto tmp = static_cast(ev->u.sval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_ushort: { auto tmp = static_cast(ev->u.usval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_long: { auto tmp = static_cast(ev->u.lval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_ulong: { auto tmp = static_cast(ev->u.ulval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_hyper: { auto tmp = static_cast(ev->u.hval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_uhyper: { if (ev->u.dval > FLT_MAX || ev->u.dval < -FLT_MAX) return false; auto tmp = static_cast(ev->u.ulval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_boolean: ev->u.dval = ev->u.bval ? 1.0 : 0.0; ev->et = ET_double; return true; case ET_float: { auto tmp = static_cast(ev->u.fval); ev->u.dval = tmp; ev->et = ET_double; return true; } case ET_double: return true; case ET_byte: { auto tmp = static_cast(ev->u.byval); ev->u.dval = tmp; ev->et = ET_double; return true; } default: OSL_ASSERT(false); return false; } case ET_byte: switch (ev->et) { case ET_short: { if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.sval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_ushort: { if (ev->u.usval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.usval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_long: { if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.lval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_ulong: { if (ev->u.ulval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.ulval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_hyper: { if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.hval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_uhyper: { if (ev->u.uhval > SAL_MAX_UINT8) return false; auto tmp = static_cast(ev->u.uhval); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_boolean: ev->u.byval = ev->u.bval ? 1 : 0; ev->et = ET_byte; return true; case ET_float: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.fval), SAL_MIN_INT8) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.fval), SAL_MAX_UINT8))) { return false; } auto tmp = static_cast(static_cast(ev->u.fval)); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_double: { if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev->u.dval), SAL_MIN_INT8) && o3tl::convertsToAtMost(o3tl::roundAway(ev->u.dval), SAL_MAX_UINT8))) { return false; } auto tmp = static_cast(static_cast(ev->u.dval)); ev->u.byval = tmp; ev->et = ET_byte; return true; } case ET_byte: return true; default: OSL_ASSERT(false); return false; } default: OSL_ASSERT(false); return false; } } bool AstExpression::coerce(ExprType t) { /* * Is it already of the right type? */ if (m_exprValue != nullptr && m_exprValue->et == t) return true; /* * OK, must coerce * * First, evaluate it, then try to coerce result type * If already evaluated, return the result */ evaluate(); if (m_exprValue == nullptr) return false; if (!coerce_value(m_exprValue.get(), t)) m_exprValue.reset(); return m_exprValue != nullptr; } bool AstExpression::compareLong(AstExpression *pExpr) { bool bRet = false; if (m_combOperator != pExpr->m_combOperator) return bRet; evaluate(); pExpr->evaluate(); if (m_exprValue == nullptr || pExpr->getExprValue() == nullptr) return bRet; if (m_exprValue->et != pExpr->getExprValue()->et) return bRet; switch (m_exprValue->et) { case ET_long: bRet = m_exprValue->u.lval == pExpr->getExprValue()->u.lval; break; default: OSL_ASSERT(false); bRet = false; break; } return bRet; } void AstExpression::evaluate() { /* * Already evaluated? */ if ( m_exprValue != nullptr ) return; /* * OK, must evaluate operator */ switch (m_combOperator) { case ExprComb::Add: case ExprComb::Minus: case ExprComb::Mul: case ExprComb::Div: case ExprComb::Mod: m_exprValue = eval_bin_op(); break; case ExprComb::Or: case ExprComb::Xor: case ExprComb::And: case ExprComb::Left: case ExprComb::Right: m_exprValue = eval_bit_op(); break; case ExprComb::UPlus: case ExprComb::UMinus: m_exprValue = eval_un_op(); break; case ExprComb::Symbol: m_exprValue = eval_symbol(); break; case ExprComb::NONE: break; } } std::unique_ptr AstExpression::eval_bin_op() { ExprType eType = ET_double; if ( m_combOperator == ExprComb::Mod ) eType = ET_hyper; if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) return nullptr; m_subExpr1->evaluate(); if (m_subExpr1->getExprValue() == nullptr) return nullptr; if (!m_subExpr1->coerce(eType)) return nullptr; m_subExpr2->evaluate(); if (m_subExpr2->getExprValue() == nullptr) return nullptr; if (!m_subExpr2->coerce(eType)) return nullptr; std::unique_ptr< AstExprValue > retval(new AstExprValue); retval->et = eType; switch (m_combOperator) { case ExprComb::Mod: if (m_subExpr2->getExprValue()->u.hval == 0) return nullptr; retval->u.hval = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval; break; case ExprComb::Add: retval->u.dval = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval; break; case ExprComb::Minus: retval->u.dval = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval; break; case ExprComb::Mul: retval->u.dval = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval; break; case ExprComb::Div: if (m_subExpr2->getExprValue()->u.dval == 0.0) return nullptr; retval->u.dval = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval; break; default: return nullptr; } return retval; } std::unique_ptr AstExpression::eval_bit_op() { if (m_subExpr1 == nullptr || m_subExpr2 == nullptr) return nullptr; m_subExpr1->evaluate(); if (m_subExpr1->getExprValue() == nullptr) return nullptr; if (!m_subExpr1->coerce(ET_long)) return nullptr; m_subExpr2->evaluate(); if (m_subExpr2->getExprValue() == nullptr) return nullptr; if (!m_subExpr2->coerce(ET_long)) return nullptr; std::unique_ptr< AstExprValue > retval(new AstExprValue); retval->et = ET_long; switch (m_combOperator) { case ExprComb::Or: retval->u.lval = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval; break; case ExprComb::Xor: retval->u.lval = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval; break; case ExprComb::And: retval->u.lval = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval; break; case ExprComb::Left: retval->u.lval = m_subExpr1->getExprValue()->u.lval << m_subExpr2->getExprValue()->u.lval; break; case ExprComb::Right: retval->u.lval = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval; break; default: return nullptr; } return retval; } std::unique_ptr AstExpression::eval_un_op() { if (m_subExpr1 == nullptr) return nullptr; m_subExpr1->evaluate(); if (m_subExpr1->getExprValue() == nullptr) return nullptr; if (!m_subExpr1->coerce(ET_double)) return nullptr; std::unique_ptr< AstExprValue > retval(new AstExprValue); retval->et = ET_double; switch (m_combOperator) { case ExprComb::UPlus: retval->u.lval = m_subExpr1->getExprValue()->u.lval; break; case ExprComb::UMinus: retval->u.lval = -(m_subExpr1->getExprValue()->u.lval); break; default: return nullptr; } return retval; } std::unique_ptr AstExpression::eval_symbol() { AstScope *pScope = nullptr; AstDeclaration *pDecl; AstConstant *pConst; /* * Is there a symbol stored? */ if (!m_xSymbolicName) { ErrorHandler::evalError(this); return nullptr; } /* * Get current scope for lookup */ if (idlc()->scopes()->depth() > 0) pScope = idlc()->scopes()->topNonNull(); if ( !pScope ) { ErrorHandler::lookupError(*m_xSymbolicName); return nullptr; } /* * Do lookup */ pDecl = pScope->lookupByName(*m_xSymbolicName); if (pDecl == nullptr) { ErrorHandler::lookupError(*m_xSymbolicName); return nullptr; } /* * Is it a constant? */ if (pDecl->getNodeType() != NT_const && pDecl->getNodeType() != NT_enum_val) { ErrorHandler::constantExpected(pDecl, *m_xSymbolicName); return nullptr; } if (!ErrorHandler::checkPublished(pDecl)) { return nullptr; } /* * OK, now evaluate the constant we just got, to produce its value */ pConst = static_cast< AstConstant* >(pDecl); pConst->getConstValue()->evaluate(); auto const val = pConst->getConstValue()->getExprValue(); return val == nullptr ? nullptr : std::make_unique(*val); } OString AstExpression::toString() { OString exprStr; if ( m_combOperator == ExprComb::Symbol ) return m_xSymbolicName ? *m_xSymbolicName : OString(""); if ( m_exprValue ) { switch (m_exprValue->et) { case ET_short: return OString::number(m_exprValue->u.sval); case ET_ushort: return OString::number(m_exprValue->u.usval); case ET_long: return OString::number(m_exprValue->u.lval); case ET_ulong: return OString::number(m_exprValue->u.ulval); case ET_hyper: return OString::number(m_exprValue->u.hval); case ET_uhyper: return OString::number(m_exprValue->u.uhval); case ET_float: return OString::number(m_exprValue->u.fval); case ET_double: return OString::number(m_exprValue->u.dval); case ET_byte: return OString::number(m_exprValue->u.byval); case ET_boolean: if ( m_exprValue->u.lval == 0) return "FALSE"; else return "TRUE"; default: OSL_ASSERT(false); return OString(); } } switch (m_combOperator) { case ExprComb::UPlus: exprStr += "+"; break; case ExprComb::UMinus: exprStr += "-"; break; default: break; } if ( m_subExpr1 ) exprStr += m_subExpr1->toString(); switch (m_combOperator) { case ExprComb::Add: exprStr += " + "; break; case ExprComb::Minus: exprStr += " - "; break; case ExprComb::Mul: exprStr += " * "; break; case ExprComb::Div: exprStr += " / "; break; case ExprComb::Mod: exprStr += " % "; break; case ExprComb::Or: exprStr += " | "; break; case ExprComb::Xor: exprStr += " ^ "; break; case ExprComb::And: exprStr += " & "; break; case ExprComb::Left: exprStr += " << "; break; case ExprComb::Right: exprStr += " >> "; break; default: break; } if ( m_subExpr2 ) exprStr += m_subExpr2->toString(); return exprStr; } // Convert the type of an AST_Expression to a char * const sal_Char* exprTypeToString(ExprType t) { switch (t) { case ET_short: return "short"; case ET_ushort: return "unsigned short"; case ET_long: return "long"; case ET_ulong: return "unsigned long"; case ET_hyper: return "hyper"; case ET_uhyper: return "unsigned hyper"; case ET_float: return "float"; case ET_double: return "double"; case ET_char: return "char"; case ET_byte: return "byte"; case ET_boolean: return "boolean"; case ET_string: return "string"; case ET_any: return "any"; case ET_type: return "type"; case ET_void: return "void"; case ET_none: return "none"; } return "unknown"; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */