> Was wandering if nim has the same limitation (as the size of the node must be 
> known at compile time)

This isn't true, you can just set the type size to the maximum of all the 
branch sizes.

I can only think of black magic ways to truly implement this and even then 
there are problems like generics being too limited.

For a start something like this compiles (the 1/2/3 suffixes are due to fields 
with same name not being allowed in different object variant branches, you can 
easily make a macro that lifts the branch fields to their own object type 
though, I should have one [here](https://github.com/metagn/variantsugar)):
    
    
    type
      NodeKind* = enum
        Sheet,
        Comment,
        Rule,
        AtRule,
        Decl
      
      NodeOf*[Kinds: static set[NodeKind]] = Node
      Node* = ref NodeObj
      NodeObj* {.acyclic.} = object
        case kind*: NodeKind
        of Sheet:
          nodes1*: seq[NodeOf[{Rule, Comment, AtRule}]]
        of Comment:
          value1*: string
        of Rule:
          selector*: string
          nodes2*: seq[NodeOf[{Decl, Comment, AtRule}]]
        of AtRule:
          name*: string
          params*: string
          nodes3*: seq[Node]
        of Decl:
          prop*: string
          value2*: string
    
    
    Run

This works as documentation. We can do something like this to add type safety, 
although it will become verbose:
    
    
    type
      NodeKind* = enum
        Sheet,
        Comment,
        Rule,
        AtRule,
        Decl
      
      NodeOf*[Kinds: static set[NodeKind]] = distinct Node
      Node* = ref NodeObj
      NodeObj* {.acyclic.} = object
        case kind*: NodeKind
        of Sheet:
          nodes1*: seq[NodeOf[{Rule, Comment, AtRule}]]
        of Comment:
          value1*: string
        of Rule:
          selector*: string
          nodes2*: seq[NodeOf[{Decl, Comment, AtRule}]]
        of AtRule:
          name*: string
          params*: string
          nodes3*: seq[Node]
        of Decl:
          prop*: string
          value2*: string
    
    proc toNodeOf[Kinds: static set[NodeKind]](n: Node): NodeOf[Kinds] =
      assert n.kind in Kinds
      NodeOf[Kinds](n)
    
    proc toNode[Kinds: static set[NodeKind]](n: NodeOf[Kinds]): Node = Node(n)
    
    let n1 = Node(kind: Sheet)
    let comment = Node(kind: Comment, value1: "coment")
    n1.nodes1.add(toNodeOf[{Rule, Comment, AtRule}](comment))
    let n2 = Node(kind: AtRule)
    n2.nodes3.add(toNode(n1.nodes1[0]))
    
    
    Run

This does not generally work with converters, due to the `static` parameter we 
are using.

Reply via email to