Open
Description
Context
I find working with types in macro quite difficult and I think Nim would gain a lot if it was easier.
The 2 main issues I've noted are:
- getTypeInst only works in a typed macro, but it doesn't work in a compile-time proc. In an untyped context, this forces us to use a helper macro with
getAST
/quote do
as we can't call a macro from a macro. - It is very easy to get
Cannot instantiate
ortype mismatch
because of forgetting to convert the NimSym given bygetTypeInst
toNimIdent
if they are not used raw.
Example:
import macros
type Conv2DLayer[T] = object
data: T
type Context[T] = ref object
data: T
proc replaceNodes*(ast: NimNode): NimNode =
# Replace NimIdent and NimSym by a fresh ident node
proc inspect(node: NimNode): NimNode =
case node.kind:
of {nnkIdent, nnkSym}:
return ident($node)
of nnkEmpty:
return node
of nnkLiterals:
return node
else:
var rTree = node.kind.newTree()
for child in node:
rTree.add inspect(child)
return rTree
result = inspect(ast)
####################################
####################################
macro ctxSubtype(context: Context): untyped =
## Extract the subtype from a Context
echo context.getTypeInst.treerepr
result = context.getTypeInst[1] # This gives a cryptic error got <Foo> expected <bar>
# result = replaceNodes(context.getTypeInst[1]) # If we replace the symbol by ident it works!
macro genModelFromCtx(modelType: untyped, context: Context): untyped =
var records = nnkRecList.newTree
let subtype = getAST(ctxSubtype(context))
let field_type = nnkBracketExpr.newTree(
ident("Conv2DLayer"), subtype
)
records.add nnkIdentDefs.newTree(
newIdentNode("field_name"),
field_type,
newEmptyNode()
)
result = nnkStmtList.newTree(
nnkTypeSection.newTree(
nnkTypeDef.newTree(
newIdentNode($modelType),
newEmptyNode(),
nnkObjectTy.newTree(
newEmptyNode(),
newEmptyNode(),
records
)
)
)
)
var ctx: Context[seq[int]]
expandMacros:
genModelFromCtx(FooType2, ctx)
## Output - before replaceNodes:
# got: <seq[int]>
# but expected: <T>
## Output fixed:
# type
# FooType2 = object
# field_name: Conv2DLayer[seq[int]]
Metadata
Metadata
Assignees
Labels
No labels