From 42c5e39694784cfd66dc902c5f8ae50a207188a1 Mon Sep 17 00:00:00 2001 From: ARCJ137442 <61109168+ARCJ137442@users.noreply.github.com> Date: Tue, 11 Jun 2024 21:26:56 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20:recycle:=20=E5=88=9D=E6=AD=A5?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E3=80=8C=E8=AF=AD=E4=B9=89=E5=8C=96=E8=AF=8D?= =?UTF-8?q?=E9=A1=B9=E9=A2=84=E6=9C=9F=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ✅现在能正确处理「带变量的可交换词项」如:「<(&&,<$1 --> lock>,<$2 --> key>) ==> <$1 --> (/,open,$2,_)>>」🆚「<(&&,<$1 --> key>,<$2 --> lock>) ==> <$2 --> (/,open,$1,_)>>」 - ♻️微调模块结构,细化拆分功能 - ⬆️升级Narsese.rs依赖版本,支持emoji解析 - ⚠️目前功能尚未完全稳定(需要实际发布性构建验证) --- Cargo.lock | 515 ++++++++++++----- Cargo.toml | 2 +- .../{vm_interact.rs => vm_interact/mod.rs} | 146 +---- .../vm_interact/narsese_expectation.rs | 168 ++++++ src/test_tools/vm_interact/term_equal.rs | 526 ++++++++++++++++++ 5 files changed, 1078 insertions(+), 279 deletions(-) rename src/test_tools/{vm_interact.rs => vm_interact/mod.rs} (55%) create mode 100644 src/test_tools/vm_interact/narsese_expectation.rs create mode 100644 src/test_tools/vm_interact/term_equal.rs diff --git a/Cargo.lock b/Cargo.lock index 22e91ec..2aa28c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,47 +13,48 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -61,19 +62,19 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.81" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "autocfg" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "babel_nar" -version = "0.23.0" +version = "0.24.0" dependencies = [ "anyhow", "clap", @@ -177,9 +178,9 @@ checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -187,9 +188,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -199,9 +200,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.4" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", @@ -211,9 +212,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "clearscreen" @@ -230,9 +231,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "colored" @@ -311,17 +312,28 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "either" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -396,9 +408,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06fddc2749e0528d2813f95e050e87e52c8cbbae56223b9babf73b3e53b0cc6" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if 1.0.0", "libc", @@ -422,18 +434,138 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f3935c160d00ac752e09787e6e6bfc26494c2183cc922f1bc678a60d4733bc2" + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -445,6 +577,12 @@ dependencies = [ "libc", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" version = "1.0.11" @@ -475,9 +613,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libredox" @@ -491,9 +629,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litemap" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" [[package]] name = "log" @@ -558,15 +702,15 @@ dependencies = [ [[package]] name = "nar_dev_utils" -version = "0.26.4" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1662c34eaa2853e1342dc1bbedf0373dc4315d1b0b7637e2c25cf424c9642355" +checksum = "de2fad06f5a0f39772634d0f72d7d114bc31f33b089012692330e914e5f02bea" [[package]] name = "narsese" -version = "0.15.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd2b29328c5c47d1b94893a9a85a58bee0165fde6c87490b0d01a3c00c41ac2b" +checksum = "c5c2614d82af57bcbb3455958079c2abd45dc32dd75f63f4c8e72a3284afe68c" dependencies = [ "lazy_static", "nar_dev_utils", @@ -574,9 +718,9 @@ dependencies = [ [[package]] name = "navm" -version = "0.15.0" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40fbc008d70ade7e0b94a9dc005ec297b229a3a3e9b0334e803ba4e605cb7dc7" +checksum = "f45bd2adea577f139276fef0b392781292eb5f73608092f2d44be76c6db2be4f" dependencies = [ "anyhow", "nar_dev_utils", @@ -638,9 +782,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -649,9 +793,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" dependencies = [ "pest", "pest_generator", @@ -659,9 +803,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" dependencies = [ "pest", "pest_meta", @@ -672,9 +816,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.9" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" dependencies = [ "once_cell", "pest", @@ -727,18 +871,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -805,16 +949,16 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "getrandom 0.2.13", + "getrandom 0.2.15", "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -824,9 +968,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -835,15 +979,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -854,24 +998,24 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", @@ -880,9 +1024,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "itoa", "ryu", @@ -927,6 +1071,18 @@ dependencies = [ "autocfg", ] +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.11.1" @@ -935,15 +1091,26 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.58" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "terminfo" version = "0.8.0" @@ -959,18 +1126,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", @@ -978,20 +1145,15 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "typenum" version = "1.17.0" @@ -1004,43 +1166,40 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" @@ -1121,7 +1280,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -1141,17 +1300,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -1162,9 +1322,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -1174,9 +1334,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -1186,9 +1346,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -1198,9 +1364,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -1210,9 +1376,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -1222,9 +1388,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -1234,9 +1400,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winsafe" @@ -1244,6 +1410,18 @@ version = "0.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d135d17ab770252ad95e9a872d365cf3090e3be864a34ab46f48555993efc904" +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "ws" version = "0.9.2" @@ -1271,3 +1449,70 @@ dependencies = [ "winapi 0.2.8", "winapi-build", ] + +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 2da9ab0..75e78f6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "babel_nar" -version = "0.23.0" +version = "0.24.0" edition = "2021" description = """ Implementation and application supports of the NAVM model diff --git a/src/test_tools/vm_interact.rs b/src/test_tools/vm_interact/mod.rs similarity index 55% rename from src/test_tools/vm_interact.rs rename to src/test_tools/vm_interact/mod.rs index f8e10f3..ff07cd5 100644 --- a/src/test_tools/vm_interact.rs +++ b/src/test_tools/vm_interact/mod.rs @@ -7,151 +7,11 @@ use nar_dev_utils::{if_return, ResultBoost}; use navm::{cmd::Cmd, output::Output, vm::VmRuntime}; use std::{ops::ControlFlow, path::Path}; -/// * 🎯统一存放与「Narsese预期识别」有关的代码 -/// * 🚩【2024-04-02 22:49:12】从[`crate::runtimes::command_vm::runtime::tests`]中迁移而来 -mod narsese_expectation { - use nar_dev_utils::if_return; - use narsese::{ - api::{GetBudget, GetPunctuation, GetStamp, GetTerm, GetTruth}, - conversion::{ - inter_type::lexical_fold::TryFoldInto, - string::impl_enum::format_instances::FORMAT_ASCII as FORMAT_ASCII_ENUM, - }, - enum_narsese::{ - Budget as EnumBudget, Narsese as EnumNarsese, Sentence as EnumSentence, - Task as EnumTask, Term as EnumTerm, Truth as EnumTruth, - }, - lexical::Narsese, - }; - use navm::output::Operation; - - /// 判断「输出是否(在Narsese语义层面)符合预期」 - /// * 🎯词法Narsese⇒枚举Narsese,以便从语义上判断 - pub fn is_expected_narsese_lexical(expected: &Narsese, out: &Narsese) -> bool { - // 临时折叠预期 - let expected = (expected.clone().try_fold_into(&FORMAT_ASCII_ENUM)) - .expect("作为预期的词法Narsese无法折叠!"); - // 与预期一致 - (out.clone() // 必须复制:折叠消耗自身 - .try_fold_into(&FORMAT_ASCII_ENUM)) - .is_ok_and(|out| is_expected_narsese(&expected, &out)) - } - - /// 判断「输出是否(在Narsese层面)符合预期」 - /// * 🎯预期词项⇒只比较词项,语句⇒只比较语句,…… - pub fn is_expected_narsese(expected: &EnumNarsese, out: &EnumNarsese) -> bool { - match ((expected), (out)) { - // 词项⇒只比较词项 | 直接判等 - (EnumNarsese::Term(term), ..) => is_expected_term(term, out.get_term()), - // 语句⇒只比较语句 - // ! 仍然不能直接判等:真值/预算值 - ( - EnumNarsese::Sentence(s_exp), - EnumNarsese::Sentence(s_out) | EnumNarsese::Task(EnumTask(s_out, ..)), - ) => is_expected_sentence(s_exp, s_out), - // 任务⇒直接判断 - // ! 仍然不能直接判等:真值/预算值 - (EnumNarsese::Task(t_exp), EnumNarsese::Task(t_out)) => is_expected_task(t_exp, t_out), - // 所有其它情况⇒都是假 - (..) => false, - } - } - - /// 判断输出的任务是否与预期任务相同 - /// * 🎯用于细粒度判断「预算值」「语句」的预期 - pub fn is_expected_task(expected: &EnumTask, out: &EnumTask) -> bool { - // 预算 - is_expected_budget(expected.get_budget(), out.get_budget()) - // 语句 - && is_expected_sentence(expected.get_sentence(), out.get_sentence()) - } - - /// 判断输出的语句是否与预期语句相同 - /// * 🎯用于细粒度判断「真值」的预期 - pub fn is_expected_sentence(expected: &EnumSentence, out: &EnumSentence) -> bool { - // 词项 - (is_expected_term(expected.get_term(),out.get_term())) - // 标点相等 - && expected.get_punctuation() == out.get_punctuation() - // 时间戳相等 - && expected.get_stamp()== out.get_stamp() - // 真值兼容 | 需要考虑「没有真值可判断」的情况 - && match (expected.get_truth(),out.get_truth()) { - // 都有⇒判断「真值是否符合预期」 - (Some(t_e), Some(t_o)) => is_expected_truth(t_e, t_o), - // 都没⇒肯定真 - (None, None) => true, - // 有一个没有⇒肯定假 - _ => false, - } - } - - /// 判断输出的词项是否与预期词项相同 - /// * 🎯用于独立出「词项预期」功能 - /// * 🚩【2024-04-02 22:55:13】目前直接判等 - pub fn is_expected_term(expected: &EnumTerm, out: &EnumTerm) -> bool { - expected == out - } - - /// 判断「输出是否在真值层面符合预期」 - /// * 🎯空真值的语句,应该符合「固定真值的语句」的预期——相当于「通配符」 - pub fn is_expected_truth(expected: &EnumTruth, out: &EnumTruth) -> bool { - match (expected, out) { - // 预期空真值⇒通配 - (EnumTruth::Empty, ..) => true, - // 预期单真值 - (EnumTruth::Single(f_e), EnumTruth::Single(f_o) | EnumTruth::Double(f_o, ..)) => { - f_e == f_o - } - // 预期双真值 - (EnumTruth::Double(..), EnumTruth::Double(..)) => expected == out, - // 其它情况 - _ => false, - } - } - - /// 判断「输出是否在预算值层面符合预期」 - /// * 🎯空预算的语句,应该符合「固定预算值的语句」的预期——相当于「通配符」 - pub fn is_expected_budget(expected: &EnumBudget, out: &EnumBudget) -> bool { - match (expected, out) { - // 预期空预算⇒通配 - (EnumBudget::Empty, ..) => true, - // 预期单预算 - ( - EnumBudget::Single(p_e), - EnumBudget::Single(p_o) | EnumBudget::Double(p_o, ..) | EnumBudget::Triple(p_o, ..), - ) => p_e == p_o, - // 预期双预算 - ( - EnumBudget::Double(p_e, d_e), - EnumBudget::Double(p_o, d_o) | EnumBudget::Triple(p_o, d_o, ..), - ) => p_e == p_o && d_e == d_o, - // 预期三预算 - (EnumBudget::Triple(..), EnumBudget::Triple(..)) => expected == out, - // 其它情况 - _ => false, - } - } - - /// 判断「输出是否在操作层面符合预期」 - /// * 🎯仅有「操作符」的「NARS操作」应该能通配所有「NARS操作」 - pub fn is_expected_operation(expected: &Operation, out: &Operation) -> bool { - // 操作符名不同⇒直接pass - if_return! { expected.operator_name != out.operator_name => false } - - // 比对操作参数:先判空 - match (expected.no_params(), out.no_params()) { - // 预期无⇒通配 - (true, ..) => true, - // 预期有,输出无⇒直接pass - (false, true) => false, - // 预期有,输出有⇒判断参数是否相同 - (false, false) => expected.params == out.params, - } - } -} +mod narsese_expectation; pub use narsese_expectation::*; +mod term_equal; + /// 实现/预期匹配功能 impl OutputExpectation { /// 判断一个「NAVM输出」是否与自身相符合 diff --git a/src/test_tools/vm_interact/narsese_expectation.rs b/src/test_tools/vm_interact/narsese_expectation.rs new file mode 100644 index 0000000..86007f4 --- /dev/null +++ b/src/test_tools/vm_interact/narsese_expectation.rs @@ -0,0 +1,168 @@ +//! * 🎯统一存放与「Narsese预期识别」有关的代码 +//! * 🚩【2024-04-02 22:49:12】从[`crate::runtimes::command_vm::runtime::tests`]中迁移而来 + +use nar_dev_utils::if_return; +use narsese::{ + api::{GetBudget, GetPunctuation, GetStamp, GetTruth, NarseseValue}, + conversion::{ + inter_type::lexical_fold::TryFoldInto, + string::impl_enum::format_instances::FORMAT_ASCII as FORMAT_ASCII_ENUM, + }, + enum_narsese::{ + Budget as EnumBudget, Narsese as EnumNarsese, Sentence as EnumSentence, Task as EnumTask, + Truth as EnumTruth, + }, + lexical::{Narsese, Sentence as LexicalSentence, Task as LexicalTask, Term}, +}; +use navm::output::Operation; + +use super::term_equal::*; + +/// 判断「输出是否(在Narsese语义层面)符合预期」 +/// * 🎯词法Narsese⇒枚举Narsese,以便从语义上判断 +pub fn is_expected_narsese_lexical(expected: &Narsese, out: &Narsese) -> bool { + _is_expected_narsese(expected.clone(), out.clone()) +} + +fn _is_expected_narsese(mut expected: Narsese, mut out: Narsese) -> bool { + // 先比对词项 + fn get_term_mut(narsese: &mut Narsese) -> &mut Term { + use NarseseValue::*; + match narsese { + Term(term) + | Sentence(LexicalSentence { term, .. }) + | Task(LexicalTask { + sentence: LexicalSentence { term, .. }, + .. + }) => term, + } + } + // * 🚩特制的「词项判等」截断性逻辑 | 🚩语义层面判等词项 + if_return! { + !semantical_equal_mut(get_term_mut(&mut expected), get_term_mut(&mut out)) => false + }; + // 临时折叠预期 + let expected = + (expected.try_fold_into(&FORMAT_ASCII_ENUM)).expect("作为预期的词法Narsese无法折叠!"); + // 与预期一致 + let out = out.try_fold_into(&FORMAT_ASCII_ENUM); // 必须复制:折叠消耗自身 + match out { + Ok(out) => is_expected_enum_residual(&expected, &out), + Err(..) => false, + } +} + +/// 判断「输出是否(在Narsese层面)符合预期」 +/// * 🎯预期词项⇒只比较词项,语句⇒只比较语句,…… +/// * 🚩【2024-06-11 16:02:10】目前对「词项比对」使用特殊逻辑,而对其它结构照常比较 +/// * ❓TODO: 【2024-06-11 21:22:15】是否需要避免重复折叠 +fn is_expected_enum_residual(expected: &EnumNarsese, out: &EnumNarsese) -> bool { + use NarseseValue::*; + match ((expected), (out)) { + // 词项⇒只比较词项 + // ! 🚩【2024-06-11 16:05:45】现在直接在词法层面判等,能运行至此都是已经词项相等的(枚举Narsese的集合相对难以统一) + (Term(_term), ..) => true, /* is_expected_term(term, out.get_term()) */ + // 语句⇒只比较语句 + // ! 仍然不能直接判等:真值/预算值 + (Sentence(s_exp), Sentence(s_out) | Task(EnumTask(s_out, ..))) => { + is_expected_sentence(s_exp, s_out) + } + // 任务⇒直接判断 + // ! 仍然不能直接判等:真值/预算值 + (Task(t_exp), Task(t_out)) => is_expected_task(t_exp, t_out), + // 所有其它情况⇒都是假 + (..) => false, + } +} + +/// 判断输出的任务是否与预期任务相同 +/// * 🎯用于细粒度判断「预算值」「语句」的预期 +pub fn is_expected_task(expected: &EnumTask, out: &EnumTask) -> bool { + // 预算 + is_expected_budget(expected.get_budget(), out.get_budget()) + // 语句 + && is_expected_sentence(expected.get_sentence(), out.get_sentence()) +} + +/// 判断输出的语句是否与预期语句相同 +/// * 🎯用于细粒度判断「真值」的预期 +pub fn is_expected_sentence(expected: &EnumSentence, out: &EnumSentence) -> bool { + // 词项 | ✅已经在词法层面判等 + // (is_expected_term(expected.get_term(),out.get_term())) && + // 标点相等 + expected.get_punctuation() == out.get_punctuation() + // 时间戳相等 + && expected.get_stamp()== out.get_stamp() + // 真值兼容 | 需要考虑「没有真值可判断」的情况 + && match (expected.get_truth(),out.get_truth()) { + // 都有⇒判断「真值是否符合预期」 + (Some(t_e), Some(t_o)) => is_expected_truth(t_e, t_o), + // 都没⇒肯定真 + (None, None) => true, + // 有一个没有⇒肯定假 + _ => false, + } +} + +// ! 🚩【2024-06-11 16:03:50】现在直接在词法层面判等Narsese词项 +// /// 判断输出的词项是否与预期词项相同 +// /// * 🎯用于独立出「词项预期」功能 +// /// * 🚩【2024-04-02 22:55:13】目前直接判等 +// pub fn is_expected_term(expected: &EnumTerm, out: &EnumTerm) -> bool { +// // expected == out +// } + +/// 判断「输出是否在真值层面符合预期」 +/// * 🎯空真值的语句,应该符合「固定真值的语句」的预期——相当于「通配符」 +pub fn is_expected_truth(expected: &EnumTruth, out: &EnumTruth) -> bool { + match (expected, out) { + // 预期空真值⇒通配 + (EnumTruth::Empty, ..) => true, + // 预期单真值 + (EnumTruth::Single(f_e), EnumTruth::Single(f_o) | EnumTruth::Double(f_o, ..)) => f_e == f_o, + // 预期双真值 + (EnumTruth::Double(..), EnumTruth::Double(..)) => expected == out, + // 其它情况 + _ => false, + } +} + +/// 判断「输出是否在预算值层面符合预期」 +/// * 🎯空预算的语句,应该符合「固定预算值的语句」的预期——相当于「通配符」 +pub fn is_expected_budget(expected: &EnumBudget, out: &EnumBudget) -> bool { + match (expected, out) { + // 预期空预算⇒通配 + (EnumBudget::Empty, ..) => true, + // 预期单预算 + ( + EnumBudget::Single(p_e), + EnumBudget::Single(p_o) | EnumBudget::Double(p_o, ..) | EnumBudget::Triple(p_o, ..), + ) => p_e == p_o, + // 预期双预算 + ( + EnumBudget::Double(p_e, d_e), + EnumBudget::Double(p_o, d_o) | EnumBudget::Triple(p_o, d_o, ..), + ) => p_e == p_o && d_e == d_o, + // 预期三预算 + (EnumBudget::Triple(..), EnumBudget::Triple(..)) => expected == out, + // 其它情况 + _ => false, + } +} + +/// 判断「输出是否在操作层面符合预期」 +/// * 🎯仅有「操作符」的「NARS操作」应该能通配所有「NARS操作」 +pub fn is_expected_operation(expected: &Operation, out: &Operation) -> bool { + // 操作符名不同⇒直接pass + if_return! { expected.operator_name != out.operator_name => false } + + // 比对操作参数:先判空 + match (expected.no_params(), out.no_params()) { + // 预期无⇒通配 + (true, ..) => true, + // 预期有,输出无⇒直接pass + (false, true) => false, + // 预期有,输出有⇒判断参数是否相同 + (false, false) => expected.params == out.params, + } +} diff --git a/src/test_tools/vm_interact/term_equal.rs b/src/test_tools/vm_interact/term_equal.rs new file mode 100644 index 0000000..fff914d --- /dev/null +++ b/src/test_tools/vm_interact/term_equal.rs @@ -0,0 +1,526 @@ +use narsese::{ + conversion::string::impl_enum::format_instances::FORMAT_ASCII as FORMAT_ASCII_ENUM, lexical::*, +}; +use std::{cmp::Ordering, collections::HashMap}; + +/// 简单获取词项的「标识符」 +/// * 🎯识别是否为「可交换词项」 +/// * ⚠️对「集合词项」只取其中的左括弧 +fn get_identifier(term: &Term) -> &str { + match term { + Atom { prefix, .. } => prefix, + Compound { connecter, .. } => connecter, + Set { left_bracket, .. } => left_bracket, + Statement { copula, .. } => copula, + } +} + +// 重命名「变量词项」 // + +/// 判断一个原子词项前缀是否为「变量词项」 +fn is_variable_atom_prefix(prefix: &str) -> bool { + // 独立变量 + prefix == FORMAT_ASCII_ENUM.atom.prefix_variable_independent + // 非独变量 + || prefix == FORMAT_ASCII_ENUM.atom.prefix_variable_dependent + // 查询变量 + || prefix == FORMAT_ASCII_ENUM.atom.prefix_variable_query +} + +// /// 判断一个词项是否为变量 +// fn is_variable_atom(term: &Term) -> bool { +// match term { +// Atom { prefix, .. } => is_variable_atom_prefix(prefix), +// _ => false, +// } +// } + +// /// 重命名变量原子词项 +// fn rename_variable_atom(term: &mut Term, new_name: &str) { +// if let Atom { name, .. } = term { +// *name = new_name.to_string() +// } +// } + +type VariableNameMap = HashMap; + +/// 重命名词项中的所有变量 +/// * 🎯给所有词项统一编号 +/// * 🚩返回:是否修改,变量映射表 +#[allow(unused)] +fn rename_variables_in_term(term: &mut Term) -> (bool, VariableNameMap) { + let mut map = VariableNameMap::new(); + rename_variables_in_term_with_map(term, &mut map); + (!map.is_empty(), map) +} + +/// 带映射地递归重命名变量 +fn rename_variables_in_term_with_map(term: &mut Term, map: &mut VariableNameMap) -> bool { + find_variables_renaming(term, map); + let modified = map.iter().any(|(k, v)| k != v); + if modified { + apply_name_substitute(term, map); + } + modified +} + +/// 寻找需要重命名的变量集合 +fn find_variables_renaming(term: &Term, map: &mut VariableNameMap) { + match term { + // * 🚩原子变量词项⇒尝试命名 + Atom { prefix, name } if is_variable_atom_prefix(prefix) => { + let new_name = match map.get(name) { + Some(n) => n.clone(), + None => (map.len() + 1).to_string(), // ? 避免已有的数字变量干扰 | 2 -> 1, 1 -> 2 + }; + // * 📌插入名称 + // if *name != new_name { + map.insert(name.clone(), new_name.clone()); + // } + // rename_variable_atom(term, &new_name); + } + // * 🚩复合词项⇒递归深入 + Compound { terms, .. } | Set { terms, .. } => terms + .iter() + .for_each(|term| find_variables_renaming(term, map)), + Statement { + subject, predicate, .. + } => [subject, predicate] + .into_iter() + .for_each(|term| find_variables_renaming(term, map)), + // * 🚩其它⇒未改变 + _ => (), + } +} + +fn apply_name_substitute(term: &mut Term, map: &VariableNameMap) { + match term { + Atom { name, .. } => { + if let Some(new_name) = map.get(name) { + *name = new_name.clone() + } + } + Compound { terms, .. } | Set { terms, .. } => { + for term in terms { + apply_name_substitute(term, map) + } + } + Statement { + subject, predicate, .. + } => { + apply_name_substitute(subject, map); + apply_name_substitute(predicate, map); + } + } +} + +// 对「可交换词项」排序 // + +/// 判断一个词项前缀是否为「可交换词项」 +/// * 🚩一元词项不被视作【可交换的】词项:无需交换 +fn is_communicative_term(identifier: &str) -> bool { + // 外延集&内涵集 + identifier == FORMAT_ASCII_ENUM.compound.brackets_set_extension.0 + || identifier == FORMAT_ASCII_ENUM.compound.brackets_set_intension.0 + // 外延交&内涵交 + || identifier == FORMAT_ASCII_ENUM.compound.connecter_intersection_extension + || identifier == FORMAT_ASCII_ENUM.compound.connecter_intersection_intension + // 合取&析取 + || identifier == FORMAT_ASCII_ENUM.compound.connecter_conjunction + || identifier == FORMAT_ASCII_ENUM.compound.connecter_disjunction + // 平行合取 + || identifier == FORMAT_ASCII_ENUM.compound.connecter_conjunction_parallel + // 相似&等价 + || identifier == FORMAT_ASCII_ENUM.statement.copula_similarity + || identifier == FORMAT_ASCII_ENUM.statement.copula_equivalence + // 并发性等价 + || identifier == FORMAT_ASCII_ENUM.statement.copula_equivalence_concurrent +} + +/// 比较两个词项的顺序 +/// * 🎯对「均为变量」的情况判断等值 +fn term_comparator(term1: &Term, term2: &Term) -> Ordering { + fn term_comparator_zipped((term1, term2): (&Term, &Term)) -> Ordering { + term_comparator(term1, term2) + } + use Ordering::*; + match (term1, term2) { + // * 🚩原子🆚原子:判断变量情况 + ( + Atom { + prefix: p1, + name: n1, + }, + Atom { + prefix: p2, + name: n2, + }, + ) => match (is_variable_atom_prefix(p1), is_variable_atom_prefix(p2)) { + // * 🚩都是变量⇒判等 + (true, true) => Equal, + (false, true) => Less, + (true, false) => Greater, + // * 🚩其它情况⇒正常按名称判断 + (false, false) => p1.cmp(p2).then(n1.cmp(n2)), + }, + // * 🚩复合🆚复合 | 集合🆚集合 ⇒ 深入 + ( + Compound { + connecter: c1, + terms: t1, + }, + Compound { + connecter: c2, + terms: t2, + }, + ) + | ( + Set { + left_bracket: c1, + terms: t1, + .. + }, + Set { + left_bracket: c2, + terms: t2, + .. + }, + ) => c1.cmp(c2).then( + t1.iter() + .zip(t2.iter()) + .map(term_comparator_zipped) + .fold(Equal, Ordering::then), + ), + // * 🚩陈述🆚陈述 + ( + Statement { + copula: c1, + subject: s1, + predicate: p1, + }, + Statement { + copula: c2, + subject: s2, + predicate: p2, + }, + ) => c1.cmp(c2).then( + ([s1, p1].into_iter()) + .zip([s2, p2]) + .map(|(inner1, inner2)| term_comparator(inner1, inner2)) + .fold(Equal, Ordering::then), + ), + // * 🚩其它类型不同的情况⇒明显的顺序(无需特别安排) + _ => term1.cmp(term2), + } +} + +/// 对内部的「可交换词项」排序 +/// * 🚩可交换词项⇒排序;不可交换⇒对其内子项排序 +fn sort_communicative_terms(term: &mut Term) -> bool { + // * 🚩尝试对内部词项排序 + let mut modified = match term { + // * 🚩复合 & 集合 + Compound { terms, .. } | Set { terms, .. } => { + let mut modified = false; + for term in terms { + // * 🚩必须全部执行排序,不能截断了事 + modified = sort_communicative_terms(term) || modified; + } + modified + } + // * 🚩陈述 + Statement { + subject, predicate, .. + } => { + let modified_subject = sort_communicative_terms(subject); + let modified_predicate = sort_communicative_terms(predicate); + modified_subject || modified_predicate + } + // * 🚩其它⇒未改变 + _ => false, + }; + // * 🚩可交换⇒自身直接元素排序 + if is_communicative_term(get_identifier(term)) { + // * 🚩必须全部执行排序,不能截断了事 + modified = sort_a_communicative_term(term) || modified; + } + modified +} + +/// 对一个「可交换词项」排序 +/// * ⚠️只在当前层中排序 +fn sort_a_communicative_term(term: &mut Term) -> bool { + match term { + // * 🚩复合 & 集合 + Compound { terms, .. } | Set { terms, .. } => { + // * 🚩将引用按原先顺序排列 + let mut ref_terms: Vec<&Term> = terms.iter().collect(); + // * 🚩尝试排序词项引用(不改变原词项序列) | ⚠️若直接改变原序列,会存在借用问题 + ref_terms.sort_by(|&t1, &t2| term_comparator(t1, t2)); + // * 🚩迭代判断相等;不相等⇒被修改(此时已经被排序) + let modified = terms.iter().zip(ref_terms).any(|(t1, t2)| t1 != t2); + // * 🚩若有修改⇒再排序一次 + if modified { + terms.sort_by(term_comparator); + } + modified + } + // * 🚩陈述 + Statement { + subject, predicate, .. + } => { + match term_comparator(subject, predicate) { + // subject ">" predicate + Ordering::Greater => { + // * 🚩调整顺序 + std::mem::swap(subject, predicate); + true // 被修改 + } + _ => false, + } + } + // * 🚩其它⇒不作为 + _ => false, + } +} + +// 对外接口 // + +const MAX_TRIES_FORMALIZE: usize = 0x100; + +/// 规范化一个词项 +/// * 📌语义上相等⇒一定会被规范到同一形式 +pub fn formalize_term(term: &mut Term) -> &mut Term { + let mut map = VariableNameMap::new(); + let mut modified; + // 修改到无法修改为止 + // * 📌循环次数有限,防止死循环 + for _ in 0..MAX_TRIES_FORMALIZE { + // 命名变量 + modified = rename_variables_in_term_with_map(term, &mut map); + // 排序 | 🚩放后头避免截断 + modified = sort_communicative_terms(term) || modified; + // * 🚩若无变化⇒退出 + if !modified { + return term; + } + // 重置 + map.clear(); + } + // * 🚩尝试多次仍未稳定⇒收集信息,panic | 📝这是个程序漏洞,而非可失败的选项:重命名+排序 必定会收敛(有待论证) + const N: usize = 0x10; + let mut stack = Vec::with_capacity(N); + for _ in 0..N { + use narsese::conversion::string::impl_lexical::format_instances::FORMAT_ASCII; + // 命名变量 + rename_variables_in_term_with_map(term, &mut map); + // 排序 + sort_communicative_terms(term); + // 打印 + stack.push(format!("modified: {:}", FORMAT_ASCII.format(term))); + // 重置 + map.clear(); + } + panic!( + "异常:程序重复尝试了{MAX_TRIES_FORMALIZE}次,仍未稳定。\n堆栈:\n{}", + stack.join("\n") + ); +} + +/// 入口:词项判等 +/// * 🚩通过「规整化词项」实现判等逻辑 +/// * 📌可交换词项「顺序不影响相等」 ⇒ 固定顺序 ⇒ 排序 +/// * 📌变量词项「编号不影响相等」 ⇒ 固定顺序 ⇒ 统一重命名 +pub fn semantical_equal_mut(term1: &mut Term, term2: &mut Term) -> bool { + *formalize_term(term1) == *formalize_term(term2) +} + +#[cfg(test)] +mod tests { + use super::*; + use narsese::conversion::string::impl_lexical::format_instances::FORMAT_ASCII; + use util::macro_once; + + fn parse_term(s: &str) -> Term { + FORMAT_ASCII + .parse(s) + .expect("Narsese解析失败") + .try_into_term() + .unwrap() + } + + macro_rules! term { + ($s:expr) => { + parse_term($s) + }; + } + + fn fmt_term(term: &Term) -> String { + FORMAT_ASCII.format(term) + } + + fn print_term(term: &Term) { + println!("{:}", fmt_term(term)); + } + + #[test] + fn rename_variables() { + fn t(s: &str) { + let term = parse_term(s); + // 普通验证 + print_term(&term); + let mut renamed = term.clone(); + rename_variables_in_term(&mut renamed); + print_term(&renamed); + // 幂等性 + let mut r_renamed = renamed.clone(); + rename_variables_in_term(&mut r_renamed); + print_term(&r_renamed); + assert_eq!(&renamed, &r_renamed) + } + t("<(&&, <$2 --> $1>, <$3 <-> $2>, S, #4) ==> < $1> ==> <$3 --> {(/, R, _, $3), $2}>>>"); + t("<(&&,<$the_one --> lock>,<$second --> key>) ==> <$the_one --> (/,open,$second,_)>>"); + t("<(&&,<$the_one --> key>,<$second --> lock>) ==> <$second --> (/,open,$the_one,_)>>"); + } + + #[test] + fn sort() { + // 普通验证 + let term = term!("<[#1, B, $1, A, $2, B] <-> (&&, #1, A, {G,E,B}, [C], D>)>"); + print_term(&term); + let mut renamed = term.clone(); + sort_communicative_terms(&mut renamed); + print_term(&renamed); + // 幂等性 + let mut r_renamed = renamed.clone(); + sort_communicative_terms(&mut r_renamed); + print_term(&r_renamed); + assert_eq!(&renamed, &r_renamed); + // 排序判等 + fn sort_eq(term1: &mut Term, term2: &mut Term) -> bool { + sort_communicative_terms(term1); + sort_communicative_terms(term2); + term1 == term2 + } + macro_once! { + macro test_ { + ($($s1:literal $t1:tt $s2:literal)*) => {$( + // ! ⚠️等号/不等号 算一个标签树(tt) + test_!{ @INNER $s1 $t1 $s2 } + )*} + (@INNER $s1:literal == $s2:literal) => { + let mut t1 = term!($s1); + let mut t2 = term!($s2); + assert!(sort_eq(&mut t1, &mut t2), "{} != {}", fmt_term(&t1), fmt_term(&t2)); + } + (@INNER $s1:literal != $s2:literal) => { + let mut t1 = term!($s1); + let mut t2 = term!($s2); + assert!(!sort_eq(&mut t1, &mut t2), "{} == {}", fmt_term(&t1), fmt_term(&t2)); + } + } + "A" == "A" + " B>" == " A>" + " B>" != " A>" + "<(&&,<$1 --> lock>,<$2 --> key>) ==> <$1 --> (/,open,$2,_)>>" == + "<(&&,<$2 --> key>,<$1 --> lock>) ==> <$1 --> (/,open,$2,_)>>" + } + } + + #[test] + fn term_compare() { + macro_once! { + macro test_ { + ($($s1:literal $t1:tt $s2:literal)*) => {$( + test_!{ @INNER $s1 ($t1) $s2 } + )*} + (@VALUE $s1:literal $t1:tt $s2:literal $ordering:expr) => { + let t1 = term!($s1); + let t2 = term!($s2); + let cmp_result = term_comparator(&t1, &t2); + assert_eq!(cmp_result, $ordering, "{} !{} {}", fmt_term(&t1), $t1, fmt_term(&t2)); + } + (@INNER $s1:literal (>) $s2:literal) => { + test_!{ @VALUE $s1 ">" $s2 Ordering::Greater } + } + (@INNER $s1:literal (<) $s2:literal) => { + test_!{ @VALUE $s1 "<" $s2 Ordering::Less } + } + (@INNER $s1:literal (==) $s2:literal) => { + test_!{ @VALUE $s1 "==" $s2 Ordering::Equal } + } + } + "A" < "B" + "$1" == "$2" + "$3" == "$2" + "$3" == "$a" + "(&&, A)" > "#1" + "(&&, #2)" == "(&&, $2)" + "<$1 --> lock>" > "<$2 --> key>" + } + } + + #[test] + fn formalize() { + fn t(s: &str) { + let mut term = parse_term(s); + print_term(&term); + formalize_term(&mut term); + print_term(&term); + // 幂等性 + let term_original = term.clone(); + formalize_term(&mut term); + print_term(&term); + assert!(term == term_original) + } + t("<(&&, <$2 --> $1>, <$3 <-> $2>, S, #4) ==> < $1> ==> <$3 --> {(/, R, _, $3), $2}>>>"); + } + + #[test] + fn semantical_eq() { + macro_once! { + macro test_ { + ($($s1:literal $t1:tt $s2:literal)*) => {$( + // ! ⚠️等号/不等号 算一个标签树(tt) + test_!{ @INNER $s1 $t1 $s2 } + )*} + // * 📌等号的情况 + (@INNER $s1:literal == $s2:literal) => { + let mut t1 = term!($s1); + let mut t2 = term!($s2); + let eq = semantical_equal_mut(&mut t1, &mut t2); + assert!(eq, "{} != {}", fmt_term(&t1), fmt_term(&t2)); + } + // * 📌不等号的情况 + (@INNER $s1:literal != $s2:literal) => { + let mut t1 = term!($s1); + let mut t2 = term!($s2); + let eq = semantical_equal_mut(&mut t1, &mut t2); + assert!(!eq, "{} == {}", fmt_term(&t1), fmt_term(&t2)); + } + } + // * 🚩源自实际场景的例子 + "<(&&,<$1 --> lock>,<$2 --> key>) ==> <$1 --> (/,open,$2,_)>>" + == "<(&&,<$1 --> key>,<$2 --> lock>) ==> <$2 --> (/,open,$1,_)>>" + "(&&,<$1 --> lock>,<$2 --> key>)" // * 📝先重命名,根据「变量均相等」交换key和lock,最后 + == "(&&,<$1 --> key>,<$2 --> lock>)" + "(&&,<$1 --> 🔒>,<$2 --> 🔑>)" // * 对emoji也差不多 + == "(&&,<$1 --> 🔑>,<$2 --> 🔒>)" + "(&&,<#1 --> 🔒>,<$2 --> 🔑>)" // ! 但这样就不行 + != "(&&,<#1 --> 🔑>,<$2 --> 🔒>)" + "$1" == "$2" + "$1" != "A" + "(/,open,$2,_)" == "(/,open,$1,_)" + "<$1 --> (/,open,$2,_)>" == "<$2 --> (/,open,$1,_)>" + "<$1 --> $2>" == "<$2 --> $1>" + "<$1 --> 2>" != "<$2 --> 1>" + "<1 --> $2>" != "<$2 --> 1>" + "<$1 --> #2>" != "<#2 --> $1>" + " #2>" != "<#2 --> ?1>" + "<$1 --> ?2>" != " $1>" + "<$1 --> #2>" == "<$2 --> #1>" + " #2>" == " #1>" + "<$1 --> ?2>" == "<$2 --> ?1>" + } + } +}