Benni Katchy
Benni Katchy

Reputation: 83

How do I call a Rascal function from Rust

I am working on a Rust CLI (using Clap) to use along side my Rascal DSL by problem is this. How do I call a Rascal function (functions defined my DSL) in my Rust CLI code? I have previously implemented this CLI in Python (using Click) and implemented the inter-ops between Rascal and Python using JPype but the performance was horrendous. I hope to improve the performance by rewriting my CLI in Rust but I am not sure how to implement the inter-ops between Rascal and Rust. I will be glad if someone could help me out.

Upvotes: 1

Views: 73

Answers (2)

Jurgen Vinju
Jurgen Vinju

Reputation: 6696

I think the best way for fast results and reasonable performance is to use rascal's built-in web application server in util::Webserver of the standard library.

  1. Use lang::json::IO for fast and convenient mappings between json values and Rascal values.
  2. The server can stream json directly.
  3. Connect the rust program via synchronous or asynchronous http requests and use a Rust library for binding JSON values.
  4. Use LOC values to identify things consistently between client and server, like qualified names in your DSL and source files.

This is basically the way the LSP services work as well. We're planning to add web sockets to util::Webserver later. The standard library has examples in vis::Charts and vis::Graphs where JSON is used to communicate with JavaScript libraries on the other side. The "DrAmbiguity" project is a much bigger example that's built on top of the "salix" UI framework, but farther from your usecase. Those vis examples simply transform rascal values to json and communicate them over http via util::WebServer.

Tip: if a Rascal web service (of type Content is returned on the REPL it will be served automatically and its index page shown in your browser without having to start a server yourself with util::WebServer. Good for testing and debugging; saves time and you always know your looking at the latest version.

An alternative, more creative, route is to use the language parametric LSP servers; using the rascal-lsp library you can spin up LSP servers and load your Rascal service implementations in there. The main module to use is util::LanguageServer. If your functionality falls within the protocol then you can develop and test it within VScode and connect it to a Rust or C based LSP client.

Finally you could copy the design of `util::TermRepl‘ and replace the java side of it by a JNI implementation that connects to the rust REPL.

I'd go for the first because you'd have that up and running in no time.

Upvotes: 0

Benni Katchy
Benni Katchy

Reputation: 83

Thanks for your response it took me a while to respond because I am still trying to fully understand the implementation you suggested. My understanding is that:

  1. I need to run a server on the Rust client (CLI) that would take user commands and convert it to a JSON payload to be sent to the Rascal backend
  2. I need to also run a server on the Rascal backend that would accept request from the client, marshal the payload sent by the client into a Rascal ADT and use it to call a Rascal function then convert the result into a JSON payload to be sent back to the server.

I assume this setup would work for any client app (Java, Python etc). I will look at the util::Webserver api to see how to spawn a server in Rascal if there are any examples I will be extremely glad if you can point me to it. I already have some experience working with lang::json::IO. Thanks once again this is very useful.

Upvotes: -1

Related Questions