1use crate::core::{
3 env::Env,
4 gc::{Block, Context, RootSet},
5 object::{CloneIn, Object},
6};
7use rune_core::macros::root;
8use rune_macros::defun;
9use std::thread::{self, JoinHandle};
10
11#[defun]
12fn go(obj: Object) {
13 go_internal(obj);
14}
15
16fn go_internal(obj: Object) -> JoinHandle<()> {
17 let block = Block::new_local_unchecked();
18 let sexp = obj.clone_in(&block);
19 let raw = sexp.into_raw();
20 crate::debug::enable_debug();
21 thread::spawn(move || {
22 let roots = &RootSet::default();
23 let cx = &mut Context::from_block(block, roots);
24 root!(env, new(Env), cx);
25 let obj = unsafe { Object::from_raw(raw) };
26 root!(obj, cx);
27 _ = crate::interpreter::eval(obj, None, env, cx);
28 })
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 #[test]
36 fn test_go() {
37 let roots = &RootSet::default();
38 let cx = &mut Context::new(roots);
39 let obj = cx.add("test string");
40 go_internal(obj).join().unwrap();
41 }
42
43 #[test]
44 fn test_go_eval() {
45 let roots = &RootSet::default();
46 let cx = &mut Context::new(roots);
47 let threads = [
48 go_internal(crate::reader::read("(if nil 1 2 3)", cx).unwrap().0),
49 go_internal(crate::reader::read("(progn (defvar foo 1) foo)", cx).unwrap().0),
50 go_internal(crate::reader::read("(progn (defvar foo 1) (makunbound 'foo) (let ((fn #'(lambda () (defvar foo 3))) (foo 7)) (funcall fn)) foo)", cx).unwrap().0),
51 ];
52 for thread in threads {
53 thread.join().unwrap();
54 }
55 }
56
57 #[test]
58 fn test_go_message() {
59 let roots = &RootSet::default();
60 println!("hello main thread");
61 let cx = &mut Context::new(roots);
62 let obj = crate::reader::read("(message \"hello from thread\")", cx).unwrap().0;
63 go_internal(obj).join().unwrap();
64 }
65}