many scripting languages has interpreter implemented in WebAssembly, notably, AssemblyScript, TypeScript, Berry, Janet, Lua, Python (reference from https://github.com/appcypher/awesome-wasm-langs )
since I really like Nim syntax, So I was trying to Port NimScript to WebAssembly, and here is what I have tried,
about NimScript, is the subset of Nim that can be evaluated by Nim's builtin virtual machine (VM). This VM is used for Nim's compiletime function evaluation features.
so If I can compile Nim's builtin virtual machine (VM) into wasm, does it mean I can input NimScript and interpret it by wasm3 running the vm?
here is what I have got so far
~/Work/wasm/nlvm/nlvm$ ls
llgen.nim lllink.nim llplatform.nim maths.nim nim.cfg nlvm nlvm.nim panicoverride.nim
but even a simple compile failed...
./nlvm c --cpu:wasm32 --os:standalone --mm:none --passl:-nostdlib maths.nim
Hint: used config file '/home/jk/Work/wasm/nlvm/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/jk/Work/wasm/nlvm/Nim/config/config.nims' [Conf]
Hint: used config file '/home/jk/Work/wasm/nlvm/nlvm/nim.cfg' [Conf]
...................................................
Hint: @["wasm-ld", "-o", "/home/jk/Work/wasm/nlvm/nlvm/maths.wasm", "-lpthread", "/home/jk/.cache/nim/maths_d/maths.o", "--export-dynamic"] [Link]
wasm-ld: error: unable to find library -lpthread
Error: linking failed
is my general direction right? can nlvm really work for what I am trying to do?
I think it can work. But compiling math.nim (why this one?) with --passl:-nostdlib and --mm:none and --os:standalone ... why? Compile nim with the newer --os:any and --mm:arc and -d:useMalloc as you need the memory management. Then set it up so that malloc is compiled by the toolchain to be mapped to WASM's mechanism.
Though it may be easier to use the default Nim compiler, compile to C and than compile that C to wasm.
compiling math.nim is just a test for nlvm, since I was learning about it.
regarding default Nim compiler, compile to C and than compile that C to wasm. does it mean nlvm is not needed?
the options from https://github.com/arnetheduck/nlvm, maybe it's too old?
# myfile.nim
proc adder*(v: int): int {.exportc.} =
v + 4
nlvm c --cpu:wasm32 --os:standalone --gc:none --passl:--no-entry myfile.nim
wasm2wat -l myfile.wasm
OK, thanks for reply,
~/Work/wasm/nlvm/Nim$ ls -h
azure-pipelines.yml build_all.bat changelogs config dist icons koch.nim.cfg nimdoc nimsuggest testament
bin build_all.sh ci copying.txt doc koch lib nim.nimble readme.md tests
build changelog.md compiler csources_v2 drnim koch.nim nimcache nimpretty security.md tools
from https://nim-lang.org/docs/nims.html NimScript, is the subset of Nim that can be evaluated by Nim's builtin virtual machine (VM). This VM is used for Nim's compiletime function evaluation features.
so How to compile Nim's builtin virtual machine (VM) to C and than compile that C to wasm?
You can compile Nim directly to WASM with emscripten or via clang's --target:wasm32 option.
Here's a repo compiling Nim code to WASM with emscripten or with clang's --target:wasm32 option. The emscripten sample uses websockets and sokol.nim. The --target:wasm32 sample uses wasmrt to export code and import JS code.
got it, maybe I can wait for some one to build the .wasm file so I can do the following example from https://github.com/beef331/wasm3
import wasm3
let
env = loadWasmEnv(readFile"NimScript.wasm")
evalScript = env.findFunction("eval")
let script = """ echo "Hello from nimScript" """
evalScript.call(script)
Update:
I have tried https://github.com/wasmerio/wasmer from https://wasmer.io/
JUST single line below, it's magic!
wasmer run python/python -- -c "print(1+1)"
I wish nimScript can have the same, but currently not there jet...
The "huge binary" isn't "huge" by today's standards and if you integrate NimScript into you app you get "hot code reloading" and it also runs in a sandbox...
But you simply gave a list of features. Not a concrete use case/application. But hey, do what you want, I personally think webassembly is so much worse than Posix with its non-existing threading, atomics, file system access...
I think this is my last reply, but I think it's a important point to share.
Posix is a old standard and it's not good for embedded device or micro kernel, I Never think making Posix in the OS is a good Idea, maybe in the old days, OS designer just made a hacking solution.
before I started learning Nim, I was a embedded software engineer, I have done many RTOS projects with C, and frustrated with it's language design drawbacks, so thank you for for make Nim as a alternative choice ! the lessons I have learned is that all computer hardware device is just a software player, in order to orchestrate them like a music Orchestra, there must be a software component exchange protocol between them. (Note: software players have different form factor and CPU architecture )
I have used wasm3 in embedded devices without any posix, and it works well, but NimScript? I am sorry, It's too big for it, so what about micropython, Lua? there are all prebuild binary and can not add, remove or update dynamically.
as you can see from my background, we have a different point of view on things, but that's not the reason I wrote this long reply, the truth is, maybe I am just a humble Nim user, but hey, why not share some thought or ideas, maybe helps.
wasm images are similar to docker images, you can build them with different features with different sized images .
for embedded device, it maybe only need a minimal featured nimScript which is small in size.
for PC or cloud device, there are also full featured wasm images when needed.
Regarding nlvm, it can compile Nim code directly to wasm - this broadly generates more efficient code mode efficiently than nim`+`clang - the thing that's missing in the Nim ecosystem in general is a standard library based on wasi - ie all interactions with the OS, environment and so on need to be written - this is not really in the domain of nlvm.
The most pragmatic route today, unless you write code entirely without standard library dependencies (ie pure nim-based algorithms) is indeed nim -> c -> emscripten -> wasm where emscripten generates an emulation layer from posix to wasm - just like with nim and c, this emulation layer adds a bit of inefficiency. We do this to run nimbus in the browser for example (https://eth-light.xyz/).
nlvm docs need updating for wasm32 + orc - ORC in general is still buggy both in nim and nlvm but it's getting there - this would indeed be the way forward for "general-purpose" wasm support, though nlvm could in theory generate wasm for the old GC as well I suspect since it has fairly tight control over gc roots.
One more thing that emscripten generally does is a javascript-based wrapper to call wasm from js - it would be a convenience to have this generated as well as part of compilation though it's an open question where that should live.