ExpressionResult SetExpression::DoEvaluate(ScriptFrame& frame, DebugHint *dhint) const { if (frame.Sandboxed) BOOST_THROW_EXCEPTION(ScriptError("Assignments are not allowed in sandbox mode.", m_DebugInfo)); DebugHint *psdhint = dhint; Value parent; String index; if (!m_Operand1->GetReference(frame, true, &parent, &index, &psdhint)) BOOST_THROW_EXCEPTION(ScriptError("Expression cannot be assigned to.", m_DebugInfo)); ExpressionResult operand2 = m_Operand2->Evaluate(frame, dhint); CHECK_RESULT(operand2); if (m_Op != OpSetLiteral) { Value object = VMOps::GetField(parent, index, frame.Sandboxed, m_DebugInfo); switch (m_Op) { case OpSetAdd: operand2 = object + operand2; break; case OpSetSubtract: operand2 = object - operand2; break; case OpSetMultiply: operand2 = object * operand2; break; case OpSetDivide: operand2 = object / operand2; break; case OpSetModulo: operand2 = object % operand2; break; case OpSetXor: operand2 = object ^ operand2; break; case OpSetBinaryAnd: operand2 = object & operand2; break; case OpSetBinaryOr: operand2 = object | operand2; break; default: VERIFY(!"Invalid opcode."); } } VMOps::SetField(parent, index, operand2.GetValue(), m_DebugInfo); if (psdhint) { psdhint->AddMessage("=", m_DebugInfo); if (psdhint != dhint) delete psdhint; } return Empty; }
bool IndexerExpression::GetReference(ScriptFrame& frame, bool init_dict, Value *parent, String *index, DebugHint **dhint) const { Value vparent; String vindex; DebugHint *psdhint = NULL; bool free_psd = false; if (dhint) psdhint = *dhint; if (frame.Sandboxed) init_dict = false; if (m_Operand1->GetReference(frame, init_dict, &vparent, &vindex, &psdhint)) { if (init_dict) { Value old_value = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_Operand1->GetDebugInfo()); if (old_value.IsEmpty() && !old_value.IsString()) VMOps::SetField(vparent, vindex, new Dictionary(), m_Operand1->GetDebugInfo()); } *parent = VMOps::GetField(vparent, vindex, frame.Sandboxed, m_DebugInfo); free_psd = true; } else { ExpressionResult operand1 = m_Operand1->Evaluate(frame); *parent = operand1.GetValue(); } ExpressionResult operand2 = m_Operand2->Evaluate(frame); *index = operand2.GetValue(); if (dhint) { if (psdhint) *dhint = new DebugHint(psdhint->GetChild(*index)); else *dhint = NULL; } if (free_psd) delete psdhint; return true; }
/** * Commits the configuration item by creating a ConfigObject * object. * * @returns The ConfigObject that was created/updated. */ ConfigObject::Ptr ConfigItem::Commit(bool discard) { #ifdef I2_DEBUG Log(LogDebug, "ConfigItem") << "Commit called for ConfigItem Type=" << GetType() << ", Name=" << GetName(); #endif /* I2_DEBUG */ /* Make sure the type is valid. */ Type::Ptr type = Type::GetByName(GetType()); ASSERT(type && ConfigObject::TypeInstance->IsAssignableFrom(type)); if (IsAbstract()) return ConfigObject::Ptr(); ConfigObject::Ptr dobj = static_pointer_cast<ConfigObject>(type->Instantiate()); dobj->SetDebugInfo(m_DebugInfo); dobj->SetZoneName(m_Zone); dobj->SetPackage(m_Package); dobj->SetName(m_Name); DebugHint debugHints; ScriptFrame frame(dobj); if (m_Scope) m_Scope->CopyTo(frame.Locals); try { m_Expression->Evaluate(frame, &debugHints); } catch (const std::exception& ex) { if (m_IgnoreOnError) { Log(LogWarning, "ConfigObject") << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex); return ConfigObject::Ptr(); } throw; } if (discard) m_Expression.reset(); String item_name; String short_name = dobj->GetShortName(); if (!short_name.IsEmpty()) { item_name = short_name; dobj->SetName(short_name); } else item_name = m_Name; String name = item_name; NameComposer *nc = dynamic_cast<NameComposer *>(type.get()); if (nc) { name = nc->MakeName(name, dobj); if (name.IsEmpty()) BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object")); } if (name != item_name) dobj->SetShortName(item_name); dobj->SetName(name); try { dobj->OnConfigLoaded(); } catch (const std::exception& ex) { if (m_IgnoreOnError) { Log(LogWarning, "ConfigObject") << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex); return ConfigObject::Ptr(); } throw; } Dictionary::Ptr persistentItem = new Dictionary(); persistentItem->Set("type", GetType()); persistentItem->Set("name", GetName()); persistentItem->Set("properties", Serialize(dobj, FAConfig)); Dictionary::Ptr dhint = debugHints.ToDictionary(); persistentItem->Set("debug_hints", dhint); Array::Ptr di = new Array(); di->Add(m_DebugInfo.Path); di->Add(m_DebugInfo.FirstLine); di->Add(m_DebugInfo.FirstColumn); di->Add(m_DebugInfo.LastLine); di->Add(m_DebugInfo.LastColumn); persistentItem->Set("debug_info", di); try { DefaultValidationUtils utils; dobj->Validate(FAConfig, utils); } catch (ValidationError& ex) { if (m_IgnoreOnError) { Log(LogWarning, "ConfigObject") << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex); return ConfigObject::Ptr(); } ex.SetDebugHint(dhint); throw; } ConfigCompilerContext::GetInstance()->WriteObject(persistentItem); persistentItem.reset(); dhint.reset(); dobj->Register(); m_Object = dobj; return dobj; }
/** * Commits the configuration item by creating a DynamicObject * object. * * @returns The DynamicObject that was created/updated. */ DynamicObject::Ptr ConfigItem::Commit(bool discard) { ASSERT(!OwnsLock()); #ifdef _DEBUG Log(LogDebug, "ConfigItem") << "Commit called for ConfigItem Type=" << GetType() << ", Name=" << GetName(); #endif /* _DEBUG */ /* Make sure the type is valid. */ Type::Ptr type = Type::GetByName(GetType()); ASSERT(type && Type::GetByName("DynamicObject")->IsAssignableFrom(type)); if (IsAbstract()) return DynamicObject::Ptr(); DynamicObject::Ptr dobj = static_pointer_cast<DynamicObject>(type->Instantiate()); dobj->SetDebugInfo(m_DebugInfo); dobj->SetTypeName(m_Type); dobj->SetZone(m_Zone); Dictionary::Ptr locals = new Dictionary(); locals->Set("__parent", m_Scope); m_Scope.reset(); dobj->SetParentScope(locals); locals.reset(); dobj->SetName(m_Name); DebugHint debugHints; try { m_Expression->Evaluate(dobj, &debugHints); } catch (const ConfigError& ex) { const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex); ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } catch (const std::exception& ex) { ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex)); } if (discard) m_Expression.reset(); dobj->SetParentScope(Object::Ptr()); String name = m_Name; NameComposer *nc = dynamic_cast<NameComposer *>(type.get()); if (nc) { name = nc->MakeName(m_Name, dobj); if (name.IsEmpty()) BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object")); } if (name != m_Name) dobj->SetShortName(m_Name); dobj->SetName(name); Dictionary::Ptr attrs = Serialize(dobj, FAConfig); Dictionary::Ptr persistentItem = new Dictionary(); persistentItem->Set("type", GetType()); persistentItem->Set("name", GetName()); persistentItem->Set("properties", attrs); persistentItem->Set("debug_hints", debugHints.ToDictionary()); ConfigCompilerContext::GetInstance()->WriteObject(persistentItem); persistentItem.reset(); ConfigType::Ptr ctype = ConfigType::GetByName(GetType()); if (!ctype) ConfigCompilerContext::GetInstance()->AddMessage(false, "No validation type found for object '" + GetName() + "' of type '" + GetType() + "'"); else { TypeRuleUtilities utils; try { attrs->Remove("name"); ctype->ValidateItem(GetName(), attrs, GetDebugInfo(), &utils); } catch (const ConfigError& ex) { const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex); ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo()); } catch (const std::exception& ex) { ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex)); } } dobj->Register(); m_Object = dobj; return dobj; }