| @@ -8,34 +8,19 @@ | |||||
| context-mode-map) | context-mode-map) | ||||
| (context-mode 1) | (context-mode 1) | ||||
| ;; additional scripts | |||||
| (defun save-and-find-test-script-and-compile () | |||||
| (interactive) | |||||
| (let ((build-script-name "test.bat")) | |||||
| (save-and-find-build-script-and-compile))) | |||||
| (defun save-and-find-run-script-and-compile () | |||||
| (interactive) | |||||
| (let ((build-script-name "run.bat")) | |||||
| (save-and-find-build-script-and-compile))) | |||||
| (defun save-and-find-debug-script-and-compile () | |||||
| (interactive) | |||||
| (let ((build-script-name "debug.bat")) | |||||
| (save-and-find-build-script-and-compile))) | |||||
| (defhydra hydra-context (context-mode-map "<f2>") | (defhydra hydra-context (context-mode-map "<f2>") | ||||
| "Context Actions:" | "Context Actions:" | ||||
| ("b" save-and-find-build-script-and-compile "build" :color blue) | ("b" save-and-find-build-script-and-compile "build" :color blue) | ||||
| ("r" save-and-find-run-script-and-compile "run" :color blue) | |||||
| ("d" save-and-find-debug-script-and-compile "debug" :color blue) | |||||
| ("t" save-and-find-test-script-and-compile "test" :color blue) | |||||
| ("o" browse-file-directory "open" :color blue) | ("o" browse-file-directory "open" :color blue) | ||||
| ("q" nil "quit" :color blue)) | ("q" nil "quit" :color blue)) | ||||
| (define-key context-mode-map (kbd "<f2>") 'hydra-context/body) | (define-key context-mode-map (kbd "<f2>") 'hydra-context/body) | ||||
| (font-lock-add-keywords 'c++-mode | |||||
| '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" . | |||||
| font-lock-keyword-face))))))) | |||||
| (font-lock-add-keywords | |||||
| 'c++-mode | |||||
| '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\)\\>" . | |||||
| font-lock-keyword-face))))))) | |||||
| (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) | (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) | ||||
| (eval . (flycheck-mode 0)) | (eval . (flycheck-mode 0)) | ||||
| (eval . (rainbow-mode 0)) | (eval . (rainbow-mode 0)) | ||||
| @@ -5,31 +5,24 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { | |||||
| return false; | return false; | ||||
| switch (n1->type) { | switch (n1->type) { | ||||
| case Lisp_Object_Type::CFunction: | |||||
| // TODO(Felix): make comparing work again. | |||||
| return false; | |||||
| /* return n1->value.built_in_function->type */ | |||||
| /* == n2->value.built_in_function->type; */ | |||||
| case Lisp_Object_Type::Function: | |||||
| // if they have the same pointer, true is | |||||
| // returned a few lines above | |||||
| return false; | |||||
| case Lisp_Object_Type::CFunction: // if they have the same | |||||
| // pointer, true is returned a | |||||
| // few lines above | |||||
| case Lisp_Object_Type::Function: return false; | |||||
| case Lisp_Object_Type::T: // code for t and nil should never be | |||||
| // reached since they are memory unique | |||||
| case Lisp_Object_Type::Nil: return true; | |||||
| case Lisp_Object_Type::Symbol: // NOTE(Felix): this will be | |||||
| // unnecessary once symbols and | |||||
| // keywords are memory unique | |||||
| case Lisp_Object_Type::Keyword: | case Lisp_Object_Type::Keyword: | ||||
| return string_equal( | |||||
| n1->value.identifier, | |||||
| n2->value.identifier); | |||||
| case Lisp_Object_Type::T: | |||||
| case Lisp_Object_Type::Nil: | |||||
| return true; | |||||
| case Lisp_Object_Type::Number: | |||||
| return n1->value.number == n2->value.number; | |||||
| return string_equal(n1->value.identifier, n2->value.identifier); | |||||
| case Lisp_Object_Type::Number: return n1->value.number == n2->value.number; | |||||
| case Lisp_Object_Type::String: return string_equal(n1->value.string, n2->value.string); | |||||
| case Lisp_Object_Type::Pair: | case Lisp_Object_Type::Pair: | ||||
| create_not_yet_implemented_error(); | create_not_yet_implemented_error(); | ||||
| return false; | return false; | ||||
| case Lisp_Object_Type::String: | |||||
| return string_equal(n1->value.string, n2->value.string); | |||||
| case Lisp_Object_Type::Symbol: | |||||
| return string_equal(n1->value.identifier, n2->value.identifier); | |||||
| } | } | ||||
| // we should never reach here | // we should never reach here | ||||
| @@ -916,7 +909,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| Lisp_Object* result; | Lisp_Object* result; | ||||
| result = eval_expr(try_part, env); | result = eval_expr(try_part, env); | ||||
| if (error) { | |||||
| if (Globals::error) { | |||||
| delete_error(); | delete_error(); | ||||
| try { | try { | ||||
| result = eval_expr(catch_part, env); | result = eval_expr(catch_part, env); | ||||
| @@ -28,7 +28,7 @@ constexpr bool is_debug_build = false; | |||||
| else \ | else \ | ||||
| while (1) \ | while (1) \ | ||||
| if (1) { \ | if (1) { \ | ||||
| if(error) { \ | |||||
| if(Globals::error) { \ | |||||
| if (log_level == Log_Level::Debug) { \ | if (log_level == Log_Level::Debug) { \ | ||||
| printf("in %s:%d\n", __FILE__, __LINE__); \ | printf("in %s:%d\n", __FILE__, __LINE__); \ | ||||
| } \ | } \ | ||||
| @@ -44,7 +44,7 @@ constexpr bool is_debug_build = false; | |||||
| else \ | else \ | ||||
| while (1) \ | while (1) \ | ||||
| if (1) { \ | if (1) { \ | ||||
| if(error) { \ | |||||
| if(Globals::error) { \ | |||||
| if (log_level == Log_Level::Debug) { \ | if (log_level == Log_Level::Debug) { \ | ||||
| printf("in %s:%d\n", __FILE__, __LINE__); \ | printf("in %s:%d\n", __FILE__, __LINE__); \ | ||||
| } \ | } \ | ||||
| @@ -1,4 +1,3 @@ | |||||
| proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> void { | proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> void { | ||||
| // NOTE(Felix): right now we are simply adding the symol at the | // NOTE(Felix): right now we are simply adding the symol at the | ||||
| // back of the list without checking if it already exists but are | // back of the list without checking if it already exists but are | ||||
| @@ -1,6 +1,6 @@ | |||||
| Error* error; | |||||
| proc delete_error() -> void { | proc delete_error() -> void { | ||||
| using Globals::error; | |||||
| if (error) { | if (error) { | ||||
| free(error); | free(error); | ||||
| error = nullptr; | error = nullptr; | ||||
| @@ -15,6 +15,7 @@ proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, S | |||||
| delete_error(); | delete_error(); | ||||
| debug_break(); | debug_break(); | ||||
| using Globals::error; | |||||
| error = new(Error); | error = new(Error); | ||||
| error->type = type; | error->type = type; | ||||
| error->message = message; | error->message = message; | ||||
| @@ -387,7 +387,7 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| return symbol; | return symbol; | ||||
| } | } | ||||
| case Lisp_Object_Type::Pair: { | case Lisp_Object_Type::Pair: { | ||||
| current_source_code = node; | |||||
| Globals::current_source_code = node; | |||||
| Lisp_Object* lispOperator; | Lisp_Object* lispOperator; | ||||
| if (node->value.pair.first->type != Lisp_Object_Type::CFunction && | if (node->value.pair.first->type != Lisp_Object_Type::CFunction && | ||||
| @@ -486,7 +486,7 @@ proc interprete_stdin() -> void { | |||||
| built_in_load(Memory::create_string("pre.slime"), env); | built_in_load(Memory::create_string("pre.slime"), env); | ||||
| if (error) { | |||||
| if (Globals::error) { | |||||
| log_error(); | log_error(); | ||||
| delete_error(); | delete_error(); | ||||
| } | } | ||||
| @@ -497,13 +497,13 @@ proc interprete_stdin() -> void { | |||||
| line = read_expression(); | line = read_expression(); | ||||
| parsed = Parser::parse_single_expression(line); | parsed = Parser::parse_single_expression(line); | ||||
| free(line); | free(line); | ||||
| if (error) { | |||||
| if (Globals::error) { | |||||
| log_error(); | log_error(); | ||||
| delete_error(); | delete_error(); | ||||
| continue; | continue; | ||||
| } | } | ||||
| evaluated = eval_expr(parsed, env); | evaluated = eval_expr(parsed, env); | ||||
| if (error) { | |||||
| if (Globals::error) { | |||||
| log_error(); | log_error(); | ||||
| delete_error(); | delete_error(); | ||||
| continue; | continue; | ||||
| @@ -12,8 +12,12 @@ proc parse_argument_list(Lisp_Object*, Function*) -> void; | |||||
| proc print_environment(Environment*) -> void; | proc print_environment(Environment*) -> void; | ||||
| proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char*; | proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char*; | ||||
| namespace Memory { | namespace Memory { | ||||
| proc get_or_create_lisp_object_keyword(const char* identifier) -> Lisp_Object*; | proc get_or_create_lisp_object_keyword(const char* identifier) -> Lisp_Object*; | ||||
| } | } | ||||
| Lisp_Object* current_source_code = nullptr; | |||||
| namespace Globals { | |||||
| Lisp_Object* current_source_code = nullptr; | |||||
| Error* error; | |||||
| } | |||||
| @@ -119,16 +119,17 @@ proc read_entire_file(char* filename) -> char* { | |||||
| proc read_expression() -> char* { | proc read_expression() -> char* { | ||||
| char* line = (char*)malloc(100); | char* line = (char*)malloc(100); | ||||
| if(line == nullptr) | |||||
| return nullptr; | |||||
| char* linep = line; | char* linep = line; | ||||
| size_t lenmax = 100, len = lenmax; | size_t lenmax = 100, len = lenmax; | ||||
| int c; | int c; | ||||
| int nesting = 0; | int nesting = 0; | ||||
| if(line == NULL) | |||||
| return NULL; | |||||
| for(;;) { | |||||
| while (true) { | |||||
| c = fgetc(stdin); | c = fgetc(stdin); | ||||
| if(c == EOF) | if(c == EOF) | ||||
| break; | break; | ||||
| @@ -137,9 +138,9 @@ proc read_expression() -> char* { | |||||
| len = lenmax; | len = lenmax; | ||||
| char * linen = (char*)realloc(linep, lenmax *= 2); | char * linen = (char*)realloc(linep, lenmax *= 2); | ||||
| if(linen == NULL) { | |||||
| if(linen == nullptr) { | |||||
| free(linep); | free(linep); | ||||
| return NULL; | |||||
| return nullptr; | |||||
| } | } | ||||
| line = linen + (line - linep); | line = linen + (line - linep); | ||||
| linep = linen; | linep = linen; | ||||
| @@ -168,8 +169,8 @@ proc read_line() -> char* { | |||||
| int nesting = 0; | int nesting = 0; | ||||
| if(line == NULL) | |||||
| return NULL; | |||||
| if(line == nullptr) | |||||
| return nullptr; | |||||
| for(;;) { | for(;;) { | ||||
| c = fgetc(stdin); | c = fgetc(stdin); | ||||
| @@ -180,9 +181,9 @@ proc read_line() -> char* { | |||||
| len = lenmax; | len = lenmax; | ||||
| char* linen = (char*)realloc(linep, lenmax *= 2); | char* linen = (char*)realloc(linep, lenmax *= 2); | ||||
| if(linen == NULL) { | |||||
| if(linen == nullptr) { | |||||
| free(linep); | free(linep); | ||||
| return NULL; | |||||
| return nullptr; | |||||
| } | } | ||||
| line = linen + (line - linep); | line = linen + (line - linep); | ||||
| linep = linen; | linep = linen; | ||||
| @@ -230,31 +231,34 @@ proc panic(char* message) -> void { | |||||
| proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> void { | proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> void { | ||||
| switch (node->type) { | switch (node->type) { | ||||
| case (Lisp_Object_Type::Nil): fprintf(file, "()"); break; | |||||
| case (Lisp_Object_Type::T): fprintf(file, "t"); break; | |||||
| case (Lisp_Object_Type::Number): fprintf(file, "%f", node->value.number); break; | |||||
| case (Lisp_Object_Type::Symbol): fprintf(file, "%s", Memory::get_c_str(node->value.identifier)); break; | |||||
| case (Lisp_Object_Type::Keyword): fprintf(file, ":%s", Memory::get_c_str(node->value.identifier)); break; | |||||
| case (Lisp_Object_Type::CFunction): fprintf(file, "[C-function]"); break; | |||||
| case (Lisp_Object_Type::Nil): fputs("()", file); break; | |||||
| case (Lisp_Object_Type::T): fputs("t", file); break; | |||||
| case (Lisp_Object_Type::Number): fprintf(file, "%f", node->value.number); break; | |||||
| case (Lisp_Object_Type::Keyword): fputs(":", file); // NOTE(Felix): intentionall fallthough | |||||
| case (Lisp_Object_Type::Symbol): fprintf(file, Memory::get_c_str(node->value.identifier)); break; | |||||
| case (Lisp_Object_Type::CFunction): fputs("[C-function]", file); break; | |||||
| case (Lisp_Object_Type::String): { | case (Lisp_Object_Type::String): { | ||||
| if (print_quotes) | |||||
| fprintf(file, "\"%s\"", Memory::get_c_str(node->value.string)); | |||||
| if (print_quotes) { | |||||
| putc('\"', file); | |||||
| fputs(Memory::get_c_str(node->value.string), file); | |||||
| putc('\"', file); | |||||
| } | |||||
| else | else | ||||
| fprintf(file, "%s", Memory::get_c_str(node->value.string)); | |||||
| fputs(Memory::get_c_str(node->value.string), file); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Function): { | case (Lisp_Object_Type::Function): { | ||||
| if (node->value.function.type == Function_Type::Lambda) | if (node->value.function.type == Function_Type::Lambda) | ||||
| fprintf(file, "[lambda]"); | |||||
| fputs("[lambda]", file); | |||||
| else if (node->value.function.type == Function_Type::Special_Lambda) | else if (node->value.function.type == Function_Type::Special_Lambda) | ||||
| fprintf(file, "[special-lambda]"); | |||||
| fputs("[special-lambda]", file); | |||||
| else if (node->value.function.type == Function_Type::Macro) | else if (node->value.function.type == Function_Type::Macro) | ||||
| fprintf(file, "[macro]"); | |||||
| fputs("[macro]", file); | |||||
| else | else | ||||
| assert(false); | assert(false); | ||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Pair): { | case (Lisp_Object_Type::Pair): { | ||||
| Lisp_Object* head = node; | Lisp_Object* head = node; | ||||
| fprintf(file, "("); | |||||
| putc('(', file); | |||||
| // NOTE(Felix): We cold do a while true here, however in case | // NOTE(Felix): We cold do a while true here, however in case | ||||
| // we want to print a broken list (for logging the error) we | // we want to print a broken list (for logging the error) we | ||||
| @@ -266,38 +270,39 @@ proc print(Lisp_Object* node, bool print_quotes = false, FILE* file = stdout) -> | |||||
| return; | return; | ||||
| if (head->type != Lisp_Object_Type::Pair) | if (head->type != Lisp_Object_Type::Pair) | ||||
| break; | break; | ||||
| fprintf(file, " "); | |||||
| putc(' ', file); | |||||
| } | } | ||||
| if (head->type != Lisp_Object_Type::Nil) { | if (head->type != Lisp_Object_Type::Nil) { | ||||
| fprintf(file, " . "); | |||||
| fputs(" . ", file); | |||||
| print(head); | print(head); | ||||
| } | } | ||||
| fprintf(file, ")"); | |||||
| putc(')', file); | |||||
| } break; | } break; | ||||
| } | } | ||||
| } | } | ||||
| proc print_error_location() -> void { | proc print_error_location() -> void { | ||||
| if (current_source_code) { | |||||
| if (Globals::current_source_code) { | |||||
| printf("%s (line %d, position %d) code:" console_red "\n ", | printf("%s (line %d, position %d) code:" console_red "\n ", | ||||
| Memory::get_c_str( | Memory::get_c_str( | ||||
| current_source_code->sourceCodeLocation->file), | |||||
| current_source_code->sourceCodeLocation->line, | |||||
| current_source_code->sourceCodeLocation->column); | |||||
| print(current_source_code); | |||||
| Globals::current_source_code->sourceCodeLocation->file), | |||||
| Globals::current_source_code->sourceCodeLocation->line, | |||||
| Globals::current_source_code->sourceCodeLocation->column); | |||||
| print(Globals::current_source_code); | |||||
| } else { | } else { | ||||
| printf("no source code location avaliable"); | |||||
| fputs("no source code location avaliable", stdout); | |||||
| } | } | ||||
| } | } | ||||
| proc log_error() -> void { | proc log_error() -> void { | ||||
| printf("%s%s%s\n", console_red, | |||||
| Memory::get_c_str(error->message), | |||||
| console_normal); | |||||
| printf(" in: %s", console_cyan); | |||||
| fputs(console_red, stdout); | |||||
| fputs(Memory::get_c_str(Globals::error->message), stdout); | |||||
| puts(console_normal); | |||||
| fputs(" in: " console_cyan, stdout); | |||||
| print_error_location(); | print_error_location(); | ||||
| printf("%s\n", console_normal); | |||||
| puts(console_normal); | |||||
| } | } | ||||
| @@ -1,17 +1,19 @@ | |||||
| #include "slime.h" | #include "slime.h" | ||||
| // using namespace Slime; | |||||
| int main(int argc, char* argv[]) { | int main(int argc, char* argv[]) { | ||||
| if (argc > 1) { | if (argc > 1) { | ||||
| if (Slime::string_equal(argv[1], "--run-tests")) { | |||||
| return Slime::run_all_tests() ? 0 : 1; | |||||
| if (string_equal(argv[1], "--run-tests")) { | |||||
| return run_all_tests() ? 0 : 1; | |||||
| } | } | ||||
| Slime::interprete_file(argv[1]); | |||||
| if (Slime::error) { | |||||
| Slime::log_error(); | |||||
| interprete_file(argv[1]); | |||||
| if (Globals::error) { | |||||
| log_error(); | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| } else { | } else { | ||||
| Slime::interprete_stdin(); | |||||
| interprete_stdin(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -12,7 +12,7 @@ | |||||
| #undef _CRT_SECURE_NO_DEPRECATE | #undef _CRT_SECURE_NO_DEPRECATE | ||||
| #undef _CRT_SECURE_NO_WARNINGS | #undef _CRT_SECURE_NO_WARNINGS | ||||
| namespace Slime { | |||||
| // namespace Slime { | |||||
| # include "./defines.cpp" | # include "./defines.cpp" | ||||
| # include "./structs.cpp" | # include "./structs.cpp" | ||||
| # include "./forward_decls.cpp" | # include "./forward_decls.cpp" | ||||
| @@ -26,4 +26,4 @@ namespace Slime { | |||||
| # include "./built_ins.cpp" | # include "./built_ins.cpp" | ||||
| # include "./testing.cpp" | # include "./testing.cpp" | ||||
| # include "./undefines.cpp" | # include "./undefines.cpp" | ||||
| } | |||||
| // } | |||||
| @@ -29,20 +29,20 @@ | |||||
| } | } | ||||
| #define assert_no_error() \ | #define assert_no_error() \ | ||||
| if (error) { \ | |||||
| print_assert_equal_fail(error, 0, size_t, "%zd"); \ | |||||
| if (Globals::error) { \ | |||||
| print_assert_equal_fail(Globals::error, 0, size_t, "%zd"); \ | |||||
| printf("\nExpected no error to occur," \ | printf("\nExpected no error to occur," \ | ||||
| " but an error occured anyways:\n"); \ | " but an error occured anyways:\n"); \ | ||||
| log_error(); \ | log_error(); \ | ||||
| return fail; \ | return fail; \ | ||||
| } \ | } \ | ||||
| #define assert_error() \ | |||||
| if (!error) { \ | |||||
| print_assert_not_equal_fail(error, 0, size_t, "%zd"); \ | |||||
| printf("\nExpected an error to occur," \ | |||||
| " but no error occured:\n"); \ | |||||
| return fail; \ | |||||
| #define assert_error() \ | |||||
| if (!Globals::error) { \ | |||||
| print_assert_not_equal_fail(Globals::error, 0, size_t, "%zd"); \ | |||||
| printf("\nExpected an error to occur," \ | |||||
| " but no error occured:\n"); \ | |||||
| return fail; \ | |||||
| } \ | } \ | ||||
| #define assert_equal_double(variable, value) \ | #define assert_equal_double(variable, value) \ | ||||
| @@ -77,40 +77,40 @@ | |||||
| #define assert_not_null(variable) \ | #define assert_not_null(variable) \ | ||||
| assert_not_equal_int(variable, nullptr) | assert_not_equal_int(variable, nullptr) | ||||
| #define invoke_test(name) \ | |||||
| printf("" #name ":"); \ | |||||
| if (name() == pass) { \ | |||||
| for(size_t i = strlen(#name); i < 70; ++i) \ | |||||
| printf((i%3==1)? "." : " "); \ | |||||
| printf("%spassed%s\n", console_green, console_normal); \ | |||||
| } \ | |||||
| else { \ | |||||
| result = false; \ | |||||
| for(int i = -1; i < 70; ++i) \ | |||||
| printf((i%3==1)? "." : " "); \ | |||||
| printf("%sfailed%s\n", console_red, console_normal); \ | |||||
| if(error) { \ | |||||
| free(error); \ | |||||
| error = 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(int i = -1; i < 70; ++i) \ | |||||
| fputs((i%3==1)? "." : " ", stdout); \ | |||||
| fputs(console_red "failed\n" console_normal, stdout); \ | |||||
| if(Globals::error) { \ | |||||
| free(Globals::error); \ | |||||
| Globals::error = nullptr; \ | |||||
| } \ | |||||
| } \ | |||||
| #define invoke_test_script(name) \ | |||||
| printf("" name ":"); \ | |||||
| if (test_file("tests/" name ".slime") == pass) { \ | |||||
| for(size_t i = strlen(name); i < 70; ++i) \ | |||||
| printf((i%3==1)? "." : " "); \ | |||||
| printf("%spassed%s\n", console_green, console_normal); \ | |||||
| } \ | |||||
| else { \ | |||||
| result = false; \ | |||||
| for(int i = -1; i < 70; ++i) \ | |||||
| printf((i%3==1)? "." : " "); \ | |||||
| printf("%sfailed%s\n", console_red, console_normal); \ | |||||
| if(error) { \ | |||||
| free(error); \ | |||||
| error = nullptr; \ | |||||
| } \ | |||||
| #define invoke_test_script(name) \ | |||||
| fputs("" name ":", stdout); \ | |||||
| if (test_file("tests/" name ".slime") == 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(int i = -1; i < 70; ++i) \ | |||||
| fputs((i%3==1)? "." : " ", stdout); \ | |||||
| fputs(console_red "failed\n" console_normal, stdout); \ | |||||
| if(Globals::error) { \ | |||||
| free(Globals::error); \ | |||||
| Globals::error = nullptr; \ | |||||
| } \ | |||||
| } | } | ||||
| proc test_eval_operands() -> testresult { | proc test_eval_operands() -> testresult { | ||||
| @@ -480,7 +480,7 @@ proc test_singular_t_and_nil() -> testresult { | |||||
| proc test_file(const char* file) -> testresult { | proc test_file(const char* file) -> testresult { | ||||
| Memory::reset(); | Memory::reset(); | ||||
| static Environment* env = Memory::create_built_ins_environment(); | |||||
| Environment* env = Memory::create_built_ins_environment(); | |||||
| Parser::init(env); | Parser::init(env); | ||||