Skip to content

Commit

Permalink
feat: 🚧 库环境基本搭建;进程读写初步封装
Browse files Browse the repository at this point in the history
  • Loading branch information
ARCJ137442 committed Mar 21, 2024
1 parent 22deb8b commit 464a5bf
Show file tree
Hide file tree
Showing 10 changed files with 326 additions and 4 deletions.
4 changes: 3 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"recommendations": [
"swellaby.vscode-rust-test-adapter",
"nyxiative.rust-and-friends"
"nyxiative.rust-and-friends",
"itsyaasir.rust-feature-toggler",
"rust-lang.rust-analyzer"
]
}
64 changes: 64 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
// 使用 IntelliSense 了解相关属性。
// 悬停以查看现有属性的描述。
// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug级单元测试",
"cargo": {
"args": [
"test",
"--no-run",
"--lib",
"--package=babel_nar"
],
"filter": {
"name": "babel_nar",
"kind": "lib"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug可执行文件「CIN启动器」",
"cargo": {
"args": [
"build",
"--bin=cin_launcher",
"--package=babel_nar"
],
"filter": {
"name": "cin_launcher",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug级单元测试「CIN启动器」",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=cin_launcher",
"--package=babel_nar"
],
"filter": {
"name": "cin_launcher",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.features": "all",
"editor.formatOnSave": true
}
31 changes: 31 additions & 0 deletions Cargo.lock

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

31 changes: 31 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,34 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

[dependencies.nar_dev_utils]
# 【2024-03-13 21:17:55】实用库现在独立为`nar_dev_utils`
# version = "0.1.0" # ! 本地依赖可以不添加版本
# *🚩【2024-03-21 09:26:38】启用所有
path = "../NAR-dev-util"
features = []

[dependencies.narsese]
# ! 本地依赖可以不添加版本
# 载入Narsese API,引入其中所有部分
path = "../Narsese.rs"
features = ["bundled"]

[dependencies.navm]
# ! 本地依赖可以不添加版本
# 载入NAVM API,引入「非公理虚拟机」模型
path = "../NAVM.rs"
features = [] # ! 【2024-03-21 09:24:51】暂时没有特性

# 定义库的特性
[features]
# 默认启用的特性
default = []
# 大杂烩
bundled = [
"implements"
]
# 各个独立的特性 #
# 具体接口实现:OpenNARS、ONA、NARS-Python、OpenJunars、PyNARS……
implements = []
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

该项目使用[语义化版本 2.0.0](https://semver.org/)进行版本号管理。

基于[**NAVM.rs**](https://github.com/ARCJ137442/NAVM.rs)的CIN(NARS计算机实现)接口
[**NAVM.rs**](https://github.com/ARCJ137442/NAVM.rs)**运行时**

- 前身为[**BabelNAR.jl**](https://github.com/ARCJ137442/BabelNAR.jl)
- 旨在方便连接各类CIN,并通过**Websocket**等服务提供**通用统一交互接口**
- 🎯为「非公理虚拟机模型」提供程序实现
- 🎯为各CIN实现**统一输入输出**形式

## 概念

Expand Down
2 changes: 2 additions & 0 deletions src/impl_runtime/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
//! 对各CIN实现「非公理虚拟机」模型
//! * 🎯基于「NAVM指令/NAVM输出↔字符串」的转换
21 changes: 20 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
//! 主模块
//! TODO: 参照**BabelNAR.jl**迁移并完善代码
//! * ✨进程IO库
//! * ✨通用运行时
//! * ✨运行时的各类实现(可选)
// 实用库别名
pub extern crate nar_dev_utils as util;

// 必选模块
util::pub_mod_and_pub_use! {
// 进程IO
process_io
// 运行时
runtime
}

// 可选模块
util::feature_pub_mod_and_reexport!{
// 运行时实现
"implements" => impl_runtime
}
167 changes: 167 additions & 0 deletions src/process_io/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
//! 用于封装抽象「进程通信」逻辑
//! 示例代码来源:https://www.nikbrendler.com/rust-process-communication/
//! * 📌基于「通道」的「子进程+专职读写的子线程」通信逻辑
//!
//! TODO: 封装抽象提取
#![allow(unused)]

use std::ffi::OsStr;
use std::io::{BufRead, BufReader, Write};
use std::process::{ChildStdin, ChildStdout, Command, Stdio};
use std::sync::mpsc::{channel, Receiver, Sender};
use std::sync::Mutex;
use std::thread;
use std::thread::sleep;
use std::time::Duration;

fn sleep_secs(secs: u64) {
sleep(Duration::from_secs(secs));
}

/// 启动子进程
fn start_process<S: AsRef<OsStr>>(
program_path: S,
sender: Sender<String>,
receiver: Receiver<String>,
) {
// 创建一个子进程
let child =
// 指令+参数
Command::new(program_path)
.arg("shell")
// 输入输出
.stdin(Stdio::piped())
.stdout(Stdio::piped())
// 产生进程
.spawn()
.expect("Failed to start process");

println!("Started process: {}", child.id());

let stdin = child.stdin.unwrap();
let stdout = child.stdout.unwrap();
/// 生成进程的「读写守护」(线程)
let thread_write_in = spawn_thread_write_in(stdin, receiver);
let thread_read_out = spawn_thread_read_out(stdout, sender);
}

/// 生成一个子线程,管理子进程的标准输入,接收通道另一端输出
/// * 📌读输入,写进程
fn spawn_thread_write_in(stdin: ChildStdin, receiver: Receiver<String>) -> thread::JoinHandle<()> {
thread::spawn(move || {
// 从通道接收者读取输入 | 从「进程消息发送者」向进程发送文本
let mut stdin = stdin;
for line in receiver {
// 写入输出
if let Err(e) = stdin.write_all(line.as_bytes()) {
println!("无法向子进程输入:{e:?}");
}
}
})
}

/// 生成一个子线程,管理子进程的标准输出,传送输出的消息到另一端
/// * 📌写输出
fn spawn_thread_read_out(stdout: ChildStdout, sender: Sender<String>) -> thread::JoinHandle<()> {
thread::spawn(move || {
// 读取输出
let mut stdout_reader = BufReader::new(stdout);
// 持续循环
loop {
// 从子进程「标准输出」读取输入
let mut buf = String::new();
match stdout_reader.read_line(&mut buf) {
// 没有任何输入⇒跳过
Ok(0) => continue,
// 有效输入
Ok(_) => {
println!("子进程输出: {buf:?}");
// 向「进程消息接收者」传递消息(实际上是「输出」)
if let Err(e) = sender.send(buf) {
println!("无法接收子进程输出:{e:?}");
break;
}
continue;
}
Err(e) => {
println!("子进程报错: {:?}", e);
break;
}
}
}
})
}

fn start_command_thread(mutex: Mutex<Sender<String>>) {
// 生成一个子线程,对上述进程进行读取
thread::spawn(move || {
let sender = mutex.lock().unwrap();
// 测试输入输出
sleep_secs(1);
sender.send("<A --> B>.\n".into()).unwrap();
sleep_secs(1);
sender.send("<B --> C>.\n".into()).unwrap();
sleep_secs(1);
sender.send("<A --> C>?\n".into()).unwrap();
sleep_secs(1);
});
}

/// 单元测试
#[cfg(test)]
mod tests {
use super::*;

// 定义一系列路径
const EXE_PATH_ONA: &str = r"..\..\NARS-executables\NAR.exe";
const EXE_PATH_REPL: &str = r"..\..\..\Julia\语言学小工Ju\繁简转换\dist\repl_简化.exe";
const EXE_PATH_ECHO: &str = r"..\NAVM.rs\target\debug\examples\echo_exe.exe";

/// 实验用测试
#[test]
fn test() {
// 创建通道
let (child_out, out_sender) = channel();
let (in_receiver, child_in) = channel();

// 启动进程
start_process(EXE_PATH_ONA, child_out, child_in);

// tx2.send(("Command 1\n".into())).unwrap();
let mutex = Mutex::new(in_receiver);
start_command_thread(mutex);
// println!("{in_receiver:?}");

// 从外部获取输出(阻塞)
// for line in out_sender {
// println!("Got this back: {}", line);
// }

// 等待
sleep_secs(5);
println!("程序结束!");
}

/// 标准案例:ONA交互
///
/// ## 测试输入
///
/// ```plaintext
/// <A --> B>.
/// <B --> C>.
/// <A --> C>?
/// ```
///
/// ## 预期输出
///
/// ```plaintext
/// Answer: <A --> C>. creationTime=2 Truth: frequency=1.000000, confidence=0.810000
/// ```
///
/// TODO: 【2024-03-21 10:02:34】按想要的「目标形式」写测试,然后以此驱动开发整个库(面向用法)
#[test]
fn test_ona() {
// let runtime = Runtime::builder();
}
}
1 change: 1 addition & 0 deletions src/runtime/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//! 用于封装表示「非公理虚拟机」运行时

0 comments on commit 464a5bf

Please sign in to comment.