How do you code the equivalent of makeType() template in
template makeType(typName: expr, base: typedesc): stmt =
type
typName = distinct base
makeType(MyType, float)
var mt = MyType(3.1415)
echo mt.float
for handling a string as makeType("MyType", float) rather than an expression?
I can do it using emit() (but it seems a bit rough) as
template makeType(typName, base: string): stmt =
emit("type " & typName & " = distinct " & base)
makeType("MyType2", "float")
var mt = MyType2(3.1415)
echo mt.float
There are a couple of different ways (emit is one of them), but you can always "reverse engineer" Nim code using a macro and macros.dumpTree/newNimNode/etc.. eg:
import macros
# First, print AST using `dumpTree`.
dumpTree:
type Foo = distinct Bar
# prints:
#
# StmtList
# TypeSection
# TypeDef
# Ident !"Foo"
# Empty
# DistinctTy
# Ident !"Bar"
# Then rebuild similar AST with a macro.
macro makeType(name,base:static[string]): typed =
newNimNode(nnkTypeSection).add(
newNimNode(nnkTypeDef).add(
newIdentNode(name),
newEmptyNode(),
newNimNode(nnkDistinctTy).add(
newIdentNode(base)
)
)
)
makeType("MyType", "float")
var mt = MyType(123.4)
echo mt.float # prints '123.4'
You could also do this, which is simpler to understand, but the same basic concept using getAst and a template.
import macros
macro makeType(name, base): typed=
template genType(tname, tbase)=
type tname = distinct tbase
result = getAst(genType(ident($name), ident($base)))
makeType("MyType", "float")
var mt = MyType(123.4)
echo mt.float
Yes, and there's also quote:
import macros
macro makeType(name,base:static[string]): typed =
let n = name.ident
let b = base.ident
return quote do:
type `n` = distinct `b`