office-gobmx/idlc/source/astexpression.cxx
2011-02-18 09:36:15 +00:00

1292 lines
42 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* 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
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_idlc.hxx"
#include <idlc/astexpression.hxx>
#include <idlc/astconstant.hxx>
#include <idlc/astscope.hxx>
#include <idlc/errorhandler.hxx>
#include <limits.h>
#include <float.h>
#undef MAXCHAR
#define MAXCHAR 127
#undef MINCHAR
#define MINCHAR -128
using namespace ::rtl;
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_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_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(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::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)
{
sal_Bool bRet = sal_False;
if (m_combOperator != pExpr->getCombOperator())
return bRet;
evaluate(EK_const);
pExpr->evaluate(EK_const);
if (m_exprValue == NULL || pExpr->getExprValue() == NULL)
return bRet;
if (m_exprValue->et != pExpr->getExprValue()->et)
return bRet;
switch (m_exprValue->et)
{
case ET_short:
bRet = (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False;
break;
case ET_ushort:
bRet = (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False;
break;
case ET_long:
bRet = (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
break;
case ET_ulong:
bRet = (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False;
break;
case ET_hyper:
bRet = (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False;
break;
case ET_uhyper:
bRet = (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False;
break;
case ET_float:
bRet = (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False;
break;
case ET_double:
bRet = (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False;
break;
case ET_byte:
bRet = (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False;
break;
case ET_boolean:
bRet = (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
break;
default:
OSL_ASSERT(false);
bRet = sal_False;
break;
}
return bRet;
}
sal_Bool AstExpression::compare(AstExpression *pExpr)
{
bool bRet = sal_False;
if (m_combOperator != pExpr->getCombOperator())
return bRet;
evaluate(EK_const);
pExpr->evaluate(EK_const);
if (m_exprValue == NULL || pExpr->getExprValue() == NULL)
return bRet;
if (m_exprValue->et != pExpr->getExprValue()->et)
return bRet;
switch (m_exprValue->et)
{
case ET_short:
bRet = (m_exprValue->u.sval == pExpr->getExprValue()->u.sval) ? sal_True : sal_False;
break;
case ET_ushort:
bRet = (m_exprValue->u.usval == pExpr->getExprValue()->u.usval) ? sal_True : sal_False;
break;
case ET_long:
bRet = (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
break;
case ET_ulong:
bRet = (m_exprValue->u.ulval == pExpr->getExprValue()->u.ulval) ? sal_True : sal_False;
break;
case ET_hyper:
bRet = (m_exprValue->u.hval == pExpr->getExprValue()->u.hval) ? sal_True : sal_False;
break;
case ET_uhyper:
bRet = (m_exprValue->u.uhval == pExpr->getExprValue()->u.uhval) ? sal_True : sal_False;
break;
case ET_float:
bRet = (m_exprValue->u.fval == pExpr->getExprValue()->u.fval) ? sal_True : sal_False;
break;
case ET_double:
bRet = (m_exprValue->u.dval == pExpr->getExprValue()->u.dval) ? sal_True : sal_False;
break;
case ET_byte:
bRet = (m_exprValue->u.byval == pExpr->getExprValue()->u.byval) ? sal_True : sal_False;
break;
case ET_boolean:
bRet = (m_exprValue->u.lval == pExpr->getExprValue()->u.lval) ? sal_True : sal_False;
break;
default:
OSL_ASSERT(false);
bRet = sal_False;
break;
}
return bRet;
}
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");
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */