No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 

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