So I understand how to instantiate a wasm module in JS. But let's say I wanted to implement a WAT REPL, what would my options be to interactively execute the user provided wat code? And output the result of that execution.
I've been doing a bit of research into how other "compiled to IL" languages do it and this led me to the .NET Roslyn Scripting API. https://weblog.west-wind.com/posts/2022/Jun/07/Runtime-CSharp-Code-Compilation-Revisited-for-Roslyn#roslyn-scripting-apis
It looks more complicated than I had hoped, compared with doing it with a simple interpreter. From what I understand, every snippet of code is basically wrapped in an assembly and that assembly is dynamically linked into the "main" REPL assembly. I haven't gone as far as trying to tease out how it's implemented in code but that seems like the gist of it.
How would this mechanism translate to WebAssembly? I guess you would somehow need to create a new module instance for each new snippet of code that is typed in the repl. But the mechanism for making all these modules behave like they are all one big happy family eludes me. I know you can import and export functions from modules, which would allow the host to pipe one function from one module into another module. But that is done at compile time, isn't it? You need to know the function names.
How would one achieve this at runtime, dynamically. Sharing Memory?
The Rust wat crate can translate WAT into a WebAssembly binary bytes. You can (relatively easily) expose this function to JS code with wasm-bindgen and then you can give the bytes to the browser as usual.
This could work well if you "just" wanted to call an exported method where the user implements the method, provides the arguments for it and gets the result. If you have more complicated code (for example an entire game where the user-provided functionality is called like a plugin), then you would probably need to add a WASM runtime to your code that would load and run the user-provided code. I can elaborate if that's what you want.
There is also something called wepl (WebAssembly REPL), but that seems to be a command line application.
@Karel Hrkal (kajacx) yeah, I would want more than that. For context, what I want to do is build a compiler/interpreter pipeline that takes Tiny-BASIC source code, compiles it to wasm and runs it using wasmtime. As part of that project, I wanted to provide a Tiny-BASIC REPL that plugs-in to this pipeline.
Having done a bit more research into it, I think that what languages like C# and Java, which have an AOT compilation step to IL before handing the IL over to their VM, do in order to provide a REPL is basically create a new assembly that wraps every input from the REPL. They use some sort of context to keep track of the state of the REPL session (mainly, the global and local variables declared and assigned to) and inject that into each new assembly.
So, if I'm thinking about emulating such a mechanism for my Tiny-BASIC compiler REPL, I would basically have the REPL host compile and instantiate a new wasm module for each input coming in from the terminal, somehow injecting the global and local variables held in the REPL context, along with the public API (exported function, shared memory etc.) of the already loaded wasm modules, and then executing that module.
At least, that's kind of how I'm conceptualizing this in my head at the moment.
You may be interested in my Project WEPL which is intended as a Wasm Component repl: https://github.com/rylev/wepl
Ryan Levick (rylev) said:
You may be interested in my Project WEPL which is intended as a Wasm Component repl: https://github.com/rylev/wepl
Looks interesting. I'll take it for a spin. Is it a JS REPL?
@Philippe Vaillancourt Ok, can you explain what would I, an user of the finished project that you are thinking of, actually do? Would I open a website with text area where I would write my in Tiny-BASIC, then hit "Run" and it would run the code? Would it be entirely on client-side, or is compilation on a server an option? Or would it be a console application?
I am not sure how you would want it to work, so I cannot help you make it unless I understand what you want to make. Explain it to me like you would explain it to someone who has never seen it before and wants to use it.
@Karel Hrkal (kajacx) I was planning to make it a console application.
The same way you can just type node
from the command line and it starts a REPL. That's the kind of experience I want for the user.
image.png
In that case, you probably want to read from and write to the terminal with WASI. I would recommend to write some minimal example in rust and see what it compiles to and then go from there. There is a lot of "background" knowledge to get first - how to crate a wasi component, how to convert the wasm binary format to the wat text format, how the wasm instructions work, how to convert the wat text format back to binary and then how to actually run that wasi component, and I don't have all the links to tutorials on how to do these things on hand unfortunately.
Last updated: Nov 22 2024 at 16:03 UTC