Skip to content

Invoke callback for partial rule in chain. - #273

Merged
hzhangxyz merged 1 commit into
mainfrom
dev/return-partial-rule-in-chain
Mar 12, 2026
Merged

Invoke callback for partial rule in chain.#273
hzhangxyz merged 1 commit into
mainfrom
dev/return-partial-rule-in-chain

Conversation

@hzhangxyz

Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings March 12, 2026 10:58
@hzhangxyz
hzhangxyz merged commit 5defbb4 into main Mar 12, 2026
88 checks passed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates ds::chain_t::execute to invoke the provided callback not only for newly-derived facts, but also for newly-generated intermediate (“partial”) rules produced during chaining.

Changes:

  • Track newly-generated partial rules during a single execute() run via a temp_rules set (deduplication).
  • Invoke the callback when a new partial rule is encountered (in addition to the existing fact-callback behavior).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/chain.cc
Comment on lines +99 to 103
if (callback(rule)) {
break_all = true;
}
} while (false);
}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When callback(rule) returns true here, break_all is set but chain_recursive continues and still iterates over facts below (and can recurse further). This violates the documented “stop searching” behavior and differs from the premises_count()==0 branch which returns immediately. Consider returning immediately (and/or checking break_all before the facts loop / before recursing) once the callback requests termination.

Copilot uses AI. Check for mistakes.
Comment thread src/chain.cc
Comment on lines +93 to +101
auto new_rule = std::unique_ptr<rule_t>(reinterpret_cast<rule_t*>(operator new(rule->data_size())));
memcpy(new_rule->head(), rule->head(), rule->data_size());
if (rules.find(new_rule) != rules.end() || temp_rules.find(new_rule) != temp_rules.end()) {
break;
}
temp_rules.emplace(std::move(new_rule));
if (callback(rule)) {
break_all = true;
}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block allocates/copies new_rule and stores it in temp_rules to deduplicate callbacks, but then invokes callback(rule) instead of using the stable copied instance. For intermediate rules, rule can point into the scratch buffer and may be overwritten later in the search, which is risky if callers retain the pointer. Prefer invoking the callback with the stored copy (or otherwise documenting/enforcing that the pointer is only valid during the callback).

Copilot uses AI. Check for mistakes.
Comment thread src/chain.cc
Comment on lines +98 to +101
temp_rules.emplace(std::move(new_rule));
if (callback(rule)) {
break_all = true;
}

Copilot AI Mar 12, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New behavior: callbacks are now invoked for newly-generated partial rules (non-zero premises) and deduplicated via temp_rules. There are existing chain_t tests, but none assert that partial-rule callbacks fire (or fire only once) and that callback returning true stops the search promptly. Adding a focused unit test would help prevent regressions in this new observable behavior.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants