Skip to content

Commit

Permalink
feat: ✨ 初步完成「路径遍历/路径构建」的「自动CIN搜索」框架
Browse files Browse the repository at this point in the history
1. ✅基于「路径遍历器」与「路径构建器」的通用搜索特征
2. ✅基本实用的「名称匹配」逻辑,及其「路径遍历」应用测试(📄遇见名称与「nars」有关的就深入)
3. ✅适用于OpenNARS、ONA的「路径构建器」
4. 🚧TODO:PyNARS的「路径构建器」
5. 🚧TODO:不同类型「CIN搜索」的统一适配(通过用户输入选取,在选择后进行匹配,尽可能数据驱动)
  • Loading branch information
ARCJ137442 committed Mar 30, 2024
1 parent 159aa91 commit e44b009
Show file tree
Hide file tree
Showing 12 changed files with 794 additions and 3 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "babel_nar"
version = "0.8.0"
version = "0.9.0"
edition = "2021"

[dependencies]
Expand Down
125 changes: 125 additions & 0 deletions src/bin/cin_launcher/cin_search/anyhow_vm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//! 🚩【2024-03-30 23:36:48】曾经的尝试:
//! * 所有「路径构建器」都返回一个动态的「虚拟机启动器」类型
//! * 启动时只需在一个「Anyhow虚拟机启动器」列表中选择
trait Turned {
fn say(&self);
}
trait Unturned {
type Target: Turned;
fn turn(self) -> Self::Target;
fn turn_box(self: Box<Self>) -> Box<Self::Target>;
fn turn_box_sized(self: Box<Self>) -> Box<Self::Target>
where
Self: Sized,
{
Box::new(self.turn())
}
}
struct U(usize);
struct T(usize);
impl Turned for T {
fn say(&self) {
print!("I'm T({})", self.0)
}
}
impl Unturned for U {
type Target = T;
fn turn(self) -> T {
T(self.0)
}
fn turn_box(self: Box<Self>) -> Box<Self::Target> {
self.turn_box_sized()
}
}
struct AnyhowUnturned<T: Turned = AnyhowTurned> {
inner: Box<dyn Unturned<Target = T>>,
}
struct AnyhowTurned {
inner: Box<dyn Turned>,
}
impl Turned for AnyhowTurned {
fn say(&self) {
self.inner.say()
}
}
impl Unturned for AnyhowUnturned<T> {
type Target = AnyhowTurned;
fn turn(self) -> AnyhowTurned {
AnyhowTurned {
inner: self.inner.turn_box(),
}
}

fn turn_box(self: Box<Self>) -> Box<Self::Target> {
self.turn_box_sized()
}
}
impl<T: Turned, U: Unturned<Target = T>> From<U> for AnyhowUnturned<T> {
fn from(value: U) -> Self {
Self {
inner: Box::new(value),
}
}
}
struct AnyhowUnturned2 {
inner: AnyhowTurned,
}

fn main() {
let unturned: AnyhowUnturned<_> = U(1).into();
}

// pub struct AnyhowLauncher<'a, Runtime: VmRuntime + 'a> {
// pub launcher: Box<dyn VmLauncher<Runtime> + 'a>,
// }

// impl<'a, Runtime: VmRuntime + 'a> AnyhowLauncher<'a, Runtime> {
// pub fn new<Launcher>(launcher: impl VmLauncher<Runtime> + 'a) -> Self
// where
// Launcher: VmLauncher<Runtime> + 'a,
// {
// Self {
// launcher: Box::new(launcher),
// }
// }
// }

// /// ! Box<Runtime>不能充当`VmLauncher`的参数:未实现`VmRuntime`
// impl<'a, Runtime: VmRuntime + 'a> VmLauncher<AnyhowRuntime<'a>> for AnyhowLauncher<'a, Runtime> {
// fn launch(self) -> AnyhowRuntime<'a> {
// AnyhowRuntime {
// inner: Box::new(self.launcher.launch()),
// }
// }
// }

// struct AnyhowRuntime<'a> {
// inner: Box<dyn VmRuntime + 'a>,
// }

// impl AnyhowRuntime<'_> {
// fn new(inner: impl VmRuntime) -> Self {
// Self {
// inner: Box::new(inner),
// }
// }
// }

// impl VmRuntime for AnyhowRuntime<'_> {
// fn input_cmd(&mut self, cmd: navm::cmd::Cmd) -> anyhow::Result<()> {
// self.inner.input_cmd(cmd)
// }

// fn fetch_output(&mut self) -> anyhow::Result<navm::output::Output> {
// self.inner.fetch_output()
// }

// fn try_fetch_output(&mut self) -> anyhow::Result<Option<navm::output::Output>> {
// self.inner.try_fetch_output()
// }

// fn terminate(self) -> anyhow::Result<()> {
// self.inner.terminate()
// }
// }
19 changes: 19 additions & 0 deletions src/bin/cin_launcher/cin_search/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! CIN启动器中有关「CIN路径构建(搜索)」的逻辑
//! * ✨根据「CIN路径构建器」搜索(判别)系统中已存在的CIN实现(并自动构建)
//! * 🚩输入:搜索起点(一般是编译后exe所在文件夹)
//! * 🚩输出:NAVM启动器列表
//! * ❓【2024-03-30 19:12:29】是否要考虑返回更细化的「CIN实例位置」而非「CIN启动器」,以避免额外的性能开销?
use nar_dev_utils::mods;

