1 /* Icinga 2 | (c) 2012 Icinga GmbH | GPLv2+ */
3 #include "config/expression.hpp"
4 #include "config/configitem.hpp"
5 #include "config/configcompiler.hpp"
6 #include "config/vmops.hpp"
7 #include "base/array.hpp"
8 #include "base/json.hpp"
9 #include "base/object.hpp"
10 #include "base/logger.hpp"
11 #include "base/exception.hpp"
12 #include "base/scriptglobal.hpp"
13 #include "base/loader.hpp"
14 #include "base/reference.hpp"
15 #include "base/namespace.hpp"
16 #include <boost/exception_ptr.hpp>
17 #include <boost/exception/errinfo_nested_exception.hpp>
19 using namespace icinga;
21 boost::signals2::signal<void (ScriptFrame&, ScriptError *ex, const DebugInfo&)> Expression::OnBreakpoint;
22 boost::thread_specific_ptr<bool> l_InBreakpointHandler;
24 Expression::~Expression()
27 void Expression::ScriptBreakpoint(ScriptFrame& frame, ScriptError *ex, const DebugInfo& di)
29 bool *inHandler = l_InBreakpointHandler.get();
30 if (!inHandler || !*inHandler) {
31 inHandler = new bool(true);
32 l_InBreakpointHandler.reset(inHandler);
33 OnBreakpoint(frame, ex, di);
38 ExpressionResult Expression::Evaluate(ScriptFrame& frame, DebugHint *dhint) const
42 /* std::ostringstream msgbuf;
43 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
44 Log(LogDebug, "Expression")
45 << "Executing:\n" << msgbuf.str();*/
48 frame.IncreaseStackDepth();
49 ExpressionResult result = DoEvaluate(frame, dhint);
50 frame.DecreaseStackDepth();
52 } catch (ScriptError& ex) {
53 frame.DecreaseStackDepth();
55 ScriptBreakpoint(frame, &ex, GetDebugInfo());
57 } catch (const std::exception& ex) {
58 frame.DecreaseStackDepth();
60 BOOST_THROW_EXCEPTION(ScriptError("Error while evaluating expression: " + String(ex.what()), GetDebugInfo())
61 << boost::errinfo_nested_exception(boost::current_exception()));
64 frame.DecreaseStackDepth();
67 bool Expression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
72 const DebugInfo& Expression::GetDebugInfo() const
74 static DebugInfo debugInfo;
78 std::unique_ptr<Expression> icinga::MakeIndexer(ScopeSpecifier scopeSpec, const String& index)
80 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
81 return std::unique_ptr<Expression>(new IndexerExpression(std::move(scope), MakeLiteral(index)));
84 void DictExpression::MakeInline()
89 LiteralExpression::LiteralExpression(Value value)
90 : m_Value(std::move(value))
93 ExpressionResult LiteralExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
98 const DebugInfo& DebuggableExpression::GetDebugInfo() const
103 VariableExpression::VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo)
104 : DebuggableExpression(debugInfo), m_Variable(std::move(variable)), m_Imports(std::move(imports))
106 m_Imports.push_back(MakeIndexer(ScopeGlobal, "System"));
107 m_Imports.push_back(std::unique_ptr<Expression>(new IndexerExpression(MakeIndexer(ScopeGlobal, "System"), MakeLiteral("Configuration"))));
108 m_Imports.push_back(MakeIndexer(ScopeGlobal, "Types"));
109 m_Imports.push_back(MakeIndexer(ScopeGlobal, "Icinga"));
112 ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
116 if (frame.Locals && frame.Locals->Get(m_Variable, &value))
118 else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
120 else if (VMOps::FindVarImport(frame, m_Imports, m_Variable, &value, m_DebugInfo))
123 return ScriptGlobal::Get(m_Variable);
126 bool VariableExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
130 if (frame.Locals && frame.Locals->Contains(m_Variable)) {
131 *parent = frame.Locals;
135 } else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->HasOwnField(m_Variable)) {
136 *parent = frame.Self;
139 *dhint = new DebugHint((*dhint)->GetChild(m_Variable));
140 } else if (VMOps::FindVarImportRef(frame, m_Imports, m_Variable, parent, m_DebugInfo)) {
142 } else if (ScriptGlobal::Exists(m_Variable)) {
143 *parent = ScriptGlobal::GetGlobals();
148 *parent = frame.Self;
153 ExpressionResult RefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
158 if (!m_Operand->GetReference(frame, false, &parent, &index, &dhint))
159 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression.", m_DebugInfo));
161 if (!parent.IsObject())
162 BOOST_THROW_EXCEPTION(ScriptError("Cannot obtain reference for expression because parent is not an object.", m_DebugInfo));
164 return new Reference(parent, index);
167 ExpressionResult DerefExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
169 ExpressionResult operand = m_Operand->Evaluate(frame);
170 CHECK_RESULT(operand);
172 Object::Ptr obj = operand.GetValue();
173 Reference::Ptr ref = dynamic_pointer_cast<Reference>(obj);
176 BOOST_THROW_EXCEPTION(ScriptError("Invalid reference specified.", GetDebugInfo()));
181 bool DerefExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
183 ExpressionResult operand = m_Operand->Evaluate(frame);
184 if (operand.GetCode() != ResultOK)
187 Reference::Ptr ref = operand.GetValue();
189 *parent = ref->GetParent();
190 *index = ref->GetIndex();
194 ExpressionResult NegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
196 ExpressionResult operand = m_Operand->Evaluate(frame);
197 CHECK_RESULT(operand);
199 return ~(long)operand.GetValue();
202 ExpressionResult LogicalNegateExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
204 ExpressionResult operand = m_Operand->Evaluate(frame);
205 CHECK_RESULT(operand);
207 return !operand.GetValue().ToBool();
210 ExpressionResult AddExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
212 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
213 CHECK_RESULT(operand1);
215 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
216 CHECK_RESULT(operand2);
218 return operand1.GetValue() + operand2.GetValue();
221 ExpressionResult SubtractExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
223 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
224 CHECK_RESULT(operand1);
226 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
227 CHECK_RESULT(operand2);
229 return operand1.GetValue() - operand2.GetValue();
232 ExpressionResult MultiplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
234 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
235 CHECK_RESULT(operand1);
237 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
238 CHECK_RESULT(operand2);
240 return operand1.GetValue() * operand2.GetValue();
243 ExpressionResult DivideExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
245 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
246 CHECK_RESULT(operand1);
248 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
249 CHECK_RESULT(operand2);
251 return operand1.GetValue() / operand2.GetValue();
254 ExpressionResult ModuloExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
256 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
257 CHECK_RESULT(operand1);
259 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
260 CHECK_RESULT(operand2);
262 return operand1.GetValue() % operand2.GetValue();
265 ExpressionResult XorExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
267 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
268 CHECK_RESULT(operand1);
270 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
271 CHECK_RESULT(operand2);
273 return operand1.GetValue() ^ operand2.GetValue();
276 ExpressionResult BinaryAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
278 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
279 CHECK_RESULT(operand1);
281 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
282 CHECK_RESULT(operand2);
284 return operand1.GetValue() & operand2.GetValue();
287 ExpressionResult BinaryOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
289 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
290 CHECK_RESULT(operand1);
292 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
293 CHECK_RESULT(operand2);
295 return operand1.GetValue() | operand2.GetValue();
298 ExpressionResult ShiftLeftExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
300 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
301 CHECK_RESULT(operand1);
303 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
304 CHECK_RESULT(operand2);
306 return operand1.GetValue() << operand2.GetValue();
309 ExpressionResult ShiftRightExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
311 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
312 CHECK_RESULT(operand1);
314 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
315 CHECK_RESULT(operand2);
317 return operand1.GetValue() >> operand2.GetValue();
320 ExpressionResult EqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
322 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
323 CHECK_RESULT(operand1);
325 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
326 CHECK_RESULT(operand2);
328 return operand1.GetValue() == operand2.GetValue();
331 ExpressionResult NotEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
333 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
334 CHECK_RESULT(operand1);
336 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
337 CHECK_RESULT(operand2);
339 return operand1.GetValue() != operand2.GetValue();
342 ExpressionResult LessThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
344 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
345 CHECK_RESULT(operand1);
347 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
348 CHECK_RESULT(operand2);
350 return operand1.GetValue() < operand2.GetValue();
353 ExpressionResult GreaterThanExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
355 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
356 CHECK_RESULT(operand1);
358 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
359 CHECK_RESULT(operand2);
361 return operand1.GetValue() > operand2.GetValue();
364 ExpressionResult LessThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
366 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
367 CHECK_RESULT(operand1);
369 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
370 CHECK_RESULT(operand2);
372 return operand1.GetValue() <= operand2.GetValue();
375 ExpressionResult GreaterThanOrEqualExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
377 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
378 CHECK_RESULT(operand1);
380 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
381 CHECK_RESULT(operand2);
383 return operand1.GetValue() >= operand2.GetValue();
386 ExpressionResult InExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
388 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
389 CHECK_RESULT(operand2);
391 if (operand2.GetValue().IsEmpty())
393 else if (!operand2.GetValue().IsObjectType<Array>())
394 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
396 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
397 CHECK_RESULT(operand1)
399 Array::Ptr arr = operand2.GetValue();
400 return arr->Contains(operand1.GetValue());
403 ExpressionResult NotInExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
405 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
406 CHECK_RESULT(operand2);
408 if (operand2.GetValue().IsEmpty())
410 else if (!operand2.GetValue().IsObjectType<Array>())
411 BOOST_THROW_EXCEPTION(ScriptError("Invalid right side argument for 'in' operator: " + JsonEncode(operand2.GetValue()), m_DebugInfo));
413 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
414 CHECK_RESULT(operand1);
416 Array::Ptr arr = operand2.GetValue();
417 return !arr->Contains(operand1.GetValue());
420 ExpressionResult LogicalAndExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
422 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
423 CHECK_RESULT(operand1);
425 if (!operand1.GetValue().ToBool())
428 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
429 CHECK_RESULT(operand2);
431 return operand2.GetValue();
435 ExpressionResult LogicalOrExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
437 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
438 CHECK_RESULT(operand1);
440 if (operand1.GetValue().ToBool())
443 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
444 CHECK_RESULT(operand2);
446 return operand2.GetValue();
450 ExpressionResult FunctionCallExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
455 if (m_FName->GetReference(frame, false, &self, &index))
456 vfunc = VMOps::GetField(self, index, frame.Sandboxed, m_DebugInfo);
458 ExpressionResult vfuncres = m_FName->Evaluate(frame);
459 CHECK_RESULT(vfuncres);
461 vfunc = vfuncres.GetValue();
464 if (vfunc.IsObjectType<Type>()) {
465 std::vector<Value> arguments;
466 arguments.reserve(m_Args.size());
467 for (const auto& arg : m_Args) {
468 ExpressionResult argres = arg->Evaluate(frame);
469 CHECK_RESULT(argres);
471 arguments.push_back(argres.GetValue());
474 return VMOps::ConstructorCall(vfunc, arguments, m_DebugInfo);
477 if (!vfunc.IsObjectType<Function>())
478 BOOST_THROW_EXCEPTION(ScriptError("Argument is not a callable object.", m_DebugInfo));
480 Function::Ptr func = vfunc;
482 if (!func->IsSideEffectFree() && frame.Sandboxed)
483 BOOST_THROW_EXCEPTION(ScriptError("Function is not marked as safe for sandbox mode.", m_DebugInfo));
485 std::vector<Value> arguments;
486 arguments.reserve(m_Args.size());
487 for (const auto& arg : m_Args) {
488 ExpressionResult argres = arg->Evaluate(frame);
489 CHECK_RESULT(argres);
491 arguments.push_back(argres.GetValue());
494 return VMOps::FunctionCall(frame, self, func, arguments);
497 ExpressionResult ArrayExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
500 result.reserve(m_Expressions.size());
502 for (const auto& aexpr : m_Expressions) {
503 ExpressionResult element = aexpr->Evaluate(frame);
504 CHECK_RESULT(element);
506 result.push_back(element.GetValue());
509 return new Array(std::move(result));
512 ExpressionResult DictExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
518 frame.Self = new Dictionary();
524 for (const auto& aexpr : m_Expressions) {
525 ExpressionResult element = aexpr->Evaluate(frame, m_Inline ? dhint : nullptr);
526 CHECK_RESULT(element);
527 result = element.GetValue();
531 std::swap(self, frame.Self);
538 std::swap(self, frame.Self);
543 ExpressionResult GetScopeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
545 if (m_ScopeSpec == ScopeLocal)
547 else if (m_ScopeSpec == ScopeThis)
549 else if (m_ScopeSpec == ScopeGlobal)
550 return ScriptGlobal::GetGlobals();
552 VERIFY(!"Invalid scope.");
555 ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
558 BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo));
560 DebugHint *psdhint = dhint;
565 if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint))
566 BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo));
568 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
569 CHECK_RESULT(operand2);
571 if (m_Op != OpSetLiteral) {
572 Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo);
576 operand2 = object + operand2;
579 operand2 = object - operand2;
582 operand2 = object * operand2;
585 operand2 = object / operand2;
588 operand2 = object % operand2;
591 operand2 = object ^ operand2;
594 operand2 = object & operand2;
597 operand2 = object | operand2;
600 VERIFY(!"Invalid opcode.");
604 VMOps::SetField(parent, index, operand2.GetValue(), m_OverrideFrozen, m_DebugInfo);
607 psdhint->AddMessage("=", m_DebugInfo);
609 if (psdhint != dhint)
616 void SetExpression::SetOverrideFrozen()
618 m_OverrideFrozen = true;
621 ExpressionResult SetConstExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
623 auto globals = ScriptGlobal::GetGlobals();
625 auto attr = globals->GetAttribute(m_Name);
627 if (dynamic_pointer_cast<ConstEmbeddedNamespaceValue>(attr)) {
628 std::ostringstream msgbuf;
629 msgbuf << "Value for constant '" << m_Name << "' was modified. This behaviour is deprecated.\n";
630 ShowCodeLocation(msgbuf, GetDebugInfo(), false);
631 Log(LogWarning, msgbuf.str());
634 ExpressionResult operandres = m_Operand->Evaluate(frame);
635 CHECK_RESULT(operandres);
636 Value operand = operandres.GetValue();
638 globals->SetAttribute(m_Name, std::make_shared<ConstEmbeddedNamespaceValue>(operand));
643 ExpressionResult ConditionalExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
645 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
646 CHECK_RESULT(condition);
648 if (condition.GetValue().ToBool())
649 return m_TrueBranch->Evaluate(frame, dhint);
650 else if (m_FalseBranch)
651 return m_FalseBranch->Evaluate(frame, dhint);
656 ExpressionResult WhileExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
659 BOOST_THROW_EXCEPTION(ScriptError("While loops are not allowed in sandbox mode.", m_DebugInfo));
662 ExpressionResult condition = m_Condition->Evaluate(frame, dhint);
663 CHECK_RESULT(condition);
665 if (!condition.GetValue().ToBool())
668 ExpressionResult loop_body = m_LoopBody->Evaluate(frame, dhint);
669 CHECK_RESULT_LOOP(loop_body);
675 ExpressionResult ReturnExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
677 ExpressionResult operand = m_Operand->Evaluate(frame);
678 CHECK_RESULT(operand);
680 return ExpressionResult(operand.GetValue(), ResultReturn);
683 ExpressionResult BreakExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
685 return ExpressionResult(Empty, ResultBreak);
688 ExpressionResult ContinueExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
690 return ExpressionResult(Empty, ResultContinue);
693 ExpressionResult IndexerExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
695 ExpressionResult operand1 = m_Operand1->Evaluate(frame, dhint);
696 CHECK_RESULT(operand1);
698 ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint);
699 CHECK_RESULT(operand2);
701 return VMOps::GetField(operand1.GetValue(), operand2.GetValue(), frame.Sandboxed, m_DebugInfo);
704 bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const
708 DebugHint *psdhint = nullptr;
709 bool free_psd = false;
717 if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) {
720 bool has_field = true;
722 if (vparent.IsObject()) {
723 Object::Ptr oparent = vparent;
724 has_field = oparent->HasOwnField(vindex);
728 old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo());
730 if (old_value.IsEmpty() && !old_value.IsString())
731 VMOps::SetField(vparent, vindex, new Dictionary(), m_OverrideFrozen, m_Operand1->GetDebugInfo());
734 *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo);
737 ExpressionResult operand1 = m_Operand1->Evaluate(frame);
738 *parent = operand1.GetValue();
741 ExpressionResult operand2 = m_Operand2->Evaluate(frame);
742 *index = operand2.GetValue();
746 *dhint = new DebugHint(psdhint->GetChild(*index));
757 void IndexerExpression::SetOverrideFrozen()
759 m_OverrideFrozen = true;
762 void icinga::BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec)
764 auto *dexpr = dynamic_cast<DictExpression *>(expr.get());
767 for (auto& expr : dexpr->m_Expressions)
768 BindToScope(expr, scopeSpec);
773 auto *aexpr = dynamic_cast<SetExpression *>(expr.get());
776 BindToScope(aexpr->m_Operand1, scopeSpec);
781 auto *iexpr = dynamic_cast<IndexerExpression *>(expr.get());
784 BindToScope(iexpr->m_Operand1, scopeSpec);
788 auto *lexpr = dynamic_cast<LiteralExpression *>(expr.get());
790 if (lexpr && lexpr->GetValue().IsString()) {
791 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
792 expr.reset(new IndexerExpression(std::move(scope), std::move(expr), lexpr->GetDebugInfo()));
795 auto *vexpr = dynamic_cast<VariableExpression *>(expr.get());
798 std::unique_ptr<Expression> scope{new GetScopeExpression(scopeSpec)};
799 expr.reset(new IndexerExpression(std::move(scope), MakeLiteral(vexpr->GetVariable()), vexpr->GetDebugInfo()));
803 ExpressionResult ThrowExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
805 ExpressionResult messageres = m_Message->Evaluate(frame);
806 CHECK_RESULT(messageres);
807 Value message = messageres.GetValue();
808 BOOST_THROW_EXCEPTION(ScriptError(message, m_DebugInfo, m_IncompleteExpr));
811 ExpressionResult ImportExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
814 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
816 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
817 ExpressionResult nameres = m_Name->Evaluate(frame);
818 CHECK_RESULT(nameres);
819 Value name = nameres.GetValue();
821 if (!name.IsString())
822 BOOST_THROW_EXCEPTION(ScriptError("Template/object name must be a string", m_DebugInfo));
824 ConfigItem::Ptr item = ConfigItem::GetByTypeAndName(Type::GetByName(type), name);
827 BOOST_THROW_EXCEPTION(ScriptError("Import references unknown template: '" + name + "'", m_DebugInfo));
829 Dictionary::Ptr scope = item->GetScope();
832 scope->CopyTo(frame.Locals);
834 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
835 CHECK_RESULT(result);
840 ExpressionResult ImportDefaultTemplatesExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
843 BOOST_THROW_EXCEPTION(ScriptError("Imports are not allowed in sandbox mode.", m_DebugInfo));
845 String type = VMOps::GetField(frame.Self, "type", frame.Sandboxed, m_DebugInfo);
846 Type::Ptr ptype = Type::GetByName(type);
848 for (const ConfigItem::Ptr& item : ConfigItem::GetDefaultTemplates(ptype)) {
849 Dictionary::Ptr scope = item->GetScope();
852 scope->CopyTo(frame.Locals);
854 ExpressionResult result = item->GetExpression()->Evaluate(frame, dhint);
855 CHECK_RESULT(result);
861 ExpressionResult FunctionExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
863 return VMOps::NewFunction(frame, m_Name, m_Args, m_ClosedVars, m_Expression);
866 ExpressionResult ApplyExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
869 BOOST_THROW_EXCEPTION(ScriptError("Apply rules are not allowed in sandbox mode.", m_DebugInfo));
871 ExpressionResult nameres = m_Name->Evaluate(frame);
872 CHECK_RESULT(nameres);
874 return VMOps::NewApply(frame, m_Type, m_Target, nameres.GetValue(), m_Filter,
875 m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
878 ExpressionResult NamespaceExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
880 Namespace::Ptr ns = new Namespace(new ConstNamespaceBehavior());
882 ScriptFrame innerFrame(true, ns);
883 ExpressionResult result = m_Expression->Evaluate(innerFrame);
884 CHECK_RESULT(result);
889 ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
892 BOOST_THROW_EXCEPTION(ScriptError("Object definitions are not allowed in sandbox mode.", m_DebugInfo));
894 ExpressionResult typeres = m_Type->Evaluate(frame, dhint);
895 CHECK_RESULT(typeres);
896 Type::Ptr type = typeres.GetValue();
901 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
902 CHECK_RESULT(nameres);
904 name = nameres.GetValue();
907 return VMOps::NewObject(frame, m_Abstract, type, name, m_Filter, m_Zone,
908 m_Package, m_DefaultTmpl, m_IgnoreOnError, m_ClosedVars, m_Expression, m_DebugInfo);
911 ExpressionResult ForExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
914 BOOST_THROW_EXCEPTION(ScriptError("For loops are not allowed in sandbox mode.", m_DebugInfo));
916 ExpressionResult valueres = m_Value->Evaluate(frame, dhint);
917 CHECK_RESULT(valueres);
919 return VMOps::For(frame, m_FKVar, m_FVVar, valueres.GetValue(), m_Expression, m_DebugInfo);
922 ExpressionResult LibraryExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
925 BOOST_THROW_EXCEPTION(ScriptError("Loading libraries is not allowed in sandbox mode.", m_DebugInfo));
927 ExpressionResult libres = m_Operand->Evaluate(frame, dhint);
928 CHECK_RESULT(libres);
930 Log(LogNotice, "config")
931 << "Ignoring explicit load request for library \"" << libres << "\".";
936 ExpressionResult IncludeExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
939 BOOST_THROW_EXCEPTION(ScriptError("Includes are not allowed in sandbox mode.", m_DebugInfo));
941 std::unique_ptr<Expression> expr;
942 String name, path, pattern;
947 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
948 CHECK_RESULT(pathres);
949 path = pathres.GetValue();
952 expr = ConfigCompiler::HandleInclude(m_RelativeBase, path, m_SearchIncludes, m_Zone, m_Package, m_DebugInfo);
955 case IncludeRecursive:
957 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
958 CHECK_RESULT(pathres);
959 path = pathres.GetValue();
963 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
964 CHECK_RESULT(patternres);
965 pattern = patternres.GetValue();
968 expr = ConfigCompiler::HandleIncludeRecursive(m_RelativeBase, path, pattern, m_Zone, m_Package, m_DebugInfo);
973 ExpressionResult nameres = m_Name->Evaluate(frame, dhint);
974 CHECK_RESULT(nameres);
975 name = nameres.GetValue();
979 ExpressionResult pathres = m_Path->Evaluate(frame, dhint);
980 CHECK_RESULT(pathres);
981 path = pathres.GetValue();
985 ExpressionResult patternres = m_Pattern->Evaluate(frame, dhint);
986 CHECK_RESULT(patternres);
987 pattern = patternres.GetValue();
990 expr = ConfigCompiler::HandleIncludeZones(m_RelativeBase, name, path, pattern, m_Package, m_DebugInfo);
994 ExpressionResult res(Empty);
997 res = expr->Evaluate(frame, dhint);
998 } catch (const std::exception&) {
1005 ExpressionResult BreakpointExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1007 ScriptBreakpoint(frame, nullptr, GetDebugInfo());
1012 ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
1015 ExpressionResult tryResult = m_TryBody->Evaluate(frame, dhint);
1016 CHECK_RESULT(tryResult);
1017 } catch (const std::exception&) {
1018 ExpressionResult exceptResult = m_ExceptBody->Evaluate(frame, dhint);
1019 CHECK_RESULT(exceptResult);