Hey all. I'm writing an app that is trying to expose an async API to the Nim VM, and have it used from within the VM as a blocking API. Basically, some way to treat a VM instance like a thread or fiber and pause/resume it. Here's a simple example:
# interpreted.nim
import api
proc main* =
doSomething()
doSomethingElse()
# compiled.nim
...
interpreter.implementRoutine "*", "api", "doSomething", proc(a: VmArgs) =
# perform some async task here. Interpreted script shouldn't continue until it's done.
let main = interpreter.selectRoutine("main")
interpreter.callRoutine(main, []) # this shouldn't block
...
One solution is to run the interpreter in its own thread and to pause/resume the thread. I expect this would work, but it seems pretty heavy, as I may have hundreds or thousands of interpreters running at a time. I looked quickly at the coro module, but in addition to being experimental, it wasn't clear to me if I can do my own scheduling. I spent a fair bit of time trying to come up with something with iterators, but I couldn't make it work.
What I ended up doing is patching the Nim VM to explicitly support pausing/resuming. https://github.com/dsrw/enu/commit/5662f28dbb5e105116cd6d1236eb6913ce79c74b. This is doing the job, but I'd like to get back onto a mainline Nim version, and I'm not sure how to proceed.
Thoughts? Is there an iterator based solution that I missed? Some kind of goto magic that I could try? Should I work to get some version of my patch included in Nim, perhaps replacing the Pausable stuff with a new NodeKind variant?
Thanks!
Should I work to get some version of my patch included in Nim, perhaps replacing the Pausable stuff with a new NodeKind variant?
Something like that but I wonder if it requires a new NodeKind at all. The PCtx already contains everything required except for the "program counter".