text: //
  //  EXTScope.h
  //  extobjc
  //
  //  Created by Justin Spahr-Summers on 2011-05-04.
  //  Copyright (C) 2012 Justin Spahr-Summers.
  //  Released under the MIT license.
  //
  
  #import "metamacros.h"
  
  /**
   * \@onExit defines some code to be executed when the current scope exits. The
   * code must be enclosed in braces and terminated with a semicolon, and will be
   * executed regardless of how the scope is exited, including from exceptions,
   * \c goto, \c return, \c break, and \c continue.
   *
   * Provided code will go into a block to be executed later. Keep this in mind as
   * it pertains to memory management, restrictions on assignment, etc. Because
   * the code is used within a block, \c return is a legal (though perhaps
   * confusing) way to exit the cleanup block early.
   *
   * Multiple \@onExit statements in the same scope are executed in reverse
   * lexical order. This helps when pairing resource acquisition with \@onExit
   * statements, as it guarantees teardown in the opposite order of acquisition.
   *
   * @note This statement cannot be used within scopes defined without braces
   * (like a one line \c if). In practice, this is not an issue, since \@onExit is
   * a useless construct in such a case anyways.
   */
  #define onExit \
      ext_keywordify \
      __strong ext_cleanupBlock_t metamacro_concat(ext_exitBlock_, __LINE__) __attribute__((cleanup(ext_executeCleanupBlock), unused)) = ^
  
  /**
   * Creates \c __weak shadow variables for each of the variables provided as
   * arguments, which can later be made strong again with #strongify.
   *
   * This is typically used to weakly reference variables in a block, but then
   * ensure that the variables stay alive during the actual execution of the block
   * (if they were live upon entry).
   *
   * See #strongify for an example of usage.
   */
  #define weakify(...) \
      ext_keywordify \
      metamacro_foreach_cxt(ext_weakify_,, __weak, __VA_ARGS__)
  
  /**
   * Like #weakify, but uses \c __unsafe_unretained instead, for targets or
   * classes that do not support weak references.
   */
  #define unsafeify(...) \
      ext_keywordify \
      metamacro_foreach_cxt(ext_weakify_,, __unsafe_unretained, __VA_ARGS__)
  
  /**
   * Strongly references each of the variables provided as arguments, which must
   * have previously been passed to #weakify.
   *
   * The strong references created will shadow the original variable names, such
   * that the original names can be used without issue (and a significantly
   * reduced risk of retain cycles) in the current scope.
   *
   * @code
  
      id foo = [[NSObject alloc] init];
      id bar = [[NSObject alloc] init];
  
      @weakify(foo, bar);
  
      // this block will not keep 'foo' or 'bar' alive
      BOOL (^matchesFooOrBar)(id) = ^ BOOL (id obj){
          // but now, upon entry, 'foo' and 'bar' will stay alive until the block has
          // finished executing
          @strongify(foo, bar);
  
          return [foo isEqual:obj] || [bar isEqual:obj];
      };
  
   * @endcode
   */
  #define strongify(...) \
      ext_keywordify \
      _Pragma("clang diagnostic push") \
      _Pragma("clang diagnostic ignored \"-Wshadow\"") \
      metamacro_foreach(ext_strongify_,, __VA_ARGS__) \
      _Pragma("clang diagnostic pop")
  
  /*** implementation details follow ***/
  typedef void (^ext_cleanupBlock_t)(void);
  
  #if defined(__cplusplus)
  extern "C" {
  #endif
      void ext_executeCleanupBlock (__strong ext_cleanupBlock_t *block);
  #if defined(__cplusplus)
  }
  #endif
  
  #define ext_weakify_(INDEX, CONTEXT, VAR) \
      CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR);
  
  #define ext_strongify_(INDEX, VAR) \
      __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_);
  
  // Details about the choice of backing keyword:
  //
  // The use of @try/@catch/@finally can cause the compiler to suppress
  // return-type warnings.
  // The use of @autoreleasepool {} is not optimized away by the compiler,
  // resulting in superfluous creation of autorelease pools.
  //
  // Since neither option is perfect, and with no other alternatives, the
  // compromise is to use @autorelease in DEBUG builds to maintain compiler
  // analysis, and to use @try/@catch otherwise to avoid insertion of unnecessary
  // autorelease pools.
  #if defined(DEBUG) && !defined(NDEBUG)
  #define ext_keywordify autoreleasepool {}
  #else
  #define ext_keywordify try {} @catch (...) {}
  #endif
  