In nim is there a way to get a list of all procedures with a given name?

99 Views Asked by At

In Nim is there a way to get a list of the declarations of all procedures with a given name which are defined at a given point in the code? For example I am looking for a function TYPE where following code

proc Sum(self: seq[int]):int =
    do something

echo $TYPE(Sum)

proc Sum(self: seq[float]):float =
    do something

echo $TYPE(Sum)

would print

@[proc Sum(self: seq[int]):int]
@[proc Sum(self: seq[int]):int, proc Sum(self: seq[float]):float]
2

There are 2 best solutions below

0
PMunch On BEST ANSWER

Given a symbol you can do it with a macro and getImpl, you just need to make sure to iterate over all the sym choices:

import macros, strutils

macro TYPE(x: typed): untyped =
  result = quote do:
    seq[string](@[])
    
  template addSignature(x: untyped) =
    let impl = x.getImpl
    assert impl.kind == nnkProcDef, "Symbol not a procedure!"
    result[1][1].add newLit(impl.repr.splitLines[0][0..^3]) # Bit of a hack
    
  if x.kind == nnkSym:
    addSignature(x)
  else:
    for y in x:
      addSignature(y)
      
  echo result.treeRepr


proc Sum(self: seq[int]):int =
  echo self

echo $TYPE(Sum)

proc Sum(self: seq[float]):float =
  echo self

echo $TYPE(Sum)
0
Bob On

You can do that with a macro. When there are multiple overloads a symbol gets stored as nnkClosedSymChoice which you can iterate through and filter to only allow for procs.

e.g.

macro definedProcs(x: typed) =
  # If there are no overloads then it would just be a `nnkSym`
  # so wrap it in `nnkClosedSymChoice` to make life easier
  let syms = if x.kind == nnkSym: nnkClosedSymChoice.newTree(x) else: x
  for x in syms:
    # Lookup the type definition, and make sure its a proc
    if x.getTypeInst().kind == nnkProcTy:
      # Do something with the proc symbol.
      # You can't call it here, but you can return
      # some code to operate on the proc

This code is missing things like error handling, but should get the job done.

Sadly you can't just make it store everything in a sequence since there are different types, but you could make it return a tuple instead like so

macro definedProcs(x: typed): tuple =
  let syms = if x.kind == nnkSym: nnkClosedSymChoice.newTree(x) else: x
  result = nnkTupleConstr.newTree()
  for x in syms:
    if x.getTypeInst().kind == nnkProcTy:
      result &= x