/// 导出模块
mods! {
// 路径遍历器
use pub path_walker;
// 路径构造器
use pub path_builder;
// anyhow | 弃用
// anyhow_vm;
// 名称匹配
use pub name_match;
}
79 changes: 79 additions & 0 deletions src/bin/cin_launcher/cin_search/name_match.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! 封装「名称匹配」逻辑
//! * 🎯用于「语义化」「模糊化」的字符串匹配
//! * ✨无视大小写匹配
//! * 📄"opennars"匹配"OpenNARS"
//! * ✨「含于」与「包含」匹配
//! * 📄"opennars"匹配"OpenNARS 3.0.4"(含于)与"nars"(包含)
//! * ✨返回一个「匹配度」的数值
//! * `0`统一表示「未匹配」
//! * 剩余值可用于排序
use nar_dev_utils::{first, if_return};

/// 名称匹配
/// * 🎯用于「语义化」「模糊化」的字符串匹配
/// * ✨无视大小写匹配
/// * 📄"opennars"匹配"OpenNARS"
/// * ✨「含于」与「包含」匹配
/// * 📄"opennars"匹配"OpenNARS 3.0.4"(含于)与"nars"(包含)
/// * ⚙️返回一个「匹配度」的数值
/// * `0`统一表示「未匹配」
/// * 剩余值可用于排序
pub fn name_match(name: &str, target: &str) -> usize {
// 完全相等⇒最高级
if_return! {
// 完全相等⇒高
name == target => 6
// 包含于⇒中
target.contains(name) => 4
// 包含⇒低
name.contains(target) => 2
}

// 忽略大小写的情况 | 忽略大小写,降一个匹配度
let name = name.to_lowercase();
let target = target.to_lowercase();

first! {
// 完全相等⇒高
name == target => 5,
// 包含于⇒中
target.contains(&name) => 3,
// 包含⇒低
name.contains(&target) => 1,
// 否则⇒不匹配
_ => 0,
}
}

/// 名称匹配/仅「含于」
/// * 🚩与[`name_match`]类似,但仅「含于」而不适配「包含」
/// * 🎯用于「长串名称作为内部关键词」的匹配
pub fn name_match_only_contains(name: &str, target: &str) -> usize {
// 完全相等⇒最高级
if_return! {
// 完全相等⇒高
name == target => 4
// 含于⇒低
target.contains(name) => 2
}

// 忽略大小写的情况 | 忽略大小写,降一个匹配度
let name = name.to_lowercase();
let target = target.to_lowercase();

first! {
// 完全相等⇒高
name == target => 3,
// 含于⇒低
target.contains(&name) => 1,
// 否则⇒不匹配
_ => 0,
}
}

/// 判断「是否匹配」,不管「匹配度」多少
/// * 🚩直接复用逻辑,以牺牲一定性能为代价
pub fn is_name_match(name: &str, target: &str) -> bool {
name_match(name, target) > 0
}
66 changes: 66 additions & 0 deletions src/bin/cin_launcher/cin_search/path_builder.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//! 统一的「路径构建器」逻辑
use navm::vm::{VmLauncher, VmRuntime};
use std::path::Path;

/// CIN路径构建器
/// * 🚩本身不承担「遍历路径」的任务,只负责
/// * 📌判断是否「可以用于构建NAVM运行时」
/// * 📌从某路径构建「NAVM启动器」
/// * ❌【2024-03-30 19:05:48】放弃「通用启动器/通用运行时」的适配尝试
/// * 📝目前[`CinSearch::Launcher`]总是要带上[`CinSearch::Runtime`]作类型参数
/// * 📌堵点:难以定义一个使用`Box<dyn VmLauncher<?>>`封装的`AnyhowVmLauncher`类型
/// * 📍问题领域:特征对象及其转换
/// * ❓一个可能的参考:[`anyhow`]对「错误类型」的统一
/// * ❌【2024-03-30 21:24:10】尝试仍然失败:有关`Box<Self>`的所有权转换问题
/// * 🔗技术参考1:<https://stackoverflow.com/questions/46620790/how-to-call-a-method-that-consumes-self-on-a-boxed-trait-object>
pub trait CinPathBuilder {
/// 搜索结果的启动器类型
/// * 📌启动后变为[`CinSearch::Runtime`]运行时类型
type Launcher: VmLauncher<Self::Runtime>;

/// 搜索结果的运行时类型
type Runtime: VmRuntime;

/// 路径匹配
/// * 🎯匹配某路径(可能是文件夹,也可能是文件)是否可用于「构建NAVM启动器」
/// * ⚠️与**该路径是否存在**有关
/// * 📌需要访问本地文件系统
/// * 📄一些CIN可能要求判断其子目录的文件(附属文件)
/// * ⚙️返回「匹配度」
/// * 📌`0`⇒不匹配,其它⇒不同程度的匹配
/// * 🎯对接「名称匹配」中的「匹配度」
/// * ✨可用于后续排序
fn match_path(&self, path: &Path) -> usize;

/// 用于检查路径是否匹配
/// * 🔗参见[`match_path`]
fn is_path_matched(&self, path: &Path) -> bool {
self.match_path(path) > 0
}

/// 路径构建
/// * 🎯从某个路径构建出一个NAVM启动器
/// * ✅除路径以外,其它参数可作默认
/// * 📄OpenNARS的「Java最大堆大小」
///
/// # Panics
///
/// ⚠️需要保证[`is_path_matched`]为真
/// * 为假时可能`panic`
fn construct_from_path(&self, path: &Path) -> Self::Launcher;

/// 尝试路径构建
/// * 🚩返回一个[`Option`]
/// * 能构建⇒返回构建后的结果 `Some((启动器, 匹配度))`
/// * 无法构建⇒返回[`None`]
#[inline]
fn try_construct_from_path(&self, path: &Path) -> Option<(Self::Launcher, usize)> {
match self.match_path(path) {
// 不匹配⇒无
0 => None,
// 匹配⇒元组
n => Some((self.construct_from_path(path), n)),
}
}
}
Loading

0 comments on commit e44b009

Please sign in to comment.