Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

127 wiersze
4.1 KiB

  1. #pragma once
  2. #include <functional>
  3. #define proc auto
  4. #define concat(x, y) x ## y
  5. #define label(x, y) concat(x, y)
  6. /**
  7. * Defer *
  8. */
  9. template<typename F>
  10. class defer_finalizer {
  11. F f;
  12. bool moved;
  13. public:
  14. template<typename T>
  15. defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { }
  16. defer_finalizer(const defer_finalizer &) = delete;
  17. defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) {
  18. other.moved = true;
  19. }
  20. ~defer_finalizer() {
  21. if (!moved) f();
  22. }
  23. };
  24. static struct {
  25. template<typename F>
  26. defer_finalizer<F> operator<<(F && f) {
  27. return defer_finalizer<F>(std::forward<F>(f));
  28. }
  29. } deferrer;
  30. #define defer auto label(__deferred_lambda_call, __COUNTER__) = deferrer << [&]
  31. #define defer_free(var) defer { free(var); }
  32. /*
  33. defer {
  34. call();
  35. };
  36. expands to:
  37. auto __deferred_lambda_call0 = deferrer << [&] {
  38. call();
  39. };
  40. */
  41. #if defined(unix) || defined(__unix__) || defined(__unix)
  42. #define NULL_HANDLE "/dev/null"
  43. #else
  44. #define NULL_HANDLE "nul"
  45. #endif
  46. #define ignore_stdout \
  47. if (0) \
  48. label(finished,__LINE__): ; \
  49. else \
  50. for (FILE* label(fluid_let_, __LINE__) = ftb_stdout;;) \
  51. for (defer{ fclose(ftb_stdout); ftb_stdout=label(fluid_let_, __LINE__) ; } ;;) \
  52. if (1) { \
  53. ftb_stdout = fopen(NULL_HANDLE, "w"); \
  54. goto label(body,__LINE__); \
  55. } \
  56. else \
  57. while (1) \
  58. if (1) { \
  59. goto label(finished, __LINE__); \
  60. } \
  61. else label(body,__LINE__):
  62. /*****************
  63. * fluid-let *
  64. *****************/
  65. #define fluid_let(var, val) \
  66. if (0) \
  67. label(finished,__LINE__): ; \
  68. else \
  69. for (auto label(fluid_let_, __LINE__) = var;;) \
  70. for (defer{var = label(fluid_let_, __LINE__);};;) \
  71. for(var = val;;) \
  72. if (1) { \
  73. goto label(body,__LINE__); \
  74. } \
  75. else \
  76. while (1) \
  77. if (1) { \
  78. goto TOKENPASTE2(finished, __LINE__); \
  79. } \
  80. else TOKENPASTE2(body,__LINE__):
  81. ;
  82. /**
  83. fluid_let(var, val) {
  84. call1(var);
  85. call2(var);
  86. }
  87. expands to
  88. if (0)
  89. finished98:;
  90. else
  91. for (auto fluid_let_98 = var;;)
  92. for (auto __deferred_lambda_call0 = deferrer << [&] { var = fluid_let_98; };;)
  93. for (var = val;;)
  94. if (1) {
  95. goto body98;
  96. } else
  97. while (1)
  98. if (1) {
  99. goto finished98;
  100. } else
  101. body98 : {
  102. call1(var);
  103. call2(var);
  104. }
  105. */