I'm trying to associate some data to a function symbol inside said function, so 
that later I can retrieve this data given a function call. Here's an example:
    
    
    import macros, tables, hashes
    
    proc hash(n: NimNode): Hash = hash($n) # Make Table compile
    
    var registry {.compiletime.}: Table[NimNode, NimNode] # Map function symbol 
=> internal function symbol
    
    macro register(functionSymbol, internalFunctionSymbol: typed): untyped =
      registry[functionSymbol] = internalFunctionSymbol
    
    macro inst(someCall: typed): untyped =
      let functionSymbol = someCall[0]
      let internalFunctionSymbol = registry[functionSymbol]
      result = newCall(internalFunctionSymbol)
    
    # So it can be used like this
    proc foo(a: int) =
      proc bar() =
        echo "foo int"
      register(foo, bar)
    
    foo(5) # Make sure `foo` is instantiated
    inst foo(5) # I expect this to be replaced with corresponding `bar()`
    
    
    Run

The example above works as expected, however it quickly gets flaky with `foo` 
overloads:
    
    
    proc foo(a: string) =
      proc bar() =
        echo "foo string"
      register(foo, bar)
    foo("hi") # Make sure `foo` is instantiated
    inst foo("hi") # I expect this to be replaced with corresponding `bar()`
    
    
    Run

The snippet above will fail with KeyError on registry lookup, even though 
there's 2 keys in the registry by this time.

It gets even worse with generics:
    
    
    proc baz[T](a: T) =
      proc bar() =
        when T is string:
          echo "baz string"
        else:
          echo "baz not string"
      register(baz, bar)
    
    baz("hi") # Make sure `baz[string]` is instantiated
    inst baz("hi") # I expect this to be replaced with corresponding `bar()`
    
    baz(5) # Make sure `baz[int]` is instantiated
    inst baz(5) # I expect this to be replaced with corresponding `bar()`
    
    
    Run

In the snippet above the registry is populated only with one symbol, even 
though `register` is called once per every instance of `baz`, thus twice in 
total. And both `inst` fail on lookup, as neither `baz[string]` nor `baz[int]` 
match that single key in the registry.

So the question is am I wrong in my expectations and why? Or is it a bug?

Reply via email to