1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <astexpression.hxx>
21 #include <astconstant.hxx>
22 #include <astscope.hxx>
23 #include <errorhandler.hxx>
25 #include <o3tl/float_int_conversion.hxx>
26 #include <osl/diagnose.h>
32 AstExpression::AstExpression(ExprComb c
, AstExpression
* pExpr1
, AstExpression
* pExpr2
)
39 AstExpression::AstExpression(sal_Int32 l
)
40 : m_combOperator(ExprComb::NONE
)
42 m_exprValue
.reset(new AstExprValue
);
43 m_exprValue
->et
= ET_long
;
44 m_exprValue
->u
.lval
= l
;
47 AstExpression::AstExpression(sal_Int32 l
, ExprType et
)
48 : m_combOperator(ExprComb::NONE
)
50 m_exprValue
.reset(new AstExprValue
);
52 m_exprValue
->u
.lval
= l
;
55 AstExpression::AstExpression(sal_Int64 h
)
56 : m_combOperator(ExprComb::NONE
)
58 m_exprValue
.reset(new AstExprValue
);
59 m_exprValue
->et
= ET_hyper
;
60 m_exprValue
->u
.hval
= h
;
63 AstExpression::AstExpression(sal_uInt64 uh
)
64 : m_combOperator(ExprComb::NONE
)
66 m_exprValue
.reset(new AstExprValue
);
67 m_exprValue
->et
= ET_uhyper
;
68 m_exprValue
->u
.uhval
= uh
;
71 AstExpression::AstExpression(double d
)
72 : m_combOperator(ExprComb::NONE
)
74 m_exprValue
.reset(new AstExprValue
);
75 m_exprValue
->et
= ET_double
;
76 m_exprValue
->u
.dval
= d
;
79 AstExpression::AstExpression(OString
* scopedName
)
80 : m_combOperator(ExprComb::Symbol
)
83 m_xSymbolicName
= *scopedName
;
86 AstExpression::~AstExpression() {}
89 * Perform the coercion from the given AstExprValue to the requested
90 * ExprType. Return an AstExprValue if successful, NULL if failed.
91 * must be done for hyper, uhyper
93 static bool coerce_value(AstExprValue
* ev
, ExprType t
)
107 if (ev
->u
.usval
> SAL_MAX_INT16
)
109 auto tmp
= static_cast<sal_Int16
>(ev
->u
.usval
);
116 if (ev
->u
.lval
< SAL_MIN_INT16
|| ev
->u
.lval
> SAL_MAX_INT16
)
118 auto tmp
= static_cast<sal_Int16
>(ev
->u
.lval
);
125 if (ev
->u
.ulval
> SAL_MAX_INT16
)
127 auto tmp
= static_cast<sal_Int16
>(ev
->u
.ulval
);
134 if (ev
->u
.hval
< SAL_MIN_INT16
|| ev
->u
.hval
> SAL_MAX_INT16
)
136 auto tmp
= static_cast<sal_Int16
>(ev
->u
.hval
);
143 if (ev
->u
.uhval
> SAL_MAX_INT16
)
145 auto tmp
= static_cast<sal_Int16
>(ev
->u
.uhval
);
152 auto tmp
= static_cast<sal_Int16
>(ev
->u
.bval
);
159 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.fval
), SAL_MIN_INT16
)
160 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_INT16
)))
164 auto tmp
= static_cast<sal_Int16
>(ev
->u
.fval
);
171 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.dval
), SAL_MIN_INT16
)
172 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_INT16
)))
176 auto tmp
= static_cast<sal_Int16
>(ev
->u
.dval
);
183 auto tmp
= static_cast<sal_Int16
>(ev
->u
.byval
);
199 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.sval
);
208 if (ev
->u
.lval
< 0 || ev
->u
.lval
> SAL_MAX_UINT16
)
210 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.lval
);
217 if (ev
->u
.ulval
> SAL_MAX_UINT16
)
219 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.ulval
);
226 if (ev
->u
.hval
< 0 || ev
->u
.hval
> SAL_MAX_UINT16
)
228 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.hval
);
235 if (ev
->u
.uhval
> SAL_MAX_UINT16
)
237 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.uhval
);
244 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.bval
);
252 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_UINT16
))
256 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.fval
);
264 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_UINT16
))
268 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.dval
);
275 auto tmp
= static_cast<sal_uInt16
>(ev
->u
.byval
);
289 auto tmp
= static_cast<sal_Int32
>(ev
->u
.sval
);
296 auto tmp
= static_cast<sal_Int32
>(ev
->u
.usval
);
305 if (ev
->u
.ulval
> SAL_MAX_INT32
)
307 auto tmp
= static_cast<sal_Int32
>(ev
->u
.ulval
);
314 if (ev
->u
.hval
< SAL_MIN_INT32
|| ev
->u
.hval
> SAL_MAX_INT32
)
316 auto tmp
= static_cast<sal_Int32
>(ev
->u
.hval
);
323 if (ev
->u
.uhval
> SAL_MAX_INT32
)
325 auto tmp
= static_cast<sal_Int32
>(ev
->u
.uhval
);
332 auto tmp
= static_cast<sal_Int32
>(ev
->u
.bval
);
339 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.fval
), SAL_MIN_INT32
)
340 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_INT32
)))
344 auto tmp
= static_cast<sal_Int32
>(ev
->u
.fval
);
351 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.dval
), SAL_MIN_INT32
)
352 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_INT32
)))
356 auto tmp
= static_cast<sal_Int32
>(ev
->u
.dval
);
363 auto tmp
= static_cast<sal_Int32
>(ev
->u
.byval
);
379 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.sval
);
386 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.usval
);
395 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.lval
);
404 if (ev
->u
.hval
< 0 || ev
->u
.hval
> SAL_MAX_UINT32
)
406 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.hval
);
413 if (ev
->u
.uhval
> SAL_MAX_UINT32
)
415 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.uhval
);
422 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.bval
);
430 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_UINT32
))
434 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.fval
);
442 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_UINT32
))
446 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.dval
);
453 auto tmp
= static_cast<sal_uInt32
>(ev
->u
.byval
);
467 auto tmp
= static_cast<sal_Int64
>(ev
->u
.sval
);
474 auto tmp
= static_cast<sal_Int64
>(ev
->u
.usval
);
481 auto tmp
= static_cast<sal_Int64
>(ev
->u
.lval
);
488 auto tmp
= static_cast<sal_Int64
>(ev
->u
.ulval
);
497 if (ev
->u
.uhval
> SAL_MAX_INT64
)
499 auto tmp
= static_cast<sal_Int64
>(ev
->u
.uhval
);
506 auto tmp
= static_cast<sal_Int64
>(ev
->u
.bval
);
513 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.fval
), SAL_MIN_INT64
)
514 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_INT64
)))
518 auto tmp
= static_cast<sal_Int64
>(ev
->u
.fval
);
525 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.dval
), SAL_MIN_INT64
)
526 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_INT64
)))
530 auto tmp
= static_cast<sal_Int64
>(ev
->u
.dval
);
537 auto tmp
= static_cast<sal_Int64
>(ev
->u
.byval
);
553 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.sval
);
560 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.usval
);
569 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.lval
);
576 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.ulval
);
585 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.hval
);
594 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.bval
);
602 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_UINT64
))
606 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.fval
);
614 || !o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_UINT64
))
618 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.dval
);
625 auto tmp
= static_cast<sal_uInt64
>(ev
->u
.byval
);
638 ev
->u
.bval
= ev
->u
.sval
!= 0;
642 ev
->u
.bval
= ev
->u
.usval
!= 0;
646 ev
->u
.bval
= ev
->u
.lval
!= 0;
650 ev
->u
.bval
= ev
->u
.ulval
!= 0;
654 ev
->u
.bval
= ev
->u
.hval
!= 0;
658 ev
->u
.bval
= ev
->u
.uhval
!= 0;
664 ev
->u
.bval
= ev
->u
.fval
!= 0.0;
668 ev
->u
.bval
= ev
->u
.dval
!= 0.0;
672 ev
->u
.bval
= ev
->u
.byval
!= 0;
684 auto tmp
= static_cast<float>(ev
->u
.sval
);
691 auto tmp
= static_cast<float>(ev
->u
.usval
);
698 auto tmp
= static_cast<float>(ev
->u
.lval
);
705 auto tmp
= static_cast<float>(ev
->u
.ulval
);
712 auto tmp
= static_cast<float>(ev
->u
.hval
);
719 if (static_cast<float>(ev
->u
.ulval
) > FLT_MAX
)
721 auto tmp
= static_cast<float>(ev
->u
.ulval
);
727 ev
->u
.fval
= ev
->u
.bval
? 1.0f
: 0.0f
;
734 if (static_cast<float>(ev
->u
.dval
) > FLT_MAX
735 || static_cast<float>(ev
->u
.dval
) < -FLT_MAX
)
737 auto tmp
= static_cast<float>(ev
->u
.dval
);
744 auto tmp
= static_cast<float>(ev
->u
.byval
);
758 auto tmp
= static_cast<double>(ev
->u
.sval
);
765 auto tmp
= static_cast<double>(ev
->u
.usval
);
772 auto tmp
= static_cast<double>(ev
->u
.lval
);
779 auto tmp
= static_cast<double>(ev
->u
.ulval
);
786 auto tmp
= static_cast<double>(ev
->u
.hval
);
793 if (ev
->u
.dval
> FLT_MAX
|| ev
->u
.dval
< -FLT_MAX
)
795 auto tmp
= static_cast<double>(ev
->u
.ulval
);
801 ev
->u
.dval
= ev
->u
.bval
? 1.0 : 0.0;
806 auto tmp
= static_cast<double>(ev
->u
.fval
);
815 auto tmp
= static_cast<double>(ev
->u
.byval
);
829 if (ev
->u
.sval
< SAL_MIN_INT8
|| ev
->u
.sval
> SAL_MAX_UINT8
)
831 auto tmp
= static_cast<unsigned char>(ev
->u
.sval
);
838 if (ev
->u
.usval
> SAL_MAX_UINT8
)
840 auto tmp
= static_cast<unsigned char>(ev
->u
.usval
);
847 if (ev
->u
.lval
< SAL_MIN_INT8
|| ev
->u
.lval
> SAL_MAX_UINT8
)
849 auto tmp
= static_cast<unsigned char>(ev
->u
.lval
);
856 if (ev
->u
.ulval
> SAL_MAX_UINT8
)
858 auto tmp
= static_cast<unsigned char>(ev
->u
.ulval
);
865 if (ev
->u
.hval
< SAL_MIN_INT8
|| ev
->u
.hval
> SAL_MAX_UINT8
)
867 auto tmp
= static_cast<unsigned char>(ev
->u
.hval
);
874 if (ev
->u
.uhval
> SAL_MAX_UINT8
)
876 auto tmp
= static_cast<unsigned char>(ev
->u
.uhval
);
882 ev
->u
.byval
= ev
->u
.bval
? 1 : 0;
887 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.fval
), SAL_MIN_INT8
)
888 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.fval
), SAL_MAX_UINT8
)))
892 auto tmp
= static_cast<unsigned char>(static_cast<sal_Int32
>(ev
->u
.fval
));
899 if (!(o3tl::convertsToAtLeast(o3tl::roundAway(ev
->u
.dval
), SAL_MIN_INT8
)
900 && o3tl::convertsToAtMost(o3tl::roundAway(ev
->u
.dval
), SAL_MAX_UINT8
)))
904 auto tmp
= static_cast<unsigned char>(static_cast<sal_Int32
>(ev
->u
.dval
));
921 bool AstExpression::coerce(ExprType t
)
924 * Is it already of the right type?
926 if (m_exprValue
!= nullptr && m_exprValue
->et
== t
)
931 * First, evaluate it, then try to coerce result type
932 * If already evaluated, return the result
935 if (m_exprValue
== nullptr)
938 if (!coerce_value(m_exprValue
.get(), t
))
941 return m_exprValue
!= nullptr;
944 bool AstExpression::compareLong(AstExpression
* pExpr
)
947 if (m_combOperator
!= pExpr
->m_combOperator
)
951 if (m_exprValue
== nullptr || pExpr
->getExprValue() == nullptr)
953 if (m_exprValue
->et
!= pExpr
->getExprValue()->et
)
955 switch (m_exprValue
->et
)
958 bRet
= m_exprValue
->u
.lval
== pExpr
->getExprValue()->u
.lval
;
968 void AstExpression::evaluate()
973 if (m_exprValue
!= nullptr)
976 * OK, must evaluate operator
978 switch (m_combOperator
)
981 case ExprComb::Minus
:
985 m_exprValue
= eval_bin_op();
991 case ExprComb::Right
:
992 m_exprValue
= eval_bit_op();
994 case ExprComb::UPlus
:
995 case ExprComb::UMinus
:
996 m_exprValue
= eval_un_op();
998 case ExprComb::Symbol
:
999 m_exprValue
= eval_symbol();
1001 case ExprComb::NONE
:
1006 std::unique_ptr
<AstExprValue
> AstExpression::eval_bin_op()
1008 ExprType eType
= ET_double
;
1010 if (m_combOperator
== ExprComb::Mod
)
1013 if (m_subExpr1
== nullptr || m_subExpr2
== nullptr)
1015 m_subExpr1
->evaluate();
1016 if (m_subExpr1
->getExprValue() == nullptr)
1018 if (!m_subExpr1
->coerce(eType
))
1020 m_subExpr2
->evaluate();
1021 if (m_subExpr2
->getExprValue() == nullptr)
1023 if (!m_subExpr2
->coerce(eType
))
1026 std::unique_ptr
<AstExprValue
> retval(new AstExprValue
);
1029 switch (m_combOperator
)
1032 if (m_subExpr2
->getExprValue()->u
.hval
== 0)
1035 = m_subExpr1
->getExprValue()->u
.hval
% m_subExpr2
->getExprValue()->u
.hval
;
1039 = m_subExpr1
->getExprValue()->u
.dval
+ m_subExpr2
->getExprValue()->u
.dval
;
1041 case ExprComb::Minus
:
1043 = m_subExpr1
->getExprValue()->u
.dval
- m_subExpr2
->getExprValue()->u
.dval
;
1047 = m_subExpr1
->getExprValue()->u
.dval
* m_subExpr2
->getExprValue()->u
.dval
;
1050 if (m_subExpr2
->getExprValue()->u
.dval
== 0.0)
1053 = m_subExpr1
->getExprValue()->u
.dval
/ m_subExpr2
->getExprValue()->u
.dval
;
1062 std::unique_ptr
<AstExprValue
> AstExpression::eval_bit_op()
1064 if (m_subExpr1
== nullptr || m_subExpr2
== nullptr)
1066 m_subExpr1
->evaluate();
1067 if (m_subExpr1
->getExprValue() == nullptr)
1069 if (!m_subExpr1
->coerce(ET_long
))
1071 m_subExpr2
->evaluate();
1072 if (m_subExpr2
->getExprValue() == nullptr)
1074 if (!m_subExpr2
->coerce(ET_long
))
1077 std::unique_ptr
<AstExprValue
> retval(new AstExprValue
);
1078 retval
->et
= ET_long
;
1080 switch (m_combOperator
)
1084 = m_subExpr1
->getExprValue()->u
.lval
| m_subExpr2
->getExprValue()->u
.lval
;
1088 = m_subExpr1
->getExprValue()->u
.lval
^ m_subExpr2
->getExprValue()->u
.lval
;
1092 = m_subExpr1
->getExprValue()->u
.lval
& m_subExpr2
->getExprValue()->u
.lval
;
1094 case ExprComb::Left
:
1095 retval
->u
.lval
= m_subExpr1
->getExprValue()->u
.lval
1096 << m_subExpr2
->getExprValue()->u
.lval
;
1098 case ExprComb::Right
:
1100 = m_subExpr1
->getExprValue()->u
.lval
>> m_subExpr2
->getExprValue()->u
.lval
;
1109 std::unique_ptr
<AstExprValue
> AstExpression::eval_un_op()
1111 if (m_subExpr1
== nullptr)
1113 m_subExpr1
->evaluate();
1114 if (m_subExpr1
->getExprValue() == nullptr)
1116 if (!m_subExpr1
->coerce(ET_double
))
1119 std::unique_ptr
<AstExprValue
> retval(new AstExprValue
);
1120 retval
->et
= ET_double
;
1122 switch (m_combOperator
)
1124 case ExprComb::UPlus
:
1125 retval
->u
.lval
= m_subExpr1
->getExprValue()->u
.lval
;
1127 case ExprComb::UMinus
:
1128 retval
->u
.lval
= -(m_subExpr1
->getExprValue()->u
.lval
);
1137 std::unique_ptr
<AstExprValue
> AstExpression::eval_symbol()
1139 AstScope
* pScope
= nullptr;
1140 AstDeclaration
* pDecl
;
1141 AstConstant
* pConst
;
1144 * Is there a symbol stored?
1146 if (!m_xSymbolicName
)
1148 ErrorHandler::evalError(this);
1152 * Get current scope for lookup
1154 if (idlc()->scopes()->depth() > 0)
1155 pScope
= idlc()->scopes()->topNonNull();
1158 ErrorHandler::lookupError(*m_xSymbolicName
);
1164 pDecl
= pScope
->lookupByName(*m_xSymbolicName
);
1165 if (pDecl
== nullptr)
1167 ErrorHandler::lookupError(*m_xSymbolicName
);
1173 if (pDecl
->getNodeType() != NT_const
&& pDecl
->getNodeType() != NT_enum_val
)
1175 ErrorHandler::constantExpected(pDecl
, *m_xSymbolicName
);
1178 if (!ErrorHandler::checkPublished(pDecl
))
1183 * OK, now evaluate the constant we just got, to produce its value
1185 pConst
= static_cast<AstConstant
*>(pDecl
);
1186 pConst
->getConstValue()->evaluate();
1187 auto const val
= pConst
->getConstValue()->getExprValue();
1188 return val
== nullptr ? nullptr : std::make_unique
<AstExprValue
>(*val
);
1191 OString
AstExpression::toString()
1194 if (m_combOperator
== ExprComb::Symbol
)
1195 return m_xSymbolicName
? *m_xSymbolicName
: OString("<Undefined Name>");
1199 switch (m_exprValue
->et
)
1202 return OString::number(m_exprValue
->u
.sval
);
1204 return OString::number(m_exprValue
->u
.usval
);
1206 return OString::number(m_exprValue
->u
.lval
);
1208 return OString::number(m_exprValue
->u
.ulval
);
1210 return OString::number(m_exprValue
->u
.hval
);
1212 return OString::number(m_exprValue
->u
.uhval
);
1214 return OString::number(m_exprValue
->u
.fval
);
1216 return OString::number(m_exprValue
->u
.dval
);
1218 return OString::number(m_exprValue
->u
.byval
);
1220 if (m_exprValue
->u
.lval
== 0)
1230 switch (m_combOperator
)
1232 case ExprComb::UPlus
:
1235 case ExprComb::UMinus
:
1242 exprStr
+= m_subExpr1
->toString();
1243 switch (m_combOperator
)
1248 case ExprComb::Minus
:
1269 case ExprComb::Left
:
1272 case ExprComb::Right
:
1280 exprStr
+= m_subExpr2
->toString();
1285 // Convert the type of an AST_Expression to a char *
1286 const char* exprTypeToString(ExprType t
)
1293 return "unsigned short";
1297 return "unsigned long";
1301 return "unsigned hyper";
1327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */