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. :)

Reply via email to