So here is my code:
proc runNimProcFromAnotherFile(filename: string) =
#[ I need to import the filename and use the proc defined inside it...]#
How do I import the file and return the proc inside it?
Thanks.
That isn't what I wanted @kidandcat. To better explain my question:
proc importNewModule(module: string) =
import module # this is just for illustration, it won't work I know. How do I do that?
something()
And the module is something like this...
proc something() = echo Hi
All I need to know is how do I import the module and use it in runtime. You can't dynamically import a module in Nim because it is a statically compiled language, (you end with your binary, you don't distribute the source code)
If you want to do that, you can compile your library as a shared library, but I'm 100% sure you don't need to do that to achieve what you want.
Dynamic imports like that are a interpreted languages thing, and humans have been creating any imaginable kind of programs without them for decades
@kidandcat, I discovered the nim compiler api which seems perfect for my use.
https://forum.nim-lang.org/t/5994
Also, the example you provided just calls out the nim compiler without returning any exported proc inside it. (Because it's runtime)
Is there any particular reason why I shouldn't use the nim compiler API? Any cons?
If you don't really care about speed - you could use the built in Nim compiler+virtiual machine as a script interpreter, (though IIRC there are limits by default that may surprise you and that can be removed, e.g. how many iterations a single loop can have is limited to 1,000,000 as this is meant to be used while compiling). Otherwise ...
Your users will need an installed, accessible compiler compatible with the one you used to build the main; that's easy if you do everything in JS (you already have the relevant JS runtime and likely compiler) but more complicated if you use other targets (C / Objective-C / C++) - is it VS2015, VS2019, mingw32, mingw64, gcc, llvm, nlvm, ...?
If the users don't provide source code, but only need to pick which module to load from a given set you already provide, either (a) import all of them in the first place, and have some logic to call the right one, or (b) use dynamic loading and possibly hot-code-reload to pick the right one to use -- and save your users the headaches from needing to have a usable compile environment.
and save your users the headaches from needing to have a usable compile environment.
That's way too negative, the binary will contain the required parts of the Nim compiler and its VM and all you need to do is to provide lib/system/, system.nim (and maybe strutils, etc) with your app and patch the line let std = findNimStdLibCompileTime() to something appropriate.
Nim doesn't have to be installed at all for this to work.
(though IIRC there are limits by default that may surprise you and that can be removed, e.g. how many iterations a single loop can have is limited to 1,000,000 as this is meant to be used while compiling). Otherwise ...
That limit can be changed at compile-time but it's a very useful thing for sandboxing. In the few benchmarks that I did, the VM runs Nim code faster than Python's VM runs Python code.
I do not know your use case, but i think embedding a compiler is a little overkill. Why can't you just include every required module? What are you'r concerns?
Can you elaborate what your use case for the REST api is?
That's way too negative, the binary will contain the required parts of the Nim compiler and its VM and all you need to do is to provide lib/system/, system.nim (and maybe strutils, etc) with your app and patch the line let std = findNimStdLibCompileTime() to something appropriate.
Was not intending to be negative, and this comment was in the context of compiling down to native code; you are of course correct (and that was my first paragraph - use the nim vm),
That limit can be changed at compile-time but it's a very useful thing for sandboxing. In the few benchmarks that I did, the VM runs Nim code faster than Python's VM runs Python code.
Indeed, that's very useful for sandboxing; I remember when Python tried to introduce sandboxing, by way of putting such limits, but it never converged - there were issues with loops, string multiplications, e.g. `` 10e10 * 'hello world' `` or `` range(10e10) `` would blow up memory; they were fixed as they were found, but their approach of rewriting bytecode was doomed to fail (and did). Implementing these restrictions within the VM is much more practical.
And I've never had a chance to use Nim VM for anything speed related, but the python speed comparison is very good news.
Here's the code:
import asynchttpserver, asyncdispatch
var givenByUser = "test.nim"
var server = newAsyncHttpServer()
proc cb(req: Request) {.async.} =
# import user.nim
# use it's main proc
await req.respond(Http200, procInFile())
waitFor server.serve(Port(8080), cb)
The code that user might provide:
proc procInFile*():string =
return "hello"
You can write a macro that produces import statements from seq of strings, but seq of strings should be known at compile time.
For example I have a macro that imports all modules in a folder recursively. This is used to run tests in individual modules.
ok, being compiled or dynamic, it might be a bad idea to let users run arbitrary code on your machine.
Better define some procedures users can call.
What kind of code the users will provide?
(If your goale is to build something like a nim playground have a look how nim playground solves this issue. https://github.com/PMunch/nim-playground )