Not quite sure where to go with this, and whether it's something I'm doing wrong, or some behavior that changed in the new (rc) version, so figured I'd give the forum a shot.
I'm trying to register some types and associated metadata during compile time, and that worked fine in 1.6.8. I also seem to get this working in 1.9.1 in a 'normal' nim run (if I'm not wrong, haven't tested thoroughly), but having issues with my nimble tests. Here's a simplified reproducable example of the code that registers types:
import std/tables
import macros
import print
type
Metadata = object
name: string
id: BiggestInt
var allInfo {.compileTime.} = initTable[string, Metadata](0)
macro addInfo*(nimType: typedesc, id: int): untyped =
let typeString: string = $nimType
result = quote do:
echo repr "ADDED " & `typeString`
allInfo[typeString] = Metadata(name: typeString, id: id.intVal)
echo "ADDED " & typeString
const ALL_METADATA* = allInfo
The ALL_METADATA const is what I'm after. And here is the test I wrote for it:
import unittest
import print
import std/tables
import const_test
addInfo(string, 0)
addInfo(int, 1)
print ALL_METADATA
test "test_key":
assert 1 == 1
assert ALL_METADATA.hasKey("int")
This works fine on nim version 1.6.8, but when I'm running the same code in 1.9.1, it looks like the ALL_METADATA const is empty.
Anybody an idea what is happening?
I think the new behavior is correct here. const ALL_METADATA = allInfo evaluates before any changes to allInfo, so the value of ALL_METADATA is locked in.
You can use something like
template saveMetadata() =
const ALL_METADATA {.inject.} = allInfo
and call saveMetadata() after all the calls to addInfo
In addition to @Hlaaftana's answer, if you don't need the data at compile time, you can do this to get it at runtime:
import std/tables
import macros
import print
type
Metadata = object
name: string
id: BiggestInt
var ALL_METADATA* = initTable[string, Metadata]()
macro addInfo*(nimType: typedesc, id: int): untyped =
let typeString: string = $nimType
result = quote do:
ALL_METADATA[`typeString`] = Metadata(name: `typeString`, id: `id`)
echo repr "ADDED " & `typeString`
echo "ADDED " & typeString
Or you can do a combo of both, just with two separate variables (one for compile-time and one for run time).