You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

118 lines
3.1 KiB

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