#define new(type) new type #define proc auto #ifdef _DEBUG constexpr bool is_debug_build = true; #else constexpr bool is_debug_build = false; #endif #define if_debug if constexpr (is_debug_build) #ifdef _MSC_VER # define if_windows if constexpr (1) # define if_linux if constexpr (0) # define debug_break() if_debug __debugbreak() #else # include # define debug_break() if_debug raise(SIGTRAP) # define if_windows if (0) # define if_linux if (1) #endif #define concat_( a, b) a##b #define label(prefix, lnum) concat_(prefix,lnum) #define try \ if (1) \ goto label(body,__LINE__); \ else \ while (1) \ if (1) { \ if(Globals::error) { \ if (log_level == Log_Level::Debug) { \ printf("in %s:%d\n", __FILE__, __LINE__); \ } \ return 0; \ } \ break; \ } \ else label(body,__LINE__): #define try_void \ if (1) \ goto label(body,__LINE__); \ else \ while (1) \ if (1) { \ if(Globals::error) { \ if (log_level == Log_Level::Debug) { \ printf("in %s:%d\n", __FILE__, __LINE__); \ } \ return; \ } \ break; \ } \ else label(body,__LINE__): #define define_array_list(type, name) \ struct name##_Array_List { \ type* data; \ int length; \ int next_index; \ }; \ \ \ proc append_to_array_list(name##_Array_List* arraylist, type element) -> void { \ if (arraylist->next_index == arraylist->length) { \ arraylist->length *= 2; \ arraylist->data = \ (type*)realloc(arraylist->data, arraylist->length * sizeof(type)); \ } \ arraylist->data[arraylist->next_index++] = element; \ } \ \ \ proc create_##name##_array_list(int initial_capacity = 16) -> name##_Array_List* { \ name##_Array_List* ret = new(name##_Array_List); \ ret->data = (type*)malloc(initial_capacity * sizeof(type)); \ ret->next_index = 0; \ ret->length = initial_capacity; \ return ret; \ } template class defer_finalizer { F f; bool moved; public: template defer_finalizer(T && f_) : f(std::forward(f_)), moved(false) { } defer_finalizer(const defer_finalizer &) = delete; defer_finalizer(defer_finalizer && other) : f(std::move(other.f)), moved(other.moved) { other.moved = true; } ~defer_finalizer() { if (!moved) f(); } }; struct { template defer_finalizer operator<<(F && f) { return defer_finalizer(std::forward(f)); } } deferrer; #define TOKENPASTE(x, y) x ## y #define TOKENPASTE2(x, y) TOKENPASTE(x, y) #define defer auto TOKENPASTE2(__deferred_lambda_call, __COUNTER__) = deferrer << [&] /* Usage of the create_error_macros: */ #define __create_error(keyword, ...) \ create_error( \ __FILE__, __LINE__, \ Memory::get_or_create_lisp_object_keyword(keyword), \ __VA_ARGS__) #define create_out_of_memory_error(...) \ __create_error("out-of-memory", __VA_ARGS__) #define create_generic_error(...) \ __create_error("generic", __VA_ARGS__) #define create_not_yet_implemented_error() \ __create_error("not-yet-implemented", "This feature has not yet been implemented.") #define create_parsing_error(...) \ __create_error("parsing-error", __VA_ARGS__) #define create_symbol_undefined_error(...) \ __create_error("symbol-undefined", __VA_ARGS__) #define create_type_missmatch_error(expected, actual) \ __create_error("type-missmatch", \ "Type missmatch: expected %s, got %s", \ expected, actual) #define create_wrong_number_of_arguments_error(expected, actual) \ __create_error("wrong-number-of-arguments", \ "Wrong number of arguments: expected %d, got %d", \ expected, actual) #define assert_arguments_length(expected, actual) \ do { \ if (expected != actual) { \ create_wrong_number_of_arguments_error(expected, actual); \ } \ } while(0) #define assert_type(_node, _type) \ do { \ if (Memory::get_type(_node) != _type) { \ create_type_missmatch_error("symbol", Lisp_Object_Type_to_string(Memory::get_type(_node))); \ } \ } while(0) #define assert(condition) \ do { \ if (!(condition)) { \ create_generic_error("Assertion-error."); \ } \ } while(0) // #define assert(cond) \ // if_debug { \ // if (!cond) { \ // if (log_level == Log_Level::Debug) { \ // printf("Assertion failed: %s %d", __FILE__, __LINE__); \ // } \ // debug_break(); \ // } \ // } else {} \ #define console_normal "\x1B[0m" #define console_red "\x1B[31m" #define console_green "\x1B[32m" #define console_cyan "\x1B[36m" // #define console_normal "" // #define console_red "" // #define console_green "" // #define console_cyan ""