Something like this? 
    
    
    import macros
    
    proc clean(a, b: int) : int =
      result = 2 * a  + b
    
    proc dirty(a,b:int): int =
      echo "dirty"
      3
    
    macro hasNoSideEffects(p : typed) : untyped =
      result = newCall("compiles", newNimNode(nnkProcDef))
      let frm = p.symbol.getImpl
      var i = 0
      # frm has an additional result node at the end, this ugly loop
      # is to construct our procDef without altering the original proc.
      while i < frm.len-1:
        if i == frm.len-1: break
        result[1].add(frm[i])
        inc i
      addPragma(result[1], newIdentNode("noSideEffect"))
    
    echo hasNoSideEffects(clean) # true
    echo hasNoSideEffects(dirty) # false
    

As NimNodes are `ref` types, I don't think you should change the ones returned 
from getImpl directly ( I may be wrong though ).

( There are probably better ways to get all childs except the last, but I can't 
seem to find them. )

When dealing with macros, it's usually useful to compare the ast you generate 
with the ast printed by `dumpTree`, eg: 
    
    
    import macros
    dumpTree:
      proc clean(a, b: int) : int {.noSideEffect.} =
        result = 2 * a  + b
    

Reply via email to