Skip to content

Commit

Permalink
feat: ✨ 增加ONA运行时支持
Browse files Browse the repository at this point in the history
  • Loading branch information
ARCJ137442 committed Mar 25, 2024
1 parent 8efe36b commit 211bdaa
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 12 deletions.
4 changes: 3 additions & 1 deletion src/bin/cin_launcher.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
//! 一个一站式启动各CIN的启动器
//! * 🎯方便启动、管理各「作为NAVM运行时的CIN」的聚合终端
//! * 📌用于集成原先「BabelNAR」「BabelNAR_Implements」两个库
//! * ✨自动根据可执行文件、配置文件、用户输入猜测CIN类型
//! * ✨自动根据可执行文件、配置文件、用户输入猜测CIN类型(字符串匹配)
//! * ✨自动查找(可能)可用的CIN可执行文件(文件搜索)
//! * ✨自动启动并管理CIN
//! TODO: 完成代码
Expand Down
2 changes: 1 addition & 1 deletion src/impl_runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
pub mod opennars;

// ONA
// TODO: 具体实现
pub mod ona;

// NARS-Python
// TODO: 具体实现
Expand Down
58 changes: 58 additions & 0 deletions src/impl_runtime/ona/launcher.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//! ONA运行时的启动器
//! * 🎯允许ONA对原先运行时特别配置功能,同时也支持为ONA定制配置
//! * 🚩只憎加「启动器」类型,而不增加「运行时」类型
//! * ✨不同启动器可以启动到相同运行时
use super::{input_translate, output_translate};
use crate::runtime::{CommandVm, CommandVmRuntime};
use navm::vm::VmLauncher;
use std::{path::PathBuf, process::Command};

/// ONA Shell启动的默认指令参数
/// * 🎯默认预置指令:`[.exe文件路径] shell`
const COMMAND_ARGS_ONA: [&str; 1] = ["shell"];

/// ONA运行时启动器
/// * 🎯配置ONA专有的东西
/// * 🎯以Java运行时专有形式启动ONA
/// * 🚩基于exe文件启动ONA Shell
/// * 默认预置指令:`[.exe文件路径] shell`
/// * 📌【2024-03-25 08:41:16】目前跟随Rust命名规则,仅首字母大写
#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Ona {
/// exe文件路径
exe_path: PathBuf,
/// ONA Shell
default_volume: Option<usize>,
}

impl Ona {
pub fn new(exe_path: impl Into<PathBuf>) -> Self {
Self {
// 转换为路径
exe_path: exe_path.into(),
// 其它全是`None`
..Default::default()
}
}
}

/// 启动到「命令行运行时」
impl VmLauncher<CommandVmRuntime> for Ona {
fn launch(self) -> CommandVmRuntime {
// 构造指令
let mut command = Command::new(self.exe_path);
// * 📝这里的`args`、`arg都返回的可变借用。。
command.args(COMMAND_ARGS_ONA);

// 构造并启动虚拟机
CommandVm::from_io_process(command.into())
// * 🚩固定的「输入输出转换器」
.input_translator(input_translate)
.output_translator(output_translate)
// 🔥启动
.launch()
}
}

// ! 单元测试见[`super`]
29 changes: 29 additions & 0 deletions src/impl_runtime/ona/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! 「非公理虚拟机」的ONA运行时
//! * 🚩只提供「一行启动」的功能封装
//! * 🎯无需自行配置「输入输出转译器」
// 转译器
util::mod_and_pub_use! {
// 转译器
translators
// 启动器
launcher
}

/// 单元测试
#[cfg(test)]
mod tests {
use super::*;
use crate::runtime::test::{_test_ona, EXE_PATH_ONA};
use navm::vm::VmLauncher;

#[test]
fn test() {
// 从别的地方获取jar路径
let jar_path = EXE_PATH_ONA;
// 一行代码启动ONA
let vm = Ona::new(jar_path).launch();
// 直接复用之前对ONA的测试
_test_ona(vm)
}
}
68 changes: 68 additions & 0 deletions src/impl_runtime/ona/translators.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
//! ONA在「命令行运行时」的转译器
//! * 🎯维护与ONA Shell的交互
//! * 📌基于命令行输入输出的字符串读写
//! * ✨NAVM指令→字符串
//! * ✨字符串→NAVM输出
use navm::{
cmd::Cmd,
output::{Operation, Output},
};
use util::ResultS;

/// ONA的「输入转译」函数
/// * 🎯用于将统一的「NAVM指令」转译为「ONA Shell输入」
pub fn input_translate(cmd: Cmd) -> ResultS<String> {
let content = match cmd {
// 直接使用「末尾」,此时将自动格式化任务(可兼容「空预算」的形式)
Cmd::NSE(..) => cmd.tail(),
// CYC指令:运行指定周期数
// ! ONA Shell同样是自动步进的
Cmd::CYC(n) => n.to_string(),
// VOL指令:调整音量
Cmd::VOL(n) => format!("*volume={n}"),
// 其它类型
// * 📌【2024-03-24 22:57:18】基本足够支持
_ => return Err(format!("该指令类型暂不支持:{cmd:?}")),
};
// 转译
Ok(content)
}

