In the previous step, you guys helped me make the declareEnum() macro that generates an enum type. Now, I need to generate a proc that uses the enum type for a parameter. My first attempt employs a template:
template declareFieldEnum*(
peripheralName: untyped,
registerName: untyped,
fieldName: untyped,
bitOffset: static int,
bitWidth: static int,
values: untyped
) {.inject.} =
declareEnum(`peripheralName _ registerName _ fieldName Val`):
values
proc `fieldName`*(
regVal: `peripheralName _ registerName Val`,
fieldVal: `peripheralName _ registerName _ fieldName Val`
): `peripheralName _ registerName Val` {.inline.} =
discard # the impl isn't important to this example
This gives me the error: Error: Expected a node of kind nnkAsgn, got nnkStmtList which suggests a mangled depth of nesting of the untyped argument I passed. Is a template the right tool for this? I'm in the deep end and could use another hand. If I can get this going, I have smooth water after this.
The problem in isolation is here (playground).
Don't know if it could be made with a template, but it works with a macro:
macro declareFieldEnum*(
peripheralName: untyped,
registerName: untyped,
fieldName: untyped,
bitOffset: static int,
bitWidth: static int,
values: untyped
) =
let enumName = ident(peripheralName.strVal & '_' & registerName.strVal & '_' & fieldName.strVal & "Val")
let regValType = ident(peripheralName.strVal & '_' & registerName.strVal & "Val")
let fieldValType = ident(peripheralName.strVal & '_' & registerName.strVal & '_' & fieldName.strVal & "Val")
let returnType = ident(peripheralName.strVal & '_' & registerName.strVal & "Val")
result = quote do:
declareEnum(`enumName`, `values`)
proc `fieldName`*(regVal: `regValType`, fieldVal: `fieldValType`): `returnType` {.inline.} =
discard # impl is not important for this example
Playground link: https://play.nim-lang.org/#pasty=qzfBKYoXoyOm
Generated code:
declareEnum(PER_REG_FLDVal):
OFF = 0
VAL1 = 1
VAL2 = 2
VAL3 = 3
VAL4 = 4
proc FLD*(regVal`gensym0: PER_REGVal; fieldVal`gensym0: PER_REG_FLDVal): PER_REGVal {.
inline.} =
discard
Thank you. I got this to compile locally and I suspect it will work.
My test project is not building for other reasons that I'm working on. So it will be a bit before I can claim full success and push to https://github.com/dwhall/minisvd2nim