📄 infer.cxx
字号:
//{{{ Banner //============================================================================//// infer.cxx//// Inference for common conflicts.////============================================================================//####COPYRIGHTBEGIN####// // ----------------------------------------------------------------------------// Copyright (C) 1999, 2000 Red Hat, Inc.//// This file is part of the eCos host tools.//// This program is free software; you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 of the License, or (at your option) // any later version.// // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for // more details.// // You should have received a copy of the GNU General Public License along with// this program; if not, write to the Free Software Foundation, Inc., // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.//// ----------------------------------------------------------------------------// //####COPYRIGHTEND####//============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): bartv// Contact(s): bartv// Date: 1999/11/1// Version: 0.01////####DESCRIPTIONEND####//============================================================================//}}}//{{{ #include's // ----------------------------------------------------------------------------#include "cdlconfig.h"// Get the infrastructure types, assertions, tracing and similar// facilities.#include <cyg/infra/cyg_ass.h>#include <cyg/infra/cyg_trac.h>// <cdlcore.hxx> defines everything implemented in this module.// It implicitly supplies <string>, <vector> and <map> because// the class definitions rely on these headers.#include <cdlcore.hxx>//}}}//{{{ Illegal value resolution // ----------------------------------------------------------------------------// This is not yet implemented.boolCdlConflict_IllegalValueBody::inner_resolve(CdlTransaction transaction, int level){ CYG_REPORT_FUNCNAMETYPE("CdlConflict_IllegalValue::inner_resolve", "result %d"); CYG_REPORT_FUNCARG3XV(this, transaction, level); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(transaction); CYG_UNUSED_PARAM(CdlTransaction, transaction); CYG_REPORT_RETVAL(false); return false;}//}}}//{{{ Requires resolution //{{{ Description // ----------------------------------------------------------------------------// The entry point for this code is// CdlConflict_RequiresBody::resolve(). "this" is a requires conflict// that needs to be resolved, if possible. There are twos argument: a// sub-transaction, which should be filled in with the solution if// possible; and a recursion level indicator, 0 if this is a top-level// inference engine invocation rather than a recursive one. There are// additional static parameters inference_recursion_limit and// inference_override which control details of the inference process.//// There are three ways in which a "requires" conflict can be// eliminated:// 1) change the terms in the expression so that the "requires" property// evaluates to true.// 2) disable the source node so that the "requires" property is ignored.// 3) or make the source node inactive, with the same effect.//// The 1st approach is generally better, but may involve changing user// settings in situations where the 2nd or 3rd would be ok. Anyway// there is clearly a need for some OR logic right from the start.//// As an example of what is involved in an inference, consider the// simple case of a "requires XXX" property. This constraint may not// be satisfied because XXX is disabled, because XXX is inactive,// or both.//// Assume for simplicity that XXX is already active. The inference// engine can now figure out that XXX must be enabled (it must be// of type bool or booldata, or else the conflict would not have// arisen). This is achieved by creating a sub-transaction,// enabling XXX in that sub-transaction, propagating the// sub-transaction and performing further inference. The inference// is successfull if no new conflicts are introduced.//// However, even if a solution is found it is not necessarily// acceptable without user confirmation, subject to// inference_override. This is handled in part by the transaction// class itself, in the resolve() and user_confirmation_required()// members. In cases where the inference engine can choose between// several alternatives it needs to consider this issue for each one.// // There are a number of key entry points://// 1) bool infer_make_active(CdlTransaction, CdlValuable, level)// Do whatever it takes to make the valuable active in// a clean sub-transaction, if possible.// 2) bool infer_make_inactive(CdlTransaction, CdlValuable, level)// Do whatever it takes to make the valuable inactive.// 3) bool infer_set_valuable_value(CdlTransaction, CdlValuable, CdlSimpleValue&, level)// Try to set the valuable to the specified value, taking into// account the different flavors.// 4) bool infer_set_valuable_bool(CdlTransaction, CdlValuable, bool, level)// Similar to (3) but deals with the boolean aspect of the valuable// rather than the data part.// 5) bool infer_subexpr(CdlTransaction, CdlExpression, int index, CdlSimpleValue& goal, level)// Process a sub-expression and try to make it evaluate to the// goal.// 6) bool infer_subexpr_bool(CdlTransaction, CdlExpression, int index, bool goal, level)// Ditto but only deal with boolean goals. If the expression starts to// involve arithmetic etc. then we need to move to infer_subexpr()//// As might be expected, the sub-expression handlers contain a big// switch statement and calls into various auxiliary functions when// necessary.//// Forward declarations are needed to allow for active_if properties and// the like.//// For convenience the various entry points check whether or not the// desired condition is already satisfied.//}}}//{{{ Forward declarations // ----------------------------------------------------------------------------static bool infer_make_active(CdlTransaction, CdlNode, int);static bool infer_make_inactive(CdlTransaction, CdlNode, int);static bool infer_set_valuable_value(CdlTransaction, CdlValuable, CdlSimpleValue&, int);static bool infer_set_valuable_bool(CdlTransaction, CdlValuable, bool, int);static bool infer_subexpr_value(CdlTransaction, CdlExpression, unsigned int, CdlSimpleValue&, int);static bool infer_subexpr_bool(CdlTransaction, CdlExpression, unsigned int, bool, int);//}}}//{{{ infer_make_active() // ----------------------------------------------------------------------------// Making a node active. This requires the following conditions to be// satisfied:// 1) the parent must be made active// 2) if the parent has flavor bool or booldata, it must be enabled// 3) any active_if properties static boolinfer_make_active(CdlTransaction transaction, CdlNode node, int level){ CYG_REPORT_FUNCNAMETYPE("infer_make_active", "result %d"); CYG_REPORT_FUNCARG3XV(transaction, node, level); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(node); bool result = false; if (transaction->is_active(node)) { result = true; CYG_REPORT_RETVAL(result); return result; } CdlContainer parent = node->get_parent(); CYG_ASSERT_CLASSC(parent); if (!transaction->is_active(parent)) { if (!infer_make_active(transaction, parent, level)) { CYG_REPORT_RETVAL(result); return result; } } // The parent is now active. Does it have to be enabled as well? CdlValuable parent_valuable = dynamic_cast<CdlValuable>(static_cast<CdlNode>(parent)); if (0 != parent_valuable) { CdlValueFlavor flavor = parent_valuable->get_flavor(); if (((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) && !parent_valuable->is_enabled(transaction)) { if (!infer_set_valuable_bool(transaction, parent_valuable, true, level)) { CYG_REPORT_RETVAL(result); return result; } } } // The parent is now active and enabled. Are there any active_if properties to worry about? CdlValuable valuable = dynamic_cast<CdlValuable>(node); if (0 != valuable) { std::vector<CdlProperty_GoalExpression> active_if_goals; std::vector<CdlProperty_GoalExpression>::iterator goal_i; valuable->get_active_if_conditions(active_if_goals); for (goal_i = active_if_goals.begin(); goal_i != active_if_goals.end(); goal_i++) { CdlEvalContext context(transaction, valuable, *goal_i); try { if (!(*goal_i)->eval(context)) { CdlExpression expr = (*goal_i)->get_expression(); if (!infer_subexpr_bool(transaction, expr, expr->first_subexpression, true, level)) { CYG_REPORT_RETVAL(result); return result; } } } catch(...) { CYG_REPORT_RETVAL(result); return result; } } } result = transaction->is_active(node); CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_make_inactive() // ----------------------------------------------------------------------------// Making a node inactive can be done in three ways:// 1) if the parent is boolean, try disabling it// 2) otherwise if the parent can be made inactive, that will do// fine.// 3) if there are any active_if properties, they could be considered// as well. For now this possibility is ignored.static boolinfer_make_inactive(CdlTransaction transaction, CdlNode node, int level){ CYG_REPORT_FUNCNAMETYPE("infer_make_inactive", "result %d"); CYG_REPORT_FUNCARG3XV(transaction, node, level); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(node); bool result = false; if (!transaction->is_active(node)) { result = true; CYG_REPORT_RETVAL(result); return result; } CdlContainer parent = node->get_parent(); if (0 == parent) { // No point in trying to disable the entire configuration. CYG_REPORT_RETVAL(result); return result; } CdlValuable parent_valuable = dynamic_cast<CdlValuable>(parent); if (0 != parent_valuable) { CdlValueFlavor flavor = parent_valuable->get_flavor(); if ((CdlValueFlavor_Bool == flavor) || (CdlValueFlavor_BoolData == flavor)) { // Since the current node is active the parent must currently be enabled. // A sub-transaction is needed because an alternative approach is // possible later on. CdlTransaction subtransaction = transaction->make(transaction->get_conflict()); if (infer_set_valuable_bool(subtransaction, parent_valuable, false, level)) { subtransaction->commit(); delete subtransaction; result = true; CYG_REPORT_RETVAL(result); return result; } else { subtransaction->cancel(); delete subtransaction; } } } // It is not possible to disable the parent. How about making it inactive? if (infer_make_inactive(transaction, parent, level)) { result = true; CYG_REPORT_RETVAL(result); return result; } // For now do not try to mess about with active_if conditions. CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_set_valuable_value() // ----------------------------------------------------------------------------// Deal with the value part of a valuable. The valuable is known to exist// and be active, so this code only deals with the actual value part.static boolinfer_set_valuable_value(CdlTransaction transaction, CdlValuable valuable, CdlSimpleValue& goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_set_valuable_value", "result %d"); CYG_REPORT_FUNCARG3XV(transaction, valuable, level); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(valuable); CYG_PRECONDITIONC(transaction->is_active(valuable)); bool result = false; const CdlValue& current_value = transaction->get_whole_value(valuable); CdlValueFlavor flavor = current_value.get_flavor(); bool bool_goal = goal.get_bool_value();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -