/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: astexpression.cxx,v $ * $Revision: 1.12 $ * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_idlc.hxx" #include #include #include #include #include #include #undef MAXCHAR #define MAXCHAR 127 #undef MINCHAR #define MINCHAR -128 using namespace ::rtl; AstExpression::AstExpression(AstExpression *pExpr, ExprType et) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = pExpr->coerce(et); if ( !m_exprValue) { idlc()->error()->coercionError(pExpr, et); } } AstExpression::AstExpression(ExprComb c, AstExpression *pExpr1, AstExpression *pExpr2) : m_combOperator(c) , m_subExpr1(pExpr1) , m_subExpr2(pExpr2) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); } AstExpression::AstExpression(sal_Int16 s) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_short; m_exprValue->u.sval = s; } AstExpression::AstExpression(sal_uInt16 us) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_ushort; m_exprValue->u.usval = us; } AstExpression::AstExpression(sal_Int32 l) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_long; m_exprValue->u.lval = l; } AstExpression::AstExpression(sal_Int32 l, ExprType et) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = et; m_exprValue->u.lval = l; } AstExpression::AstExpression(sal_uInt32 ul) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_ulong; m_exprValue->u.ulval = ul; } AstExpression::AstExpression(sal_Int64 h) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_hyper; m_exprValue->u.hval = h; } AstExpression::AstExpression(sal_uInt64 uh) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_uhyper; m_exprValue->u.uhval = uh; } AstExpression::AstExpression(float f) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_float; m_exprValue->u.fval = f; } AstExpression::AstExpression(double d) : m_combOperator(EC_none) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(NULL) { fillDefinitionDetails(); m_exprValue = new AstExprValue(); m_exprValue->et = ET_double; m_exprValue->u.dval = d; } AstExpression::AstExpression(::rtl::OString* scopedName) : m_combOperator(EC_symbol) , m_subExpr1(NULL) , m_subExpr2(NULL) , m_exprValue(NULL) , m_pSymbolicName(scopedName) { fillDefinitionDetails(); } AstExpression::~AstExpression() { if ( m_exprValue ) delete m_exprValue; if ( m_subExpr1 ) delete m_subExpr1; if ( m_subExpr2 ) delete m_subExpr2; if ( m_pSymbolicName ) delete m_pSymbolicName; } /* * 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 AstExprValue * coerce_value(AstExprValue *ev, ExprType t) { if (ev == NULL) return NULL; switch (t) { case ET_short: switch (ev->et) { case ET_short: return ev; case ET_ushort: if (ev->u.usval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.usval; ev->et = ET_short; return ev; case ET_long: if (ev->u.lval < SAL_MIN_INT16 || ev->u.lval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.lval; ev->et = ET_short; return ev; case ET_ulong: if (ev->u.ulval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.ulval; ev->et = ET_short; return ev; case ET_hyper: if (ev->u.hval < SAL_MIN_INT16 || ev->u.hval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.hval; ev->et = ET_short; return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.uhval; ev->et = ET_short; return ev; case ET_boolean: ev->u.sval = (sal_Int16)ev->u.bval; ev->et = ET_short; return ev; case ET_float: if (ev->u.fval < SAL_MIN_INT16 || ev->u.fval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.fval; ev->et = ET_short; return ev; case ET_double: if (ev->u.dval < SAL_MIN_INT16 || ev->u.dval > SAL_MAX_INT16) return NULL; ev->u.sval = (sal_Int16)ev->u.dval; ev->et = ET_short; return ev; case ET_byte: ev->u.sval = (sal_Int16)ev->u.byval; ev->et = ET_short; return ev; default: OSL_ASSERT(false); return NULL; } case ET_ushort: switch (ev->et) { case ET_short: if (ev->u.sval < 0) return NULL; ev->u.usval = (sal_uInt16)ev->u.sval; ev->et = ET_ushort; return ev; case ET_ushort: return ev; case ET_long: if (ev->u.lval < 0 || ev->u.lval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.lval; ev->et = ET_ushort; return ev; case ET_ulong: if (ev->u.ulval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.ulval; ev->et = ET_ushort; return ev; case ET_hyper: if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.hval; ev->et = ET_ushort; return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.uhval; ev->et = ET_ushort; return ev; case ET_boolean: ev->u.usval = (sal_uInt16)ev->u.bval; ev->et = ET_short; return ev; case ET_float: if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.fval; ev->et = ET_short; return ev; case ET_double: if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT16) return NULL; ev->u.usval = (sal_uInt16)ev->u.dval; ev->et = ET_short; return ev; case ET_byte: ev->u.usval = (sal_uInt16)ev->u.byval; ev->et = ET_ushort; return ev; default: OSL_ASSERT(false); return NULL; } case ET_long: switch (ev->et) { case ET_short: ev->u.lval = (sal_Int32)ev->u.sval; ev->et = ET_long; return ev; case ET_ushort: ev->u.lval = (sal_Int32)ev->u.usval; ev->et = ET_long; return ev; case ET_long: return ev; case ET_ulong: if (ev->u.ulval > SAL_MAX_INT32) return NULL; ev->u.lval = (sal_Int32)ev->u.ulval; ev->et = ET_long; return ev; case ET_hyper: if (ev->u.hval < SAL_MIN_INT32 || ev->u.hval > SAL_MAX_INT32) return NULL; ev->u.lval = (sal_Int32)ev->u.hval; ev->et = ET_long; return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_INT32) return NULL; ev->u.lval = (sal_Int32)ev->u.uhval; ev->et = ET_long; return ev; case ET_boolean: ev->u.lval = (sal_Int32)ev->u.bval; ev->et = ET_long; return ev; case ET_float: if (ev->u.fval < SAL_MIN_INT32 || ev->u.fval > SAL_MAX_INT32) return NULL; ev->u.lval = (sal_Int32)ev->u.fval; ev->et = ET_long; return ev; case ET_double: if (ev->u.dval < SAL_MIN_INT32 || ev->u.dval > SAL_MAX_INT32) return NULL; ev->u.lval = (sal_Int32)ev->u.dval; ev->et = ET_long; return ev; case ET_byte: ev->u.lval = (sal_Int32) ev->u.byval; ev->et = ET_long; return ev; default: OSL_ASSERT(false); return NULL; } case ET_ulong: switch (ev->et) { case ET_short: if (ev->u.sval < 0) return NULL; ev->u.ulval = (sal_uInt32)ev->u.sval; ev->et = ET_ulong; return ev; case ET_ushort: ev->u.ulval = (sal_uInt32)ev->u.usval; ev->et = ET_ulong; return ev; case ET_long: if (ev->u.lval < 0) return NULL; ev->u.ulval = (sal_uInt32)ev->u.lval; ev->et = ET_ulong; return ev; case ET_ulong: return ev; case ET_hyper: if (ev->u.hval < 0 || ev->u.hval > SAL_MAX_UINT32) return NULL; ev->u.lval = (sal_uInt32)ev->u.hval; ev->et = ET_ulong; return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_UINT32) return NULL; ev->u.ulval = (sal_uInt32)ev->u.uhval; ev->et = ET_ulong; return ev; case ET_boolean: ev->u.ulval = (sal_uInt32)ev->u.bval; ev->et = ET_ulong; return ev; case ET_float: if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT32) return NULL; ev->u.ulval = (sal_uInt32)ev->u.fval; ev->et = ET_ulong; return ev; case ET_double: if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT32) return NULL; ev->u.ulval = (sal_uInt32)ev->u.dval; ev->et = ET_ulong; return ev; case ET_byte: ev->u.ulval = (sal_uInt32)ev->u.byval; ev->et = ET_ulong; return ev; default: OSL_ASSERT(false); return NULL; } case ET_hyper: switch (ev->et) { case ET_short: ev->u.hval = (sal_Int64)ev->u.sval; ev->et = ET_hyper; return ev; case ET_ushort: ev->u.hval = (sal_Int64)ev->u.usval; ev->et = ET_hyper; return ev; case ET_long: ev->u.hval = (sal_Int64)ev->u.lval; ev->et = ET_hyper; return ev; case ET_ulong: ev->u.hval = (sal_Int64)ev->u.ulval; ev->et = ET_hyper; return ev; case ET_hyper: return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_INT64) return NULL; ev->u.hval = (sal_Int64)ev->u.uhval; ev->et = ET_long; return ev; case ET_boolean: ev->u.hval = (sal_Int64)ev->u.bval; ev->et = ET_hyper; return ev; case ET_float: if (ev->u.fval < SAL_MIN_INT64 || ev->u.fval > SAL_MAX_INT64) return NULL; ev->u.hval = (sal_Int64)ev->u.fval; ev->et = ET_hyper; return ev; case ET_double: if (ev->u.dval < SAL_MIN_INT64 || ev->u.dval > SAL_MAX_INT64) return NULL; ev->u.hval = (sal_Int64)ev->u.dval; ev->et = ET_hyper; return ev; case ET_byte: ev->u.hval = (sal_Int64)ev->u.byval; ev->et = ET_hyper; return ev; default: OSL_ASSERT(false); return NULL; } case ET_uhyper: switch (ev->et) { case ET_short: if (ev->u.sval < 0) return NULL; ev->u.uhval = (sal_uInt64)ev->u.sval; ev->et = ET_uhyper; return ev; case ET_ushort: ev->u.uhval = (sal_uInt64)ev->u.usval; ev->et = ET_uhyper; return ev; case ET_long: if (ev->u.lval < 0) return NULL; ev->u.uhval = (sal_uInt64)ev->u.lval; ev->et = ET_uhyper; return ev; case ET_ulong: ev->u.uhval = (sal_uInt64)ev->u.ulval; ev->et = ET_uhyper; return ev; case ET_hyper: if (ev->u.hval < 0) return NULL; ev->u.uhval = (sal_uInt64)ev->u.hval; ev->et = ET_uhyper; return ev; case ET_uhyper: return ev; case ET_boolean: ev->u.uhval = (sal_uInt64)ev->u.bval; ev->et = ET_uhyper; return ev; case ET_float: if (ev->u.fval < 0.0 || ev->u.fval > SAL_MAX_UINT64) return NULL; ev->u.uhval = (sal_uInt64)ev->u.fval; ev->et = ET_uhyper; return ev; case ET_double: if (ev->u.dval < 0.0 || ev->u.dval > SAL_MAX_UINT64) return NULL; ev->u.uhval = (sal_uInt64)ev->u.dval; ev->et = ET_uhyper; return ev; case ET_byte: ev->u.uhval = (sal_uInt64)ev->u.byval; ev->et = ET_uhyper; return ev; default: OSL_ASSERT(false); return NULL; } case ET_boolean: switch (ev->et) { case ET_short: ev->u.bval = (ev->u.sval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_ushort: ev->u.bval = (ev->u.usval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_long: ev->u.bval = (ev->u.lval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_ulong: ev->u.bval = (ev->u.ulval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_hyper: ev->u.bval = (ev->u.hval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_uhyper: ev->u.bval = (ev->u.uhval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_boolean: return ev; case ET_float: ev->u.bval = (ev->u.fval == 0.0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_double: ev->u.bval = (ev->u.dval == 0.0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; case ET_byte: ev->u.bval = (ev->u.byval == 0) ? sal_False : sal_True; ev->et = ET_boolean; return ev; default: OSL_ASSERT(false); return NULL; } case ET_float: switch (ev->et) { case ET_short: ev->u.fval = (float)ev->u.sval; ev->et = ET_float; return ev; case ET_ushort: ev->u.fval = (float)ev->u.usval; ev->et = ET_float; return ev; case ET_long: ev->u.fval = (float)ev->u.lval; ev->et = ET_float; return ev; case ET_ulong: ev->u.fval = (float)ev->u.ulval; ev->et = ET_float; return ev; case ET_hyper: ev->u.fval = (float)ev->u.hval; ev->et = ET_float; return ev; case ET_uhyper: if ((float)ev->u.ulval > FLT_MAX) return NULL; ev->u.fval = (float)ev->u.ulval; ev->et = ET_float; return ev; case ET_boolean: ev->u.fval = (ev->u.bval == sal_True) ? 1.0f : 0.0f; ev->et = ET_float; return ev; case ET_float: return ev; case ET_double: if ((float)ev->u.dval > FLT_MAX || (float)ev->u.dval < -FLT_MAX) return NULL; ev->u.fval = (float)ev->u.dval; ev->et = ET_float; return ev; case ET_byte: ev->u.fval = (float)ev->u.byval; ev->et = ET_float; return ev; default: OSL_ASSERT(false); return NULL; } case ET_double: switch (ev->et) { case ET_short: ev->u.dval = (double)ev->u.sval; ev->et = ET_double; return ev; case ET_ushort: ev->u.dval = (double)ev->u.usval; ev->et = ET_double; return ev; case ET_long: ev->u.dval = (double)ev->u.lval; ev->et = ET_double; return ev; case ET_ulong: ev->u.dval = (double)ev->u.ulval; ev->et = ET_double; return ev; case ET_hyper: ev->u.dval = (double)ev->u.hval; ev->et = ET_double; return ev; case ET_uhyper: if ((double)ev->u.dval > FLT_MAX || (double)ev->u.dval < -FLT_MAX) return NULL; ev->u.dval = (double)ev->u.ulval; ev->et = ET_double; return ev; case ET_boolean: ev->u.dval = (ev->u.bval == sal_True) ? 1.0 : 0.0; ev->et = ET_double; return ev; case ET_float: ev->u.dval = (double)ev->u.fval; ev->et = ET_double; return ev; case ET_double: return ev; case ET_byte: ev->u.dval = (double)ev->u.byval; ev->et = ET_double; return ev; default: OSL_ASSERT(false); return NULL; } case ET_byte: switch (ev->et) { case ET_short: if (ev->u.sval < SAL_MIN_INT8 || ev->u.sval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar)ev->u.sval; ev->et = ET_byte; return ev; case ET_ushort: if (ev->u.usval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar)ev->u.usval; ev->et = ET_byte; return ev; case ET_long: if (ev->u.lval < SAL_MIN_INT8 || ev->u.lval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.lval; ev->et = ET_byte; return ev; case ET_ulong: if (ev->u.ulval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.ulval; ev->et = ET_byte; return ev; case ET_hyper: if (ev->u.hval < SAL_MIN_INT8 || ev->u.hval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.hval; ev->et = ET_byte; return ev; case ET_uhyper: if (ev->u.uhval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.uhval; ev->et = ET_byte; return ev; case ET_boolean: ev->u.byval = (ev->u.bval == sal_False) ? 1 : 0; ev->et = ET_byte; return ev; case ET_float: if (ev->u.fval < SAL_MIN_INT8 || ev->u.fval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.fval; ev->et = ET_byte; return ev; case ET_double: if (ev->u.dval < SAL_MIN_INT8 || ev->u.dval > SAL_MAX_UINT8) return NULL; ev->u.byval = (sal_uChar) ev->u.dval; ev->et = ET_byte; return ev; case ET_byte: return ev; default: OSL_ASSERT(false); return NULL; } default: OSL_ASSERT(false); return NULL; } } /* * Evaluate the expression with the evaluation kind requested. Supported * evaluation kinds are * - EK_const: The expression must evaluate to a constant * - EK_positive_int: The expression must further evaluate to a * positive integer */ static AstExprValue * eval_kind(AstExprValue *ev, EvalKind ek) { if (ek == EK_const) return ev; if (ek == EK_positive_int) return coerce_value(ev, ET_ulong); return NULL; } AstExprValue* AstExpression::eval(EvalKind ek) { AstExprValue *v = NULL; /* * Call internal evaluator which does not coerce value to * EvalKind-expected format */ v = eval_internal(ek); /* * Then coerce according to EvalKind-expected format */ return eval_kind(v, ek); } AstExprValue* AstExpression::coerce(ExprType t, sal_Bool bAssign) { AstExprValue *copy; /* * Is it already of the right type? */ if (m_exprValue != NULL && m_exprValue->et == t) return m_exprValue; /* * OK, must coerce * * First, evaluate it, then try to coerce result type * If already evaluated, return the result */ m_exprValue = eval_internal(EK_const); if (m_exprValue == NULL) return NULL; /* * Create a copy to contain coercion result */ copy = new AstExprValue; copy->et = m_exprValue->et; switch (m_exprValue->et) { case ET_short: copy->u.sval = m_exprValue->u.sval; break; case ET_ushort: copy->u.usval = m_exprValue->u.usval; break; case ET_long: copy->u.lval = m_exprValue->u.lval; break; case ET_ulong: copy->u.ulval = m_exprValue->u.ulval; break; case ET_hyper: copy->u.hval = m_exprValue->u.hval; break; case ET_uhyper: copy->u.uhval = m_exprValue->u.uhval; break; case ET_boolean: copy->u.bval = m_exprValue->u.bval; break; case ET_float: copy->u.fval = m_exprValue->u.fval; break; case ET_double: copy->u.dval = m_exprValue->u.dval; break; case ET_byte: copy->u.byval = m_exprValue->u.byval; break; default: OSL_ASSERT(false); break; } if (bAssign) { m_exprValue = coerce_value(copy, t); return m_exprValue; } return coerce_value(copy, t); } void AstExpression::evaluate(EvalKind ek) { m_exprValue = eval_internal(ek); m_exprValue = eval_kind(m_exprValue, ek); } sal_Bool AstExpression::operator==(AstExpression *pExpr) { if (m_combOperator != pExpr->getCombOperator()) return sal_False; evaluate(EK_const); pExpr->evaluate(EK_const); if (m_exprValue == NULL || pExpr->getExprValue() == NULL) return sal_False; if (m_exprValue->et != pExpr->getExprValue()->et) return sal_False; switch (m_exprValue->et) { case ET_short: return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False; case ET_ushort: return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False; case ET_long: return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; case ET_ulong: return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False; case ET_hyper: return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False; case ET_uhyper: return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False; case ET_float: return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False; case ET_double: return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False; case ET_byte: return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False; case ET_boolean: return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; default: OSL_ASSERT(false); return sal_False; } return sal_False; } sal_Bool AstExpression::compare(AstExpression *pExpr) { if (m_combOperator != pExpr->getCombOperator()) return sal_False; evaluate(EK_const); pExpr->evaluate(EK_const); if (m_exprValue == NULL || pExpr->getExprValue() == NULL) return sal_False; if (m_exprValue->et != pExpr->getExprValue()->et) return sal_False; switch (m_exprValue->et) { case ET_short: return (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False; case ET_ushort: return (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False; case ET_long: return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; case ET_ulong: return (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False; case ET_hyper: return (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False; case ET_uhyper: return (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False; case ET_float: return (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False; case ET_double: return (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False; case ET_byte: return (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False; case ET_boolean: return (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False; default: OSL_ASSERT(false); return sal_False; } return sal_False; } void AstExpression::fillDefinitionDetails() { m_pScope = idlc()->scopes()->depth() > 0 ? idlc()->scopes()->top() : NULL; m_lineNo = idlc()->getLineNumber(); m_fileName = idlc()->getFileName(); } AstExprValue* AstExpression::eval_internal(EvalKind ek) { /* * Already evaluated? */ if ( m_exprValue != NULL ) return eval_kind(m_exprValue, ek); /* * OK, must evaluate operator */ switch (m_combOperator) { case EC_add: case EC_minus: case EC_mul: case EC_div: case EC_mod: m_exprValue = eval_bin_op(ek); return eval_kind(m_exprValue, ek); case EC_or: case EC_xor: case EC_and: case EC_left: case EC_right: m_exprValue = eval_bit_op(ek); return eval_kind(m_exprValue, ek); case EC_u_plus: case EC_u_minus: case EC_bit_neg: m_exprValue = eval_un_op(ek); return eval_kind(m_exprValue, ek); case EC_symbol: m_exprValue = eval_symbol(ek); return eval_kind(m_exprValue, ek); case EC_none: return NULL; } return NULL; } AstExprValue* AstExpression::eval_bin_op(EvalKind ek) { AstExprValue *retval = NULL; ExprType eType = ET_double; if ( m_combOperator == EC_mod ) eType = ET_hyper; if (ek != EK_const && ek != EK_positive_int) return NULL; if (m_subExpr1 == NULL || m_subExpr2 == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); if (m_subExpr1->getExprValue() == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->coerce(eType)); if (m_subExpr1->getExprValue() == NULL) return NULL; m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek)); if (m_subExpr2->getExprValue() == NULL) return NULL; m_subExpr2->setExprValue(m_subExpr2->coerce(eType)); if (m_subExpr2->getExprValue() == NULL) return NULL; retval = new AstExprValue(); retval->et = eType; switch (m_combOperator) { case EC_mod: if (m_subExpr2->getExprValue()->u.hval == 0) return NULL; retval->u.hval = m_subExpr1->getExprValue()->u.hval % m_subExpr2->getExprValue()->u.hval; break; case EC_add: retval->u.dval = m_subExpr1->getExprValue()->u.dval + m_subExpr2->getExprValue()->u.dval; break; case EC_minus: retval->u.dval = m_subExpr1->getExprValue()->u.dval - m_subExpr2->getExprValue()->u.dval; break; case EC_mul: retval->u.dval = m_subExpr1->getExprValue()->u.dval * m_subExpr2->getExprValue()->u.dval; break; case EC_div: if (m_subExpr2->getExprValue()->u.dval == 0.0) return NULL; retval->u.dval = m_subExpr1->getExprValue()->u.dval / m_subExpr2->getExprValue()->u.dval; break; default: return NULL; } return retval; } AstExprValue* AstExpression::eval_bit_op(EvalKind ek) { AstExprValue *retval = NULL; if (ek != EK_const && ek != EK_positive_int) return NULL; if (m_subExpr1 == NULL || m_subExpr2 == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); if (m_subExpr1->getExprValue() == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long)); if (m_subExpr1->getExprValue() == NULL) return NULL; m_subExpr2->setExprValue(m_subExpr2->eval_internal(ek)); if (m_subExpr2->getExprValue() == NULL) return NULL; m_subExpr2->setExprValue(m_subExpr2->coerce(ET_long)); if (m_subExpr2->getExprValue() == NULL) return NULL; retval = new AstExprValue; retval->et = ET_long; switch (m_combOperator) { case EC_or: retval->u.lval = m_subExpr1->getExprValue()->u.lval | m_subExpr2->getExprValue()->u.lval; break; case EC_xor: retval->u.lval = m_subExpr1->getExprValue()->u.lval ^ m_subExpr2->getExprValue()->u.lval; break; case EC_and: retval->u.lval = m_subExpr1->getExprValue()->u.lval & m_subExpr2->getExprValue()->u.lval; break; case EC_left: retval->u.lval = m_subExpr1->getExprValue()->u.lval << m_subExpr2->getExprValue()->u.lval; break; case EC_right: retval->u.lval = m_subExpr1->getExprValue()->u.lval >> m_subExpr2->getExprValue()->u.lval; break; default: return NULL; } return retval; } AstExprValue* AstExpression::eval_un_op(EvalKind ek) { AstExprValue *retval = NULL; if (m_exprValue != NULL) return m_exprValue; if (ek != EK_const && ek != EK_positive_int) return NULL; if (m_subExpr1 == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->eval_internal(ek)); if (m_subExpr1->getExprValue() == NULL) return NULL; m_subExpr1->setExprValue(m_subExpr1->coerce(ET_double)); if (m_subExpr1->getExprValue() == NULL) return NULL; retval = new AstExprValue(); retval->et = ET_double; switch (m_combOperator) { case EC_u_plus: retval->u.lval = m_subExpr1->getExprValue()->u.lval; break; case EC_u_minus: retval->u.lval = -(m_subExpr1->getExprValue()->u.lval); break; case EC_bit_neg: m_subExpr1->setExprValue(m_subExpr1->coerce(ET_long)); if (m_subExpr1->getExprValue() == NULL) return NULL; retval->u.lval = ~m_subExpr1->getExprValue()->u.lval; break; default: return NULL; } return retval; } AstExprValue* AstExpression::eval_symbol(EvalKind ek) { AstScope *pScope = 0; AstDeclaration *pDecl; AstConstant *pConst; /* * Is there a symbol stored? */ if (m_pSymbolicName == NULL) { idlc()->error()->evalError(this); return NULL; } /* * Get current scope for lookup */ if (idlc()->scopes()->depth() > 0) pScope = idlc()->scopes()->topNonNull(); if ( !pScope ) { idlc()->error()->lookupError(*m_pSymbolicName); return NULL; } /* * Do lookup */ pDecl = pScope->lookupByName(*m_pSymbolicName); if (pDecl == NULL) { idlc()->error()->lookupError(*m_pSymbolicName); return NULL; } /* * Is it a constant? */ if (pDecl->getNodeType() != NT_const && pDecl->getNodeType() != NT_enum_val) { idlc()->error()->constantExpected(pDecl, *m_pSymbolicName); return NULL; } if (!idlc()->error()->checkPublished(pDecl)) { return NULL; } /* * OK, now evaluate the constant we just got, to produce its value */ pConst = static_cast< AstConstant* >(pDecl); if (pConst == NULL) return NULL; return pConst->getConstValue()->eval_internal(ek); } OString AstExpression::toString() { OString exprStr; if ( m_combOperator == EC_symbol ) return *m_pSymbolicName; if ( m_exprValue ) { switch (m_exprValue->et) { case ET_short: return OString::valueOf((sal_Int32)m_exprValue->u.sval); case ET_ushort: return OString::valueOf((sal_Int32)m_exprValue->u.usval); case ET_long: return OString::valueOf(m_exprValue->u.lval); case ET_ulong: return OString::valueOf((sal_Int32)m_exprValue->u.ulval); case ET_hyper: return OString::valueOf(m_exprValue->u.hval); case ET_uhyper: return OString::valueOf((sal_Int64)m_exprValue->u.uhval); case ET_float: return OString::valueOf(m_exprValue->u.fval); case ET_double: return OString::valueOf(m_exprValue->u.dval); case ET_byte: return OString::valueOf((sal_Int32)m_exprValue->u.byval); case ET_boolean: if ( m_exprValue->u.lval == 0) return OString("FALSE"); else return OString("TRUE"); default: OSL_ASSERT(false); return OString(); } } switch (m_combOperator) { case EC_u_plus: exprStr += OString("+"); break; case EC_u_minus: exprStr += OString("-"); break; case EC_bit_neg: exprStr += OString("~"); break; default: break; } if ( m_subExpr1 ) exprStr += m_subExpr1->toString(); switch (m_combOperator) { case EC_add: exprStr += OString(" + "); break; case EC_minus: exprStr += OString(" - "); break; case EC_mul: exprStr += OString(" * "); break; case EC_div: exprStr += OString(" / "); break; case EC_mod: exprStr += OString(" % "); break; case EC_or: exprStr += OString(" | "); break; case EC_xor: exprStr += OString(" ^ "); break; case EC_and: exprStr += OString(" & "); break; case EC_left: exprStr += OString(" << "); break; case EC_right: exprStr += OString(" >> "); 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* SAL_CALL 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 ("unkown"); }