Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

180 rader
6.1 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 line_label(x) label(x, __LINE__)
  12. // #ifndef min
  13. // #define min(a, b) ((a) < (b)) ? (a) : (b)
  14. // #endif
  15. // #ifndef max
  16. // #define max(a, b) ((a) > (b)) ? (a) : (b)
  17. // #endif
  18. /**
  19. * Defer *
  20. */
  21. template<typename F>
  22. class defer_finalizer {
  23. F f;
  24. bool moved;
  25. public:
  26. template<typename T>
  27. defer_finalizer(T && f_) : f(std::forward<T>(f_)), moved(false) { }
  28. defer_finalizer(const defer_finalizer &) = delete;
  29. defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) {
  30. other.moved = true;
  31. }
  32. ~defer_finalizer() {
  33. if (!moved) f();
  34. }
  35. };
  36. static struct {
  37. template<typename F>
  38. defer_finalizer<F> operator<<(F && f) {
  39. return defer_finalizer<F>(std::forward<F>(f));
  40. }
  41. } deferrer;
  42. #define defer auto label(__deferred_lambda_call, __COUNTER__) = deferrer << [&]
  43. #define defer_free(var) defer { free(var); }
  44. /*
  45. defer {
  46. call();
  47. };
  48. expands to:
  49. auto __deferred_lambda_call0 = deferrer << [&] {
  50. call();
  51. };
  52. */
  53. #if defined(unix) || defined(__unix__) || defined(__unix)
  54. #define NULL_HANDLE "/dev/null"
  55. #else
  56. #define NULL_HANDLE "nul"
  57. #endif
  58. #define ignore_stdout \
  59. if (0) \
  60. label(finished,__LINE__): ; \
  61. else \
  62. for (FILE* label(fluid_let_, __LINE__) = ftb_stdout;;) \
  63. for (defer{ fclose(ftb_stdout); ftb_stdout=label(fluid_let_, __LINE__) ; } ;;) \
  64. if (1) { \
  65. ftb_stdout = fopen(NULL_HANDLE, "w"); \
  66. goto label(body,__LINE__); \
  67. } \
  68. else \
  69. while (1) \
  70. if (1) { \
  71. goto label(finished, __LINE__); \
  72. } \
  73. else label(body,__LINE__):
  74. /*****************
  75. * fluid-let *
  76. *****************/
  77. #define fluid_let(var, val) \
  78. if (0) \
  79. label(finished,__LINE__): ; \
  80. else \
  81. for (auto label(fluid_let_, __LINE__) = var;;) \
  82. for (defer{var = label(fluid_let_, __LINE__);};;) \
  83. for(var = val;;) \
  84. if (1) { \
  85. goto label(body,__LINE__); \
  86. } \
  87. else \
  88. while (1) \
  89. if (1) { \
  90. goto TOKENPASTE2(finished, __LINE__); \
  91. } \
  92. else TOKENPASTE2(body,__LINE__):
  93. ;
  94. /**
  95. fluid_let(var, val) {
  96. call1(var);
  97. call2(var);
  98. }
  99. expands to
  100. if (0)
  101. finished98:;
  102. else
  103. for (auto fluid_let_98 = var;;)
  104. for (auto __deferred_lambda_call0 = deferrer << [&] { var = fluid_let_98; };;)
  105. for (var = val;;)
  106. if (1) {
  107. goto body98;
  108. } else
  109. while (1)
  110. if (1) {
  111. goto finished98;
  112. } else
  113. body98 : {
  114. call1(var);
  115. call2(var);
  116. }
  117. */
  118. #define panic(...) \
  119. do { \
  120. print("%{color<}[Panic]%{>color} in " \
  121. "file %{color<}%{->char}%{>color} " \
  122. "line %{color<}%{u32}%{>color}: " \
  123. "(%{color<}%{->char}%{>color})\n", \
  124. console_red, console_cyan, __FILE__, console_cyan, __LINE__, \
  125. console_cyan, __func__); \
  126. print("%{color<}", console_red); \
  127. print(__VA_ARGS__); \
  128. print("%{>color}\n"); \
  129. fflush(stdout); \
  130. print_stacktrace(); \
  131. debug_break(); \
  132. } while(0)
  133. #define panic_if(cond, ...) \
  134. if(!(cond)); \
  135. else panic(__VA_ARGS__)
  136. #ifdef FTB_DEBUG_LOG
  137. # define debug_log(...) \
  138. do { \
  139. print("%{color<}[INFO " __FILE__ ":%{color<}%{->char}" \
  140. "%{>color}]%{>color} ", \
  141. console_green, console_cyan, __func__); \
  142. println(__VA_ARGS__); \
  143. } while (0)
  144. #else
  145. # define debug_log(...)
  146. #endif
  147. #ifdef FTB_WINDOWS
  148. # define debug_break() __debugbreak()
  149. #else
  150. # define debug_break() raise(SIGTRAP);
  151. #endif