sigmaSd / IRust

Cross Platform Rust Repl

Home Page:https://crates.io/crates/irust

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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/

@Boscop You might look into Rune or Rhai, both of which are Rust-like scripting languages designed for easy embedding into Rust programs.

I believe this can be closed now, feel free to reopen if needed.