Hello everyone, so I'm trying to make a simple C compiler in Nim. I needed to 
change AST node types, so I wrote something like this: 
    
    
    type
      Ast = ref object of RootObj
      A = ref object of Ast
      B = ref object of Ast
      B1 = ref object of B
      B2 = ref object of B
      C = ref object of Ast
        b: B
    
    method change(ast: var Ast) {.base.} =
      discard
    method change(ast: var B) =
      if ast of B1:
         ast = B2()
    method change(ast: var C) =
      ast.b.change()
    
    
    Run

This worked well, so I added D: 
    
    
    ...
    type D = ref object of Ast
      bs: seq[B]
    ...
    method change(ast: var D) =
      for b in ast.bs.mitems:
        b.change()
    
    
    Run

And this also worked well, so I decided to move this into iterator: 
    
    
    type
      Ast = ...
    
    iterator msub(ast: Ast): var Ast =
      if ast of C:
        yield ast.C.b.Ast
      elif ast of D:
        for b in ast.D.bs.mitems:
          yield b.Ast
    method change(ast: var Ast) {.base.} =
      for sub in ast.msub:
        sub.change()
    method change(ast: var B) =
      if ast of B1:
         ast = B2()
    
    
    Run

And suddenly this didn't work. Also it raised error not in the Nim compiler but 
in the gcc. Here is the error for the sake of completeness: 
    
    
    error: '*b' is a pointer; did you mean to use '->'?
           sub = &b->Sup;
                   ^~
                   ->
    
    
    Run

I read some related issues, and found out that accroding to Araq `var Ast` and 
`var B` have no subtype relation, so all of this was invalid.

While I don't understand why that should be that way, I also don't understand 
how things like that should be written in Nim. Or should I return changed 
version of AST node? This is still strange to me. Also, why the compiler 
allowed me to use that before, but didn't allow it when I switched to 
iterators? Could someone please explain that to me?

Reply via email to