/// ONA的「输出转译」函数
/// * 🎯用于将ONA Shell的输出(字符串)转译为「NAVM输出」
/// * 🚩直接根据选取的「头部」进行匹配
pub fn output_translate(content: String) -> ResultS<Output> {
// 根据冒号分隔一次,然后得到「头部」
let head = content.split_once(':').unwrap_or(("", "")).0.to_lowercase();
// 根据「头部」生成输出
let output = match &*head {
"answer" => Output::ANSWER {
content_raw: content,
// TODO: 有待捕获转译
narsese: None,
},
"derived" => Output::OUT {
content_raw: content,
// TODO: 有待捕获转译
narsese: None,
},
"input" => Output::IN { content },
"anticipate" => Output::ANTICIPATE {
content_raw: content,
// TODO: 有待捕获转译
narsese: None,
},
"exe" => Output::EXE {
content_raw: content,
// TODO: 有待捕获转译
operation: Operation::new("UNKNOWN", [].into_iter()),
},
"err" | "error" => Output::ERROR {
description: content,
},
_ => Output::OTHER { content },
};
// 返回
Ok(output)
}
46 changes: 36 additions & 10 deletions src/runtime/command_vm/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ pub(crate) mod test {
/// 实用测试工具/等待
pub fn await_fetch_until(
vm: &mut CommandVmRuntime,
criterion: impl Fn(Output, String) -> bool,
) {
criterion: impl Fn(&Output, String) -> bool,
) -> Output {
// 不断拉取输出
// TODO: 💭【2024-03-24 18:21:28】后续可以结合「流式处理者列表」做集成测试
loop {
Expand All @@ -118,8 +118,8 @@ pub(crate) mod test {
_ => println!("捕获到其它输出!内容:{output:?}"),
}
// 包含⇒结束
if criterion(output, raw_content) {
break;
if criterion(&output, raw_content) {
break output;
}
}
}
Expand All @@ -128,8 +128,8 @@ pub(crate) mod test {
pub fn input_cmd_and_await(
vm: &mut CommandVmRuntime,
cmd: Cmd,
criterion: impl Fn(Output, String) -> bool,
) {
criterion: impl Fn(&Output, String) -> bool,
) -> Output {
// 构造并输入任务
vm.input_cmd(cmd).expect("无法输入指令!");
// 「contains」非空⇒等待
Expand All @@ -144,16 +144,19 @@ pub(crate) mod test {
vm: &mut CommandVmRuntime,
cmd: Cmd,
expected_contains: &str,
) {
) -> Option<Output> {
// 空预期⇒直接输入
// * 🎯在后边测试中统一使用闭包,并且不会因此「空头拉取输出」
// * 📄【2024-03-24 18:47:20】有过「之前的CYC把Answer拉走了,导致后边的Answer等不到」的情况
// * ⚠️不能简化:区别在「是否会拉取输入,即便条件永真」
match expected_contains.is_empty() {
true => vm.input_cmd(cmd).expect("无法输入NAVM指令!"),
false => input_cmd_and_await(vm, cmd, |_, raw_content| {
true => {
vm.input_cmd(cmd).expect("无法输入NAVM指令!");
None
}
false => Some(input_cmd_and_await(vm, cmd, |_, raw_content| {
raw_content.contains(expected_contains)
}),
})),
}
}

Expand Down Expand Up @@ -217,6 +220,7 @@ pub(crate) mod test {
_test_opennars(vm);
}

/// 通用测试/OpenNARS
pub fn _test_opennars(mut vm: CommandVmRuntime) {
// 专有闭包 | ⚠️无法再提取出另一个闭包:重复借用问题
let mut input_cmd_and_await =
Expand Down Expand Up @@ -250,6 +254,28 @@ pub(crate) mod test {
_test_pynars(vm);
}

/// 通用测试/ONA
pub fn _test_ona(mut vm: CommandVmRuntime) {
// 专有闭包 | ⚠️无法再提取出另一个闭包:重复借用问题
let mut input_cmd_and_await =
|cmd, contains| input_cmd_and_await_contains(&mut vm, cmd, contains);
// input_cmd_and_await(Cmd::VOL(0), "");
input_cmd_and_await(Cmd::NSE(nse_task!(<A --> B>.)), "<A --> B>.");
input_cmd_and_await(Cmd::NSE(nse_task!(<B --> C>.)), "<B --> C>.");
input_cmd_and_await(Cmd::NSE(nse_task!(<A --> C>?)), "<A --> C>?");
input_cmd_and_await(Cmd::CYC(5), ""); // * CYC无需自动等待

// 等待回答(字符串)
await_fetch_until(&mut vm, |o, raw_content| {
matches!(o, Output::ANSWER { .. }) && raw_content.contains("<A --> C>.")
});

// 终止虚拟机
vm.terminate().expect("无法终止虚拟机");
println!("Virtual machine terminated...");
}

/// 通用测试/PyNARS
pub fn _test_pynars(mut vm: CommandVmRuntime) {
// // 睡眠等待
// // std::thread::sleep(std::time::Duration::from_secs(1));
Expand Down

0 comments on commit 211bdaa

Please sign in to comment.