選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。
 
 
 
 

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