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.
 
 
 
 

216 lines
7.7 KiB

  1. #pragma once
  2. #include "platform.hpp"
  3. #ifdef FTB_WINDOWS
  4. #else
  5. # include <signal.h> // for sigtrap
  6. #endif
  7. #include <functional>
  8. #define proc auto
  9. #define concat(x, y) x ## y
  10. #define label(x, y) concat(x, y)
  11. #define MPI_LABEL(id1,id2) \
  12. label(MPI_LABEL_ ## id1 ## _ ## id2 ## _, __LINE__)
  13. #define MPP_DECLARE(labid, declaration) \
  14. if (0) \
  15. ; \
  16. else \
  17. for (declaration;;) \
  18. if (1) { \
  19. goto MPI_LABEL(labid, body); \
  20. MPI_LABEL(labid, done): break; \
  21. } else \
  22. while (1) \
  23. if (1) \
  24. goto MPI_LABEL(labid, done); \
  25. else \
  26. MPI_LABEL(labid, body):
  27. #define MPP_BEFORE(labid,before) \
  28. if (1) { \
  29. before; \
  30. goto MPI_LABEL(labid, body); \
  31. } else \
  32. MPI_LABEL(labid, body):
  33. #define MPP_AFTER(labid,after) \
  34. if (1) \
  35. goto MPI_LABEL(labid, body); \
  36. else \
  37. while (1) \
  38. if (1) { \
  39. after; \
  40. break; \
  41. } else \
  42. MPI_LABEL(labid, body):
  43. // #ifndef min
  44. #define min(a, b) ((a) < (b)) ? (a) : (b)
  45. // #endif
  46. // #ifndef max
  47. #define max(a, b) ((a) > (b)) ? (a) : (b)
  48. // #endif
  49. /**
  50. * Defer *
  51. */
  52. template<typename F>
  53. class defer_finalizer {
  54. F f;
  55. bool moved;
  56. public:
  57. template<typename T>
  58. defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { }
  59. defer_finalizer(const defer_finalizer &) = delete;
  60. defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) {
  61. other.moved = true;
  62. }
  63. ~defer_finalizer() {
  64. if (!moved) f();
  65. }
  66. };
  67. static struct {
  68. template<typename F>
  69. defer_finalizer<F> operator<<(F && f) {
  70. return defer_finalizer<F>(std::forward<F>(f));
  71. }
  72. } deferrer;
  73. #define defer auto label(__deferred_lambda_call, __COUNTER__) = deferrer << [&]
  74. #define defer_free(var) defer { free(var); }
  75. /*
  76. defer {
  77. call();
  78. };
  79. expands to:
  80. auto __deferred_lambda_call0 = deferrer << [&] {
  81. call();
  82. };
  83. */
  84. #if defined(unix) || defined(__unix__) || defined(__unix)
  85. #define NULL_HANDLE "/dev/null"
  86. #else
  87. #define NULL_HANDLE "nul"
  88. #endif
  89. #define ignore_stdout \
  90. if (0) \
  91. label(finished,__LINE__): ; \
  92. else \
  93. for (FILE* label(fluid_let_, __LINE__) = ftb_stdout;;) \
  94. for (defer{ fclose(ftb_stdout); ftb_stdout=label(fluid_let_, __LINE__) ; } ;;) \
  95. if (1) { \
  96. ftb_stdout = fopen(NULL_HANDLE, "w"); \
  97. goto label(body,__LINE__); \
  98. } \
  99. else \
  100. while (1) \
  101. if (1) { \
  102. goto label(finished, __LINE__); \
  103. } \
  104. else label(body,__LINE__):
  105. /*****************
  106. * fluid-let *
  107. *****************/
  108. #define fluid_let(var, val) \
  109. if (0) \
  110. label(finished,__LINE__): ; \
  111. else \
  112. for (auto label(fluid_let_, __LINE__) = var;;) \
  113. for (defer{var = label(fluid_let_, __LINE__);};;) \
  114. for(var = val;;) \
  115. if (1) { \
  116. goto label(body,__LINE__); \
  117. } \
  118. else \
  119. while (1) \
  120. if (1) { \
  121. goto TOKENPASTE2(finished, __LINE__); \
  122. } \
  123. else TOKENPASTE2(body,__LINE__):
  124. ;
  125. /**
  126. fluid_let(var, val) {
  127. call1(var);
  128. call2(var);
  129. }
  130. expands to
  131. if (0)
  132. finished98:;
  133. else
  134. for (auto fluid_let_98 = var;;)
  135. for (auto __deferred_lambda_call0 = deferrer << [&] { var = fluid_let_98; };;)
  136. for (var = val;;)
  137. if (1) {
  138. goto body98;
  139. } else
  140. while (1)
  141. if (1) {
  142. goto finished98;
  143. } else
  144. body98 : {
  145. call1(var);
  146. call2(var);
  147. }
  148. */
  149. #define panic(...) \
  150. do { \
  151. print("%{color<}[Panic]%{>color} in " \
  152. "file %{color<}%{->char}%{>color} " \
  153. "line %{color<}%{u32}%{>color}: " \
  154. "(%{color<}%{->char}%{>color})\n", \
  155. console_red, console_cyan, __FILE__, console_cyan, __LINE__, \
  156. console_cyan, __func__); \
  157. print("%{color<}", console_red); \
  158. print(__VA_ARGS__); \
  159. print("%{>color}\n"); \
  160. fflush(stdout); \
  161. print_stacktrace(); \
  162. debug_break(); \
  163. } while(0)
  164. #define panic_if(cond, ...) \
  165. if(!(cond)); \
  166. else panic(__VA_ARGS__)
  167. #ifdef FTB_DEBUG_LOG
  168. # define debug_log(...) \
  169. do { \
  170. print("%{color<}[INFO " __FILE__ ":%{color<}%{->char}" \
  171. "%{>color}]%{>color} ", \
  172. console_green, console_cyan, __func__); \
  173. println(__VA_ARGS__); \
  174. } while (0)
  175. #else
  176. # define debug_log(...)
  177. #endif
  178. #ifdef FTB_WINDOWS
  179. # define debug_break() __debugbreak()
  180. #else
  181. # define debug_break() raise(SIGTRAP);
  182. #endif