1 /******************************************************************************
3 * Copyright (C) 2012-2018 Icinga Development Team (https://www.icinga.com/) *
5 * This program is free software; you can redistribute it and/or *
6 * modify it under the terms of the GNU General Public License *
7 * as published by the Free Software Foundation; either version 2 *
8 * of the License, or (at your option) any later version. *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software Foundation *
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ******************************************************************************/
20 #include "config/expression.hpp"
21 #include "config/configitem.hpp"
22 #include "config/configcompiler.hpp"
23 #include "config/vmops.hpp"
24 #include "base/array.hpp"
25 #include "base/json.hpp"
26 #include "base/object.hpp"
27 #include "base/logger.hpp"
28 #include "base/exception.hpp"
29 #include "base/scriptglobal.hpp"
30 #include "base/loader.hpp"
31 #include "base/reference.hpp"
32 #include "base/namespace.hpp"
33 #include <boost/exception_ptr.hpp>
34 #include <boost/exception/errinfo_nested_exception.hpp>
36 using namespace icinga;
38 boost::signals2::signal<void (ScriptFrame&, ScriptError *ex, const DebugInfo&)> Expression::OnBreakpoint;
39 boost::thread_specific_ptr<bool> l_InBreakpointHandler;
41 Expression::~Expression()
44 void Expression::ScriptBreakpoint(ScriptFrame& frame, ScriptError *ex, const DebugInfo& di)
46 bool *inHandler = l_InBreakpointHandler.get();
47 if (!inHandler || !*inHandler) {
48 inHandler = new bool(true);
49 l_InBreakpointHandler.reset(inHandler);
50 OnBreakpoint(frame, ex, di);
55 ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
59 /* std::ostringstream msgbuf;
60 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
61 Log(LogDebug, "Expression")
62 << "Executing:\n" << msgbuf.str();*/
65 frame.IncreaseStackDepth();
66 ExpressionResult result = DoEvaluate(frame, dhint);
67 frame.DecreaseStackDepth();
69 } catch (ScriptError& ex) {
70 frame.DecreaseStackDepth();
72 ScriptBreakpoint(frame, &ex, GetDebugInfo());
74 } catch (const std::exception& ex) {
75 frame.DecreaseStackDepth();
77 BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
78 << boost::errinfo_nested_exception(boost::current_exception()));
81 frame.DecreaseStackDepth();
84 bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
89 const DebugInfo& Expression::GetDebugInfo() const
91 static DebugInfo debugInfo;
95 std::unique_ptr<Expression> icinga::MakeIndexer(ScopeSpecifier scopeSpec, const String& index)
97 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
98 return std::unique_ptr<Expression>(new IndexerExpression(std::move(scope), MakeLiteral(index)));
101 void DictExpression::MakeInline()
106 LiteralExpression::LiteralExpression(Value value)
107 : m_Value(std::move(value))
110 ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
115 const DebugInfo& DebuggableExpression::GetDebugInfo() const
120 ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
124 if (frame.Locals && frame.Locals->Get(m_Variable, &value))
126 else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
128 else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
131 return ScriptGlobal::Get(m_Variable);
134 bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
138 if (frame.Locals && frame.Locals->Contains(m_Variable)) {
139 *parent = frame.Locals;
143 } else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->HasOwnField(m_Variable)) {
144 *parent = frame.Self;
147 *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
148 } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
150 } else if (ScriptGlobal::Exists(m_Variable)) {
151 *parent = ScriptGlobal::GetGlobals();
156 *parent = frame.Self;
161 ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
166 if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
167 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
169 if (!parent.IsObject())
170 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
172 return new Reference(parent, index);
175 ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
177 ExpressionResult operand = m_Operand->Evaluate(frame);
178 CHECK_RESULT(operand);
180 Object::Ptr obj = operand.GetValue();
181 Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
184 BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
189 bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
191 ExpressionResult operand = m_Operand->Evaluate(frame);
192 if (operand.GetCode() != ResultOK)
195 Reference::Ptr ref = operand.GetValue();
197 *parent = ref->GetParent();
198 *index = ref->GetIndex();
202 ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
204 ExpressionResult operand = m_Operand->Evaluate(frame);
205 CHECK_RESULT(operand);
207 return ~(long)operand.GetValue();
210 ExpressionResult LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
212 ExpressionResult operand = m_Operand->Evaluate(frame);
213 CHECK_RESULT(operand);
215 return !operand.GetValue().ToBool();
218 ExpressionResult AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
220 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
221 CHECK_RESULT(operand1);
223 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
224 CHECK_RESULT(operand2);
226 return operand1.GetValue() + operand2.GetValue();
229 ExpressionResult SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
231 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
232 CHECK_RESULT(operand1);
234 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
235 CHECK_RESULT(operand2);
237 return operand1.GetValue() - operand2.GetValue();
240 ExpressionResult MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
242 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
243 CHECK_RESULT(operand1);
245 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
246 CHECK_RESULT(operand2);
248 return operand1.GetValue() * operand2.GetValue();
251 ExpressionResult DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
253 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
254 CHECK_RESULT(operand1);
256 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
257 CHECK_RESULT(operand2);
259 return operand1.GetValue() / operand2.GetValue();
262 ExpressionResult ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
264 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
265 CHECK_RESULT(operand1);
267 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
268 CHECK_RESULT(operand2);
270 return operand1.GetValue() % operand2.GetValue();
273 ExpressionResult XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
275 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
276 CHECK_RESULT(operand1);
278 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
279 CHECK_RESULT(operand2);
281 return operand1.GetValue() ^ operand2.GetValue();
284 ExpressionResult BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
286 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
287 CHECK_RESULT(operand1);
289 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
290 CHECK_RESULT(operand2);
292 return operand1.GetValue() & operand2.GetValue();
295 ExpressionResult BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
297 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
298 CHECK_RESULT(operand1);
300 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
301 CHECK_RESULT(operand2);
303 return operand1.GetValue() | operand2.GetValue();
306 ExpressionResult ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
308 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
309 CHECK_RESULT(operand1);
311 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
312 CHECK_RESULT(operand2);
314 return operand1.GetValue() << operand2.GetValue();
317 ExpressionResult ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
319 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
320 CHECK_RESULT(operand1);
322 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
323 CHECK_RESULT(operand2);
325 return operand1.GetValue() >> operand2.GetValue();
328 ExpressionResult EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
330 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
331 CHECK_RESULT(operand1);
333 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
334 CHECK_RESULT(operand2);
336 return operand1.GetValue() == operand2.GetValue();
339 ExpressionResult NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
341 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
342 CHECK_RESULT(operand1);
344 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
345 CHECK_RESULT(operand2);
347 return operand1.GetValue() != operand2.GetValue();
350 ExpressionResult LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
352 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
353 CHECK_RESULT(operand1);
355 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
356 CHECK_RESULT(operand2);
358 return operand1.GetValue() < operand2.GetValue();
361 ExpressionResult GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
363 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
364 CHECK_RESULT(operand1);
366 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
367 CHECK_RESULT(operand2);
369 return operand1.GetValue() > operand2.GetValue();
372 ExpressionResult LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
374 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
375 CHECK_RESULT(operand1);
377 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
378 CHECK_RESULT(operand2);
380 return operand1.GetValue() <= operand2.GetValue();
383 ExpressionResult GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
385 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
386 CHECK_RESULT(operand1);
388 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
389 CHECK_RESULT(operand2);
391 return operand1.GetValue() >= operand2.GetValue();
394 ExpressionResult InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
396 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
397 CHECK_RESULT(operand2);
399 if (operand2.GetValue().IsEmpty())
401 else if (!operand2.GetValue().IsObjectType<Array>())
402 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
404 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
405 CHECK_RESULT(operand1)
407 Array::Ptr arr = operand2.GetValue();
408 return arr->Contains(operand1.GetValue());
411 ExpressionResult NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
413 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
414 CHECK_RESULT(operand2);
416 if (operand2.GetValue().IsEmpty())
418 else if (!operand2.GetValue().IsObjectType<Array>())
419 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
421 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
422 CHECK_RESULT(operand1);
424 Array::Ptr arr = operand2.GetValue();
425 return !arr->Contains(operand1.GetValue());
428 ExpressionResult LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
430 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
431 CHECK_RESULT(operand1);
433 if (!operand1.GetValue().ToBool())
436 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
437 CHECK_RESULT(operand2);
439 return operand2.GetValue();
443 ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
445 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
446 CHECK_RESULT(operand1);
448 if (operand1.GetValue().ToBool())
451 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
452 CHECK_RESULT(operand2);
454 return operand2.GetValue();
458 ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
463 if (m_FName->GetReference(frame, false, &self, &index))
464 vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
466 ExpressionResult vfuncres = m_FName->Evaluate(frame);
467 CHECK_RESULT(vfuncres);
469 vfunc = vfuncres.GetValue();
472 if (vfunc.IsObjectType<Type>()) {
473 std::vector<Value> arguments;
474 arguments.reserve(m_Args.size());
475 for (const auto& arg : m_Args) {
476 ExpressionResult argres = arg->Evaluate(frame);
477 CHECK_RESULT(argres);
479 arguments.push_back(argres.GetValue());
482 return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
485 if (!vfunc.IsObjectType<Function>())
486 BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));
488 Function::Ptr func = vfunc;
490 if (!func->IsSideEffectFree() && frame.Sandboxed)
491 BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));
493 std::vector<Value> arguments;
494 arguments.reserve(m_Args.size());
495 for (const auto& arg : m_Args) {
496 ExpressionResult argres = arg->Evaluate(frame);
497 CHECK_RESULT(argres);
499 arguments.push_back(argres.GetValue());
502 return VMOps::FunctionCall(frame, self, func, arguments);
505 ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
508 result.reserve(m_Expressions.size());
510 for (const auto& aexpr : m_Expressions) {
511 ExpressionResult element = aexpr->Evaluate(frame);
512 CHECK_RESULT(element);
514 result.push_back(element.GetValue());
517 return new Array(std::move(result));
520 ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
526 frame.Self = new Dictionary();
532 for (const auto& aexpr : m_Expressions) {
533 ExpressionResult element = aexpr->Evaluate(frame, m_Inline ? dhint : nullptr);
534 CHECK_RESULT(element);
535 result = element.GetValue();
539 std::swap(self, frame.Self);
546 std::swap(self, frame.Self);
551 ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
553 if (m_ScopeSpec == ScopeLocal)
555 else if (m_ScopeSpec == ScopeThis)
557 else if (m_ScopeSpec == ScopeGlobal)
558 return ScriptGlobal::GetGlobals();
560 VERIFY(!"Invalid scope.");
563 ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
566 BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo));
568 DebugHint *psdhint = dhint;
573 if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
574 BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
576 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
577 CHECK_RESULT(operand2);
579 if (m_Op != OpSetLiteral) {
580 Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo);
584 operand2 = object + operand2;
587 operand2 = object - operand2;
590 operand2 = object * operand2;
593 operand2 = object / operand2;
596 operand2 = object % operand2;
599 operand2 = object ^ operand2;
602 operand2 = object & operand2;
605 operand2 = object | operand2;
608 VERIFY(!"Invalid opcode.");
612 VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
615 psdhint->AddMessage("=", m_DebugInfo);
617 if (psdhint != dhint)
624 void SetExpression::SetOverrideFrozen()
626 m_OverrideFrozen = true;
629 ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
631 auto globals = ScriptGlobal::GetGlobals();
633 auto attr = globals->GetAttribute(m_Name);
635 if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
636 std::ostringstream msgbuf;
637 msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
638 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
639 Log(LogWarning, msgbuf.str());
642 ExpressionResult operandres = m_Operand->Evaluate(frame);
643 CHECK_RESULT(operandres);
644 Value operand = operandres.GetValue();
646 globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
651 ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
653 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
654 CHECK_RESULT(condition);
656 if (condition.GetValue().ToBool())
657 return m_TrueBranch->Evaluate(frame, dhint);
658 else if (m_FalseBranch)
659 return m_FalseBranch->Evaluate(frame, dhint);
664 ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
667 BOOST_THROW_EXCEPTION(ScriptError("While loops are not allowed in sandbox mode.", m_DebugInfo));
670 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
671 CHECK_RESULT(condition);
673 if (!condition.GetValue().ToBool())
676 ExpressionResult loop_body = m_LoopBody->Evaluate(frame, dhint);
677 CHECK_RESULT_LOOP(loop_body);
683 ExpressionResult ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
685 ExpressionResult operand = m_Operand->Evaluate(frame);
686 CHECK_RESULT(operand);
688 return ExpressionResult(operand.GetValue(), ResultReturn);
691 ExpressionResult BreakExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
693 return ExpressionResult(Empty, ResultBreak);
696 ExpressionResult ContinueExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
698 return ExpressionResult(Empty, ResultContinue);
701 ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
703 ExpressionResult operand1 = m_Operand1->Evaluate(frame, dhint);
704 CHECK_RESULT(operand1);
706 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
707 CHECK_RESULT(operand2);
709 return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), frame.Sandboxed, m_DebugInfo);
712 bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
716 DebugHint *psdhint = nullptr;
717 bool free_psd = false;
725 if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
728 bool has_field = true;
730 if (vparent.IsObject()) {
731 Object::Ptr oparent = vparent;
732 has_field = oparent->HasOwnField(vindex);
736 old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
738 if (old_value.IsEmpty() && !old_value.IsString())
739 VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
742 *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
745 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
746 *parent = operand1.GetValue();
749 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
750 *index = operand2.GetValue();
754 *dhint = new DebugHint(psdhint->GetChild(*index));
765 void IndexerExpression::SetOverrideFrozen()
767 m_OverrideFrozen = true;
770 void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
772 auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
775 for (auto& expr : dexpr->m_Expressions)
776 BindToScope(expr, scopeSpec);
781 auto *aexpr = dynamic_cast<SetExpression *>(expr.get());
784 BindToScope(aexpr->m_Operand1, scopeSpec);
789 auto *iexpr = dynamic_cast<IndexerExpression *>(expr.get());
792 BindToScope(iexpr->m_Operand1, scopeSpec);
796 auto *lexpr = dynamic_cast<LiteralExpression *>(expr.get());
798 if (lexpr && lexpr->GetValue().IsString()) {
799 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
800 expr.reset(new IndexerExpression(std::move(scope), std::move(expr), lexpr->GetDebugInfo()));
803 auto *vexpr = dynamic_cast<VariableExpression *>(expr.get());
806 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
807 expr.reset(new IndexerExpression(std::move(scope), MakeLiteral(vexpr->GetVariable()), vexpr->GetDebugInfo()));
811 ExpressionResult ThrowExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
813 ExpressionResult messageres = m_Message->Evaluate(frame);
814 CHECK_RESULT(messageres);
815 Value message = messageres.GetValue();
816 BOOST_THROW_EXCEPTION(ScriptError(message, m_DebugInfo, m_IncompleteExpr));
819 ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
822 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
824 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
825 ExpressionResult nameres = m_Name->Evaluate(frame);
826 CHECK_RESULT(nameres);
827 Value name = nameres.GetValue();
829 if (!name.IsString())
830 BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo));
832 ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(Type::GetByName(type), name);
835 BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo));
837 Dictionary::Ptr scope = item->GetScope();
840 scope->CopyTo(frame.Locals);
842 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
843 CHECK_RESULT(result);
848 ExpressionResult ImportDefaultTemplatesExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
851 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
853 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
854 Type::Ptr ptype = Type::GetByName(type);
856 for (const ConfigItem::Ptr& item : ConfigItem::GetDefaultTemplates(ptype)) {
857 Dictionary::Ptr scope = item->GetScope();
860 scope->CopyTo(frame.Locals);
862 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
863 CHECK_RESULT(result);
869 ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
871 return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
874 ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
877 BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo));
879 ExpressionResult nameres = m_Name->Evaluate(frame);
880 CHECK_RESULT(nameres);
882 return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
883 m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
886 ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
889 BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo));
891 ExpressionResult typeres = m_Type->Evaluate(frame, dhint);
892 CHECK_RESULT(typeres);
893 Type::Ptr type = typeres.GetValue();
898 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
899 CHECK_RESULT(nameres);
901 name = nameres.GetValue();
904 return VMOps::NewObject(frame, m_Abstract, type, name, m_Filter, m_Zone,
905 m_Package, m_DefaultTmpl, m_IgnoreOnError, m_ClosedVars, m_Expression, m_DebugInfo);
908 ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
911 BOOST_THROW_EXCEPTION(ScriptError("For loops are not allowed in sandbox mode.", m_DebugInfo));
913 ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
914 CHECK_RESULT(valueres);
916 return VMOps::For(frame, m_FKVar, m_FVVar, valueres.GetValue(), m_Expression, m_DebugInfo);
919 ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
922 BOOST_THROW_EXCEPTION(ScriptError("Loading libraries is not allowed in sandbox mode.", m_DebugInfo));
924 ExpressionResult libres = m_Operand->Evaluate(frame, dhint);
925 CHECK_RESULT(libres);
927 Log(LogNotice, "config")
928 << "Ignoring explicit load request for library \"" << libres << "\".";
933 ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
936 BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));
938 std::unique_ptr<Expression> expr;
939 String name, path, pattern;
944 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
945 CHECK_RESULT(pathres);
946 path = pathres.GetValue();
949 expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
952 case IncludeRecursive:
954 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
955 CHECK_RESULT(pathres);
956 path = pathres.GetValue();
960 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
961 CHECK_RESULT(patternres);
962 pattern = patternres.GetValue();
965 expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
970 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
971 CHECK_RESULT(nameres);
972 name = nameres.GetValue();
976 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
977 CHECK_RESULT(pathres);
978 path = pathres.GetValue();
982 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
983 CHECK_RESULT(patternres);
984 pattern = patternres.GetValue();
987 expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
991 ExpressionResult res(Empty);
994 res = expr->Evaluate(frame, dhint);
995 } catch (const std::exception&) {
1002 ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1004 ScriptBreakpoint(frame, nullptr, GetDebugInfo());
1009 ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1011 if (frame.Sandboxed)
1012 BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
1014 ExpressionResult importres = m_Name->Evaluate(frame);
1015 CHECK_RESULT(importres);
1016 Value import = importres.GetValue();
1018 if (!import.IsObjectType<Dictionary>())
1019 BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo));
1021 ScriptFrame::AddImport(import);
1026 ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1029 ExpressionResult tryResult = m_TryBody->Evaluate(frame, dhint);
1030 CHECK_RESULT(tryResult);
1031 } catch (const std::exception&) {
1032 ExpressionResult exceptResult = m_ExceptBody->Evaluate(frame, dhint);
1033 CHECK_RESULT(exceptResult);