| @@ -32,13 +32,13 @@ auto create_error(const char* c_func_name, const char* c_file_name, | |||||
| print("\n%{color<}%{->Str} error:%{>color} %{->Str}\n", | print("\n%{color<}%{->Str} error:%{>color} %{->Str}\n", | ||||
| console_red, &(error->type), &(error->message)); | console_red, &(error->type), &(error->message)); | ||||
| printf("in"); | |||||
| print("in"); | |||||
| s32 spacing = 30-((s32)strlen(c_file_name) + (s32)log10(c_file_line)); | s32 spacing = 30-((s32)strlen(c_file_name) + (s32)log10(c_file_line)); | ||||
| if (spacing < 1) spacing = 1; | if (spacing < 1) spacing = 1; | ||||
| for (s32 i = 0; i < spacing; ++i) | for (s32 i = 0; i < spacing; ++i) | ||||
| printf(" "); | |||||
| printf("%s (%u) ", c_file_name, c_file_line); | |||||
| printf("-> %s\n", c_func_name); | |||||
| print(" "); | |||||
| print("%s (%u) ", c_file_name, c_file_line); | |||||
| print("-> %s\n", c_func_name); | |||||
| } | } | ||||
| #define __create_error(keyword, ...) \ | #define __create_error(keyword, ...) \ | ||||
| @@ -1,4 +1,5 @@ | |||||
| #pragma once | #pragma once | ||||
| #include <functional> | |||||
| #define proc auto | #define proc auto | ||||
| #define concat(x, y) x ## y | #define concat(x, y) x ## y | ||||
| @@ -51,6 +52,25 @@ expands to: | |||||
| }; | }; | ||||
| */ | */ | ||||
| #define ignore_stdout \ | |||||
| if (0) \ | |||||
| label(finished,__LINE__): ; \ | |||||
| else \ | |||||
| for (FILE* tmp = ftb_stdout;;) \ | |||||
| for (defer{ fclose(ftb_stdout); ftb_stdout= tmp; } ;;) \ | |||||
| if (1) { \ | |||||
| ftb_stdout = fopen("nul", "w"); \ | |||||
| goto label(body,__LINE__); \ | |||||
| } \ | |||||
| else \ | |||||
| while (1) \ | |||||
| if (1) { \ | |||||
| goto label(finished, __LINE__); \ | |||||
| } \ | |||||
| else label(body,__LINE__): | |||||
| /***************** | /***************** | ||||
| * fluid-let * | * fluid-let * | ||||
| *****************/ | *****************/ | ||||
| @@ -9,6 +9,8 @@ | |||||
| #include "hashmap.hpp" | #include "hashmap.hpp" | ||||
| FILE* ftb_stdout = stdout; | |||||
| #define str_eq(s1, s2) (strcmp(s1, s2) == 0) | #define str_eq(s1, s2) (strcmp(s1, s2) == 0) | ||||
| #define console_normal "\x1B[0m" | #define console_normal "\x1B[0m" | ||||
| @@ -371,7 +373,7 @@ int print(static_string format, ...) { | |||||
| va_list arg_list; | va_list arg_list; | ||||
| va_start(arg_list, format); | va_start(arg_list, format); | ||||
| int num_printed_chars = print_va_args_to_file(stdout, format, &arg_list); | |||||
| int num_printed_chars = print_va_args_to_file(ftb_stdout, format, &arg_list); | |||||
| va_end(arg_list); | va_end(arg_list); | ||||
| @@ -406,7 +408,6 @@ int print_str(FILE* f, char* str) { | |||||
| return print_to_file(f, "%s", str); | return print_to_file(f, "%s", str); | ||||
| } | } | ||||
| int print_color_start(FILE* f, char* str) { | int print_color_start(FILE* f, char* str) { | ||||
| color_stack.append(str); | color_stack.append(str); | ||||
| return print_to_file(f, "%s", str); | return print_to_file(f, "%s", str); | ||||
| @@ -0,0 +1,87 @@ | |||||
| typedef s32 testresult; | |||||
| #define epsilon 2.2204460492503131E-16 | |||||
| #define pass 1 | |||||
| #define fail 0 | |||||
| #define print_assert_equal_fail(variable, value, type, format) \ | |||||
| print("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \ | |||||
| "\n\texpected: " format \ | |||||
| "\n\tgot: " format "\n", \ | |||||
| __FILE__, __LINE__, (type)value, (type)variable) | |||||
| #define print_assert_not_equal_fail(variable, value, type, format) \ | |||||
| print("\n%s:%d: Assertion failed\n\tfor '" #variable "'" \ | |||||
| "\n\texpected not: " format \ | |||||
| "\n\tgot anyways: " format "\n", \ | |||||
| __FILE__, __LINE__, (type)(value), (type)(variable)) | |||||
| #define assert_equal_string(variable, value) \ | |||||
| if (!string_equal(variable, value)) { \ | |||||
| print_assert_equal_fail(&(variable), &(value), String*, "%{->Str}"); \ | |||||
| return fail; \ | |||||
| } | |||||
| #define assert_equal_int(variable, value) \ | |||||
| if (variable != value) { \ | |||||
| print_assert_equal_fail(variable, value, size_t, "%{u64}"); \ | |||||
| return fail; \ | |||||
| } | |||||
| #define assert_not_equal_int(variable, value) \ | |||||
| if (variable == value) { \ | |||||
| print_assert_not_equal_fail(variable, value, size_t, "%{u64}"); \ | |||||
| return fail; \ | |||||
| } | |||||
| #define assert_no_error() \ | |||||
| if (error) { \ | |||||
| print_assert_equal_fail(error, 0, size_t, "%{u64}"); \ | |||||
| printf("\nExpected no error to occur," \ | |||||
| " but an error occured anyways:\n"); \ | |||||
| return fail; \ | |||||
| } \ | |||||
| #define assert_error() \ | |||||
| if (!error) { \ | |||||
| print_assert_not_equal_fail(error, 0, void*, "%{->}"); \ | |||||
| printf("\nExpected an error to occur," \ | |||||
| " but no error occured:\n"); \ | |||||
| return fail; \ | |||||
| } \ | |||||
| #define assert_equal_f64(variable, value) \ | |||||
| if (fabsl((f64)variable - (f64)value) > epsilon) { \ | |||||
| print_assert_equal_fail(variable, value, f64, "%{f64}"); \ | |||||
| return fail; \ | |||||
| } | |||||
| #define assert_not_equal_f64(variable, value) \ | |||||
| if (fabsl((f64)variable - (f64)value) <= epsilon) { \ | |||||
| print_assert_not_equal_fail(variable, value, f64, "%{f64}"); \ | |||||
| return fail; \ | |||||
| } | |||||
| #define assert_null(variable) \ | |||||
| assert_equal_int(variable, nullptr) | |||||
| #define assert_not_null(variable) \ | |||||
| assert_not_equal_int(variable, nullptr) | |||||
| #define invoke_test(name) \ | |||||
| fputs("" #name ":", stdout); \ | |||||
| if (name() == pass) { \ | |||||
| for(size_t i = strlen(#name); i < 70; ++i) \ | |||||
| fputs((i%3==1)? "." : " ", stdout); \ | |||||
| fputs(console_green "passed\n" console_normal, stdout); \ | |||||
| } \ | |||||
| else { \ | |||||
| result = false; \ | |||||
| for(s32 i = -1; i < 70; ++i) \ | |||||
| fputs((i%3==1)? "." : " ", stdout); \ | |||||
| fputs(console_red "failed\n" console_normal, stdout); \ | |||||
| if(error) { \ | |||||
| free(error); \ | |||||
| error = nullptr; \ | |||||
| } \ | |||||
| } \ | |||||
| @@ -23,13 +23,20 @@ typedef char path_char; | |||||
| #endif | #endif | ||||
| struct String { | struct String { | ||||
| u32 length; | |||||
| u64 length; | |||||
| char* data; | char* data; | ||||
| }; | }; | ||||
| inline String make_heap_string(const char* str) { | |||||
| inline auto make_heap_string(const char* str) -> String { | |||||
| String ret; | String ret; | ||||
| ret.length = strlen(str); | ret.length = strlen(str); | ||||
| ret.data = _strdup(str); | ret.data = _strdup(str); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| inline const String make_static_string(char* str) { | |||||
| String ret; | |||||
| ret.length = strlen(str); | |||||
| ret.data = str; | |||||
| return ret; | |||||
| } | |||||