Runtime-compatible types to represent Nim (untyped) AST including filename, line and column information
Serialization of these types into an S-expression format that can be directly inserted inside a Nim triple-quoted string
Deserialization to these types that works in the compile-time VM
Conversion from these types into the compile-time NimNode type that can be used in macros
This allows complex systems that generate Nim code to do it in a much faster and easier way than the current alternatives (making all code run only in the compile-time VM, generating it as raw text, interfacing with the compiler codebase etc.). Examples of use cases may be templating engines, alternative parsers etc.
As a demonstration of what we can do, lispnim is a rudimentary version of Lisp that directly maps to Nim code using this library. lispnimgen is a simple binary Nimble package that generates Nim files from lispnim files, in the sense that the Nim file loads the serialized version at compile-time. lispnimgentest is a demonstration of how one can write a Nimble package in lispnim, then generate the Nim files in the installation process of the package.
# testpkg/src/testpkg.lispnim
(proc (foo *) ((x y int) int) (do
(= result (* x y))
(if (< result 0)
(raise (newException ValueError "result cannot be negative")))))
# testpkg/testpkg.nimble
...
requires "https://github.com/metagn/lispnimgen"
import os, strutils
after install:
let lispnimgenPath = strip staticExec"nimble path lispnimgen"
let exePath = lispnimgenPath / "lispnimgen"
# run lispnimgen on install path
exec quoteShellCommand([exePath, getPkgDir()])
Installing testpkg will generate a Nim file in its path like:
# testpkg.nim
import nuance/[fromsexp, comptime]
load(parseSexp("""<serialized ast of testpkg.lispnim>"""))
Using --excessiveStackTrace:off, we get the output:
21
main.nim(4) cmdfile
testpkg.lispnim(5) foo
Error: unhandled exception: result cannot be negative [ValueError]
We can see that the file and line information has been kept for errors. Note that this is only possible because of the macros.setLineInfo proc which exists in Nim version 1.6.12 or higher, meaning custom information will not persist on older versions.
A binary serialization option may be added in the future for faster deserializing at compile time,
All linked libraries are tested on the C, JavaScript and NimScript backends. The NimScript backend means that they all work on the compile-time VM as well.
Name: nuance
Author: metagn
Posting:
nuance is a library that provides:
This allows complex systems that generate Nim code to do it in a much faster and easier way than the current alternatives (making all code run only in the compile-time VM, generating it as raw text, interfacing with the compiler codebase etc.). Examples of use cases may be templating engines, alternative parsers etc.
As a demonstration of what we can do, lispnim is a rudimentary version of Lisp that directly maps to Nim code using this library. lispnimgen is a simple binary Nimble package that generates Nim files from lispnim files, in the sense that the Nim file loads the serialized version at compile-time. lispnimgentest is a demonstration of how one can write a Nimble package in lispnim, then generate the Nim files in the installation process of the package.
Installing
testpkg
will generate a Nim file in its path like:We can then import and use this module:
Using
--excessiveStackTrace:off
, we get the output:We can see that the file and line information has been kept for errors. Note that this is only possible because of the macros.setLineInfo proc which exists in Nim version 1.6.12 or higher, meaning custom information will not persist on older versions.
A binary serialization option may be added in the future for faster deserializing at compile time,
All linked libraries are tested on the C, JavaScript and NimScript backends. The NimScript backend means that they all work on the compile-time VM as well.