📄 infer.cxx
字号:
return result; } } if (CdlInfer::set_valuable_bool(transaction, valuable, true, level)) { result = true; } } else { // If the valuable should evaluate to false then it must be either // inactive or it must be disabled or have a zero value. if (!transaction->is_active(valuable)) { // The goal is already satisfied, no need to proceed result = true; CYG_REPORT_RETVAL(result); return result; } // There is a choice to be made so two sub-transactions are // needed. Disabling is generally preferred to making inactive. CdlTransaction value_transaction = transaction->make(transaction->get_conflict()); CdlTransaction inactive_transaction = 0; bool value_result = CdlInfer::set_valuable_bool(value_transaction, valuable, false, level); if (value_result && !value_transaction->user_confirmation_required()) { value_transaction->commit(); delete value_transaction; value_transaction = 0; result = true; CYG_REPORT_RETVAL(result); return result; } inactive_transaction = transaction->make(transaction->get_conflict()); bool inactive_result = CdlInfer::make_inactive(inactive_transaction, valuable, level); if (!inactive_result) { if (value_result) { // Changing the value is the only solution. inactive_transaction->cancel(); value_transaction->commit(); result = true; } else { inactive_transaction->cancel(); value_transaction->cancel(); result = false; } } else { if (!value_result) { // Making the valuable inactive is the only solution. value_transaction->cancel(); inactive_transaction->commit(); result = true; } else if (!inactive_transaction->user_confirmation_required()) { // Disabling the valuable would require user confirmation, making it inactive does not value_transaction->cancel(); inactive_transaction->commit(); result = true; } else { // Both approaches are valid but would require user confirmation. // Pick the preferred one. if (value_transaction->is_preferable_to(inactive_transaction)) { inactive_transaction->cancel(); value_transaction->commit(); result = true; } else { value_transaction->cancel(); inactive_transaction->commit(); result = true; } } } delete value_transaction; delete inactive_transaction; value_transaction = 0; inactive_transaction = 0; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// Try to set a valuable to a particular value. Of course the reference// may not be bound yet.//// First check whether or not the valuable is currently active. If it is// inactive and the goal is 0 then we have succeeded. If it is active and// the goal is 0 then we could try to make the valuable inactive, but// this possibility is ignored for now in case it leads to unexpected// behaviour. If it is active then we try to set the value, using// CdlInfer::set_valuable_value().static boolinfer_handle_reference_value(CdlTransaction transaction, CdlValuable valuable, CdlSimpleValue& goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_handle_reference", "result %d"); CYG_REPORT_FUNCARG3XV(transaction, valuable, level); bool result = false; if (0 == valuable) { if (goal == (cdl_int) 0) { result = true; } } else { bool active = transaction->is_active(valuable); if (!active) { if (goal == (cdl_int) 0) { result = true; } } else { result = CdlInfer::set_valuable_value(transaction, valuable, goal, level); } } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_handle_xxx_constant() // ----------------------------------------------------------------------------// Somewhere in the expression processing we have encountered a string// constant. The expression cannot be changed, so either the goal matches// the constant or it does not.static boolinfer_handle_string_constant_bool(CdlSimpleValue& constant, bool goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_string_constant_bool", "result %d"); bool result = false; if (goal) { if (("" != constant.get_value()) && ("0" != constant.get_value())) { result = true; } } else { if (("" == constant.get_value()) || ("0" == constant.get_value())) { result = true; } } CYG_REPORT_RETVAL(result); return result;}static boolinfer_handle_string_constant_value(CdlSimpleValue& constant, CdlSimpleValue& goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_string_constant_value", "result %d"); bool result = false; if (constant.get_value() == goal.get_value()) { result = true; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// Integers are also fairly straightforward.static boolinfer_handle_integer_constant_bool(CdlSimpleValue& constant, bool goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_integer_constant_bool", "result %d"); CYG_PRECONDITIONC(constant.has_integer_value()); bool result = false; if (goal) { if (0 != constant.get_integer_value()) { result = true; } } else { if (0 == constant.get_integer_value()) { result = true; } } CYG_REPORT_RETVAL(result); return result;}static boolinfer_handle_integer_constant_value(CdlSimpleValue& constant, CdlSimpleValue& goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_integer_constant_value", "result %d"); CYG_PRECONDITIONC(constant.has_integer_value()); bool result = false; if (goal.has_integer_value() && (constant.get_integer_value() == goal.get_integer_value())) { result = true; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// Doubles are also straightforward, except than an exact comparision may// be too strict. There is not a lot that can be done about this right now.// Future enhancements to CDL may support tolerances.static boolinfer_handle_double_constant_bool(CdlSimpleValue& constant, bool goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_double_constant_bool", "result %d"); CYG_PRECONDITIONC(constant.has_double_value()); bool result = false; if (goal) { if (0.0 != constant.get_double_value()) { result = true; } } else { if (0.0 == constant.get_double_value()) { result = true; } } CYG_REPORT_RETVAL(result); return result;}static boolinfer_handle_double_constant_value(CdlSimpleValue& constant, CdlSimpleValue& goal){ CYG_REPORT_FUNCNAMETYPE("infer_handle_double_constant_value", "result %d"); CYG_PRECONDITIONC(constant.has_double_value()); bool result = false; if (goal.has_double_value() && (constant.get_double_value() == goal.get_double_value())) { result = true; } CYG_REPORT_RETVAL(result); return result;}//}}}//{{{ infer_handle_logical_xxx() // ----------------------------------------------------------------------------// Logical not simply involves inverting the goal and then trying to infer// the rest of the sub-expression. There is little point in touching// the other arguments.static boolinfer_handle_logical_NOT_bool(CdlTransaction transaction, CdlExpression expr, unsigned int index, bool goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_handle_logical_NOT_bool", "result %d"); bool result = CdlInfer::subexpr_bool(transaction, expr, index, !goal, level); CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// Depending on the goal, we want either both sides of the AND to evaluate to// true, or we want one of the sides to evaluate to false.static boolinfer_handle_AND_bool(CdlTransaction transaction, CdlExpression expr, unsigned int lhs, unsigned int rhs, bool goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_handle_AND_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; if (goal) { // Both sides must be true in the same transaction, in case // the solutions overlap in conflicting ways. A sub-transaction // is still used to avoid polluting current values if the lhs // can be inferred but not the rhs. CdlTransaction sub_transaction = transaction->make(transaction->get_conflict()); if (CdlInfer::subexpr_bool(sub_transaction, expr, lhs, true, level) && CdlInfer::subexpr_bool(sub_transaction, expr, rhs, true, level)) { sub_transaction->commit(); result = true; } else { sub_transaction->cancel(); } delete sub_transaction; } else { // We need to try out both sides of the OR and see which one is preferable. // An optimization would be to only try the LHS, but trying both allows // for a more informed choice. CdlTransaction lhs_transaction = transaction->make(transaction->get_conflict()); CdlTransaction rhs_transaction = transaction->make(transaction->get_conflict()); bool lhs_result = CdlInfer::subexpr_bool(lhs_transaction, expr, lhs, false, level); bool rhs_result = CdlInfer::subexpr_bool(rhs_transaction, expr, rhs, false, level); result = infer_choose2(lhs_transaction, lhs_result, rhs_transaction, rhs_result); } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------// The support for the other logical operations involves basically minor// variants of the above.static boolinfer_handle_OR_bool(CdlTransaction transaction, CdlExpression expr, unsigned int lhs, unsigned int rhs, bool goal, int level){ CYG_REPORT_FUNCNAMETYPE("infer_handle_OR_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; if (goal) { // We need to try out both sides of the OR and see which one is preferable. // An optimization would be to only try the LHS, but trying both allows // for a more informed choice. CdlTransaction lhs_transaction = transaction->make(transaction->get_conflict()); CdlTransaction rhs_transaction = transaction->make(transaction->get_conflict()); bool lhs_result = CdlInfer::subexpr_bool(lhs_transaction, expr, lhs, true, level); bool rhs_result = CdlInfer::subexpr_bool(rhs_transaction, expr, rhs, true, level); result = infer_choose2(lhs_transaction, lhs_result, rhs_transaction, rhs_result); } else { // !(A || B) -> !A && !B CdlTransaction sub_transaction = transaction->make(transaction->get_conflict());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -