#define new(type) new type #define proc auto #ifdef _DEBUG # define if_debug if constexpr (true) #else # define if_debug if constexpr (false) #endif #ifdef _MSC_VER # define debug_break() if_debug __debugbreak() # define if_windows if constexpr (true) # define if_linux if constexpr (false) #else # define debug_break() if_debug raise(SIGTRAP) # define if_windows if constexpr (false) # define if_linux if constexpr (true) #endif #define concat_( a, b) a##b #define label(prefix, lnum) concat_(prefix,lnum) #define try_or_else_return(val) \ if (1) \ goto label(body,__LINE__); \ else \ while (1) \ if (1) { \ if (Globals::error) { \ if (Globals::log_level == Log_Level::Debug) { \ printf("in %s:%d\n", __FILE__, __LINE__); \ } \ return val; \ } \ break; \ } \ else label(body,__LINE__): ; #define try_struct try_or_else_return({}) #define try_void try_or_else_return() #define try try_or_else_return(0) #define dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) #define ignore_logging fluid_let(Globals::log_level, Log_Level::None) #define define_array_list(type, name) \ \ struct name##_Array_List { \ type* data; \ int length; \ int next_index; \ }; \ \ proc remove_index_from_array_list(name##_Array_List* arraylist, int index) -> void { \ arraylist->data[index] = \ arraylist->data[--(arraylist->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; \ arraylist->next_index++; \ } \ \ proc _merge_array_lists(name##_Array_List* arr, int start, int mid, int end) -> void { \ int start2 = mid + 1; \ \ /* If the direct merge is already sorted */ \ if ((size_t)arr->data[mid] <= (size_t)arr->data[start2]) { \ return; \ } \ \ /* Two pointers to maintain start of both arrays to merge */ \ while (start <= mid && start2 <= end) { \ if ((size_t)arr->data[start] <= (size_t)arr->data[start2]) { \ start++; \ } \ else { \ type value = arr->data[start2]; \ int index = start2; \ \ /* Shift all the elements between element 1; element 2, right by 1. */ \ while (index != start) { \ arr->data[index] = arr->data[index - 1]; \ index--; \ } \ arr->data[start] = value; \ \ /* Update all the pointers */ \ start++; \ mid++; \ start2++; \ } \ } \ } \ \ proc sort_array_list(name##_Array_List* arraylist, int left=-1, int right=-1) -> void { \ if (left == -1) { \ sort_array_list(arraylist, 0, arraylist->next_index - 1); \ return; \ } else if (left == right) { \ return; \ } \ \ int middle = left + (right-left) / 2; \ \ sort_array_list(arraylist, left, middle); \ sort_array_list(arraylist, middle+1, right); \ \ _merge_array_lists(arraylist, left, middle, right); \ } \ \ proc sorted_array_list_find(name##_Array_List* arraylist, type elem, int left=-1, int right=-1) -> int { \ if (left == -1) { \ return sorted_array_list_find(arraylist, elem, 0, arraylist->next_index - 1); \ } else if (left == right) { \ if ((size_t)arraylist->data[left] == (size_t)elem) \ return left; \ return -1; \ } else if (right < left) \ return -1; \ \ int middle = left + (right-left) / 2; \ \ if ((size_t)arraylist->data[middle] < (size_t)elem) \ return sorted_array_list_find(arraylist, elem, middle+1, right); \ if ((size_t)arraylist->data[middle] > (size_t)elem) \ return sorted_array_list_find(arraylist, elem, left, middle-1); \ return middle; \ } \ \ proc create_##name##_array_list(int initial_capacity = 16) -> name##_Array_List { \ name##_Array_List ret; \ ret.data = (type*)malloc(initial_capacity * sizeof(type)); \ ret.next_index = 0; \ ret.length = initial_capacity; \ return ret; \ } /* * iterate over array lists */ #define for_array_list(l) \ if (int it_index = 0); else \ for (auto it = (l).data[0]; \ it_index < (l).next_index; \ it=(l).data[++it_index]) /* * iterate over lisp vectors */ #define for_lisp_vector(v) \ if (!v); else \ if (int it_index = 0); else \ for (auto it = v->value.vector.data; \ it_index < v->value.vector.length; \ it=v->value.vector.data+(++it_index)) /* * iterate over lisp lists */ #define for_lisp_list(l) \ if (!l); else \ if (int it_index = 0); else \ for (Lisp_Object* head = l, *it; \ Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \ head = head->value.pair.rest, ++it_index) /** 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 create_too_many_arguments_error(expected, actual) \ __create_error("wrong-number-of-arguments", \ "Wrong number of arguments: expected less or equal to %d, got %d", \ expected, actual) #define create_too_few_arguments_error(expected, actual) \ __create_error("wrong-number-of-arguments", \ "Wrong number of arguments: expected greater or equal to %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_arguments_length_less_equal(expected, actual) \ do { \ if (expected < actual) { \ create_too_many_arguments_error(expected, actual); \ } \ } while(0) #define assert_arguments_length_greater_equal(expected, actual) \ do { \ if (expected > actual) { \ create_too_few_arguments_error(expected, actual); \ } \ } while(0) #define assert_type(_node, _type) \ do { \ if (Memory::get_type(_node) != _type) { \ create_type_missmatch_error( \ Lisp_Object_Type_to_string(_type), \ 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 ""