Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

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