keywords.emplace_back("globals");
keywords.emplace_back("locals");
keywords.emplace_back("use");
- keywords.emplace_back("__using");
+ keywords.emplace_back("using");
+ keywords.emplace_back("namespace");
keywords.emplace_back("default");
keywords.emplace_back("ignore_on_error");
keywords.emplace_back("current_filename");
#include "base/scriptframe.hpp"
#include "base/scriptglobal.hpp"
+#include "base/namespace.hpp"
#include "base/exception.hpp"
using namespace icinga;
boost::thread_specific_ptr<std::stack<ScriptFrame *> > ScriptFrame::m_ScriptFrames;
-Array::Ptr ScriptFrame::m_Imports;
+
+static auto l_InternalNSBehavior = new ConstNamespaceBehavior();
INITIALIZE_ONCE_WITH_PRIORITY([]() {
- Dictionary::Ptr systemNS = new Dictionary();
- ScriptGlobal::Set("System", systemNS);
- ScriptFrame::AddImport(systemNS);
+ Namespace::Ptr globalNS = ScriptGlobal::GetGlobals();
+
+ auto systemNSBehavior = new ConstNamespaceBehavior();
+ systemNSBehavior->Freeze();
+ Namespace::Ptr systemNS = new Namespace(systemNSBehavior);
+ globalNS->SetAttribute("System", std::make_shared<ConstEmbeddedNamespaceValue>(systemNS));
- Dictionary::Ptr typesNS = new Dictionary();
- ScriptGlobal::Set("Types", typesNS);
- ScriptFrame::AddImport(typesNS);
+ auto typesNSBehavior = new ConstNamespaceBehavior();
+ typesNSBehavior->Freeze();
+ Namespace::Ptr typesNS = new Namespace(typesNSBehavior);
+ globalNS->SetAttribute("Types", std::make_shared<ConstEmbeddedNamespaceValue>(typesNS));
- Dictionary::Ptr deprecatedNS = new Dictionary();
- ScriptGlobal::Set("Deprecated", deprecatedNS);
- ScriptFrame::AddImport(deprecatedNS);
+ auto statsNSBehavior = new ConstNamespaceBehavior();
+ statsNSBehavior->Freeze();
+ Namespace::Ptr statsNS = new Namespace(statsNSBehavior);
+ globalNS->SetAttribute("StatsFunctions", std::make_shared<ConstEmbeddedNamespaceValue>(statsNS));
+
+ Namespace::Ptr internalNS = new Namespace(l_InternalNSBehavior);
+ globalNS->SetAttribute("Internal", std::make_shared<ConstEmbeddedNamespaceValue>(internalNS));
}, 50);
+INITIALIZE_ONCE_WITH_PRIORITY([]() {
+ l_InternalNSBehavior->Freeze();
+}, 0);
+
ScriptFrame::ScriptFrame(bool allocLocals)
: Locals(allocLocals ? new Dictionary() : nullptr), Self(ScriptGlobal::GetGlobals()), Sandboxed(false), Depth(0)
{
frames->push(frame);
}
-
-Array::Ptr ScriptFrame::GetImports()
-{
- return m_Imports;
-}
-
-void ScriptFrame::AddImport(const Object::Ptr& import)
-{
- Array::Ptr imports;
-
- if (!m_Imports)
- imports = new Array();
- else
- imports = m_Imports->ShallowClone();
-
- imports->Add(import);
-
- m_Imports = imports;
-}
-
static ScriptFrame *GetCurrentFrame();
- static Array::Ptr GetImports();
- static void AddImport(const Object::Ptr& import);
-
private:
static boost::thread_specific_ptr<std::stack<ScriptFrame *> > m_ScriptFrames;
- static Array::Ptr m_Imports;
static void PushFrame(ScriptFrame *frame);
static ScriptFrame *PopFrame();
globals return T_GLOBALS;
locals return T_LOCALS;
use return T_USE;
-__using return T_USING;
+using return T_USING;
apply return T_APPLY;
default return T_DEFAULT;
to return T_TO;
current_filename return T_CURRENT_FILENAME;
current_line return T_CURRENT_LINE;
debugger return T_DEBUGGER;
+namespace return T_NAMESPACE;
=\> return T_FOLLOWS;
\<\< return T_SHIFT_LEFT;
\>\> return T_SHIFT_RIGHT;
%token T_CURRENT_FILENAME "current_filename (T_CURRENT_FILENAME)"
%token T_CURRENT_LINE "current_line (T_CURRENT_LINE)"
%token T_DEBUGGER "debugger (T_DEBUGGER)"
+%token T_NAMESPACE "namespace (T_NAMESPACE)"
%token T_USE "use (T_USE)"
-%token T_USING "__using (T_USING)"
+%token T_USING "using (T_USING)"
%token T_OBJECT "object (T_OBJECT)"
%token T_TEMPLATE "template (T_TEMPLATE)"
%token T_INCLUDE "include (T_INCLUDE)"
{
$$ = new BreakpointExpression(@$);
}
+ | T_NAMESPACE rterm
+ {
+ BeginFlowControlBlock(context, FlowControlReturn, false);
+ }
+ rterm_scope_require_side_effect
+ {
+ EndFlowControlBlock(context);
+
+ std::unique_ptr<Expression> expr{$2};
+ BindToScope(expr, ScopeGlobal);
+ $$ = new SetExpression(std::move(expr), OpSetLiteral, std::unique_ptr<Expression>(new NamespaceExpression(std::unique_ptr<Expression>($4), @$)), @$);
+ }
| T_USING rterm
{
- $$ = new UsingExpression(std::unique_ptr<Expression>($2), @$);
+ std::shared_ptr<Expression> expr{$2};
+ context->AddImport(expr);
+ $$ = MakeLiteralRaw();
}
| apply
| object
}
| T_IDENTIFIER
{
- $$ = new VariableExpression(*$1, @1);
+ $$ = new VariableExpression(*$1, context->GetImports(), @1);
delete $1;
}
| T_MULTIPLY rterm %prec DEREF_OP
use_specifier_item: identifier
{
- $$ = new std::pair<String, std::unique_ptr<Expression> >(*$1, std::unique_ptr<Expression>(new VariableExpression(*$1, @1)));
+ $$ = new std::pair<String, std::unique_ptr<Expression> >(*$1, std::unique_ptr<Expression>(new VariableExpression(*$1, context->GetImports(), @1)));
delete $1;
}
| identifier T_SET rterm
#endif /* _WIN32 */
}
+void ConfigCompiler::AddImport(const std::shared_ptr<Expression>& import)
+{
+ m_Imports.push_back(import);
+}
+
+std::vector<std::shared_ptr<Expression> > ConfigCompiler::GetImports() const
+{
+ return m_Imports;
+}
void SetPackage(const String& package);
String GetPackage() const;
+ void AddImport(const std::shared_ptr<Expression>& import);
+ std::vector<std::shared_ptr<Expression> > GetImports() const;
+
static void CollectIncludes(std::vector<std::unique_ptr<Expression> >& expressions,
const String& file, const String& zone, const String& package);
std::istream *m_Input;
String m_Zone;
String m_Package;
+ std::vector<std::shared_ptr<Expression> > m_Imports;
void *m_Scanner;
return m_DebugInfo;
}
+VariableExpression::VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo)
+ : DebuggableExpression(debugInfo), m_Variable(std::move(variable)), m_Imports(std::move(imports))
+{
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "System"));
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "Types"));
+ m_Imports.push_back(MakeIndexer(ScopeGlobal, "Icinga"));
+}
+
ExpressionResult VariableExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
Value value;
return value;
else if (frame.Self.IsObject() && frame.Locals != frame.Self.Get<Object::Ptr>() && frame.Self.Get<Object::Ptr>()->GetOwnField(m_Variable, &value))
return value;
- else if (VMOps::FindVarImport(frame, m_Variable, &value, m_DebugInfo))
+ else if (VMOps::FindVarImport(frame, m_Imports, m_Variable, &value, m_DebugInfo))
return value;
else
return ScriptGlobal::Get(m_Variable);
if (dhint && *dhint)
*dhint = new DebugHint((*dhint)->GetChild(m_Variable));
- } else if (VMOps::FindVarImportRef(frame, m_Variable, parent, m_DebugInfo)) {
+ } else if (VMOps::FindVarImportRef(frame, m_Imports, m_Variable, parent, m_DebugInfo)) {
return true;
} else if (ScriptGlobal::Exists(m_Variable)) {
*parent = ScriptGlobal::GetGlobals();
m_Package, m_FKVar, m_FVVar, m_FTerm, m_ClosedVars, m_IgnoreOnError, m_Expression, m_DebugInfo);
}
+ExpressionResult NamespaceExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
+{
+ Namespace::Ptr ns = new Namespace(new ConstNamespaceBehavior());
+
+ ScriptFrame innerFrame(true, ns);
+ ExpressionResult result = m_Expression->Evaluate(innerFrame);
+ CHECK_RESULT(result);
+
+ return ns;
+}
+
ExpressionResult ObjectExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
if (frame.Sandboxed)
return Empty;
}
-ExpressionResult UsingExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
-{
- if (frame.Sandboxed)
- BOOST_THROW_EXCEPTION(ScriptError("Using directives are not allowed in sandbox mode.", m_DebugInfo));
-
- ExpressionResult importres = m_Name->Evaluate(frame);
- CHECK_RESULT(importres);
- Value import = importres.GetValue();
-
- if (!import.IsObjectType<Dictionary>())
- BOOST_THROW_EXCEPTION(ScriptError("The parameter must resolve to an object of type 'Dictionary'", m_DebugInfo));
-
- ScriptFrame::AddImport(import);
-
- return Empty;
-}
-
ExpressionResult TryExceptExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const
{
try {
class VariableExpression final : public DebuggableExpression
{
public:
- VariableExpression(String variable, const DebugInfo& debugInfo = DebugInfo())
- : DebuggableExpression(debugInfo), m_Variable(std::move(variable))
- { }
+ VariableExpression(String variable, std::vector<std::shared_ptr<Expression> > imports, const DebugInfo& debugInfo = DebugInfo());
String GetVariable() const
{
private:
String m_Variable;
+ std::vector<std::shared_ptr<Expression> > m_Imports;
friend void BindToScope(std::unique_ptr<Expression>& expr, ScopeSpecifier scopeSpec);
};
std::shared_ptr<Expression> m_Expression;
};
+class NamespaceExpression final : public DebuggableExpression
+{
+public:
+ NamespaceExpression(std::unique_ptr<Expression> expression, const DebugInfo& debugInfo = DebugInfo())
+ : DebuggableExpression(debugInfo), m_Expression(std::move(expression))
+ { }
+
+protected:
+ ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
+
+private:
+ std::shared_ptr<Expression> m_Expression;
+};
+
class ObjectExpression final : public DebuggableExpression
{
public:
ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
};
-class UsingExpression final : public DebuggableExpression
-{
-public:
- UsingExpression(std::unique_ptr<Expression> name, const DebugInfo& debugInfo = DebugInfo())
- : DebuggableExpression(debugInfo), m_Name(std::move(name))
- { }
-
-protected:
- ExpressionResult DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const override;
-
-private:
- std::unique_ptr<Expression> m_Name;
-};
-
class TryExceptExpression final : public DebuggableExpression
{
public:
class VMOps
{
public:
- static inline bool FindVarImportRef(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
+ static inline bool FindVarImportRef(ScriptFrame& frame, const std::vector<std::shared_ptr<Expression> >& imports, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
{
- Array::Ptr imports = ScriptFrame::GetImports();
-
- ObjectLock olock(imports);
- for (const Value& import : imports) {
- Object::Ptr obj = import;
+ for (const auto& import : imports) {
+ ExpressionResult res = import->Evaluate(frame);
+ Object::Ptr obj = res.GetValue();
if (obj->HasOwnField(name)) {
- *result = import;
+ *result = obj;
return true;
}
}
return false;
}
- static inline bool FindVarImport(ScriptFrame& frame, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
+ static inline bool FindVarImport(ScriptFrame& frame, const std::vector<std::shared_ptr<Expression> >& imports, const String& name, Value *result, const DebugInfo& debugInfo = DebugInfo())
{
Value parent;
- if (FindVarImportRef(frame, name, &parent, debugInfo)) {
+ if (FindVarImportRef(frame, imports, name, &parent, debugInfo)) {
*result = GetField(parent, name, frame.Sandboxed, debugInfo);
return true;
}
}
}
- {
- Array::Ptr imports = ScriptFrame::GetImports();
- ObjectLock olock(imports);
- for (const Value& import : imports) {
- AddSuggestions(matches, word, "", false, import);
- }
- }
+ AddSuggestions(matches, word, "", false, ScriptGlobal::Get("System"));
+ AddSuggestions(matches, word, "", false, ScriptGlobal::Get("Types"));
+ AddSuggestions(matches, word, "", false, ScriptGlobal::Get("Icinga"));
String::SizeType cperiod = word.RFind(".");