2013-10-20 15:06:05 +02:00
/******************************************************************************
* Icinga 2 *
2014-03-19 01:02:29 +01:00
* Copyright ( C ) 2012 - 2014 Icinga Development Team ( http : //www.icinga.org) *
2013-10-20 15:06:05 +02:00
* *
* This program is free software ; you can redistribute it and / or *
* modify it under the terms of the GNU General Public License *
* as published by the Free Software Foundation ; either version 2 *
* of the License , or ( at your option ) any later version . *
* *
* This program 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 General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the Free Software Foundation *
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "config/aexpression.h"
2014-03-22 08:40:09 +01:00
# include "config/configerror.h"
2014-03-18 15:29:04 +01:00
# include "base/array.h"
# include "base/serializer.h"
# include "base/context.h"
2014-03-19 10:51:09 +01:00
# include "base/scriptfunction.h"
2014-03-22 10:29:45 +01:00
# include "base/scriptvariable.h"
2014-03-23 19:58:24 +01:00
# include "base/utility.h"
2014-03-24 09:15:45 +01:00
# include "base/objectlock.h"
2014-03-18 15:29:04 +01:00
# include <boost/foreach.hpp>
2014-03-22 08:40:09 +01:00
# include <boost/exception_ptr.hpp>
# include <boost/exception/errinfo_nested_exception.hpp>
2013-10-20 15:06:05 +02:00
using namespace icinga ;
2014-03-22 10:29:45 +01:00
AExpression : : AExpression ( OpCallback op , const Value & operand1 , const DebugInfo & di )
2014-03-23 11:27:40 +01:00
: m_Operator ( op ) , m_Operand1 ( operand1 ) , m_Operand2 ( ) , m_DebugInfo ( di )
2014-03-22 10:29:45 +01:00
{ }
AExpression : : AExpression ( OpCallback op , const Value & operand1 , const Value & operand2 , const DebugInfo & di )
: m_Operator ( op ) , m_Operand1 ( operand1 ) , m_Operand2 ( operand2 ) , m_DebugInfo ( di )
{ }
Value AExpression : : Evaluate ( const Dictionary : : Ptr & locals ) const
2013-10-20 15:06:05 +02:00
{
2014-03-22 10:29:45 +01:00
try {
2014-03-23 19:58:24 +01:00
return m_Operator ( this , locals ) ;
2014-03-22 10:29:45 +01:00
} catch ( const std : : exception & ex ) {
if ( boost : : get_error_info < boost : : errinfo_nested_exception > ( ex ) )
throw ;
else
2014-03-23 11:27:40 +01:00
BOOST_THROW_EXCEPTION ( ConfigError ( " Error while evaluating expression: " + String ( ex . what ( ) ) ) < < boost : : errinfo_nested_exception ( boost : : current_exception ( ) ) < < errinfo_debuginfo ( m_DebugInfo ) ) ;
2014-03-22 10:29:45 +01:00
}
2013-10-20 15:06:05 +02:00
}
2014-03-23 11:27:40 +01:00
void AExpression : : ExtractPath ( const std : : vector < String > & path , const Array : : Ptr & result ) const
{
ASSERT ( ! path . empty ( ) ) ;
if ( m_Operator = = & AExpression : : OpDict ) {
Array : : Ptr exprl = m_Operand1 ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( exprl ) ;
2014-03-23 11:27:40 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & expr , exprl ) {
expr - > ExtractPath ( path , result ) ;
}
2014-03-23 19:58:24 +01:00
} else if ( ( m_Operator = = & AExpression : : OpSet | | m_Operator = = & AExpression : : OpSetPlus | |
m_Operator = = & AExpression : : OpSetMinus | | m_Operator = = & AExpression : : OpSetMultiply | |
m_Operator = = & AExpression : : OpSetDivide ) & & path [ 0 ] = = m_Operand1 ) {
2014-03-23 11:27:40 +01:00
AExpression : : Ptr exprl = m_Operand2 ;
if ( path . size ( ) = = 1 ) {
2014-03-24 11:23:05 +01:00
if ( m_Operator = = & AExpression : : OpSet )
result - > Clear ( ) ;
if ( exprl - > m_Operator ! = & AExpression : : OpDict )
BOOST_THROW_EXCEPTION ( ConfigError ( " The ' " + path [ 0 ] + " ' attribute must be a dictionary. " ) < < errinfo_debuginfo ( m_DebugInfo ) ) ;
2014-03-23 19:58:24 +01:00
Array : : Ptr subexprl = exprl - > m_Operand1 ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( subexprl ) ;
2014-03-23 19:58:24 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & expr , subexprl ) {
result - > Add ( expr ) ;
}
2014-03-23 11:27:40 +01:00
return ;
}
std : : vector < String > sub_path ( path . begin ( ) + 1 , path . end ( ) ) ;
exprl - > ExtractPath ( sub_path , result ) ;
}
}
void AExpression : : FindDebugInfoPath ( const std : : vector < String > & path , DebugInfo & result ) const
{
ASSERT ( ! path . empty ( ) ) ;
if ( m_Operator = = & AExpression : : OpDict ) {
Array : : Ptr exprl = m_Operand1 ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( exprl ) ;
2014-03-23 11:27:40 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & expr , exprl ) {
expr - > FindDebugInfoPath ( path , result ) ;
}
2014-03-23 19:58:24 +01:00
} else if ( ( m_Operator = = & AExpression : : OpSet | | m_Operator = = & AExpression : : OpSetPlus | |
m_Operator = = & AExpression : : OpSetMinus | | m_Operator = = & AExpression : : OpSetMultiply | |
m_Operator = = & AExpression : : OpSetDivide ) & & path [ 0 ] = = m_Operand1 ) {
2014-03-23 11:27:40 +01:00
AExpression : : Ptr exprl = m_Operand2 ;
if ( path . size ( ) = = 1 ) {
result = m_DebugInfo ;
} else {
std : : vector < String > sub_path ( path . begin ( ) + 1 , path . end ( ) ) ;
exprl - > FindDebugInfoPath ( sub_path , result ) ;
}
}
}
void AExpression : : MakeInline ( void )
{
2014-03-23 17:26:31 +01:00
if ( m_Operator = = & AExpression : : OpDict )
m_Operand2 = true ;
2014-03-23 11:27:40 +01:00
}
2014-03-23 19:58:24 +01:00
void AExpression : : DumpOperand ( std : : ostream & stream , const Value & operand , int indent ) {
if ( operand . IsObjectType < Array > ( ) ) {
Array : : Ptr arr = operand ;
stream < < String ( indent , ' ' ) < < " Array: \n " ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( arr ) ;
2014-03-23 19:58:24 +01:00
BOOST_FOREACH ( const Value & elem , arr ) {
DumpOperand ( stream , elem , indent + 1 ) ;
}
} else if ( operand . IsObjectType < AExpression > ( ) ) {
AExpression : : Ptr left = operand ;
left - > Dump ( stream , indent ) ;
} else {
stream < < String ( indent , ' ' ) < < JsonSerialize ( operand ) < < " \n " ;
}
}
2014-03-24 09:27:46 +01:00
void AExpression : : Dump ( std : : ostream & stream , int indent ) const
2014-03-23 19:58:24 +01:00
{
String sym = Utility : : GetSymbolName ( reinterpret_cast < const void * > ( m_Operator ) ) ;
stream < < String ( indent , ' ' ) < < " op: " < < Utility : : DemangleSymbolName ( sym ) < < " \n " ;
stream < < String ( indent , ' ' ) < < " left: \n " ;
DumpOperand ( stream , m_Operand1 , indent + 1 ) ;
stream < < String ( indent , ' ' ) < < " right: \n " ;
DumpOperand ( stream , m_Operand2 , indent + 1 ) ;
}
2014-03-22 10:29:45 +01:00
Value AExpression : : EvaluateOperand1 ( const Dictionary : : Ptr & locals ) const
2013-10-20 15:06:05 +02:00
{
2014-03-22 10:29:45 +01:00
return static_cast < AExpression : : Ptr > ( m_Operand1 ) - > Evaluate ( locals ) ;
2013-10-20 15:06:05 +02:00
}
2014-03-22 10:29:45 +01:00
Value AExpression : : EvaluateOperand2 ( const Dictionary : : Ptr & locals ) const
{
return static_cast < AExpression : : Ptr > ( m_Operand2 ) - > Evaluate ( locals ) ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpLiteral ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > m_Operand1 ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpVariable ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-24 09:10:37 +01:00
Dictionary : : Ptr scope = locals ;
while ( scope ) {
if ( scope - > Contains ( expr - > m_Operand1 ) )
return scope - > Get ( expr - > m_Operand1 ) ;
scope = scope - > Get ( " __parent " ) ;
}
return ScriptVariable : : Get ( expr - > m_Operand1 ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpNegate ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return ~ ( long ) expr - > EvaluateOperand1 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpAdd ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) + expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSubtract ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) - expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpMultiply ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) * expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpDivide ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) / expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpBinaryAnd ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) & expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpBinaryOr ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) | expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpShiftLeft ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) < < expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpShiftRight ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) > > expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpEqual ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) = = expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpNotEqual ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) ! = expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpLessThan ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) < expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpGreaterThan ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) > expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpLessThanOrEqual ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) < = expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpGreaterThanOrEqual ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) > = expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpIn ( const AExpression * expr , const Dictionary : : Ptr & locals )
2013-10-20 15:06:05 +02:00
{
2014-03-23 19:58:24 +01:00
Value right = expr - > EvaluateOperand2 ( locals ) ;
2014-03-22 10:29:45 +01:00
if ( ! right . IsObjectType < Array > ( ) )
BOOST_THROW_EXCEPTION ( ConfigError ( " Invalid right side argument for 'in' operator: " + JsonSerialize ( right ) ) ) ;
2014-03-23 19:58:24 +01:00
Value left = expr - > EvaluateOperand1 ( locals ) ;
2014-03-22 10:29:45 +01:00
Array : : Ptr arr = right ;
bool found = false ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( arr ) ;
2014-03-22 10:29:45 +01:00
BOOST_FOREACH ( const Value & value , arr ) {
if ( value = = left ) {
found = true ;
break ;
}
}
return found ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpNotIn ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return ! OpIn ( expr , locals ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpLogicalAnd ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) . ToBool ( ) & & expr - > EvaluateOperand2 ( locals ) . ToBool ( ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpLogicalOr ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
return expr - > EvaluateOperand1 ( locals ) . ToBool ( ) | | expr - > EvaluateOperand2 ( locals ) . ToBool ( ) ;
2014-03-22 10:29:45 +01:00
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpFunctionCall ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
String funcName = expr - > m_Operand1 ;
2014-03-22 10:29:45 +01:00
ScriptFunction : : Ptr func = ScriptFunctionRegistry : : GetInstance ( ) - > GetItem ( funcName ) ;
if ( ! func )
BOOST_THROW_EXCEPTION ( ConfigError ( " Function ' " + funcName + " ' does not exist. " ) ) ;
2014-03-23 19:58:24 +01:00
Array : : Ptr arr = expr - > EvaluateOperand2 ( locals ) ;
2014-03-19 10:51:09 +01:00
std : : vector < Value > arguments ;
2014-03-24 09:15:45 +01:00
ObjectLock olock ( arr ) ;
2014-03-22 10:29:45 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & aexpr , arr ) {
arguments . push_back ( aexpr - > Evaluate ( locals ) ) ;
}
2013-10-20 15:06:05 +02:00
2014-03-22 10:29:45 +01:00
return func - > Invoke ( arguments ) ;
}
2013-10-20 15:06:05 +02:00
2014-03-23 19:58:24 +01:00
Value AExpression : : OpArray ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-22 10:29:45 +01:00
{
2014-03-23 19:58:24 +01:00
Array : : Ptr arr = expr - > m_Operand1 ;
2014-03-22 10:29:45 +01:00
Array : : Ptr result = make_shared < Array > ( ) ;
2014-03-18 15:29:04 +01:00
2014-03-22 10:29:45 +01:00
if ( arr ) {
2014-03-24 09:15:45 +01:00
ObjectLock olock ( arr ) ;
2014-03-22 10:29:45 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & aexpr , arr ) {
result - > Add ( aexpr - > Evaluate ( locals ) ) ;
2014-03-22 08:40:09 +01:00
}
2013-10-20 15:06:05 +02:00
}
2014-03-22 10:29:45 +01:00
return result ;
2013-11-03 10:41:30 +01:00
}
2014-03-23 11:27:40 +01:00
2014-03-23 19:58:24 +01:00
Value AExpression : : OpDict ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Array : : Ptr arr = expr - > m_Operand1 ;
bool in_place = expr - > m_Operand2 ;
2014-03-23 11:27:40 +01:00
Dictionary : : Ptr result = make_shared < Dictionary > ( ) ;
2014-03-24 09:10:37 +01:00
result - > Set ( " __parent " , locals ) ;
2014-03-23 11:27:40 +01:00
if ( arr ) {
2014-03-24 09:15:45 +01:00
ObjectLock olock ( arr ) ;
2014-03-23 11:27:40 +01:00
BOOST_FOREACH ( const AExpression : : Ptr & aexpr , arr ) {
aexpr - > Evaluate ( in_place ? locals : result ) ;
}
}
2014-03-24 09:10:37 +01:00
result - > Remove ( " __parent " ) ;
2014-03-23 11:27:40 +01:00
return result ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSet ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Value right = expr - > EvaluateOperand2 ( locals ) ;
locals - > Set ( expr - > m_Operand1 , right ) ;
2014-03-23 11:27:40 +01:00
return right ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSetPlus ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Value left = locals - > Get ( expr - > m_Operand1 ) ;
AExpression : : Ptr exp_right = expr - > m_Operand2 ;
2014-03-23 17:26:31 +01:00
Dictionary : : Ptr xlocals = locals ;
2014-03-23 19:58:24 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
2014-03-23 17:26:31 +01:00
xlocals = left ;
2014-03-23 19:58:24 +01:00
if ( ! xlocals )
xlocals = make_shared < Dictionary > ( ) ;
2014-03-24 09:44:18 +01:00
xlocals - > Set ( " __parent " , locals ) ;
2014-03-23 19:58:24 +01:00
}
Value result = left + expr - > EvaluateOperand2 ( xlocals ) ;
2014-03-24 09:44:18 +01:00
2014-03-24 11:34:41 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
Dictionary : : Ptr dict = result ;
dict - > Remove ( " __parent " ) ;
}
2014-03-24 09:44:18 +01:00
2014-03-23 19:58:24 +01:00
locals - > Set ( expr - > m_Operand1 , result ) ;
2014-03-23 11:27:40 +01:00
return result ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSetMinus ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Value left = locals - > Get ( expr - > m_Operand1 ) ;
AExpression : : Ptr exp_right = expr - > m_Operand2 ;
2014-03-23 17:26:31 +01:00
Dictionary : : Ptr xlocals = locals ;
2014-03-23 19:58:24 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
2014-03-23 17:26:31 +01:00
xlocals = left ;
2014-03-23 19:58:24 +01:00
if ( ! xlocals )
xlocals = make_shared < Dictionary > ( ) ;
2014-03-24 09:44:18 +01:00
xlocals - > Set ( " __parent " , locals ) ;
2014-03-23 19:58:24 +01:00
}
Value result = left - expr - > EvaluateOperand2 ( xlocals ) ;
2014-03-24 09:44:18 +01:00
2014-03-24 11:34:41 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
Dictionary : : Ptr dict = result ;
dict - > Remove ( " __parent " ) ;
}
2014-03-24 09:44:18 +01:00
2014-03-23 19:58:24 +01:00
locals - > Set ( expr - > m_Operand1 , result ) ;
2014-03-23 11:27:40 +01:00
return result ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSetMultiply ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Value left = locals - > Get ( expr - > m_Operand1 ) ;
AExpression : : Ptr exp_right = expr - > m_Operand2 ;
2014-03-23 17:26:31 +01:00
Dictionary : : Ptr xlocals = locals ;
2014-03-23 19:58:24 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
2014-03-23 17:26:31 +01:00
xlocals = left ;
2014-03-23 19:58:24 +01:00
if ( ! xlocals )
xlocals = make_shared < Dictionary > ( ) ;
2014-03-24 09:44:18 +01:00
xlocals - > Set ( " __parent " , locals ) ;
2014-03-23 19:58:24 +01:00
}
Value result = left * expr - > EvaluateOperand2 ( xlocals ) ;
2014-03-24 09:44:18 +01:00
2014-03-24 11:34:41 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
Dictionary : : Ptr dict = result ;
dict - > Remove ( " __parent " ) ;
}
2014-03-24 09:44:18 +01:00
2014-03-23 19:58:24 +01:00
locals - > Set ( expr - > m_Operand1 , result ) ;
2014-03-23 11:27:40 +01:00
return result ;
}
2014-03-23 19:58:24 +01:00
Value AExpression : : OpSetDivide ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 11:27:40 +01:00
{
2014-03-23 19:58:24 +01:00
Value left = locals - > Get ( expr - > m_Operand1 ) ;
AExpression : : Ptr exp_right = expr - > m_Operand2 ;
2014-03-23 17:26:31 +01:00
Dictionary : : Ptr xlocals = locals ;
2014-03-23 19:58:24 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
2014-03-23 17:26:31 +01:00
xlocals = left ;
2014-03-23 19:58:24 +01:00
if ( ! xlocals )
xlocals = make_shared < Dictionary > ( ) ;
2014-03-24 09:44:18 +01:00
xlocals - > Set ( " __parent " , locals ) ;
2014-03-23 19:58:24 +01:00
}
Value result = left / expr - > EvaluateOperand2 ( xlocals ) ;
2014-03-24 09:44:18 +01:00
2014-03-24 11:34:41 +01:00
if ( exp_right - > m_Operator = = & AExpression : : OpDict ) {
Dictionary : : Ptr dict = result ;
dict - > Remove ( " __parent " ) ;
}
2014-03-24 09:44:18 +01:00
2014-03-23 19:58:24 +01:00
locals - > Set ( expr - > m_Operand1 , result ) ;
2014-03-23 11:27:40 +01:00
return result ;
}
2014-03-23 17:26:31 +01:00
2014-03-23 19:58:24 +01:00
Value AExpression : : OpIndexer ( const AExpression * expr , const Dictionary : : Ptr & locals )
2014-03-23 17:26:31 +01:00
{
2014-03-24 11:23:47 +01:00
Dictionary : : Ptr dict = OpVariable ( expr , locals ) ;
2014-03-24 09:06:16 +01:00
if ( ! dict )
BOOST_THROW_EXCEPTION ( ConfigError ( " Script variable ' " + expr - > m_Operand1 + " ' not set in this scope. " ) ) ;
2014-03-23 19:58:24 +01:00
return dict - > Get ( expr - > m_Operand2 ) ;
2014-03-23 17:26:31 +01:00
}