-
Notifications
You must be signed in to change notification settings - Fork 23
Open
Description
Abstract
Implement the following function:
# module std/macros
proc addCompileTimeExitProc*(cb: proc(): NimNode) {.compileTime.} =
# Schedules `cb` to be executed as if it was a macro call
# at the end of main module. Appends result of `cb` at the
# end of main module.
Motivation
No response
Description
It effectively allows to achieve the same results as #563 was proposed for, albeit in a slightly more convoluted way. On the plus side, the implementation of this magic is trivial.
Code Examples
An example of how delayed CT evaluation can be implemented on top of this (no additional compiler help required):
import macros
proc defineDelayed[T](val: T): NimNode = quote: `val`
macro delayedConstPtrAux[T](prc: static[proc(): NimNode]): untyped =
let s = genSym(nskProc, "delayed")
result = quote do:
proc `s`(): pointer
`s`()
let bbb = prc
addCompileTimeExitProc() do() -> NimNode:
let a = bbb()
result = quote do:
proc `s`(): pointer {.inline, stackTrace: off, enforceNoRaises.} =
const b = `a`
when compiles(addr b):
addr b
else:
var g {.global.} = `a`
addr g
template delayedConstPtr*[T](val: T): ptr T =
# Returns pointer to const data generated from `val` compile-time
# expression at the end of compilation.
cast[ptr T](delayedConstPtrAux[T](proc(): NimNode = defineDelayed(val)))
when isMainModule: # Test
var registry {.compileTime.}: seq[string]
macro registerSomething*(a: static[string]): untyped =
registry.add(a)
proc testRegistry*() =
let r = delayedConstPtr(registry)
doAssert($r[] == """@["foo", "bar"]""")
echo "TEST PASSED"
testRegistry()
registerSomething("foo")
registerSomething("bar")
Backwards Compatibility
It is 100% backward compatible
Implementation
I've posted a PR to demonstrate this, please feel free to play around.
levovix0, hugosenari, RSDuck and ASVIEST
Metadata
Metadata
Assignees
Labels
No labels