diff --git a/.github/workflows/Threading.yml b/.github/workflows/Threading.yml new file mode 100644 index 0000000..28c15c7 --- /dev/null +++ b/.github/workflows/Threading.yml @@ -0,0 +1,31 @@ +name: threading + +on: + push: + branches: + - '*' + pull_request: + branches: + - main + +jobs: + reasoning: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + components: clippy + override: true + + - name: Repl + run: | + cargo build --features="repl" --release + + - name: Threading + run: | + ./target/release/3body -V + ./target/release/3body -c '给 cx 以 程心(); 给 星环公司 以 法则(name, y, limit) { 给 掩体纪年 以 y; 面壁 (掩体纪年 <= limit) { 冬眠(1000); 广播([name, 掩体纪年]); 掩体纪年 = 掩体纪年 + 1; } } cx.thread(星环公司, ["掩体工程", 0, 11]) 冬眠(5000) cx.thread(星环公司, ["研制曲率飞船", 5, 11]) 冬眠(6000)' + ./target/release/3body -c '给 cx 以 程心(); 给 星环公司 以 法则(name, y, limit) { 给 掩体纪年 以 y; 面壁 (掩体纪年 <= limit) { 冬眠(1000); 广播([name, 掩体纪年]); 掩体纪年 = 掩体纪年 + 1; } } 给 秘密研究 以 cx.thread(星环公司, ["重启光速飞船的研究", 11, 66]) cx.join(秘密研究)' diff --git a/Cargo.lock b/Cargo.lock index 6bf6835..b67f0b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.3.8" @@ -23,6 +38,21 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -199,6 +229,12 @@ dependencies = [ "cc", ] +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + [[package]] name = "half" version = "2.4.0" @@ -251,9 +287,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.149" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "linux-raw-sys" @@ -369,6 +405,15 @@ dependencies = [ "libc", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "nibble_vec" version = "0.1.0" @@ -389,6 +434,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.19.0" @@ -407,6 +461,12 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -545,6 +605,12 @@ dependencies = [ "unicode-normalization-alignments", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + [[package]] name = "rustix" version = "0.38.20" @@ -710,18 +776,19 @@ dependencies = [ [[package]] name = "three_body_interpreter" -version = "0.6.1" +version = "0.6.3" dependencies = [ "llm", "llm-base", "rand", "spinoff", + "tokio", "unicode-xid", ] [[package]] name = "three_body_lang" -version = "0.6.1" +version = "0.6.3" dependencies = [ "rustyline", "rustyline-derive", @@ -743,6 +810,28 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "pin-project-lite", + "tokio-macros", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.58", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -825,7 +914,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -834,13 +923,29 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -849,38 +954,86 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index ef40197..7cfcba7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ name = "three_body_lang" description = "Three Body Language written in Rust" edition = "2021" -version = "0.6.1" +version = "0.6.3" authors = ["meloalright", "rustq"] license = "MIT" @@ -12,7 +12,7 @@ members = ["interpreter"] [dependencies] rustyline = { version = "12.0.0", optional = true } rustyline-derive = { version = "0.4.0", optional = true } -three_body_interpreter = { version = "0.6.1", path = "./interpreter", features = ["sophon"] } +three_body_interpreter = { version = "0.6.3", path = "./interpreter", features = ["sophon", "threading"] } [[bin]] name = "3body" diff --git a/README.md b/README.md index 68992f6..5bb9f63 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,7 @@ $ 3body // > true ``` + ## Summary |Token|3body-lang|Explanation| @@ -215,6 +216,32 @@ $ 3body |exit|毁灭|"destroy"| |deep-equal|没关系的都一样|"It's okay. It's all the same."| +## 🧶 Threading + +三体编程语言可以通过 "程心" 创建并管理线程。 + +Able to use threading to create and handle threads. + +#### Threads Create + +```rust +给 cx 以 程心(); + +cx.thread(星环公司, ["掩体工程", 0, 11]) +cx.thread(星环公司, ["研制曲率飞船", 5, 11]) +``` + +#### Threads Await + +```rust +给 cx 以 程心(); + +给 秘密研究 以 cx.thread(星环公司, ["重启光速飞船的研究", 11, 66]); +cx.join(秘密研究) +``` + +⚛️ Example threading of "星环公司" in [runs/11302243115](https://github.com/rustq/3body-lang/actions/runs/11302243115/job/31437809217) + ## 🤗 LLM 三体编程语言可以通过 "智子工程" 加载本地大语言模型进行推理。 diff --git a/interpreter/Cargo.toml b/interpreter/Cargo.toml index 485abd7..46aca3f 100644 --- a/interpreter/Cargo.toml +++ b/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "three_body_interpreter" description = "Three Body interpreter" -version = "0.6.1" +version = "0.6.3" edition = "2021" authors = ["meloalright", "rustq"] license = "MIT" @@ -17,7 +17,9 @@ rand = { version = "0.8.5" } llm = { version = "0.1.1", optional = true } llm-base = { version = "0.1.1", optional = true } spinoff = { version = "0.7.0", default-features = false, features = ["dots", "arc", "line"], optional = true } +tokio = { version = "1.40.0", features = ["sync", "time", "macros", "rt-multi-thread"], optional = true } [features] default = [] -sophon = ["llm", "llm-base", "spinoff"] \ No newline at end of file +sophon = ["llm", "llm-base", "spinoff"] +threading = ["tokio"] \ No newline at end of file diff --git a/interpreter/src/evaluator/builtins.rs b/interpreter/src/evaluator/builtins.rs index 98f3cfd..e850700 100644 --- a/interpreter/src/evaluator/builtins.rs +++ b/interpreter/src/evaluator/builtins.rs @@ -1,9 +1,15 @@ use std::collections::HashMap; +use std::cell::RefCell; +use std::rc::Rc; + extern crate rand; use crate::evaluator::object::Object; use crate::evaluator::object::NativeObject; +use crate::evaluator::env::Env; +use crate::evaluator::Evaluator; +use crate::ast; use rand::distributions::Uniform; use rand::{thread_rng, Rng}; @@ -44,6 +50,11 @@ pub fn new_builtins() -> HashMap { String::from("智子工程"), Object::Builtin(1, three_body_sophon_engineering), ); + #[cfg(feature="threading")] // threading + builtins.insert( + String::from("程心"), + Object::Builtin(0, three_body_threading), + ); builtins } @@ -174,7 +185,7 @@ fn three_body_sophon_engineering(args: Vec) -> Object { }; let model_type = model_type.as_str(); - + let model_path = { match model_path { @@ -208,7 +219,7 @@ fn three_body_sophon_engineering(args: Vec) -> Object { .unwrap_or_else(|err| { panic!("Failed to load {model_type} model from {model_path:?}: {err}") }); - + let model = Box::leak(model); println!( @@ -289,11 +300,11 @@ fn three_body_sophon_engineering(args: Vec) -> Object { |t| { print!("{t}"); std::io::stdout().flush().unwrap(); - + Ok(()) }, ); - + match res { Err(err) => println!("\n{err}"), _ => () @@ -315,7 +326,7 @@ fn three_body_sophon_engineering(args: Vec) -> Object { NativeObject::LLMModel(model_ptr) => { model_ptr.clone() }, - _ => panic!() + _ => panic!(), } }, _ => panic!() @@ -337,6 +348,99 @@ fn three_body_sophon_engineering(args: Vec) -> Object { } } + + +#[cfg(feature="threading")] +fn three_body_threading(args: Vec) -> Object { + let mut session_hash = HashMap::new(); + { + fn three_body_thread_new(args: Vec) -> Object { + match &args[0] { + Object::Function(params, ast, env ) => { + + let stmts = ast.clone(); + let params = params.clone(); + + let literals: Vec = match &args[1] { + Object::Array(arr) => { + arr.iter().map(|o| match o { + Object::Int(i) => ast::Literal::Int(i.clone()), + Object::String(str) => ast::Literal::String(str.clone()), + Object::Bool(bool) => ast::Literal::Bool(bool.clone()), + _ => todo!(), + }).collect() + }, + _ => panic!() + }; + + let mut handle = std::thread::spawn(move || { + let local_set = tokio::task::LocalSet::new(); + let rt = tokio::runtime::Builder::new_current_thread() + .enable_all() + .build() + .unwrap(); + + local_set.spawn_local(async move { + let mut ev = Evaluator { + env: { + let scoped_env = Rc::new(RefCell::new(Env::from(new_builtins()))); + + for (i, ident) in params.iter().enumerate() { + let crate::ast::Ident(name) = ident.clone(); + let o = match &literals[i] { + ast::Literal::Int(i) => Object::Int(i.clone()), + ast::Literal::String(str) => Object::String(str.clone()), + ast::Literal::Bool(bo) => Object::Bool(bo.clone()), + _ => todo!(), + }; + scoped_env.borrow_mut().set(name, o.clone()); + } + + scoped_env + }, + }; + ev.eval(&stmts); + }); + + rt.block_on(local_set); + }); + + let handle = Box::leak(Box::new(handle)); + let handle_ptr = &mut *handle as *mut std::thread::JoinHandle<()>; + Object::Native(Box::new(NativeObject::Thread(handle_ptr))) + } + _ => panic!() + } + } + session_hash.insert(Object::String("thread".to_owned()), Object::Builtin(2, three_body_thread_new)); + } + + + + { + fn three_body_thread_join(args: Vec) -> Object { + match &args[0] { + Object::Native(ptr) => { + let handle_ptr = match **ptr { + NativeObject::Thread(handle_ptr) => { + handle_ptr.clone() + } + _ => panic!() + }; + unsafe { Box::from_raw(handle_ptr) }.join(); + Object::Null + }, + _ => panic!() + } + } + session_hash.insert(Object::String("join".to_owned()), Object::Builtin(1, three_body_thread_join)); + } + + + Object::Hash(session_hash) + +} + #[cfg(test)] mod tests { use super::*; @@ -578,4 +682,6 @@ mod tests { assert_eq!(got, expected); } } + + } diff --git a/interpreter/src/evaluator/object.rs b/interpreter/src/evaluator/object.rs index 026abda..3a0234d 100644 --- a/interpreter/src/evaluator/object.rs +++ b/interpreter/src/evaluator/object.rs @@ -16,6 +16,8 @@ pub type BuiltinFunc = fn(Vec) -> Object; pub enum NativeObject { #[cfg(feature="sophon")] LLMModel(*mut dyn llm::Model), + #[cfg(feature="threading")] + Thread(*mut std::thread::JoinHandle<()>), } #[derive(PartialEq, Clone, Debug)]