The implementation of `Any` in the standard library package 
[typeinfo](https://nim-lang.org/docs/typeinfo.html) and the implementation of 
`Variant` in @yglukhov's lovely [variant](https://github.com/yglukhov/variant) 
package take an interestingly different approach to dissecting and using types 
during compile-time execution. `typeinfo`'s approach is based on 
`getTypeInfo()`, which yields a `PNimType`. `variant`'s approach is based on 
`getTypeImpl()`, which yield a `NimNode`.

What are the strengths and weaknesses of these two approaches? Do they have 
different limitations? Different maintainability? Are they ultimately 
complementary? I.e. if a package goes far enough in dissecting and using types, 
will it tend to use both? (And if so, is that a good thing?)

The implementation of `Any` begins by converting the type to a `PNimType`: 
    
    
    proc toAny*[T](x: var T): Any {.inline.} =
      newAny(addr(x), cast[PNimType](getTypeInfo(x)))
    
    
    Run

Then it dissects and uses that `PNimType` (as `rawType`). Here's a 
representative example: 
    
    
    proc invokeNewSeq*(x: Any, len: int) =
      assert x.rawType.kind == tySequence
      var z = newSeq(x.rawType, len)
      genericShallowAssign(x.value, addr(z), x.rawType)
    
    
    Run

In contrast, the implementation of `Variant` begins by obtaining the type's 
implementation as a `NimNode`: 
    
    
    proc mangledName(t: NimNode): string =
        mangledNameAux(getTypeImpl(t)[1])
    
    
    Run

Then it dissects the type by understanding that `NimNode` and by navigating 
deeper with additional calls to `getTypeImpl()` or `getImpl()`. Here's a 
representative example: 
    
    
    proc mangledNameAux(t: NimNode): string =
        case t.typeKind
        of ntyAlias:
            assert(t.kind == nnkSym)
            let impl = t.symbol.getImpl()
            assert(impl.kind == nnkTypeDef)
            result = mangledNameAux(impl[^1])
        . . .
        of ntySequence:
            let impl = t.getTypeImpl()
            assert impl.kind == nnkBracketExpr
            assert impl.len == 2
            result = "seq[" & mangledNameAux(impl[^1]) & "]"
        . . .
    
    
    Run

Thoughts on the pros and cons of these two approaches?

Dean 

Reply via email to