If all of your procs are going to look like newFooBar above there, it's
possible to generate with a macro.
import macros, tables
type
Tensor[T] = object
discard
Model = object
field1: string
field2: string
field3: int
FooObj = object
field1: Tensor[float]
field2: Table[string, float]
field3: int
proc unpack[T; U](arg: T, to: var U) = discard
proc newVar(name, dtype: NimNode): NimNode =
result = nnkVarSection.newTree(
nnkIdentDefs.newTree(
ident(name.toStrLit.strVal), # replace by new ident
dtype,
newEmptyNode()
)
)
echo result.repr
macro genNewObjProc(obj, model: typed): untyped =
let objFields = obj.getType[1].getTypeImpl[2] # get recList of type
let modelFields = obj.getType[1].getTypeImpl[2] # get recList of type
doAssert objFields.len == modelFields.len
var body = newStmtList()
let modelIdent = ident"model"
# variable to hold object constructor `FooBar(field1: field1,...)`
var objConstr = nnkObjConstr.newTree(obj)
for i in 0 ..< objFields.len:
let modelName = ident(modelFields[i][0].toStrLit.strVal) # replace by
new ident
doAssert eqIdent(objFields[i][0], modelName)
let objType = objFields[i][1]
body.add newVar(modelName, objType)
body.add quote do:
unpack(`modelIdent`.`modelName`, `modelName`)
# add to object constructor
objConstr.add nnkExprColonExpr.newTree(modelName, modelName)
# add resulting `FooObj` call
let resIdent = ident"result"
body.add quote do:
`resIdent` = `objConstr`
let procParams = [obj, # return type
nnkIdentDefs.newTree(modelIdent,
model,
newEmptyNode())]
result = newProc(name = ident("new" & obj.toStrLit.strVal),
params = procParams,
body = body)
echo result.repr
genNewObjProc(FooObj, Model)
Run
I'm not sure how helpful it is to get such a macro if one isn't familiar with
macros. But since it's fun to write I might as well give you a solution. :)