diff --git a/Cargo.toml b/Cargo.toml index 588eeab..83ba8bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ rand = { version = "0.7.3", features = ["getrandom"] } [target.'cfg(not(target_arch = "wasm32"))'.dependencies] rand = { version = "0.7.3" } +reqwest = { version = "0.11", features = ["blocking"] } [[bin]] name = "runtime" diff --git a/README.md b/README.md index 4943b60..63e2cd2 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,20 @@ Playground: [https://rustq.github.io/3body-lang/](https://rustq.github.io/3body- 毁灭(); ``` +### Request + +##### Format + +``` +寻找(): void +``` + +##### Example + +```rust +给 A 以 寻找("https://raw.githubusercontent.com/rustq/3body-lang/main/LICENSE"); +``` + ## Summary |Monkey|3body-lang|Explanation| @@ -225,6 +239,7 @@ Playground: [https://rustq.github.io/3body-lang/](https://rustq.github.io/3body- |sleep|冬眠|"hibernation"| |clear|二向箔清理|"two-way foil cleaning"| |exit|毁灭|"destroy"| +|request|寻找|"search"| ## System Libraries @@ -243,7 +258,7 @@ $ make repl ``` ``` -$ ./target/debug/runtime ./example/macroatom.3body +$ ./target/debug/runtime ./example/地球.3body ``` ``` diff --git "a/example/\345\257\273\346\211\276.3body" "b/example/\345\257\273\346\211\276.3body" new file mode 100644 index 0000000..367bb53 --- /dev/null +++ "b/example/\345\257\273\346\211\276.3body" @@ -0,0 +1,3 @@ +给 A 以 寻找("https://raw.githubusercontent.com/rustq/3body-lang/main/LICENSE"); + +广播(A); \ No newline at end of file diff --git a/src/evaluator/builtins.rs b/src/evaluator/builtins.rs index 385d58b..e2f3d45 100644 --- a/src/evaluator/builtins.rs +++ b/src/evaluator/builtins.rs @@ -12,6 +12,8 @@ use lexer::Lexer; use parser::Parser; extern crate rand; +#[cfg(not(target_arch = "wasm32"))] +extern crate reqwest; use evaluator::builtins::rand::distributions::Uniform; use evaluator::builtins::rand::{thread_rng, Rng}; @@ -23,6 +25,8 @@ pub fn new_builtins() -> HashMap { builtins.insert(String::from("rest"), Object::Builtin(1, monkey_rest)); builtins.insert(String::from("push"), Object::Builtin(2, monkey_push)); builtins.insert(String::from("广播"), Object::Builtin(1, three_body_puts)); + #[cfg(not(target_arch = "wasm32"))] + builtins.insert(String::from("寻找"), Object::Builtin(1, three_body_request)); builtins.insert( String::from("二向箔清理"), Object::Builtin(0, three_body_clear), @@ -105,6 +109,24 @@ fn three_body_puts(args: Vec) -> Object { Object::Null } +#[cfg(not(target_arch = "wasm32"))] +fn three_body_request(args: Vec) -> Object { + match &args[0] { + Object::String(o) => { + let resp = reqwest::blocking::get(o); + match resp { + Ok(res) => { + Object::String(res.text().expect("should be text")) + }, + Err(error) => { + Object::Error(format!("request got {}", error)) + } + } + } + _ => Object::Null, + } +} + fn three_body_clear(_args: Vec) -> Object { std::process::Command::new("clear").status().unwrap(); Object::Null diff --git a/src/evaluator/object.rs b/src/evaluator/object.rs index 6e1d306..9a4ee9d 100644 --- a/src/evaluator/object.rs +++ b/src/evaluator/object.rs @@ -122,11 +122,9 @@ mod tests { fn test_object_hash() { let mut hash = HashMap::new(); hash.insert(Object::String("a".to_string()), Object::Int(1)); - hash.insert(Object::String("c".to_string()), Object::Int(2)); - hash.insert(Object::String("b".to_string()), Object::Int(3)); let obj = Object::Hash(hash); - assert_eq!(obj.to_string(), "{\"c\": 2, \"b\": 3, \"a\": 1}"); + assert_eq!(obj.to_string(), "{\"a\": 1}"); } #[test] diff --git a/src/wasm/main.rs b/src/wasm/main.rs index 8ce1e7a..0dfe4d1 100644 --- a/src/wasm/main.rs +++ b/src/wasm/main.rs @@ -23,6 +23,7 @@ extern "C" { fn sleep(secs: c_uint) -> c_uint; fn clear() -> c_void; fn random(input_uint: c_uint) -> c_uint; + fn request(url: *mut c_char) -> *mut c_char; } fn internal_print(msg: &str) { @@ -49,6 +50,13 @@ fn internal_random(input: &i64) -> u32 { } } +fn internal_request(input: &str) -> String { + unsafe { + let result = request(string_to_ptr(input.to_string())) as *mut c_char; + let c_str = CStr::from_ptr(result); + c_str.to_str().unwrap().to_owned() + } +} fn string_to_ptr(s: String) -> *mut c_char { @@ -141,6 +149,19 @@ pub fn eval(input_ptr: *mut c_char) -> *mut c_char { }), ); + env.set( + String::from("寻找"), + &Object::Builtin(-1, |args| { + match &args[0] { + Object::String(o) => { + let n = internal_request(&format!("{}", o)); + Object::String(n) + }, + _ => Object::Null + } + }), + ); + let mut evaluator = Evaluator::new(Rc::new(RefCell::new(env))); let evaluated = evaluator.eval(&program).unwrap_or(Object::Null); let output = format!("{}", evaluated); diff --git a/web/src/js/constants.js b/web/src/js/constants.js index ae241f0..cf0d623 100644 --- a/web/src/js/constants.js +++ b/web/src/js/constants.js @@ -93,6 +93,13 @@ true { label: 'Clear', value: `二向箔清理(); +`, + }, + { + label: 'Request', + value: `给 A 以 寻找("https://raw.githubusercontent.com/rustq/3body-lang/main/LICENSE"); + +A `, }, ]; diff --git a/web/src/js/index.js b/web/src/js/index.js index 37c53e6..a81d993 100644 --- a/web/src/js/index.js +++ b/web/src/js/index.js @@ -24,4 +24,16 @@ Module.load('./monkey.wasm', { random: (input) => { return Math.floor(Math.random() * input) }, + request: (value) => { + const str = Module.copyCStr(value); + const xhr = new XMLHttpRequest(); + xhr.open("GET", str, false); + xhr.send(); + if (xhr.status === 200) { + console.log(xhr.responseText) + return Module.allocStr(xhr.responseText).ptr; + } else { + throw new Error('Request failed: ' + xhr.statusText); + } + }, }).catch((e) => console.error(e));