mirror of https://github.com/Icinga/icinga2.git
parent
14c94fabde
commit
d366dd8e30
|
@ -181,6 +181,7 @@ static void MakeRBinaryOp(Expression** result, Expression *left, Expression *rig
|
|||
%type <csop> combined_set_op
|
||||
%type <type> type
|
||||
%type <expr> rterm
|
||||
%type <expr> rterm_without_indexer
|
||||
%type <expr> rterm_array
|
||||
%type <expr> rterm_scope
|
||||
%type <expr> lterm
|
||||
|
@ -505,17 +506,10 @@ identifier_items_inner: /* empty */
|
|||
}
|
||||
;
|
||||
|
||||
indexer: identifier
|
||||
{
|
||||
$$ = new std::vector<Expression *>();
|
||||
$$->push_back(MakeLiteral($1));
|
||||
free($1);
|
||||
}
|
||||
| identifier indexer_items
|
||||
indexer: rterm_without_indexer indexer_items
|
||||
{
|
||||
$$ = $2;
|
||||
$$->insert($$->begin(), MakeLiteral($1));
|
||||
free($1);
|
||||
$$->insert($$->begin(), $1);
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -591,6 +585,16 @@ lterm: T_LOCAL indexer combined_set_op rterm
|
|||
$$ = new SetExpression(*$1, $2, $3, false, DebugInfoRange(@1, @3));
|
||||
delete $1;
|
||||
}
|
||||
| T_LOCAL identifier combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression(MakeIndexer($2), $3, $4, true, DebugInfoRange(@1, @4));
|
||||
free($2);
|
||||
}
|
||||
| identifier combined_set_op rterm
|
||||
{
|
||||
$$ = new SetExpression(MakeIndexer($1), $2, $3, false, DebugInfoRange(@1, @3));
|
||||
free($1);
|
||||
}
|
||||
| T_INCLUDE rterm
|
||||
{
|
||||
VMFrame frame;
|
||||
|
@ -735,7 +739,18 @@ rterm_scope: '{' newlines lterm_items newlines '}'
|
|||
}
|
||||
;
|
||||
|
||||
rterm: T_STRING
|
||||
rterm: rterm_without_indexer
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| indexer
|
||||
{
|
||||
$$ = new IndexerExpression(*$1, @1);
|
||||
delete $1;
|
||||
}
|
||||
;
|
||||
|
||||
rterm_without_indexer: T_STRING
|
||||
{
|
||||
$$ = MakeLiteral($1);
|
||||
free($1);
|
||||
|
@ -748,11 +763,6 @@ rterm: T_STRING
|
|||
{
|
||||
$$ = MakeLiteral();
|
||||
}
|
||||
| rterm '.' T_IDENTIFIER
|
||||
{
|
||||
$$ = new IndexerExpression($1, MakeLiteral($3), DebugInfoRange(@1, @3));
|
||||
free($3);
|
||||
}
|
||||
| rterm '(' rterm_items ')'
|
||||
{
|
||||
$$ = new FunctionCallExpression($1, *$3, DebugInfoRange(@1, @4));
|
||||
|
@ -771,10 +781,6 @@ rterm: T_STRING
|
|||
{
|
||||
$$ = new NegateExpression($2, DebugInfoRange(@1, @2));
|
||||
}
|
||||
| rterm '[' rterm ']'
|
||||
{
|
||||
$$ = new IndexerExpression($1, $3, DebugInfoRange(@1, @4));
|
||||
}
|
||||
| rterm_array
|
||||
{
|
||||
$$ = $1;
|
||||
|
|
|
@ -100,10 +100,7 @@ ConfigItem::Ptr ConfigItemBuilder::Compile(void)
|
|||
Array::Ptr templateArray = new Array();
|
||||
templateArray->Add(m_Name);
|
||||
|
||||
std::vector<Expression *> indexer;
|
||||
indexer.push_back(new LiteralExpression("templates"));
|
||||
|
||||
exprs.push_back(new SetExpression(indexer, OpSetAdd,
|
||||
exprs.push_back(new SetExpression(MakeIndexer("templates"), OpSetAdd,
|
||||
new LiteralExpression(templateArray), false, m_DebugInfo));
|
||||
|
||||
DictExpression *dexpr = new DictExpression(m_Expressions, m_DebugInfo);
|
||||
|
|
|
@ -64,7 +64,7 @@ const DebugInfo& Expression::GetDebugInfo(void) const
|
|||
std::vector<Expression *> icinga::MakeIndexer(const String& index1)
|
||||
{
|
||||
std::vector<Expression *> result;
|
||||
result.push_back(MakeLiteral(index1));
|
||||
result.push_back(new VariableExpression(index1));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,20 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
|
|||
|
||||
for (Array::SizeType i = 0; i < m_Indexer.size(); i++) {
|
||||
Expression *indexExpr = m_Indexer[i];
|
||||
String tempindex = indexExpr->Evaluate(frame, dhint);
|
||||
|
||||
String tempindex;
|
||||
|
||||
if (i == 0) {
|
||||
VariableExpression *vexpr = dynamic_cast<VariableExpression *>(indexExpr);
|
||||
|
||||
if (!vexpr) {
|
||||
object = indexExpr->Evaluate(frame, dhint);
|
||||
continue;
|
||||
}
|
||||
|
||||
tempindex = vexpr->GetVariable();
|
||||
} else
|
||||
tempindex = indexExpr->Evaluate(frame, dhint);
|
||||
|
||||
if (psdhint) {
|
||||
sdhint = psdhint->GetChild(tempindex);
|
||||
|
@ -290,7 +303,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
|
|||
break;
|
||||
}
|
||||
|
||||
object = VMOps::Indexer(frame, parent, tempindex);
|
||||
object = VMOps::GetField(parent, tempindex);
|
||||
|
||||
if (i != m_Indexer.size() - 1 && object.IsEmpty()) {
|
||||
object = new Dictionary();
|
||||
|
@ -333,7 +346,7 @@ Value SetExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
|
|||
|
||||
Value IndexerExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
|
||||
{
|
||||
return VMOps::Indexer(frame, m_Operand1->Evaluate(frame), m_Operand2->Evaluate(frame));
|
||||
return VMOps::Indexer(frame, m_Indexer);
|
||||
}
|
||||
|
||||
Value ImportExpression::DoEvaluate(VMFrame& frame, DebugHint *dhint) const
|
||||
|
|
|
@ -213,6 +213,11 @@ public:
|
|||
: DebuggableExpression(debugInfo), m_Variable(variable)
|
||||
{ }
|
||||
|
||||
String GetVariable(void) const
|
||||
{
|
||||
return m_Variable;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
|
||||
|
||||
|
@ -532,15 +537,18 @@ private:
|
|||
|
||||
};
|
||||
|
||||
class I2_CONFIG_API IndexerExpression : public BinaryExpression
|
||||
class I2_CONFIG_API IndexerExpression : public DebuggableExpression
|
||||
{
|
||||
public:
|
||||
IndexerExpression(Expression *operand1, Expression *operand2, const DebugInfo& debugInfo = DebugInfo())
|
||||
: BinaryExpression(operand1, operand2, debugInfo)
|
||||
IndexerExpression(const std::vector<Expression *>& indexer, const DebugInfo& debugInfo = DebugInfo())
|
||||
: DebuggableExpression(debugInfo), m_Indexer(indexer)
|
||||
{ }
|
||||
|
||||
protected:
|
||||
virtual Value DoEvaluate(VMFrame& frame, DebugHint *dhint) const;
|
||||
|
||||
private:
|
||||
std::vector<Expression *> m_Indexer;
|
||||
};
|
||||
|
||||
class I2_CONFIG_API ImportExpression : public DebuggableExpression
|
||||
|
|
|
@ -72,32 +72,19 @@ public:
|
|||
return func->Invoke(arguments);
|
||||
}
|
||||
|
||||
static inline Value Indexer(VMFrame& frame, const Value& value, const String& index)
|
||||
static inline Value Indexer(VMFrame& frame, const std::vector<Expression *>& indexer)
|
||||
{
|
||||
if (value.IsObjectType<Dictionary>()) {
|
||||
Dictionary::Ptr dict = value;
|
||||
return dict->Get(index);
|
||||
} else if (value.IsObjectType<Array>()) {
|
||||
Array::Ptr arr = value;
|
||||
return arr->Get(Convert::ToLong(index));
|
||||
} else if (value.IsObject()) {
|
||||
Object::Ptr object = value;
|
||||
Type::Ptr type = object->GetReflectionType();
|
||||
Value result = indexer[0]->Evaluate(frame);
|
||||
|
||||
if (!type)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Dot operator applied to object which does not support reflection"));
|
||||
for (int i = 1; i < indexer.size(); i++) {
|
||||
if (result.IsEmpty())
|
||||
return Empty;
|
||||
|
||||
int field = type->GetFieldId(index);
|
||||
|
||||
if (field == -1)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Tried to access invalid property '" + index + "'"));
|
||||
|
||||
return object->GetField(field);
|
||||
} else if (value.IsEmpty()) {
|
||||
return Empty;
|
||||
} else {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Dot operator cannot be applied to type '" + value.GetTypeName() + "'"));
|
||||
Value index = indexer[i]->Evaluate(frame);
|
||||
result = GetField(result, index);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline Value NewFunction(VMFrame& frame, const String& name, const std::vector<String>& args,
|
||||
|
@ -234,45 +221,62 @@ public:
|
|||
|
||||
if (dict)
|
||||
return dict->Get(field);
|
||||
else {
|
||||
Type::Ptr type = context->GetReflectionType();
|
||||
|
||||
if (!type)
|
||||
return Empty;
|
||||
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
|
||||
|
||||
int fid = type->GetFieldId(field);
|
||||
|
||||
if (fid == -1)
|
||||
return Empty;
|
||||
|
||||
return context->GetField(fid);
|
||||
if (arr) {
|
||||
int index = Convert::ToLong(field);
|
||||
return arr->Get(index);
|
||||
}
|
||||
|
||||
Type::Ptr type = context->GetReflectionType();
|
||||
|
||||
if (!type)
|
||||
return Empty;
|
||||
|
||||
int fid = type->GetFieldId(field);
|
||||
|
||||
if (fid == -1)
|
||||
return Empty;
|
||||
|
||||
return context->GetField(fid);
|
||||
}
|
||||
|
||||
static inline void SetField(const Object::Ptr& context, const String& field, const Value& value)
|
||||
{
|
||||
Dictionary::Ptr dict = dynamic_pointer_cast<Dictionary>(context);
|
||||
|
||||
if (dict)
|
||||
if (dict) {
|
||||
dict->Set(field, value);
|
||||
else {
|
||||
Type::Ptr type = context->GetReflectionType();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!type)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Cannot set field on object."));
|
||||
Array::Ptr arr = dynamic_pointer_cast<Array>(context);
|
||||
|
||||
int fid = type->GetFieldId(field);
|
||||
if (arr) {
|
||||
int index = Convert::ToLong(field);
|
||||
if (index >= arr->GetLength())
|
||||
arr->Resize(index + 1);
|
||||
arr->Set(index, value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fid == -1)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' does not exist."));
|
||||
Type::Ptr type = context->GetReflectionType();
|
||||
|
||||
try {
|
||||
context->SetField(fid, value);
|
||||
} catch (const boost::bad_lexical_cast&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
|
||||
} catch (const std::bad_cast&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
|
||||
}
|
||||
if (!type)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Cannot set field on object."));
|
||||
|
||||
int fid = type->GetFieldId(field);
|
||||
|
||||
if (fid == -1)
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' does not exist."));
|
||||
|
||||
try {
|
||||
context->SetField(fid, value);
|
||||
} catch (const boost::bad_lexical_cast&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
|
||||
} catch (const std::bad_cast&) {
|
||||
BOOST_THROW_EXCEPTION(ConfigError("Attribute '" + field + "' cannot be set to value of type '" + value.GetTypeName() + "'"));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -208,10 +208,9 @@ BOOST_AUTO_TEST_CASE(advanced)
|
|||
BOOST_CHECK(expr->Evaluate(frame) == 3);
|
||||
delete expr;
|
||||
|
||||
/* Uncomment this once #7800 is fixed
|
||||
expr = ConfigCompiler::CompileText("<test>", "local v = { a = 3}; v.a");
|
||||
BOOST_CHECK(expr->Evaluate(frame) == 3);
|
||||
delete expr;*/
|
||||
delete expr;
|
||||
|
||||
expr = ConfigCompiler::CompileText("<test>", "a = 3 b = 3");
|
||||
BOOST_CHECK(expr == NULL);
|
||||
|
|
Loading…
Reference in New Issue