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-27 12:30:24 +01:00
# include "config/configitem.h"
2014-03-30 15:04:53 +02:00
# include "config/configitembuilder.h"
# include "config/applyrule.h"
2014-04-23 12:44:36 +02:00
# include "config/objectrule.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-28 12:17:22 +01:00
# include "base/object.h"
2014-03-29 13:48:04 +01:00
# include "base/logger_fwd.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-29 13:48:04 +01:00
# ifdef _DEBUG
if ( m_Operator ! = & AExpression : : OpLiteral ) {
std : : ostringstream msgbuf ;
ShowCodeFragment ( msgbuf , m_DebugInfo , false ) ;
Log ( LogDebug , " config " , " Executing: \n " + msgbuf . str ( ) ) ;
}
# endif /* _DEBUG */
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 : : 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-28 13:25:40 +01:00
Value AExpression : : OpLogicalNegate ( const AExpression * expr , const Dictionary : : Ptr & locals )
{
return ! expr - > EvaluateOperand1 ( locals ) . ToBool ( ) ;
}
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
2014-03-28 12:17:22 +01:00
if ( right . IsEmpty ( ) )
return false ;
else if ( ! right . IsObjectType < Array > ( ) )
2014-03-22 10:29:45 +01:00
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-04-02 09:04:17 +02:00
Value funcName = expr - > EvaluateOperand1 ( locals ) ;
ScriptFunction : : Ptr func ;
if ( funcName . IsObjectType < ScriptFunction > ( ) )
func = funcName ;
else
func = ScriptFunction : : GetByName ( funcName ) ;
2014-03-22 10:29:45 +01:00
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 ) {
2014-04-09 10:36:57 +02:00
Dictionary : : Ptr alocals = in_place ? locals : result ;
aexpr - > Evaluate ( alocals ) ;
if ( alocals - > Contains ( " __result " ) )
break ;
2014-03-23 11:27:40 +01:00
}
}
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-30 10:00:11 +02:00
Value index = expr - > EvaluateOperand1 ( locals ) ;
2014-03-23 19:58:24 +01:00
Value right = expr - > EvaluateOperand2 ( locals ) ;
2014-03-30 10:00:11 +02:00
locals - > Set ( index , 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-30 10:00:11 +02:00
Value index = expr - > EvaluateOperand1 ( locals ) ;
Value left = locals - > Get ( index ) ;
2014-03-23 19:58:24 +01:00
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-30 10:00:11 +02:00
locals - > Set ( index , 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-30 10:00:11 +02:00
Value index = expr - > EvaluateOperand1 ( locals ) ;
Value left = locals - > Get ( index ) ;
2014-03-23 19:58:24 +01:00
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-30 10:00:11 +02:00
locals - > Set ( index , 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-30 10:00:11 +02:00
Value index = expr - > EvaluateOperand1 ( locals ) ;
Value left = locals - > Get ( index ) ;
2014-03-23 19:58:24 +01:00
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-30 10:00:11 +02:00
locals - > Set ( index , 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-30 10:00:11 +02:00
Value index = expr - > EvaluateOperand1 ( locals ) ;
Value left = locals - > Get ( index ) ;
2014-03-23 19:58:24 +01:00
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-30 10:00:11 +02:00
locals - > Set ( index , 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-28 12:17:22 +01:00
Value value = expr - > EvaluateOperand1 ( locals ) ;
Value index = expr - > EvaluateOperand2 ( locals ) ;
if ( value . IsObjectType < Dictionary > ( ) ) {
Dictionary : : Ptr dict = value ;
return dict - > Get ( index ) ;
} else if ( value . IsObjectType < Object > ( ) ) {
Object : : Ptr object = value ;
const Type * type = object - > GetReflectionType ( ) ;
if ( ! type )
BOOST_THROW_EXCEPTION ( ConfigError ( " Dot operator applied to object which does not support reflection " ) ) ;
int field = type - > GetFieldId ( index ) ;
if ( field = = - 1 )
BOOST_THROW_EXCEPTION ( ConfigError ( " Tried to access invalid property ' " + index + " ' " ) ) ;
return object - > GetField ( field ) ;
2014-03-28 16:32:15 +01:00
} else if ( value . IsEmpty ( ) ) {
return Empty ;
2014-03-28 12:17:22 +01:00
} else {
BOOST_THROW_EXCEPTION ( ConfigError ( " Dot operator cannot be applied to type ' " + value . GetTypeName ( ) + " ' " ) ) ;
}
2014-03-23 17:26:31 +01:00
}
2014-03-27 12:30:24 +01:00
Value AExpression : : OpImport ( const AExpression * expr , const Dictionary : : Ptr & locals )
{
Value type = expr - > EvaluateOperand1 ( locals ) ;
Value name = expr - > EvaluateOperand2 ( locals ) ;
ConfigItem : : Ptr item = ConfigItem : : GetObject ( type , name ) ;
if ( ! item )
BOOST_THROW_EXCEPTION ( ConfigError ( " Import references unknown template: ' " + name + " ' " ) ) ;
item - > GetExpressionList ( ) - > Evaluate ( locals ) ;
return Empty ;
}
2014-03-30 15:04:53 +02:00
Value AExpression : : FunctionWrapper ( const std : : vector < Value > & arguments , const Array : : Ptr & funcargs , const AExpression : : Ptr & expr , const Dictionary : : Ptr & scope )
{
if ( arguments . size ( ) < funcargs - > GetLength ( ) )
BOOST_THROW_EXCEPTION ( ConfigError ( " Too few arguments for function " ) ) ;
Dictionary : : Ptr locals = make_shared < Dictionary > ( ) ;
locals - > Set ( " __parent " , scope ) ;
for ( int i = 0 ; i < std : : min ( arguments . size ( ) , funcargs - > GetLength ( ) ) ; i + + )
locals - > Set ( funcargs - > Get ( i ) , arguments [ i ] ) ;
2014-04-02 09:04:49 +02:00
expr - > Evaluate ( locals ) ;
return locals - > Get ( " __result " ) ;
2014-03-30 15:04:53 +02:00
}
Value AExpression : : OpFunction ( const AExpression * expr , const Dictionary : : Ptr & locals )
{
Array : : Ptr left = expr - > m_Operand1 ;
AExpression : : Ptr aexpr = left - > Get ( 1 ) ;
String name = left - > Get ( 0 ) ;
Array : : Ptr funcargs = expr - > m_Operand2 ;
2014-04-02 09:04:17 +02:00
ScriptFunction : : Ptr func = make_shared < ScriptFunction > ( boost : : bind ( & AExpression : : FunctionWrapper , _1 , funcargs , aexpr , locals ) ) ;
if ( ! name . IsEmpty ( ) )
ScriptFunction : : Register ( name , func ) ;
return func ;
2014-03-30 15:04:53 +02:00
}
Value AExpression : : OpApply ( const AExpression * expr , const Dictionary : : Ptr & locals )
{
Array : : Ptr left = expr - > m_Operand1 ;
AExpression : : Ptr exprl = expr - > m_Operand2 ;
String type = left - > Get ( 0 ) ;
2014-04-05 12:56:56 +02:00
String target = left - > Get ( 1 ) ;
AExpression : : Ptr aname = left - > Get ( 2 ) ;
AExpression : : Ptr filter = left - > Get ( 3 ) ;
2014-03-30 15:04:53 +02:00
String name = aname - > Evaluate ( locals ) ;
2014-04-05 12:56:56 +02:00
ApplyRule : : AddRule ( type , target , name , exprl , filter , expr - > m_DebugInfo , locals ) ;
2014-03-30 15:04:53 +02:00
return Empty ;
}
Value AExpression : : OpObject ( const AExpression * expr , const Dictionary : : Ptr & locals )
{
Array : : Ptr left = expr - > m_Operand1 ;
AExpression : : Ptr exprl = expr - > m_Operand2 ;
bool abstract = left - > Get ( 0 ) ;
String type = left - > Get ( 1 ) ;
AExpression : : Ptr aname = left - > Get ( 2 ) ;
2014-04-23 12:44:36 +02:00
AExpression : : Ptr filter = left - > Get ( 3 ) ;
2014-03-30 15:04:53 +02:00
String name = aname - > Evaluate ( locals ) ;
ConfigItemBuilder : : Ptr item = make_shared < ConfigItemBuilder > ( expr - > m_DebugInfo ) ;
2014-04-05 22:53:44 +02:00
String checkName = name ;
2014-03-30 15:04:53 +02:00
2014-04-05 22:53:44 +02:00
if ( ! abstract ) {
2014-04-06 08:09:49 +02:00
const NameComposer * nc = dynamic_cast < const NameComposer * > ( Type : : GetByName ( type ) ) ;
2014-04-05 22:53:44 +02:00
2014-04-06 08:09:49 +02:00
if ( nc )
checkName = nc - > MakeName ( name , Dictionary : : Ptr ( ) ) ;
2014-04-05 22:53:44 +02:00
}
if ( ! checkName . IsEmpty ( ) ) {
2014-04-05 23:07:52 +02:00
ConfigItem : : Ptr oldItem = ConfigItem : : GetObject ( type , checkName ) ;
2014-04-05 22:53:44 +02:00
if ( oldItem ) {
std : : ostringstream msgbuf ;
msgbuf < < " Object ' " < < name < < " ' of type ' " < < type < < " ' re-defined: " < < expr - > m_DebugInfo < < " ; previous definition: " < < oldItem - > GetDebugInfo ( ) ;
BOOST_THROW_EXCEPTION ( ConfigError ( msgbuf . str ( ) ) < < errinfo_debuginfo ( expr - > m_DebugInfo ) ) ;
}
2014-03-30 15:04:53 +02:00
}
item - > SetType ( type ) ;
if ( name . FindFirstOf ( " ! " ) ! = String : : NPos ) {
std : : ostringstream msgbuf ;
msgbuf < < " Name for object ' " < < name < < " ' of type ' " < < type < < " ' is invalid: Object names may not contain '!' " ;
BOOST_THROW_EXCEPTION ( ConfigError ( msgbuf . str ( ) ) < < errinfo_debuginfo ( expr - > m_DebugInfo ) ) ;
}
item - > SetName ( name ) ;
item - > AddExpression ( exprl ) ;
item - > SetAbstract ( abstract ) ;
item - > SetScope ( locals ) ;
item - > Compile ( ) - > Register ( ) ;
2014-04-23 12:44:36 +02:00
ObjectRule : : AddRule ( type , name , exprl , filter , expr - > m_DebugInfo , locals ) ;
2014-03-30 15:04:53 +02:00
return Empty ;
2014-04-02 09:04:17 +02:00
}