📄 infer.cxx
字号:
// ----------------------------------------------------------------------------// Handle expressions of the form A == B. If B is constant then this// corresponds to an infer_subexpr_value() for A. Alternatively if// A is constant then this corresponds to an infer_subexpr_value() for B.//// There are other possibilities. If B has a calculated value then that// could be treated as if it were a constant. We could try two// sub-transactions, either setting A to the current value of subexpr B,// or vice versa. And so on.static boolinfer_handle_equal_bool(CdlTransaction transaction, CdlExpression expr, unsigned int lhs, unsigned int rhs, bool goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_handle_equal_bool", "result %d"); CYG_REPORT_FUNCARG4XV(transaction, expr, lhs, rhs); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(expr); CYG_PRECONDITIONC(lhs != rhs); bool result = false; CdlSubexpression& lhs_subexpr = expr->sub_expressions[lhs]; CdlSubexpression& rhs_subexpr = expr->sub_expressions[rhs]; // For now we can only deal with equality, not inequality. if (goal) { if ((CdlExprOp_StringConstant == lhs_subexpr.op) || (CdlExprOp_IntegerConstant == lhs_subexpr.op) || (CdlExprOp_DoubleConstant == lhs_subexpr.op)) { result = infer_subexpr_value(transaction, expr, rhs, lhs_subexpr.constants, level); } else if ((CdlExprOp_StringConstant == rhs_subexpr.op) || (CdlExprOp_IntegerConstant == rhs_subexpr.op) || (CdlExprOp_DoubleConstant == rhs_subexpr.op)) { result = infer_subexpr_value(transaction, expr, lhs, rhs_subexpr.constants, level); } } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_subexpr_bool() // ----------------------------------------------------------------------------static boolinfer_subexpr_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_subexpr_bool", "result %d"); CYG_REPORT_FUNCARG5XV(transaction, expr, index, goal, level); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(expr); CYG_PRECONDITIONC((0 <= index) && (index < expr->sub_expressions.size())); bool result = false; CdlSubexpression& subexpr = expr->sub_expressions[index]; switch(subexpr.op) { case CdlExprOp_Reference : // The most common case. Follow the reference, and call the appropriate function. // Note that the reference may be unbound. { CdlNode node = expr->references[subexpr.reference_index].get_destination(); CdlValuable valuable = 0; if (0 != node) { valuable = dynamic_cast<CdlValuable>(node); } result = infer_handle_reference_bool(transaction, valuable, goal, level); break; } case CdlExprOp_StringConstant : result = infer_handle_string_constant_bool(subexpr.constants, goal); break; case CdlExprOp_IntegerConstant : result = infer_handle_integer_constant_bool(subexpr.constants, goal); break; case CdlExprOp_DoubleConstant : result = infer_handle_double_constant_bool(subexpr.constants, goal); break; case CdlExprOp_LogicalNot : result = infer_handle_logical_NOT_bool(transaction, expr, subexpr.lhs_index, goal, level); break; case CdlExprOp_And : result = infer_handle_AND_bool(transaction, expr, subexpr.lhs_index, subexpr.rhs_index, goal, level); break; case CdlExprOp_Or : result = infer_handle_OR_bool(transaction, expr, subexpr.lhs_index, subexpr.rhs_index, goal, level); break; case CdlExprOp_Equal : result = infer_handle_equal_bool(transaction, expr, subexpr.lhs_index, subexpr.rhs_index, goal, level); break; default: // No other inferences are implemented at this stage. break; } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_subexpr_value() static boolinfer_subexpr_value(CdlTransaction transaction, CdlExpression expr, unsigned int index, CdlSimpleValue& goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_subexpr_value", "result %d"); CYG_REPORT_FUNCARG4XV(transaction, expr, index, level); CYG_PRECONDITION_CLASSC(transaction); CYG_PRECONDITION_CLASSC(expr); CYG_PRECONDITIONC((0 <= index) && (index < expr->sub_expressions.size())); bool result = false; CdlSubexpression& subexpr = expr->sub_expressions[index]; switch(subexpr.op) { case CdlExprOp_Reference : // The most common case. Follow the reference, and call the appropriate function. // Note that the reference may be unbound. { CdlNode node = expr->references[subexpr.reference_index].get_destination(); CdlValuable valuable = 0; if (0 != node) { valuable = dynamic_cast<CdlValuable>(node); } result = infer_handle_reference_value(transaction, valuable, goal, level); break; } case CdlExprOp_StringConstant : result = infer_handle_string_constant_value(subexpr.constants, goal); break; case CdlExprOp_IntegerConstant : result = infer_handle_integer_constant_value(subexpr.constants, goal); break; case CdlExprOp_DoubleConstant : result = infer_handle_double_constant_value(subexpr.constants, goal); break; case CdlExprOp_LogicalNot : result = infer_handle_logical_NOT_value(transaction, expr, subexpr.lhs_index, goal, level); break; case CdlExprOp_And : result = infer_handle_OR_value(transaction, expr, subexpr.lhs_index, subexpr.rhs_index, goal, level); break; case CdlExprOp_Or : result = infer_handle_AND_value(transaction, expr, subexpr.lhs_index, subexpr.rhs_index, goal, level); break; default: // No other inferences are implemented at this stage. break; } CYG_REPORT_RETVAL(result); return result;}//}}}//}}}//{{{ CdlConflict_Requires::inner_resolve() // ----------------------------------------------------------------------------// Resolving a requires conflict. There are three ways of tackling// this problem, in order of preference://// 1) change the terms in the expression to make it evaluate to// true.// 2) disable the source so that the requires property is no longer// relevant.// 3) make the source inactive, with the same effect.//// The first one should always be tried. If it is entirely successful// then there is no point in looking any further. If user confirmation// is required then the second approach should be tried. If that is// entirely successful then there is no point in looking further.// If user confirmation is required then the third approach should// be tried.boolCdlConflict_RequiresBody::inner_resolve(CdlTransaction transaction, int level){ CYG_REPORT_FUNCNAME("CdlConflict_Requires::inner_resolve"); CYG_REPORT_FUNCARG3XV(this, transaction, level); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(transaction); bool result = false; CdlProperty_GoalExpression gexpr = dynamic_cast<CdlProperty_GoalExpression>(this->get_property()); CdlExpression expr = gexpr->get_expression(); // Only create the sub-transactions when needed CdlTransaction expr_transaction = 0; CdlTransaction disable_transaction = 0; CdlTransaction inactive_transaction = 0; // Keep track of the preferred solution found to date. CdlTransaction preferred_transaction = 0; expr_transaction = transaction->make(this); if (!infer_subexpr_bool(expr_transaction, expr, expr->first_subexpression, true, level)) { // No luck here. expr_transaction->cancel(); delete expr_transaction; expr_transaction = 0; } else { // We have a possible solution. How acceptable is it? if (!expr_transaction->user_confirmation_required()) { // Whoopee. expr_transaction->commit(); delete expr_transaction; result = true; CYG_REPORT_RETVAL(result); return result; } else { // Maybe we can do better. preferred_transaction = expr_transaction; expr_transaction = 0; } } // Disabling the source only makes sense if we have a bool or booldata item. CdlValuable valuable = dynamic_cast<CdlValuable>(this->get_node()); CYG_ASSERT_CLASSC(valuable); if ((CdlValueFlavor_Bool == valuable->get_flavor()) || (CdlValueFlavor_BoolData == valuable->get_flavor())) { disable_transaction = transaction->make(this); if (!infer_set_valuable_bool(disable_transaction, valuable, false, level)) { // No luck here either. disable_transaction->cancel(); delete disable_transaction; disable_transaction = 0; } else { if (!disable_transaction->user_confirmation_required()) { disable_transaction->commit(); delete disable_transaction; if (0 != preferred_transaction) { preferred_transaction->cancel(); delete preferred_transaction; preferred_transaction = 0; } result = true; CYG_REPORT_RETVAL(result); return result; } else if (0 == preferred_transaction) { preferred_transaction = disable_transaction; } else if (disable_transaction->is_preferable_to(preferred_transaction)) { preferred_transaction->cancel(); delete preferred_transaction; preferred_transaction = disable_transaction; disable_transaction = 0; } else { disable_transaction->cancel(); delete disable_transaction; disable_transaction = 0; } } } // Now try for the inactive approach. This may work in cases where the disable // approach does not if e.g. there are dependencies between two nodes in the // same container, or if the source of the conflict is not boolean. inactive_transaction = transaction->make(this); if (!infer_make_inactive(inactive_transaction, valuable, level)) { inactive_transaction->cancel(); delete inactive_transaction; inactive_transaction = 0; } else { if (!inactive_transaction->user_confirmation_required()) { inactive_transaction->commit(); delete inactive_transaction; if (0 != preferred_transaction) { preferred_transaction->cancel(); delete preferred_transaction; preferred_transaction = 0; } result = true; CYG_REPORT_RETVAL(result); return result; } else if (0 == preferred_transaction) { preferred_transaction = inactive_transaction; } else if (inactive_transaction->is_preferable_to(preferred_transaction)) { preferred_transaction->cancel(); delete preferred_transaction; preferred_transaction = inactive_transaction; inactive_transaction = 0; } else { inactive_transaction->cancel(); delete inactive_transaction; inactive_transaction = 0; } } // Is there any solution at all? If so then use the currently-preferred one. if (0 != preferred_transaction) { preferred_transaction->commit(); delete preferred_transaction; preferred_transaction = 0; result = true; } CYG_REPORT_RETVAL(result); return result;}//}}}//}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -