Tracking calls inside the call chain seems like exactly what the effects system 
is for:
    
    
    import std/[macros,effecttraits]
    type
      FooTag = object
    
    macro callsFoo(p:proc):untyped =
      for t in getTagsList(p):
        if t.eqIdent("FooTag"):
          return newLit(true)
      newLit(false)
    
    
    template wasItCalled(body: untyped) =
      body
      static:
        proc bodyproc() =
          body
        when bodyproc.callsFoo:
          echo "called"
        else:
          echo "not called"
    
    
    proc foo(){.tags:[FooTag].} =
      discard
    
    proc baz(p:proc()) = p()
    # extra indirection for extra credit.
    # I actually thought this is supposed
    # to require: 'effectsof' but it works?
    
    # can't wrap this, it's user-controlled
    proc bar() =
      baz(foo)
    
    wasItCalled:
      discard
      # This should echo 'not called', and does
    
    wasItCalled:
      foo()
      # This should echo 'called', and does
    
    wasItCalled:
      bar()
      # This should echo 'called', and does
    
    
    Run

Reply via email to