Using IRust for live scripting of a host
Boscop opened this issue · comments
Hi, thanks for making this :)
How hard would it be to make IRust useable for live scripting of a host, e.g. for music live coding in Rust?
It seems like this crate contains not only the Rust interpreter but also the code that deals with the console.
Would it be possible to use this crate as a lib and just use the interpreter part, and feed it as input the contents of a file which gets auto-reloaded from disk (via the hotwatch
crate), so that the editing could be done in one's favorite editor?
Hello,
Thanks for cheking this out!
IRust interpeter is just println!("{}", expression)
for a real repl in this regard check out https://github.com/google/evcxr/ it has jupyter notrbook support which might be what you want
Basicly the idea behind IRust is instead of focusing on the interpeter (since its relly hard for a compiled language) it focus on the exprience Ipython like, also the advantage is even the output is a slow compared to what someone is used to like from other repls, it is guatenteed to be correct ( also I tried cranelift backend and it improves the situation)
So back to your question, here are a couple of ideas:
There are crates that run the rust code like cargo script, alternatively with IRust here is whats currently possible:
- first there is the
:edit
command that you can use to edit the repl content in an external editor - there is also
:load
that takes a rust file and put it as is inside the repl :add
is actually useful here you can use it inside the project your editing like this ':add .' and it will add it as a dependency
Now that I gave more thoughts I like the idea of splitting the interpreter in its own crate.
I imagnie the API will looks something like
pub struct Repl{/**/}
impl Repl {
pub fn new() -> Self {/**/}
pub fn append(&mut self, code: &str) {/**/}
pub fn eval(&self, code: &str) -> Result<String> {/**/}
pub fn eval_without_context(&self, code: &str) -> Result<String> {/**/}
/**/
}
#[test]
fn test_repl() {
let mut repl = Repl::new();
repl.append(stringify!(let x = "hello";))
assert_eq!(repl.eval("x"),Ok("hello"))
assert!(repl.eval_without_context("x").is_err())
}
The main logic is in two files https://github.com/sigmaSd/IRust/blob/master/src/irust/repl.rs https://github.com/sigmaSd/IRust/blob/master/src/irust/cargo_cmds.rs
Here is a prototype https://github.com/sigmaSd/IRust/tree/irust_repl
There is now a split crate irust_repl
(The only required dependency for now is once_cell)
There are a lot of functions in the API due to how to IRust uses it, but for normal usage it would look something like:
use irust_repl::Repl;
use irust_repl::cargo_cmds::ToolChain;
let mut repl = Repl::new();
repl.insert("let a = 5+4;");
assert_eq!(repl.eval("a", ToolChain::Stable), 9);
assert_eq!(repl.eval(1+1, ToolChain::Beta), 2);
For the interactive usage use case it would be something like
//in psuedo code
let repl = Arc::new(Mutex::new(Repl::new()));
spawn_thread:
loop {
watch(script_file)
if file_changed:
// Invalidate the repl on any change
repl.reset();
repl.insert(std::fs::read_file(script_file))
}
main_thread:
loop {
let input = read_stdin();
let output = repl.eval(input);
print(output)
}
Btw the above interactive example is equivalant to using IRust :load
/:reload
commands
I evaluated the options and the one that seems the most convenient with IRust is using :add $Path_to_project
Here is a little guide https://sigmasd.github.io/irust_book/interactive-usage/
I believe this can be closed now, feel free to reopen if needed.