From 09c60630688a96384cdbc5a12ab9a8c27d691c0e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 04:35:43 +0000 Subject: [PATCH 1/8] Initial plan From ac3b1d95193675e66de26c6bb28bb5f4c6e8d79b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 04:41:57 +0000 Subject: [PATCH 2/8] Add rename function for term_t and rule_t to add prefix/suffix to variables Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- include/ds/rule.hh | 7 +++ include/ds/term.hh | 7 +++ src/rename.cc | 91 +++++++++++++++++++++++++++++ tests/test_rename.cc | 136 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 241 insertions(+) create mode 100644 src/rename.cc create mode 100644 tests/test_rename.cc diff --git a/include/ds/rule.hh b/include/ds/rule.hh index 81745cd..6cc6941 100644 --- a/include/ds/rule.hh +++ b/include/ds/rule.hh @@ -115,6 +115,13 @@ namespace ds { /// @param check_tail 可选的尾指针检查。 /// @return 自身,如果匹配失败则返回nullptr,如果尾指针检查失败则返回nullptr,在尾指针检查正常时,匹配失败会将本对象设置为null。 rule_t* match(rule_t* rule_1, rule_t* rule_2, std::byte* check_tail = nullptr); + + /// @brief 将rule中的所有variable添加prefix和suffix, 结果更新至本对象。 + /// @param rule 待被重命名的rule。 + /// @param prefix_and_suffix 只有一个conclusion的rule,conclusion是含有两个item的list,分别表示prefix和suffix。 + /// @param check_tail 可选的尾指针检查。 + /// @return 自身,是一个rule_t对象的指针,如果尾指针检查失败则返回nullptr。 + rule_t* rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail = nullptr); }; } // namespace ds diff --git a/include/ds/term.hh b/include/ds/term.hh index 886394f..0a049d7 100644 --- a/include/ds/term.hh +++ b/include/ds/term.hh @@ -154,6 +154,13 @@ namespace ds { /// @param check_tail 可选的尾指针检查。 /// @return 自身,如果匹配失败则返回nullptr,如果尾指针检查失败则返回nullptr,在尾指针检查正常时,匹配失败会将本对象设置为null。 term_t* match(term_t* term_1, term_t* term_2, const char* scope_1, const char* scope_2, std::byte* check_tail = nullptr); + + /// @brief 将term中的所有variable添加prefix和suffix, 结果更新至本对象。 + /// @param term 待被重命名的term。 + /// @param prefix_and_suffix 含有两个item的list,分别表示prefix和suffix。 + /// @param check_tail 可选的尾指针检查。 + /// @return 自身,是一个term_t对象的指针,如果尾指针检查失败则返回nullptr。 + term_t* rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail = nullptr); }; } // namespace ds diff --git a/src/rename.cc b/src/rename.cc new file mode 100644 index 0000000..534b21d --- /dev/null +++ b/src/rename.cc @@ -0,0 +1,91 @@ +#include + +#include +#include +#include +#include +#include +#include + +namespace ds { + term_t* term_t::rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail) { + list_t* ps_list = prefix_and_suffix->list(); + if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { + return nullptr; + } + item_t* prefix = ps_list->term(0)->item(); + item_t* suffix = ps_list->term(1)->item(); + if (prefix == nullptr || suffix == nullptr) [[unlikely]] { + return nullptr; + } + char* prefix_str = prefix->name()->get_string(); + char* suffix_str = suffix->name()->get_string(); + length_t prefix_len = strlen(prefix_str); + length_t suffix_len = strlen(suffix_str); + + switch (term->get_type()) { + case term_type_t::variable: { + char* name_str = term->variable()->name()->get_string(); + length_t name_len = strlen(name_str); + length_t new_len = prefix_len + name_len + suffix_len + 1; + if (set_variable(check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + if (variable()->name()->set_length(new_len, check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + char* dst = variable()->name()->get_string(); + memcpy(dst, prefix_str, prefix_len); + memcpy(dst + prefix_len, name_str, name_len); + memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + dst[new_len - 1] = '\0'; + return this; + } + case term_type_t::item: { + if (check_before_fail(check_tail, this, term->data_size())) [[unlikely]] { + return nullptr; + } + memcpy(this, term, term->data_size()); + return this; + } + case term_type_t::list: { + list_t* src = term->list(); + if (set_list(check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + list_t* dst = list(); + if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + for (length_t index = 0; index < dst->get_list_size(); ++index) { + if (dst->term(index)->rename(src->term(index), prefix_and_suffix, check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + dst->update_term_size(index); + } + return this; + } + default: + return nullptr; + } + } + + rule_t* rule_t::rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail) { + term_t* ps_term = prefix_and_suffix->only_conclusion(); + if (ps_term == nullptr) [[unlikely]] { + return nullptr; + } + list_t* dst = this; + list_t* src = rule; + if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + for (length_t index = 0; index < dst->get_list_size(); ++index) { + if (dst->term(index)->rename(src->term(index), ps_term, check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + dst->update_term_size(index); + } + return this; + } +} // namespace ds diff --git a/tests/test_rename.cc b/tests/test_rename.cc new file mode 100644 index 0000000..e5398ac --- /dev/null +++ b/tests/test_rename.cc @@ -0,0 +1,136 @@ +#include +#include +#include + +class TestRename : public ::testing::Test { + protected: + const ds::length_t buffer_size = 200; + + TestRename() { } + ~TestRename() override { } + void SetUp() override { + result_t = reinterpret_cast(operator new(buffer_size)); + result_r = reinterpret_cast(operator new(buffer_size)); + } + void TearDown() override { + operator delete(result_t); + operator delete(result_r); + } + + ds::term_t* result_t; + ds::rule_t* result_r; + + void rename_term_check(const char* term_text, const char* prefix_suffix_text, const char* expect_text) { + auto term = ds::text_to_term(term_text, buffer_size); + auto prefix_suffix = ds::text_to_term(prefix_suffix_text, buffer_size); + EXPECT_NE(result_t->rename(term.get(), prefix_suffix.get(), nullptr), nullptr); + auto result = ds::term_to_text(result_t, buffer_size); + EXPECT_STREQ(result.get(), expect_text); + auto correct_length = result_t->data_size(); + EXPECT_NE(result_t->rename(term.get(), prefix_suffix.get(), reinterpret_cast(result_t) + correct_length), nullptr); + for (auto i = 0; i < correct_length; ++i) { + EXPECT_EQ(result_t->rename(term.get(), prefix_suffix.get(), reinterpret_cast(result_t) + i), nullptr); + } + } + + void rename_rule_check(const char* rule_text, const char* prefix_suffix_text, const char* expect_text) { + auto rule = ds::text_to_rule(rule_text, buffer_size); + auto prefix_suffix = ds::text_to_rule(prefix_suffix_text, buffer_size); + EXPECT_NE(result_r->rename(rule.get(), prefix_suffix.get(), nullptr), nullptr); + auto result = ds::rule_to_text(result_r, buffer_size); + EXPECT_STREQ(result.get(), expect_text); + auto correct_length = result_r->data_size(); + EXPECT_NE(result_r->rename(rule.get(), prefix_suffix.get(), reinterpret_cast(result_r) + correct_length), nullptr); + for (auto i = 0; i < correct_length; ++i) { + EXPECT_EQ(result_r->rename(rule.get(), prefix_suffix.get(), reinterpret_cast(result_r) + i), nullptr); + } + } +}; + +TEST_F(TestRename, rename_term_variable) { + // Test basic variable renaming + rename_term_check("`x", "(pre_ _suf)", "`pre_x_suf"); + rename_term_check("`abc", "(a_ _z)", "`a_abc_z"); + // Test with empty prefix/suffix (using _ as empty string representation in item) + rename_term_check("`x", "(_ _)", "`_x_"); + rename_term_check("`var", "(prefix _)", "`prefixvar_"); + rename_term_check("`var", "(_ suffix)", "`_varsuffix"); +} + +TEST_F(TestRename, rename_term_item) { + // Items should not be renamed + rename_term_check("item", "(pre_ _suf)", "item"); + rename_term_check("abc", "(a_ _z)", "abc"); +} + +TEST_F(TestRename, rename_term_list) { + // List with variables should have all variables renamed + rename_term_check("(`x `y)", "(p_ _s)", "(`p_x_s `p_y_s)"); + rename_term_check("(a `x b `y)", "(pre_ _suf)", "(a `pre_x_suf b `pre_y_suf)"); + // Nested lists + rename_term_check("((`x))", "(p_ _s)", "((`p_x_s))"); + rename_term_check("((`x `y) `z)", "(a_ _b)", "((`a_x_b `a_y_b) `a_z_b)"); +} + +TEST_F(TestRename, rename_term_mixed) { + // Mixed term with item and variable + rename_term_check("(item `var)", "(pre _suf)", "(item `prevar_suf)"); + rename_term_check("(f `a `b c)", "(x y)", "(f `xay `xby c)"); +} + +TEST_F(TestRename, rename_term_invalid) { + // Invalid prefix_and_suffix (not a list) + auto term = ds::text_to_term("`x", buffer_size); + auto invalid_ps = ds::text_to_term("item", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps.get(), nullptr), nullptr); + + // Invalid prefix_and_suffix (list size != 2) + auto invalid_ps_size = ds::text_to_term("(a)", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps_size.get(), nullptr), nullptr); + + auto invalid_ps_size3 = ds::text_to_term("(a b c)", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps_size3.get(), nullptr), nullptr); + + // Invalid prefix_and_suffix (elements are not items) + auto invalid_ps_elem = ds::text_to_term("(`a b)", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps_elem.get(), nullptr), nullptr); + + // Null term + ds::term_t* null_term = reinterpret_cast(operator new(buffer_size)); + null_term->set_null(nullptr); + auto valid_ps = ds::text_to_term("(a b)", buffer_size); + EXPECT_EQ(result_t->rename(null_term, valid_ps.get(), nullptr), nullptr); + operator delete(null_term); +} + +TEST_F(TestRename, rename_rule_basic) { + rename_rule_check("`x", "(pre_ _suf)", "----\n`pre_x_suf\n"); + rename_rule_check("item", "(pre_ _suf)", "----\nitem\n"); + rename_rule_check("(`x `y)", "(a b)", "----\n(`axb `ayb)\n"); +} + +TEST_F(TestRename, rename_rule_with_premises) { + rename_rule_check( + "`p\n" + "`q\n" + "----------\n" + "`r\n", + "(pre_ _suf)", + "`pre_p_suf\n" + "`pre_q_suf\n" + "----------\n" + "`pre_r_suf\n" + ); + + rename_rule_check( + "(`p -> `q)\n" + "`p\n" + "----------\n" + "`q\n", + "(x y)", + "(`xpy -> `xqy)\n" + "`xpy\n" + "--------------\n" + "`xqy\n" + ); +} From f65648bdf6e26d5d86ad7c10bbbd0e3acc16a0d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 04:45:32 +0000 Subject: [PATCH 3/8] Add CodeQL build artifacts to .gitignore Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- .gitignore | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5199a53..6e26988 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,6 @@ build dist node_modules coverage -compile_commands.json \ No newline at end of file +compile_commands.json +_codeql_build_dir +_codeql_detected_source_root \ No newline at end of file From 558c653f684a55bde29d8a4119ed77d5273c7f74 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 05:02:15 +0000 Subject: [PATCH 4/8] Change rename interface to support empty prefix/suffix: ((prefix) (suffix)) Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- include/ds/rule.hh | 2 +- include/ds/term.hh | 2 +- src/rename.cc | 45 +++++++++++++++++++++++++------- tests/test_rename.cc | 62 ++++++++++++++++++++++++++------------------ 4 files changed, 75 insertions(+), 36 deletions(-) diff --git a/include/ds/rule.hh b/include/ds/rule.hh index 6cc6941..d6dcf97 100644 --- a/include/ds/rule.hh +++ b/include/ds/rule.hh @@ -118,7 +118,7 @@ namespace ds { /// @brief 将rule中的所有variable添加prefix和suffix, 结果更新至本对象。 /// @param rule 待被重命名的rule。 - /// @param prefix_and_suffix 只有一个conclusion的rule,conclusion是含有两个item的list,分别表示prefix和suffix。 + /// @param prefix_and_suffix 只有一个conclusion的rule,conclusion是含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。例如 ((prefix_) (_suffix)), ((prefix_) ()), (() (_suffix)), (() ())。 /// @param check_tail 可选的尾指针检查。 /// @return 自身,是一个rule_t对象的指针,如果尾指针检查失败则返回nullptr。 rule_t* rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail = nullptr); diff --git a/include/ds/term.hh b/include/ds/term.hh index 0a049d7..2144312 100644 --- a/include/ds/term.hh +++ b/include/ds/term.hh @@ -157,7 +157,7 @@ namespace ds { /// @brief 将term中的所有variable添加prefix和suffix, 结果更新至本对象。 /// @param term 待被重命名的term。 - /// @param prefix_and_suffix 含有两个item的list,分别表示prefix和suffix。 + /// @param prefix_and_suffix 含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。例如 ((prefix_) (_suffix)), ((prefix_) ()), (() (_suffix)), (() ())。 /// @param check_tail 可选的尾指针检查。 /// @return 自身,是一个term_t对象的指针,如果尾指针检查失败则返回nullptr。 term_t* rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail = nullptr); diff --git a/src/rename.cc b/src/rename.cc index 534b21d..38fc1c0 100644 --- a/src/rename.cc +++ b/src/rename.cc @@ -13,15 +13,38 @@ namespace ds { if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { return nullptr; } - item_t* prefix = ps_list->term(0)->item(); - item_t* suffix = ps_list->term(1)->item(); - if (prefix == nullptr || suffix == nullptr) [[unlikely]] { + // prefix_and_suffix is ((prefix) (suffix)), each element is a list of 0 or 1 items + list_t* prefix_list = ps_list->term(0)->list(); + list_t* suffix_list = ps_list->term(1)->list(); + if (prefix_list == nullptr || suffix_list == nullptr) [[unlikely]] { + return nullptr; + } + // Get prefix string (empty if list is empty) + char* prefix_str = nullptr; + length_t prefix_len = 0; + if (prefix_list->get_list_size() == 1) { + item_t* prefix_item = prefix_list->term(0)->item(); + if (prefix_item == nullptr) [[unlikely]] { + return nullptr; + } + prefix_str = prefix_item->name()->get_string(); + prefix_len = strlen(prefix_str); + } else if (prefix_list->get_list_size() != 0) [[unlikely]] { + return nullptr; + } + // Get suffix string (empty if list is empty) + char* suffix_str = nullptr; + length_t suffix_len = 0; + if (suffix_list->get_list_size() == 1) { + item_t* suffix_item = suffix_list->term(0)->item(); + if (suffix_item == nullptr) [[unlikely]] { + return nullptr; + } + suffix_str = suffix_item->name()->get_string(); + suffix_len = strlen(suffix_str); + } else if (suffix_list->get_list_size() != 0) [[unlikely]] { return nullptr; } - char* prefix_str = prefix->name()->get_string(); - char* suffix_str = suffix->name()->get_string(); - length_t prefix_len = strlen(prefix_str); - length_t suffix_len = strlen(suffix_str); switch (term->get_type()) { case term_type_t::variable: { @@ -35,9 +58,13 @@ namespace ds { return nullptr; } char* dst = variable()->name()->get_string(); - memcpy(dst, prefix_str, prefix_len); + if (prefix_len > 0) { + memcpy(dst, prefix_str, prefix_len); + } memcpy(dst + prefix_len, name_str, name_len); - memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + if (suffix_len > 0) { + memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + } dst[new_len - 1] = '\0'; return this; } diff --git a/tests/test_rename.cc b/tests/test_rename.cc index e5398ac..ac2aebd 100644 --- a/tests/test_rename.cc +++ b/tests/test_rename.cc @@ -48,34 +48,38 @@ class TestRename : public ::testing::Test { }; TEST_F(TestRename, rename_term_variable) { - // Test basic variable renaming - rename_term_check("`x", "(pre_ _suf)", "`pre_x_suf"); - rename_term_check("`abc", "(a_ _z)", "`a_abc_z"); - // Test with empty prefix/suffix (using _ as empty string representation in item) - rename_term_check("`x", "(_ _)", "`_x_"); - rename_term_check("`var", "(prefix _)", "`prefixvar_"); - rename_term_check("`var", "(_ suffix)", "`_varsuffix"); + // Test basic variable renaming with new interface ((prefix) (suffix)) + rename_term_check("`x", "((pre_) (_suf))", "`pre_x_suf"); + rename_term_check("`abc", "((a_) (_z))", "`a_abc_z"); + // Test with empty prefix (only suffix) + rename_term_check("`x", "(() (_suf))", "`x_suf"); + rename_term_check("`var", "(() (suffix))", "`varsuffix"); + // Test with empty suffix (only prefix) + rename_term_check("`x", "((pre_) ())", "`pre_x"); + rename_term_check("`var", "((prefix) ())", "`prefixvar"); + // Test with both empty (no change to variable name) + rename_term_check("`x", "(() ())", "`x"); } TEST_F(TestRename, rename_term_item) { // Items should not be renamed - rename_term_check("item", "(pre_ _suf)", "item"); - rename_term_check("abc", "(a_ _z)", "abc"); + rename_term_check("item", "((pre_) (_suf))", "item"); + rename_term_check("abc", "((a_) (_z))", "abc"); } TEST_F(TestRename, rename_term_list) { // List with variables should have all variables renamed - rename_term_check("(`x `y)", "(p_ _s)", "(`p_x_s `p_y_s)"); - rename_term_check("(a `x b `y)", "(pre_ _suf)", "(a `pre_x_suf b `pre_y_suf)"); + rename_term_check("(`x `y)", "((p_) (_s))", "(`p_x_s `p_y_s)"); + rename_term_check("(a `x b `y)", "((pre_) (_suf))", "(a `pre_x_suf b `pre_y_suf)"); // Nested lists - rename_term_check("((`x))", "(p_ _s)", "((`p_x_s))"); - rename_term_check("((`x `y) `z)", "(a_ _b)", "((`a_x_b `a_y_b) `a_z_b)"); + rename_term_check("((`x))", "((p_) (_s))", "((`p_x_s))"); + rename_term_check("((`x `y) `z)", "((a_) (_b))", "((`a_x_b `a_y_b) `a_z_b)"); } TEST_F(TestRename, rename_term_mixed) { // Mixed term with item and variable - rename_term_check("(item `var)", "(pre _suf)", "(item `prevar_suf)"); - rename_term_check("(f `a `b c)", "(x y)", "(f `xay `xby c)"); + rename_term_check("(item `var)", "((pre) (_suf))", "(item `prevar_suf)"); + rename_term_check("(f `a `b c)", "((x) (y))", "(f `xay `xby c)"); } TEST_F(TestRename, rename_term_invalid) { @@ -85,28 +89,36 @@ TEST_F(TestRename, rename_term_invalid) { EXPECT_EQ(result_t->rename(term.get(), invalid_ps.get(), nullptr), nullptr); // Invalid prefix_and_suffix (list size != 2) - auto invalid_ps_size = ds::text_to_term("(a)", buffer_size); + auto invalid_ps_size = ds::text_to_term("((a))", buffer_size); EXPECT_EQ(result_t->rename(term.get(), invalid_ps_size.get(), nullptr), nullptr); - auto invalid_ps_size3 = ds::text_to_term("(a b c)", buffer_size); + auto invalid_ps_size3 = ds::text_to_term("((a) (b) (c))", buffer_size); EXPECT_EQ(result_t->rename(term.get(), invalid_ps_size3.get(), nullptr), nullptr); - // Invalid prefix_and_suffix (elements are not items) - auto invalid_ps_elem = ds::text_to_term("(`a b)", buffer_size); + // Invalid prefix_and_suffix (elements are not lists) + auto invalid_ps_elem = ds::text_to_term("(a b)", buffer_size); EXPECT_EQ(result_t->rename(term.get(), invalid_ps_elem.get(), nullptr), nullptr); + // Invalid prefix_and_suffix (inner list element is variable, not item) + auto invalid_ps_var = ds::text_to_term("((`a) (b))", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps_var.get(), nullptr), nullptr); + + // Invalid prefix_and_suffix (inner list has more than 1 element) + auto invalid_ps_multi = ds::text_to_term("((a b) (c))", buffer_size); + EXPECT_EQ(result_t->rename(term.get(), invalid_ps_multi.get(), nullptr), nullptr); + // Null term ds::term_t* null_term = reinterpret_cast(operator new(buffer_size)); null_term->set_null(nullptr); - auto valid_ps = ds::text_to_term("(a b)", buffer_size); + auto valid_ps = ds::text_to_term("((a) (b))", buffer_size); EXPECT_EQ(result_t->rename(null_term, valid_ps.get(), nullptr), nullptr); operator delete(null_term); } TEST_F(TestRename, rename_rule_basic) { - rename_rule_check("`x", "(pre_ _suf)", "----\n`pre_x_suf\n"); - rename_rule_check("item", "(pre_ _suf)", "----\nitem\n"); - rename_rule_check("(`x `y)", "(a b)", "----\n(`axb `ayb)\n"); + rename_rule_check("`x", "((pre_) (_suf))", "----\n`pre_x_suf\n"); + rename_rule_check("item", "((pre_) (_suf))", "----\nitem\n"); + rename_rule_check("(`x `y)", "((a) (b))", "----\n(`axb `ayb)\n"); } TEST_F(TestRename, rename_rule_with_premises) { @@ -115,7 +127,7 @@ TEST_F(TestRename, rename_rule_with_premises) { "`q\n" "----------\n" "`r\n", - "(pre_ _suf)", + "((pre_) (_suf))", "`pre_p_suf\n" "`pre_q_suf\n" "----------\n" @@ -127,7 +139,7 @@ TEST_F(TestRename, rename_rule_with_premises) { "`p\n" "----------\n" "`q\n", - "(x y)", + "((x) (y))", "(`xpy -> `xqy)\n" "`xpy\n" "--------------\n" From dc1a9e1a71caf0372a01ed806247e7c75645ec72 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 05:21:31 +0000 Subject: [PATCH 5/8] Refactor rename.cc: extract prefix/suffix once at start with helper functions, use Chinese comments Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- src/rename.cc | 105 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/src/rename.cc b/src/rename.cc index 38fc1c0..0cb3fcb 100644 --- a/src/rename.cc +++ b/src/rename.cc @@ -8,56 +8,89 @@ #include namespace ds { - term_t* term_t::rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail) { + /// @brief 从prefix_and_suffix中提取prefix和suffix字符串。 + /// @param prefix_and_suffix 格式为((prefix) (suffix))的term,每个内部list包含0或1个item。 + /// @param prefix_str 输出参数,prefix字符串指针,如果prefix为空则为nullptr。 + /// @param prefix_len 输出参数,prefix字符串长度。 + /// @param suffix_str 输出参数,suffix字符串指针,如果suffix为空则为nullptr。 + /// @param suffix_len 输出参数,suffix字符串长度。 + /// @return 成功返回true,格式错误返回false。 + static bool extract_prefix_suffix( + term_t* prefix_and_suffix, + char*& prefix_str, + length_t& prefix_len, + char*& suffix_str, + length_t& suffix_len + ) { list_t* ps_list = prefix_and_suffix->list(); if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { - return nullptr; + return false; } - // prefix_and_suffix is ((prefix) (suffix)), each element is a list of 0 or 1 items + // prefix_and_suffix格式为((prefix) (suffix)),每个元素是包含0或1个item的list list_t* prefix_list = ps_list->term(0)->list(); list_t* suffix_list = ps_list->term(1)->list(); if (prefix_list == nullptr || suffix_list == nullptr) [[unlikely]] { - return nullptr; + return false; } - // Get prefix string (empty if list is empty) - char* prefix_str = nullptr; - length_t prefix_len = 0; + // 获取prefix字符串(如果list为空则为nullptr) + prefix_str = nullptr; + prefix_len = 0; if (prefix_list->get_list_size() == 1) { item_t* prefix_item = prefix_list->term(0)->item(); if (prefix_item == nullptr) [[unlikely]] { - return nullptr; + return false; } prefix_str = prefix_item->name()->get_string(); prefix_len = strlen(prefix_str); } else if (prefix_list->get_list_size() != 0) [[unlikely]] { - return nullptr; + return false; } - // Get suffix string (empty if list is empty) - char* suffix_str = nullptr; - length_t suffix_len = 0; + // 获取suffix字符串(如果list为空则为nullptr) + suffix_str = nullptr; + suffix_len = 0; if (suffix_list->get_list_size() == 1) { item_t* suffix_item = suffix_list->term(0)->item(); if (suffix_item == nullptr) [[unlikely]] { - return nullptr; + return false; } suffix_str = suffix_item->name()->get_string(); suffix_len = strlen(suffix_str); } else if (suffix_list->get_list_size() != 0) [[unlikely]] { - return nullptr; + return false; } + return true; + } + /// @brief 内部递归函数,使用已提取的prefix和suffix字符串对term进行重命名。 + /// @param result 存放结果的term指针。 + /// @param term 待被重命名的term。 + /// @param prefix_str prefix字符串指针,可以为nullptr。 + /// @param prefix_len prefix字符串长度。 + /// @param suffix_str suffix字符串指针,可以为nullptr。 + /// @param suffix_len suffix字符串长度。 + /// @param check_tail 可选的尾指针检查。 + /// @return 成功返回result,失败返回nullptr。 + static term_t* rename_with_strings( + term_t* result, + term_t* term, + char* prefix_str, + length_t prefix_len, + char* suffix_str, + length_t suffix_len, + std::byte* check_tail + ) { switch (term->get_type()) { case term_type_t::variable: { char* name_str = term->variable()->name()->get_string(); length_t name_len = strlen(name_str); length_t new_len = prefix_len + name_len + suffix_len + 1; - if (set_variable(check_tail) == nullptr) [[unlikely]] { + if (result->set_variable(check_tail) == nullptr) [[unlikely]] { return nullptr; } - if (variable()->name()->set_length(new_len, check_tail) == nullptr) [[unlikely]] { + if (result->variable()->name()->set_length(new_len, check_tail) == nullptr) [[unlikely]] { return nullptr; } - char* dst = variable()->name()->get_string(); + char* dst = result->variable()->name()->get_string(); if (prefix_len > 0) { memcpy(dst, prefix_str, prefix_len); } @@ -66,49 +99,69 @@ namespace ds { memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); } dst[new_len - 1] = '\0'; - return this; + return result; } case term_type_t::item: { - if (check_before_fail(check_tail, this, term->data_size())) [[unlikely]] { + if (check_before_fail(check_tail, result, term->data_size())) [[unlikely]] { return nullptr; } - memcpy(this, term, term->data_size()); - return this; + memcpy(result, term, term->data_size()); + return result; } case term_type_t::list: { list_t* src = term->list(); - if (set_list(check_tail) == nullptr) [[unlikely]] { + if (result->set_list(check_tail) == nullptr) [[unlikely]] { return nullptr; } - list_t* dst = list(); + list_t* dst = result->list(); if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { return nullptr; } for (length_t index = 0; index < dst->get_list_size(); ++index) { - if (dst->term(index)->rename(src->term(index), prefix_and_suffix, check_tail) == nullptr) [[unlikely]] { + if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { return nullptr; } dst->update_term_size(index); } - return this; + return result; } default: return nullptr; } } + term_t* term_t::rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail) { + // 在开头提取prefix和suffix字符串,避免每次递归时重复解析 + char* prefix_str; + length_t prefix_len; + char* suffix_str; + length_t suffix_len; + if (!extract_prefix_suffix(prefix_and_suffix, prefix_str, prefix_len, suffix_str, suffix_len)) [[unlikely]] { + return nullptr; + } + return rename_with_strings(this, term, prefix_str, prefix_len, suffix_str, suffix_len, check_tail); + } + rule_t* rule_t::rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail) { term_t* ps_term = prefix_and_suffix->only_conclusion(); if (ps_term == nullptr) [[unlikely]] { return nullptr; } + // 在开头提取prefix和suffix字符串,避免每次递归时重复解析 + char* prefix_str; + length_t prefix_len; + char* suffix_str; + length_t suffix_len; + if (!extract_prefix_suffix(ps_term, prefix_str, prefix_len, suffix_str, suffix_len)) [[unlikely]] { + return nullptr; + } list_t* dst = this; list_t* src = rule; if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { return nullptr; } for (length_t index = 0; index < dst->get_list_size(); ++index) { - if (dst->term(index)->rename(src->term(index), ps_term, check_tail) == nullptr) [[unlikely]] { + if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { return nullptr; } dst->update_term_size(index); From ee94086269fe5b159f7637968c041bb741fd2e1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 05:45:16 +0000 Subject: [PATCH 6/8] Use anonymous namespace and replace strlen with get_length() in rename.cc Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- src/rename.cc | 221 ++++++++++++++++++++++++++------------------------ 1 file changed, 113 insertions(+), 108 deletions(-) diff --git a/src/rename.cc b/src/rename.cc index 0cb3fcb..29ee6e4 100644 --- a/src/rename.cc +++ b/src/rename.cc @@ -8,127 +8,132 @@ #include namespace ds { - /// @brief 从prefix_and_suffix中提取prefix和suffix字符串。 - /// @param prefix_and_suffix 格式为((prefix) (suffix))的term,每个内部list包含0或1个item。 - /// @param prefix_str 输出参数,prefix字符串指针,如果prefix为空则为nullptr。 - /// @param prefix_len 输出参数,prefix字符串长度。 - /// @param suffix_str 输出参数,suffix字符串指针,如果suffix为空则为nullptr。 - /// @param suffix_len 输出参数,suffix字符串长度。 - /// @return 成功返回true,格式错误返回false。 - static bool extract_prefix_suffix( - term_t* prefix_and_suffix, - char*& prefix_str, - length_t& prefix_len, - char*& suffix_str, - length_t& suffix_len - ) { - list_t* ps_list = prefix_and_suffix->list(); - if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { - return false; - } - // prefix_and_suffix格式为((prefix) (suffix)),每个元素是包含0或1个item的list - list_t* prefix_list = ps_list->term(0)->list(); - list_t* suffix_list = ps_list->term(1)->list(); - if (prefix_list == nullptr || suffix_list == nullptr) [[unlikely]] { - return false; - } - // 获取prefix字符串(如果list为空则为nullptr) - prefix_str = nullptr; - prefix_len = 0; - if (prefix_list->get_list_size() == 1) { - item_t* prefix_item = prefix_list->term(0)->item(); - if (prefix_item == nullptr) [[unlikely]] { + namespace { + /// @brief 从prefix_and_suffix中提取prefix和suffix字符串。 + /// @param prefix_and_suffix 格式为((prefix) (suffix))的term,每个内部list包含0或1个item。 + /// @param prefix_str 输出参数,prefix字符串指针,如果prefix为空则为nullptr。 + /// @param prefix_len 输出参数,prefix字符串长度。 + /// @param suffix_str 输出参数,suffix字符串指针,如果suffix为空则为nullptr。 + /// @param suffix_len 输出参数,suffix字符串长度。 + /// @return 成功返回true,格式错误返回false。 + bool extract_prefix_suffix( + term_t* prefix_and_suffix, + char*& prefix_str, + length_t& prefix_len, + char*& suffix_str, + length_t& suffix_len + ) { + list_t* ps_list = prefix_and_suffix->list(); + if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { return false; } - prefix_str = prefix_item->name()->get_string(); - prefix_len = strlen(prefix_str); - } else if (prefix_list->get_list_size() != 0) [[unlikely]] { - return false; - } - // 获取suffix字符串(如果list为空则为nullptr) - suffix_str = nullptr; - suffix_len = 0; - if (suffix_list->get_list_size() == 1) { - item_t* suffix_item = suffix_list->term(0)->item(); - if (suffix_item == nullptr) [[unlikely]] { + // prefix_and_suffix格式为((prefix) (suffix)),每个元素是包含0或1个item的list + list_t* prefix_list = ps_list->term(0)->list(); + list_t* suffix_list = ps_list->term(1)->list(); + if (prefix_list == nullptr || suffix_list == nullptr) [[unlikely]] { return false; } - suffix_str = suffix_item->name()->get_string(); - suffix_len = strlen(suffix_str); - } else if (suffix_list->get_list_size() != 0) [[unlikely]] { - return false; - } - return true; - } - - /// @brief 内部递归函数,使用已提取的prefix和suffix字符串对term进行重命名。 - /// @param result 存放结果的term指针。 - /// @param term 待被重命名的term。 - /// @param prefix_str prefix字符串指针,可以为nullptr。 - /// @param prefix_len prefix字符串长度。 - /// @param suffix_str suffix字符串指针,可以为nullptr。 - /// @param suffix_len suffix字符串长度。 - /// @param check_tail 可选的尾指针检查。 - /// @return 成功返回result,失败返回nullptr。 - static term_t* rename_with_strings( - term_t* result, - term_t* term, - char* prefix_str, - length_t prefix_len, - char* suffix_str, - length_t suffix_len, - std::byte* check_tail - ) { - switch (term->get_type()) { - case term_type_t::variable: { - char* name_str = term->variable()->name()->get_string(); - length_t name_len = strlen(name_str); - length_t new_len = prefix_len + name_len + suffix_len + 1; - if (result->set_variable(check_tail) == nullptr) [[unlikely]] { - return nullptr; - } - if (result->variable()->name()->set_length(new_len, check_tail) == nullptr) [[unlikely]] { - return nullptr; - } - char* dst = result->variable()->name()->get_string(); - if (prefix_len > 0) { - memcpy(dst, prefix_str, prefix_len); - } - memcpy(dst + prefix_len, name_str, name_len); - if (suffix_len > 0) { - memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + // 获取prefix字符串(如果list为空则为nullptr) + prefix_str = nullptr; + prefix_len = 0; + if (prefix_list->get_list_size() == 1) { + item_t* prefix_item = prefix_list->term(0)->item(); + if (prefix_item == nullptr) [[unlikely]] { + return false; + } + prefix_str = prefix_item->name()->get_string(); + // get_length()返回的是包含末尾\0的长度,所以需要减1 + prefix_len = prefix_item->name()->get_length() - 1; + } else if (prefix_list->get_list_size() != 0) [[unlikely]] { + return false; } - dst[new_len - 1] = '\0'; - return result; - } - case term_type_t::item: { - if (check_before_fail(check_tail, result, term->data_size())) [[unlikely]] { - return nullptr; + // 获取suffix字符串(如果list为空则为nullptr) + suffix_str = nullptr; + suffix_len = 0; + if (suffix_list->get_list_size() == 1) { + item_t* suffix_item = suffix_list->term(0)->item(); + if (suffix_item == nullptr) [[unlikely]] { + return false; + } + suffix_str = suffix_item->name()->get_string(); + // get_length()返回的是包含末尾\0的长度,所以需要减1 + suffix_len = suffix_item->name()->get_length() - 1; + } else if (suffix_list->get_list_size() != 0) [[unlikely]] { + return false; } - memcpy(result, term, term->data_size()); - return result; + return true; } - case term_type_t::list: { - list_t* src = term->list(); - if (result->set_list(check_tail) == nullptr) [[unlikely]] { - return nullptr; + + /// @brief 内部递归函数,使用已提取的prefix和suffix字符串对term进行重命名。 + /// @param result 存放结果的term指针。 + /// @param term 待被重命名的term。 + /// @param prefix_str prefix字符串指针,可以为nullptr。 + /// @param prefix_len prefix字符串长度。 + /// @param suffix_str suffix字符串指针,可以为nullptr。 + /// @param suffix_len suffix字符串长度。 + /// @param check_tail 可选的尾指针检查。 + /// @return 成功返回result,失败返回nullptr。 + term_t* rename_with_strings( + term_t* result, + term_t* term, + char* prefix_str, + length_t prefix_len, + char* suffix_str, + length_t suffix_len, + std::byte* check_tail + ) { + switch (term->get_type()) { + case term_type_t::variable: { + // get_length()返回的是包含末尾\0的长度,所以需要减1 + length_t name_len = term->variable()->name()->get_length() - 1; + length_t new_len = prefix_len + name_len + suffix_len + 1; + if (result->set_variable(check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + if (result->variable()->name()->set_length(new_len, check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + char* name_str = term->variable()->name()->get_string(); + char* dst = result->variable()->name()->get_string(); + if (prefix_len > 0) { + memcpy(dst, prefix_str, prefix_len); + } + memcpy(dst + prefix_len, name_str, name_len); + if (suffix_len > 0) { + memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + } + dst[new_len - 1] = '\0'; + return result; } - list_t* dst = result->list(); - if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { - return nullptr; + case term_type_t::item: { + if (check_before_fail(check_tail, result, term->data_size())) [[unlikely]] { + return nullptr; + } + memcpy(result, term, term->data_size()); + return result; } - for (length_t index = 0; index < dst->get_list_size(); ++index) { - if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { + case term_type_t::list: { + list_t* src = term->list(); + if (result->set_list(check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + list_t* dst = result->list(); + if (dst->set_list_size(src->get_list_size(), check_tail) == nullptr) [[unlikely]] { return nullptr; } - dst->update_term_size(index); + for (length_t index = 0; index < dst->get_list_size(); ++index) { + if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { + return nullptr; + } + dst->update_term_size(index); + } + return result; + } + default: + return nullptr; } - return result; - } - default: - return nullptr; } - } + } // namespace term_t* term_t::rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail) { // 在开头提取prefix和suffix字符串,避免每次递归时重复解析 From 821cf76b1a123e980dc5a71c6e2dda928b289d05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 06:07:04 +0000 Subject: [PATCH 7/8] Use prefix_suffix_t struct for parameters and replace '\\0' with 0 Co-authored-by: hzhangxyz <11623447+hzhangxyz@users.noreply.github.com> --- src/rename.cc | 81 +++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 47 deletions(-) diff --git a/src/rename.cc b/src/rename.cc index 29ee6e4..89acf91 100644 --- a/src/rename.cc +++ b/src/rename.cc @@ -9,20 +9,19 @@ namespace ds { namespace { + /// @brief 存储prefix和suffix字符串信息的结构体。 + struct prefix_suffix_t { + char* prefix_str; // prefix字符串指针,如果prefix为空则为nullptr + length_t prefix_len; // prefix字符串长度 + char* suffix_str; // suffix字符串指针,如果suffix为空则为nullptr + length_t suffix_len; // suffix字符串长度 + }; + /// @brief 从prefix_and_suffix中提取prefix和suffix字符串。 /// @param prefix_and_suffix 格式为((prefix) (suffix))的term,每个内部list包含0或1个item。 - /// @param prefix_str 输出参数,prefix字符串指针,如果prefix为空则为nullptr。 - /// @param prefix_len 输出参数,prefix字符串长度。 - /// @param suffix_str 输出参数,suffix字符串指针,如果suffix为空则为nullptr。 - /// @param suffix_len 输出参数,suffix字符串长度。 + /// @param ps 输出参数,存储提取的prefix和suffix信息。 /// @return 成功返回true,格式错误返回false。 - bool extract_prefix_suffix( - term_t* prefix_and_suffix, - char*& prefix_str, - length_t& prefix_len, - char*& suffix_str, - length_t& suffix_len - ) { + bool extract_prefix_suffix(term_t* prefix_and_suffix, prefix_suffix_t* ps) { list_t* ps_list = prefix_and_suffix->list(); if (ps_list == nullptr || ps_list->get_list_size() != 2) [[unlikely]] { return false; @@ -34,30 +33,30 @@ namespace ds { return false; } // 获取prefix字符串(如果list为空则为nullptr) - prefix_str = nullptr; - prefix_len = 0; + ps->prefix_str = nullptr; + ps->prefix_len = 0; if (prefix_list->get_list_size() == 1) { item_t* prefix_item = prefix_list->term(0)->item(); if (prefix_item == nullptr) [[unlikely]] { return false; } - prefix_str = prefix_item->name()->get_string(); + ps->prefix_str = prefix_item->name()->get_string(); // get_length()返回的是包含末尾\0的长度,所以需要减1 - prefix_len = prefix_item->name()->get_length() - 1; + ps->prefix_len = prefix_item->name()->get_length() - 1; } else if (prefix_list->get_list_size() != 0) [[unlikely]] { return false; } // 获取suffix字符串(如果list为空则为nullptr) - suffix_str = nullptr; - suffix_len = 0; + ps->suffix_str = nullptr; + ps->suffix_len = 0; if (suffix_list->get_list_size() == 1) { item_t* suffix_item = suffix_list->term(0)->item(); if (suffix_item == nullptr) [[unlikely]] { return false; } - suffix_str = suffix_item->name()->get_string(); + ps->suffix_str = suffix_item->name()->get_string(); // get_length()返回的是包含末尾\0的长度,所以需要减1 - suffix_len = suffix_item->name()->get_length() - 1; + ps->suffix_len = suffix_item->name()->get_length() - 1; } else if (suffix_list->get_list_size() != 0) [[unlikely]] { return false; } @@ -67,26 +66,20 @@ namespace ds { /// @brief 内部递归函数,使用已提取的prefix和suffix字符串对term进行重命名。 /// @param result 存放结果的term指针。 /// @param term 待被重命名的term。 - /// @param prefix_str prefix字符串指针,可以为nullptr。 - /// @param prefix_len prefix字符串长度。 - /// @param suffix_str suffix字符串指针,可以为nullptr。 - /// @param suffix_len suffix字符串长度。 + /// @param ps 包含prefix和suffix信息的结构体指针。 /// @param check_tail 可选的尾指针检查。 /// @return 成功返回result,失败返回nullptr。 term_t* rename_with_strings( term_t* result, term_t* term, - char* prefix_str, - length_t prefix_len, - char* suffix_str, - length_t suffix_len, + prefix_suffix_t* ps, std::byte* check_tail ) { switch (term->get_type()) { case term_type_t::variable: { // get_length()返回的是包含末尾\0的长度,所以需要减1 length_t name_len = term->variable()->name()->get_length() - 1; - length_t new_len = prefix_len + name_len + suffix_len + 1; + length_t new_len = ps->prefix_len + name_len + ps->suffix_len + 1; if (result->set_variable(check_tail) == nullptr) [[unlikely]] { return nullptr; } @@ -95,14 +88,14 @@ namespace ds { } char* name_str = term->variable()->name()->get_string(); char* dst = result->variable()->name()->get_string(); - if (prefix_len > 0) { - memcpy(dst, prefix_str, prefix_len); + if (ps->prefix_len > 0) { + memcpy(dst, ps->prefix_str, ps->prefix_len); } - memcpy(dst + prefix_len, name_str, name_len); - if (suffix_len > 0) { - memcpy(dst + prefix_len + name_len, suffix_str, suffix_len); + memcpy(dst + ps->prefix_len, name_str, name_len); + if (ps->suffix_len > 0) { + memcpy(dst + ps->prefix_len + name_len, ps->suffix_str, ps->suffix_len); } - dst[new_len - 1] = '\0'; + dst[new_len - 1] = 0; return result; } case term_type_t::item: { @@ -122,7 +115,7 @@ namespace ds { return nullptr; } for (length_t index = 0; index < dst->get_list_size(); ++index) { - if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { + if (rename_with_strings(dst->term(index), src->term(index), ps, check_tail) == nullptr) [[unlikely]] { return nullptr; } dst->update_term_size(index); @@ -137,14 +130,11 @@ namespace ds { term_t* term_t::rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail) { // 在开头提取prefix和suffix字符串,避免每次递归时重复解析 - char* prefix_str; - length_t prefix_len; - char* suffix_str; - length_t suffix_len; - if (!extract_prefix_suffix(prefix_and_suffix, prefix_str, prefix_len, suffix_str, suffix_len)) [[unlikely]] { + prefix_suffix_t ps; + if (!extract_prefix_suffix(prefix_and_suffix, &ps)) [[unlikely]] { return nullptr; } - return rename_with_strings(this, term, prefix_str, prefix_len, suffix_str, suffix_len, check_tail); + return rename_with_strings(this, term, &ps, check_tail); } rule_t* rule_t::rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail) { @@ -153,11 +143,8 @@ namespace ds { return nullptr; } // 在开头提取prefix和suffix字符串,避免每次递归时重复解析 - char* prefix_str; - length_t prefix_len; - char* suffix_str; - length_t suffix_len; - if (!extract_prefix_suffix(ps_term, prefix_str, prefix_len, suffix_str, suffix_len)) [[unlikely]] { + prefix_suffix_t ps; + if (!extract_prefix_suffix(ps_term, &ps)) [[unlikely]] { return nullptr; } list_t* dst = this; @@ -166,7 +153,7 @@ namespace ds { return nullptr; } for (length_t index = 0; index < dst->get_list_size(); ++index) { - if (rename_with_strings(dst->term(index), src->term(index), prefix_str, prefix_len, suffix_str, suffix_len, check_tail) == nullptr) [[unlikely]] { + if (rename_with_strings(dst->term(index), src->term(index), &ps, check_tail) == nullptr) [[unlikely]] { return nullptr; } dst->update_term_size(index); From b4511c7c7cd70b4a4945a82d674d774ae1799e4a Mon Sep 17 00:00:00 2001 From: Hao Zhang Date: Tue, 25 Nov 2025 14:24:39 +0800 Subject: [PATCH 8/8] Clang format. --- include/ds/rule.hh | 2 +- include/ds/term.hh | 2 +- src/rename.cc | 11 +++-------- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/include/ds/rule.hh b/include/ds/rule.hh index d6dcf97..732a42c 100644 --- a/include/ds/rule.hh +++ b/include/ds/rule.hh @@ -118,7 +118,7 @@ namespace ds { /// @brief 将rule中的所有variable添加prefix和suffix, 结果更新至本对象。 /// @param rule 待被重命名的rule。 - /// @param prefix_and_suffix 只有一个conclusion的rule,conclusion是含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。例如 ((prefix_) (_suffix)), ((prefix_) ()), (() (_suffix)), (() ())。 + /// @param prefix_and_suffix 只有一个conclusion的rule,conclusion是含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。 /// @param check_tail 可选的尾指针检查。 /// @return 自身,是一个rule_t对象的指针,如果尾指针检查失败则返回nullptr。 rule_t* rename(rule_t* rule, rule_t* prefix_and_suffix, std::byte* check_tail = nullptr); diff --git a/include/ds/term.hh b/include/ds/term.hh index 2144312..b80120e 100644 --- a/include/ds/term.hh +++ b/include/ds/term.hh @@ -157,7 +157,7 @@ namespace ds { /// @brief 将term中的所有variable添加prefix和suffix, 结果更新至本对象。 /// @param term 待被重命名的term。 - /// @param prefix_and_suffix 含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。例如 ((prefix_) (_suffix)), ((prefix_) ()), (() (_suffix)), (() ())。 + /// @param prefix_and_suffix 含有两个list的list,每个内部list包含0或1个item,分别表示prefix和suffix。 /// @param check_tail 可选的尾指针检查。 /// @return 自身,是一个term_t对象的指针,如果尾指针检查失败则返回nullptr。 term_t* rename(term_t* term, term_t* prefix_and_suffix, std::byte* check_tail = nullptr); diff --git a/src/rename.cc b/src/rename.cc index 89acf91..e6fedc9 100644 --- a/src/rename.cc +++ b/src/rename.cc @@ -11,9 +11,9 @@ namespace ds { namespace { /// @brief 存储prefix和suffix字符串信息的结构体。 struct prefix_suffix_t { - char* prefix_str; // prefix字符串指针,如果prefix为空则为nullptr + char* prefix_str; // prefix字符串指针,如果prefix为空则为nullptr length_t prefix_len; // prefix字符串长度 - char* suffix_str; // suffix字符串指针,如果suffix为空则为nullptr + char* suffix_str; // suffix字符串指针,如果suffix为空则为nullptr length_t suffix_len; // suffix字符串长度 }; @@ -69,12 +69,7 @@ namespace ds { /// @param ps 包含prefix和suffix信息的结构体指针。 /// @param check_tail 可选的尾指针检查。 /// @return 成功返回result,失败返回nullptr。 - term_t* rename_with_strings( - term_t* result, - term_t* term, - prefix_suffix_t* ps, - std::byte* check_tail - ) { + term_t* rename_with_strings(term_t* result, term_t* term, prefix_suffix_t* ps, std::byte* check_tail) { switch (term->get_type()) { case term_type_t::variable: { // get_length()返回的是包含末尾\0的长度,所以需要减1