beef331 / website

Code for the official Nim programming language website
https://nim-lang.org
19 stars 1 forks source link

nuance #79

Closed metagn closed 1 year ago

metagn commented 1 year ago

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.

# 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>"""))

We can then import and use this module:

import testpkg
# or
import pkg/testpkg

echo foo(3, 7)
echo foo(3, -7)

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.