Skip to content

feat: Add generator for chain and search. - #275

Merged
hzhangxyz merged 1 commit into
mainfrom
dev/generator
Mar 15, 2026
Merged

feat: Add generator for chain and search.#275
hzhangxyz merged 1 commit into
mainfrom
dev/generator

Conversation

@hzhangxyz

Copy link
Copy Markdown
Member

No description provided.

Copilot AI review requested due to automatic review settings March 14, 2026 05:40

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 introduces generator-based iteration for the core inference engines (search_t and chain_t), and wires that iteration model through the Python bindings so engines can be consumed via for ... in ... while keeping the existing callback-style execute() API.

Changes:

  • Add iterator() generators to ds::search_t and ds::chain_t, and re-implement execute() on top of them.
  • Expose generator iteration to Python via a new bound Iterator helper plus __iter__ in the Python wrapper classes.
  • Bump the C++ language standard to C++23 and update C++ chain tests’ expected counts.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
tests/test_chain.cc Updates expected chain_t::execute() counts to reflect step-wise yielding behavior.
src/search.cc Adds search_t::iterator() generator and refactors execute() to iterate it.
src/chain.cc Adds chain_t::iterator() generator (recursive yielding) and refactors execute() accordingly.
include/ds/search.hh Declares search_t::iterator() and includes <generator>.
include/ds/chain.hh Declares chain_t::iterator() and includes <generator>.
apyds/search_t.py Adds Search.__iter__() that consumes the bound iterator and yields cloned Rules.
apyds/chain_t.py Adds Chain.__iter__() that consumes the bound iterator and yields cloned Rules.
apyds/ds.cc Adds a C++ Iterator wrapper around std::generator and binds iter() for Search/Chain.
CMakeLists.txt Raises the project C++ standard requirement to C++23.

💡 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 include/ds/search.hh Outdated
Comment on lines +70 to +72
/// @brief 执行一轮搜索操作,以生成器方式迭代所有匹配的规则。
/// @return 生成器,每次迭代返回一个匹配的规则指针。
std::generator<rule_t*> iterator();
Comment thread CMakeLists.txt Outdated
target_sources(${PROJECT_NAME} PRIVATE ${SOURCES})
target_include_directories(${PROJECT_NAME} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_23)
Comment thread apyds/ds.cc
Comment on lines 197 to +214
@@ -177,4 +207,12 @@ PYBIND11_MODULE(_ds, m, py::mod_gil_not_used()) {
chain_t.def("reset", &ds::chain_t::reset);
chain_t.def("add", &ds::chain_t::add);
chain_t.def("execute", &ds::chain_t::execute);
chain_t.def(
"iter",
[](ds::chain_t& self) { return Iterator(std::move(self.iterator())); },
py::return_value_policy::reference_internal
);
Comment thread include/ds/chain.hh
length_t execute(const std::function<bool(rule_t*)>& callback);

/// @brief 执行一轮搜索操作,以生成器方式迭代所有匹配的规则。
/// @return 生成器,每次迭代返回一个匹配的规则指针。
Comment thread src/chain.cc
Comment on lines +77 to +81
++current_cycle;
for (auto it = temp_facts.begin(); it != temp_facts.end();) {
auto node = temp_facts.extract(it++);
facts.emplace(std::move(node.value()), current_cycle);
}
Comment thread src/chain.cc Outdated
Comment on lines +126 to +128
co_yield std::ranges::elements_of(
chain_recursive(chain_recursive, rule.get(), buffer.get(), reinterpret_cast<std::byte*>(buffer.get()) + buffer_size)
);
Comment thread src/search.cc
Comment on lines +68 to +84
// RAII guard,确保无论是否提前退出,清理代码都会执行
struct guard_t {
std::function<void()> cleanup;
~guard_t() {
cleanup();
}
} guard{[&]() {
++current_cycle;
for (auto it = temp_rules.begin(); it != temp_rules.end();) {
auto node = temp_rules.extract(it++);
rules.emplace(std::move(node.value()), current_cycle);
}
for (auto it = temp_facts.begin(); it != temp_facts.end();) {
auto node = temp_facts.extract(it++);
facts.emplace(std::move(node.value()), current_cycle);
}
}};
Comment thread src/chain.cc
Comment on lines +70 to +82
// RAII guard,确保无论是否提前退出,清理代码都会执行
struct guard_t {
std::function<void()> cleanup;
~guard_t() {
cleanup();
}
} guard{[&]() {
++current_cycle;
for (auto it = temp_facts.begin(); it != temp_facts.end();) {
auto node = temp_facts.extract(it++);
facts.emplace(std::move(node.value()), current_cycle);
}
}};
Comment thread apyds/ds.cc
Comment on lines +13 to +25
ds::rule_t* next() {
if (initialized) {
++*iterator;
} else {
iterator = std::make_unique<iterator_t>(generator.begin());
initialized = true;
}
if (*iterator == generator.end()) {
return nullptr;
}
ds::rule_t* result = **iterator;
return result;
}
Comment thread src/chain.cc
Comment on lines +135 to 143
length_t chain_t::execute(const std::function<bool(rule_t*)>& callback) {
length_t count = 0;
for (auto* rule : iterator()) {
++count;
if (callback(rule)) {
break;
}
}

if (!break_all) {
done_cycle = current_cycle;
}
++current_cycle;
length_t count = temp_facts.size();
for (auto it = temp_facts.begin(); it != temp_facts.end();) {
auto node = temp_facts.extract(it++);
facts.emplace(std::move(node.value()), current_cycle);
}
return count;
@hzhangxyz
hzhangxyz force-pushed the dev/generator branch 10 times, most recently from 988eb7c to d3b7f77 Compare March 15, 2026 04:55
@hzhangxyz
hzhangxyz merged commit 9fa5fed into main Mar 15, 2026
86 checks passed
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