As for now, template + getAst seems preferred over quote. Please note it 
provides you template hygiene, meaning the symbols are generated, thus your 
private variable will actually be private (as it will be treated as a new 
_symbol_ rather than an identifier).
    
    
    import macros
    from strutils import `%`
    
    
    proc my_enter(x: int): int =
      echo "my_enter was called"
      return x
    
    proc my_exit(x: int) =
      echo "my_exit was called"
    
    macro take(args, body: untyped): untyped =
      # Check the grammar
      if args.kind != nnkInfix or args.len != 3 or $args[0] != "as":
        error "`(value) as (name)` expected in take, found: `$1`" % [args.repr]
      
      # Value of an argument
      let varValue = args[1]
      
      # Variable name
      let varName = args[^1]
      
      template takeImpl(name, value, body) =
        block:
          var private {.genSym.} = value
          var name = my_enter(private)
          try:
            body
          finally:
            my_exit(private)
      
      getAst(takeImpl(varName, varValue, body))
    
    take 3 as f:
      echo f
    
    take 6 as f:
      echo f
    
    # test if it provides a useful error message:
    take 7 of f:
      echo f
    

Reply via email to