| @@ -1,28 +1,21 @@ | |||||
| @echo off | @echo off | ||||
| @setlocal | @setlocal | ||||
| pushd %~dp0 | |||||
| pushd %~dp0\bin | |||||
| set exeName=slime.exe | set exeName=slime.exe | ||||
| pushd bin | |||||
| taskkill /F /IM %exeName% > NUL 2> NUL | taskkill /F /IM %exeName% > NUL 2> NUL | ||||
| echo ---------- Compiling ---------- | echo ---------- Compiling ---------- | ||||
| call ..\timecmd cl ../src/main.cpp /D_DEBUG /Zi /std:c++latest /Fe%exeName% /W3 /wd4003 /nologo /EHsc /link /NODEFAULTLIB:libucrt libucrtd.lib | |||||
| call ..\timecmd cl ../src/main.cpp /D_PROFILING /D_DEBUG /D_DONT_BREAK_ON_ERRORS /Zi /std:c++latest /Fe%exeName% /W3 /wd4003 /nologo /EHsc /link /NODEFAULTLIB:libucrt libucrtd.lib | |||||
| rem call ..\timecmd clang-cl ../src/main.cpp -o %exeName% /O2 /std:c++latest /W3 /Zi /EHsc | rem call ..\timecmd clang-cl ../src/main.cpp -o %exeName% /O2 /std:c++latest /W3 /Zi /EHsc | ||||
| popd | |||||
| if %errorlevel% == 0 ( | if %errorlevel% == 0 ( | ||||
| echo. | echo. | ||||
| echo ---- Running Tests ---- | echo ---- Running Tests ---- | ||||
| echo. | echo. | ||||
| call timecmd bin\slime.exe --run-tests | |||||
| echo. | |||||
| echo ---- Genderating Docs ---- | |||||
| echo. | |||||
| call timecmd bin\slime generate-docs.slime | |||||
| call timecmd slime.exe --run-tests | |||||
| ) else ( | ) else ( | ||||
| echo. | echo. | ||||
| echo Fuckin' ell | echo Fuckin' ell | ||||
| @@ -54,19 +54,24 @@ proc built_in_load(String* file_name) -> Lisp_Object* { | |||||
| file_content = read_entire_file(fullpath); | file_content = read_entire_file(fullpath); | ||||
| if (!file_content) { | if (!file_content) { | ||||
| create_generic_error("The file '%s' was not found " | |||||
| "(neither in the cwd nor in slime's bin dir)", | |||||
| Memory::get_c_str(file_name)); | |||||
| char* cwd = get_cwd(); | |||||
| defer { | |||||
| free(cwd); | |||||
| }; | |||||
| create_generic_error("The file to load '%s' was not found: " | |||||
| "neither in the cwd (%s) " | |||||
| "nor in slime's exe dir (%s)", | |||||
| Memory::get_c_str(file_name), cwd, fullpath); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| Lisp_Object* result = Memory::nil; | Lisp_Object* result = Memory::nil; | ||||
| Lisp_Object_Array_List* program; | |||||
| Lisp_Object_Array_List program; | |||||
| try program = Parser::parse_program(Memory::create_string(fullpath), file_content); | try program = Parser::parse_program(Memory::create_string(fullpath), file_content); | ||||
| for (int i = 0; i < program->next_index; ++i) { | |||||
| try result = eval_expr(program->data[i]); | |||||
| for (int i = 0; i < program.next_index; ++i) { | |||||
| try result = eval_expr(program.data[i]); | |||||
| } | } | ||||
| return result; | return result; | ||||
| } | } | ||||
| @@ -75,7 +80,7 @@ proc built_in_import(String* file_name) -> Lisp_Object* { | |||||
| // create new empty environment | // create new empty environment | ||||
| Environment* new_env; | Environment* new_env; | ||||
| try new_env = Memory::create_child_environment(get_root_environment()); | try new_env = Memory::create_child_environment(get_root_environment()); | ||||
| append_to_array_list(get_current_environment()->parents, new_env); | |||||
| append_to_array_list(&get_current_environment()->parents, new_env); | |||||
| push_environment(new_env); | push_environment(new_env); | ||||
| defer { | defer { | ||||
| @@ -130,9 +135,9 @@ proc load_built_ins_into_environment() -> void { | |||||
| parse_argument_list(arguments->value.pair.first, &ret->value.function); | parse_argument_list(arguments->value.pair.first, &ret->value.function); | ||||
| } | } | ||||
| } else { | } else { | ||||
| ret->value.function.positional_arguments = create_positional_argument_list(1); | |||||
| ret->value.function.keyword_arguments = create_keyword_argument_list(1); | |||||
| ret->value.function.rest_argument = nullptr; | |||||
| ret->value.function.args.positional = create_positional_argument_list(1); | |||||
| ret->value.function.args.keyword = create_keyword_argument_list(1); | |||||
| ret->value.function.args.rest = nullptr; | |||||
| } | } | ||||
| arguments = arguments->value.pair.rest; | arguments = arguments->value.pair.rest; | ||||
| @@ -948,39 +953,39 @@ proc load_built_ins_into_environment() -> void { | |||||
| printf("Arguments:\n==========\n"); | printf("Arguments:\n==========\n"); | ||||
| printf("Postitional: {"); | printf("Postitional: {"); | ||||
| if (fun->value.function.positional_arguments->next_index != 0) { | |||||
| if (fun->value.function.args.positional.symbols.next_index != 0) { | |||||
| printf("%s", | printf("%s", | ||||
| Memory::get_c_str(fun->value.function.positional_arguments->symbols[0]->value.symbol.identifier)); | |||||
| for (int i = 1; i < fun->value.function.positional_arguments->next_index; ++i) { | |||||
| Memory::get_c_str(fun->value.function.args.positional.symbols.data[0]->value.symbol.identifier)); | |||||
| for (int i = 1; i < fun->value.function.args.positional.symbols.next_index; ++i) { | |||||
| printf(", %s", | printf(", %s", | ||||
| Memory::get_c_str(fun->value.function.positional_arguments->symbols[i]->value.symbol.identifier)); | |||||
| Memory::get_c_str(fun->value.function.args.positional.symbols.data[i]->value.symbol.identifier)); | |||||
| } | } | ||||
| } | } | ||||
| printf("}\n"); | printf("}\n"); | ||||
| printf("Keyword: {"); | printf("Keyword: {"); | ||||
| if (fun->value.function.keyword_arguments->values->next_index != 0) { | |||||
| if (fun->value.function.args.keyword.values.next_index != 0) { | |||||
| printf("%s", | printf("%s", | ||||
| Memory::get_c_str(fun->value.function.keyword_arguments->keywords->data[0]->value.symbol.identifier)); | |||||
| if (fun->value.function.keyword_arguments->values->data[0]) { | |||||
| Memory::get_c_str(fun->value.function.args.keyword.keywords.data[0]->value.symbol.identifier)); | |||||
| if (fun->value.function.args.keyword.values.data[0]) { | |||||
| printf(" ("); | printf(" ("); | ||||
| print(fun->value.function.keyword_arguments->values->data[0]); | |||||
| print(fun->value.function.args.keyword.values.data[0]); | |||||
| printf(")"); | printf(")"); | ||||
| } | } | ||||
| for (int i = 1; i < fun->value.function.keyword_arguments->values->next_index; ++i) { | |||||
| for (int i = 1; i < fun->value.function.args.keyword.values.next_index; ++i) { | |||||
| printf(", %s", | printf(", %s", | ||||
| Memory::get_c_str(fun->value.function.keyword_arguments->keywords->data[i]->value.symbol.identifier)); | |||||
| if (fun->value.function.keyword_arguments->values->data[i]) { | |||||
| Memory::get_c_str(fun->value.function.args.keyword.keywords.data[i]->value.symbol.identifier)); | |||||
| if (fun->value.function.args.keyword.values.data[i]) { | |||||
| printf(" ("); | printf(" ("); | ||||
| print(fun->value.function.keyword_arguments->values->data[i]); | |||||
| print(fun->value.function.args.keyword.values.data[i]); | |||||
| printf(")"); | printf(")"); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| printf("}\n"); | printf("}\n"); | ||||
| printf("Rest: {"); | printf("Rest: {"); | ||||
| if (fun->value.function.rest_argument) | |||||
| if (fun->value.function.args.rest) | |||||
| printf("%s", | printf("%s", | ||||
| Memory::get_c_str(fun->value.function.rest_argument)); | |||||
| Memory::get_c_str(fun->value.function.args.rest)); | |||||
| printf("}\n"); | printf("}\n"); | ||||
| } | } | ||||
| @@ -1014,7 +1019,7 @@ proc load_built_ins_into_environment() -> void { | |||||
| try assert_arguments_length(1, arguments_length); | try assert_arguments_length(1, arguments_length); | ||||
| try assert_type(arguments->value.pair.first, Lisp_Object_Type::String); | try assert_type(arguments->value.pair.first, Lisp_Object_Type::String); | ||||
| generate_docs(arguments->value.pair.first->value.string); | |||||
| try generate_docs(arguments->value.pair.first->value.string); | |||||
| return Memory::t; | return Memory::t; | ||||
| }); | }); | ||||
| @@ -37,8 +37,9 @@ | |||||
| } \ | } \ | ||||
| else label(body,__LINE__): | else label(body,__LINE__): | ||||
| #define try_void try_or_else_return() | |||||
| #define try try_or_else_return(0) | |||||
| #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 dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) | ||||
| #define ignore_logging fluid_let(Globals::log_level, Log_Level::None) | #define ignore_logging fluid_let(Globals::log_level, Log_Level::None) | ||||
| @@ -53,16 +54,17 @@ | |||||
| \ | \ | ||||
| proc remove_index_from_array_list(name##_Array_List* arraylist, int index) -> void { \ | proc remove_index_from_array_list(name##_Array_List* arraylist, int index) -> void { \ | ||||
| arraylist->data[index] = \ | arraylist->data[index] = \ | ||||
| arraylist->data[--arraylist->next_index]; \ | |||||
| arraylist->data[--(arraylist->next_index)]; \ | |||||
| } \ | } \ | ||||
| \ | \ | ||||
| proc append_to_array_list(name##_Array_List* arraylist, type element) -> void { \ | proc append_to_array_list(name##_Array_List* arraylist, type element) -> void { \ | ||||
| if (arraylist->next_index == arraylist->length) { \ | |||||
| arraylist->length *= 2; \ | |||||
| arraylist->data = \ | |||||
| if (arraylist->next_index == arraylist->length) { \ | |||||
| arraylist->length *= 2; \ | |||||
| arraylist->data = \ | |||||
| (type*)realloc(arraylist->data, arraylist->length * sizeof(type)); \ | (type*)realloc(arraylist->data, arraylist->length * sizeof(type)); \ | ||||
| } \ | } \ | ||||
| arraylist->data[arraylist->next_index++] = element; \ | |||||
| arraylist->data[arraylist->next_index] = element; \ | |||||
| arraylist->next_index++; \ | |||||
| } \ | } \ | ||||
| \ | \ | ||||
| proc _merge_array_lists(name##_Array_List* arr, int start, int mid, int end) -> void { \ | proc _merge_array_lists(name##_Array_List* arr, int start, int mid, int end) -> void { \ | ||||
| @@ -99,7 +101,7 @@ | |||||
| \ | \ | ||||
| proc sort_array_list(name##_Array_List* arraylist, int left=-1, int right=-1) -> void { \ | proc sort_array_list(name##_Array_List* arraylist, int left=-1, int right=-1) -> void { \ | ||||
| if (left == -1) { \ | if (left == -1) { \ | ||||
| sort_array_list(arraylist, 0, arraylist->next_index - 1); \ | |||||
| sort_array_list(arraylist, 0, arraylist->next_index - 1); \ | |||||
| return; \ | return; \ | ||||
| } else if (left == right) { \ | } else if (left == right) { \ | ||||
| return; \ | return; \ | ||||
| @@ -107,17 +109,17 @@ | |||||
| \ | \ | ||||
| int middle = left + (right-left) / 2; \ | int middle = left + (right-left) / 2; \ | ||||
| \ | \ | ||||
| sort_array_list(arraylist, left, middle); \ | |||||
| sort_array_list(arraylist, middle+1, right); \ | |||||
| sort_array_list(arraylist, left, middle); \ | |||||
| sort_array_list(arraylist, middle+1, right); \ | |||||
| \ | \ | ||||
| _merge_array_lists(arraylist, left, middle, 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 { \ | proc sorted_array_list_find(name##_Array_List* arraylist, type elem, int left=-1, int right=-1) -> int { \ | ||||
| if (left == -1) { \ | if (left == -1) { \ | ||||
| return sorted_array_list_find(arraylist, elem, 0, arraylist->next_index - 1); \ | return sorted_array_list_find(arraylist, elem, 0, arraylist->next_index - 1); \ | ||||
| } else if (left == right) { \ | } else if (left == right) { \ | ||||
| if ((size_t)arraylist->data[left] == (size_t)elem) \ | |||||
| if ((size_t)arraylist->data[left] == (size_t)elem) \ | |||||
| return left; \ | return left; \ | ||||
| return -1; \ | return -1; \ | ||||
| } else if (right < left) \ | } else if (right < left) \ | ||||
| @@ -125,18 +127,18 @@ | |||||
| \ | \ | ||||
| int middle = left + (right-left) / 2; \ | int middle = left + (right-left) / 2; \ | ||||
| \ | \ | ||||
| if ((size_t)arraylist->data[middle] < (size_t)elem) \ | |||||
| if ((size_t)arraylist->data[middle] < (size_t)elem) \ | |||||
| return sorted_array_list_find(arraylist, elem, middle+1, right); \ | return sorted_array_list_find(arraylist, elem, middle+1, right); \ | ||||
| if ((size_t)arraylist->data[middle] > (size_t)elem) \ | |||||
| if ((size_t)arraylist->data[middle] > (size_t)elem) \ | |||||
| return sorted_array_list_find(arraylist, elem, left, middle-1); \ | return sorted_array_list_find(arraylist, elem, left, middle-1); \ | ||||
| return middle; \ | return middle; \ | ||||
| } \ | } \ | ||||
| \ | \ | ||||
| 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; \ | |||||
| 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; \ | return ret; \ | ||||
| } | } | ||||
| @@ -145,13 +147,11 @@ | |||||
| * iterate over array lists | * iterate over array lists | ||||
| */ | */ | ||||
| #define for_array_list(l) \ | #define for_array_list(l) \ | ||||
| if (!l); \ | |||||
| if (int it_index = 0); \ | |||||
| else \ | else \ | ||||
| if (int it_index = 0); \ | |||||
| else \ | |||||
| for (auto it = l->data[0]; \ | |||||
| it_index < l->next_index; \ | |||||
| it=l->data[++it_index]) | |||||
| for (auto it = (l).data[0]; \ | |||||
| it_index < (l).next_index; \ | |||||
| it=(l).data[++it_index]) | |||||
| /* | /* | ||||
| * iterate over lisp vectors | * iterate over lisp vectors | ||||
| @@ -1,41 +1,38 @@ | |||||
| proc generate_docs(String* path) -> void { | proc generate_docs(String* path) -> void { | ||||
| // save the current working directory | |||||
| char* cwd = get_cwd(); | |||||
| // get the direction of the exe | |||||
| char* exe_path = get_exe_dir(); | |||||
| change_cwd(exe_path); | |||||
| defer { | |||||
| // switch back to the users directory | |||||
| change_cwd(cwd); | |||||
| free(exe_path); | |||||
| free(cwd); | |||||
| }; | |||||
| FILE *f = fopen(Memory::get_c_str(path), "w"); | FILE *f = fopen(Memory::get_c_str(path), "w"); | ||||
| if (!f) { | if (!f) { | ||||
| create_generic_error("The file for writing the documentation " | |||||
| "could not be opened for writing."); | |||||
| create_generic_error("The file for writing the documentation (%s) " | |||||
| "could not be opened for writing.", Memory::get_c_str(path)); | |||||
| return; | return; | ||||
| } | } | ||||
| defer { | defer { | ||||
| fclose(f); | fclose(f); | ||||
| }; | }; | ||||
| Environment_Array_List* visited = create_Environment_array_list(); | |||||
| Environment_Array_List visited = create_Environment_array_list(); | |||||
| // recursive inner funciton | |||||
| std::function<void(Environment*, char* prefix)> print_this_env; | std::function<void(Environment*, char* prefix)> print_this_env; | ||||
| print_this_env = [&](Environment* env, char* prefix) -> void { | print_this_env = [&](Environment* env, char* prefix) -> void { | ||||
| bool we_already_printed = false; | bool we_already_printed = false; | ||||
| // TODO(Felix): Make a generic array_list_contains function | // TODO(Felix): Make a generic array_list_contains function | ||||
| for (int i = 0; i < visited->next_index; ++i) { | |||||
| if (visited->data[i] == env) { | |||||
| for_array_list(visited) { | |||||
| if (it == env) { | |||||
| we_already_printed = true; | we_already_printed = true; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (!we_already_printed) { | if (!we_already_printed) { | ||||
| append_to_array_list(visited, env); | |||||
| printf("Working ion env::::"); | |||||
| print_environment(env); | |||||
| printf("\n--------------------------------\n"); | |||||
| append_to_array_list(&visited, env); | |||||
| push_environment(env); | |||||
| defer { | |||||
| pop_environment(); | |||||
| }; | |||||
| for (int i = 0; i < env->next_index; ++i) { | for (int i = 0; i < env->next_index; ++i) { | ||||
| fprintf(f, "\\hrule\n* =%s%s= \n" | fprintf(f, "\\hrule\n* =%s%s= \n" | ||||
| // " :PROPERTIES:\n" | // " :PROPERTIES:\n" | ||||
| @@ -46,10 +43,10 @@ proc generate_docs(String* path) -> void { | |||||
| * sourcecodeLocation | * sourcecodeLocation | ||||
| */ | */ | ||||
| if (env->values[i]->sourceCodeLocation) { | if (env->values[i]->sourceCodeLocation) { | ||||
| fprintf(f, "\n - defined in :: =%s:%d:%d=", | |||||
| Memory::get_c_str(env->values[i]->sourceCodeLocation->file), | |||||
| env->values[i]->sourceCodeLocation->line, | |||||
| env->values[i]->sourceCodeLocation->column); | |||||
| try_void fprintf(f, "\n - defined in :: =%s:%d:%d=", | |||||
| Memory::get_c_str(env->values[i]->sourceCodeLocation->file), | |||||
| env->values[i]->sourceCodeLocation->line, | |||||
| env->values[i]->sourceCodeLocation->column); | |||||
| } | } | ||||
| /* | /* | ||||
| * type | * type | ||||
| @@ -57,8 +54,8 @@ proc generate_docs(String* path) -> void { | |||||
| Lisp_Object_Type type = Memory::get_type(env->values[i]); | Lisp_Object_Type type = Memory::get_type(env->values[i]); | ||||
| Lisp_Object* LOtype; | Lisp_Object* LOtype; | ||||
| try_void LOtype = eval_expr(Memory::create_list( | try_void LOtype = eval_expr(Memory::create_list( | ||||
| Memory::get_or_create_lisp_object_symbol("type"), | |||||
| env->values[i])); | |||||
| Memory::get_or_create_lisp_object_symbol("type"), | |||||
| env->values[i])); | |||||
| fprintf(f, "\n - type :: ="); | fprintf(f, "\n - type :: ="); | ||||
| print(LOtype, true, f); | print(LOtype, true, f); | ||||
| @@ -89,43 +86,43 @@ proc generate_docs(String* path) -> void { | |||||
| Lisp_Object* fun = env->values[i]; | Lisp_Object* fun = env->values[i]; | ||||
| bool printed_at_least_some_args = false; | bool printed_at_least_some_args = false; | ||||
| fprintf(f, "\n - arguments :: "); | fprintf(f, "\n - arguments :: "); | ||||
| if (fun->value.function.positional_arguments->next_index != 0) { | |||||
| if (fun->value.function.args.positional.symbols.next_index != 0) { | |||||
| if (!printed_at_least_some_args) | if (!printed_at_least_some_args) | ||||
| fprintf(f, ":"); | fprintf(f, ":"); | ||||
| fprintf(f, "\n - postitional :: "); | fprintf(f, "\n - postitional :: "); | ||||
| fprintf(f, "=%s=", Memory::get_c_str(fun->value.function.positional_arguments->symbols[0]->value.symbol.identifier)); | |||||
| for (int i = 1; i < fun->value.function.positional_arguments->next_index; ++i) { | |||||
| fprintf(f, ", =%s=", Memory::get_c_str(fun->value.function.positional_arguments->symbols[i]->value.symbol.identifier)); | |||||
| try_void fprintf(f, "=%s=", Memory::get_c_str(fun->value.function.args.positional.symbols.data[0]->value.symbol.identifier)); | |||||
| for (int i = 1; i < fun->value.function.args.positional.symbols.next_index; ++i) { | |||||
| fprintf(f, ", =%s=", Memory::get_c_str(fun->value.function.args.positional.symbols.data[i]->value.symbol.identifier)); | |||||
| } | } | ||||
| } | } | ||||
| if (fun->value.function.keyword_arguments->values->next_index != 0) { | |||||
| if (fun->value.function.args.keyword.values.next_index != 0) { | |||||
| if (!printed_at_least_some_args) | if (!printed_at_least_some_args) | ||||
| fprintf(f, ":"); | fprintf(f, ":"); | ||||
| fprintf(f, "\n - keyword :: "); | fprintf(f, "\n - keyword :: "); | ||||
| fprintf(f, "=%s=", Memory::get_c_str(fun->value.function.keyword_arguments->keywords->data[0]->value.symbol.identifier)); | |||||
| if (fun->value.function.keyword_arguments->values->data[0]) { | |||||
| fprintf(f, "=%s=", Memory::get_c_str(fun->value.function.args.keyword.keywords.data[0]->value.symbol.identifier)); | |||||
| if (fun->value.function.args.keyword.values.data[0]) { | |||||
| fprintf(f, " =("); | fprintf(f, " =("); | ||||
| print(fun->value.function.keyword_arguments->values->data[0], true, f); | |||||
| print(fun->value.function.args.keyword.values.data[0], true, f); | |||||
| fprintf(f, ")="); | fprintf(f, ")="); | ||||
| } | } | ||||
| for (int i = 1; i < fun->value.function.keyword_arguments->values->next_index; ++i) { | |||||
| fprintf(f, ", =%s=", Memory::get_c_str(fun->value.function.keyword_arguments->keywords->data[i]->value.symbol.identifier)); | |||||
| if (fun->value.function.keyword_arguments->values->data[i]) { | |||||
| for (int i = 1; i < fun->value.function.args.keyword.values.next_index; ++i) { | |||||
| fprintf(f, ", =%s=", Memory::get_c_str(fun->value.function.args.keyword.keywords.data[i]->value.symbol.identifier)); | |||||
| if (fun->value.function.args.keyword.values.data[i]) { | |||||
| fprintf(f, " =("); | fprintf(f, " =("); | ||||
| print(fun->value.function.keyword_arguments->values->data[i], true, f); | |||||
| print(fun->value.function.args.keyword.values.data[i], true, f); | |||||
| fprintf(f, ")="); | fprintf(f, ")="); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (fun->value.function.rest_argument) { | |||||
| if (fun->value.function.args.rest) { | |||||
| if (!printed_at_least_some_args) | if (!printed_at_least_some_args) | ||||
| fprintf(f, ":"); | fprintf(f, ":"); | ||||
| fprintf(f, "\n - rest :: =%s=", Memory::get_c_str(fun->value.function.rest_argument)); | |||||
| fprintf(f, "\n - rest :: =%s=", Memory::get_c_str(fun->value.function.args.rest->value.symbol.identifier)); | |||||
| } | } | ||||
| // if no args at all | // if no args at all | ||||
| if (fun->value.function.positional_arguments->next_index == 0 && | |||||
| fun->value.function.keyword_arguments->values->next_index == 0 && | |||||
| !fun->value.function.rest_argument) | |||||
| if (fun->value.function.args.positional.symbols.next_index == 0 && | |||||
| fun->value.function.args.keyword.values.next_index == 0 && | |||||
| !fun->value.function.args.rest) | |||||
| { | { | ||||
| fprintf(f, "none."); | fprintf(f, "none."); | ||||
| } | } | ||||
| @@ -137,22 +134,22 @@ proc generate_docs(String* path) -> void { | |||||
| else | else | ||||
| fprintf(f, "none\n"); | fprintf(f, "none\n"); | ||||
| if (Memory::get_type(env->values[i]) == Lisp_Object_Type::Function && | |||||
| env->values[i]->userType && | |||||
| (string_equal(env->values[i]->userType->value.symbol.identifier, "package") || | |||||
| string_equal(env->values[i]->userType->value.symbol.identifier, "constructor"))) | |||||
| { | |||||
| char new_prefix[200]; | |||||
| strcpy(new_prefix, prefix); | |||||
| strcat(new_prefix, env->keys[i]); | |||||
| strcat(new_prefix, " "); | |||||
| print_this_env(env->values[i]->value.function.parent_environment, new_prefix); | |||||
| } | |||||
| // if (Memory::get_type(env->values[i]) == Lisp_Object_Type::Function && | |||||
| // env->values[i]->userType && | |||||
| // (string_equal(env->values[i]->userType->value.symbol.identifier, "package") || | |||||
| // string_equal(env->values[i]->userType->value.symbol.identifier, "constructor"))) | |||||
| // { | |||||
| // char new_prefix[200]; | |||||
| // strcpy(new_prefix, prefix); | |||||
| // strcat(new_prefix, env->keys[i]); | |||||
| // strcat(new_prefix, " "); | |||||
| // print_this_env(env->values[i]->value.function.parent_environment, new_prefix); | |||||
| // } | |||||
| } | } | ||||
| } | } | ||||
| for (int i = 0; i < env->parents->next_index; ++i) { | |||||
| print_this_env(env->parents->data[i], prefix); | |||||
| for (int i = 0; i < env->parents.next_index; ++i) { | |||||
| print_this_env(env->parents.data[i], prefix); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -31,9 +31,9 @@ proc environment_binds_symbol(String* identifier, Environment* env) -> bool { | |||||
| proc find_binding_environment(String* identifier, Environment* env) -> Environment* { | proc find_binding_environment(String* identifier, Environment* env) -> Environment* { | ||||
| if (environment_binds_symbol(identifier, env)) | if (environment_binds_symbol(identifier, env)) | ||||
| return env; | return env; | ||||
| for (int i = 0; i < env->parents->next_index; ++i) { | |||||
| if (environment_binds_symbol(identifier, env->parents->data[i])) | |||||
| return env->parents->data[i]; | |||||
| for (int i = 0; i < env->parents.next_index; ++i) { | |||||
| if (environment_binds_symbol(identifier, env->parents.data[i])) | |||||
| return env->parents.data[i]; | |||||
| } | } | ||||
| return get_root_environment(); | return get_root_environment(); | ||||
| } | } | ||||
| @@ -46,8 +46,8 @@ proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| if (result) | if (result) | ||||
| return result; | return result; | ||||
| for (int i = 0; i < env->parents->next_index; ++i) { | |||||
| result = try_lookup_symbol(node, env->parents->data[i]); | |||||
| for (int i = 0; i < env->parents.next_index; ++i) { | |||||
| result = try_lookup_symbol(node, env->parents.data[i]); | |||||
| if (result) | if (result) | ||||
| return result; | return result; | ||||
| @@ -65,22 +65,22 @@ proc try_lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| inline proc push_environment(Environment* env) -> void { | inline proc push_environment(Environment* env) -> void { | ||||
| using namespace Globals::Current_Execution; | using namespace Globals::Current_Execution; | ||||
| append_to_array_list(envi_stack, env); | |||||
| append_to_array_list(&envi_stack, env); | |||||
| } | } | ||||
| inline proc pop_environment() -> void { | inline proc pop_environment() -> void { | ||||
| using namespace Globals::Current_Execution; | using namespace Globals::Current_Execution; | ||||
| --envi_stack->next_index; | |||||
| --envi_stack.next_index; | |||||
| } | } | ||||
| inline proc get_root_environment() -> Environment* { | inline proc get_root_environment() -> Environment* { | ||||
| using namespace Globals::Current_Execution; | using namespace Globals::Current_Execution; | ||||
| return envi_stack->data[0]; | |||||
| return envi_stack.data[0]; | |||||
| } | } | ||||
| inline proc get_current_environment() -> Environment* { | inline proc get_current_environment() -> Environment* { | ||||
| using namespace Globals::Current_Execution; | using namespace Globals::Current_Execution; | ||||
| return envi_stack->data[envi_stack->next_index-1]; | |||||
| return envi_stack.data[envi_stack.next_index-1]; | |||||
| } | } | ||||
| proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | ||||
| @@ -115,11 +115,11 @@ proc print_environment_indent(Environment* env, int indent) -> void { | |||||
| printf(" (%lld)", (long long)env->values[i]); | printf(" (%lld)", (long long)env->values[i]); | ||||
| puts(""); | puts(""); | ||||
| } | } | ||||
| for (int i = 0; i < env->parents->next_index; ++i) { | |||||
| for (int i = 0; i < env->parents.next_index; ++i) { | |||||
| print_indent(indent); | print_indent(indent); | ||||
| printf("parent (%lld)", (long long)env->parents->data[i]); | |||||
| printf("parent (%lld)", (long long)env->parents.data[i]); | |||||
| puts(":"); | puts(":"); | ||||
| print_environment_indent(env->parents->data[i], indent+4); | |||||
| print_environment_indent(env->parents.data[i], indent+4); | |||||
| } | } | ||||
| } | } | ||||
| @@ -9,8 +9,10 @@ proc delete_error() -> void { | |||||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { | proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { | ||||
| if (Globals::log_level > Log_Level::None) | |||||
| printf("Error created in:\n%s:%d\n", c_file_name, c_file_line); | |||||
| if (Globals::log_level > Log_Level::None) { | |||||
| printf("Error created in:\n %s:%d\n", c_file_name, c_file_line); | |||||
| printf(" -> %s\n", Memory::get_c_str(message)); | |||||
| } | |||||
| delete_error(); | delete_error(); | ||||
| if (Globals::breaking_on_errors) { | if (Globals::breaking_on_errors) { | ||||
| @@ -9,19 +9,19 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| }; | }; | ||||
| Lisp_Object* sym, *val; // used as temp storage to use `try` | Lisp_Object* sym, *val; // used as temp storage to use `try` | ||||
| String_Array_List* read_in_keywords; | |||||
| String_Array_List read_in_keywords; | |||||
| int obligatory_keywords_count = 0; | int obligatory_keywords_count = 0; | ||||
| int read_obligatory_keywords_count = 0; | int read_obligatory_keywords_count = 0; | ||||
| proc read_positional_args = [&]() -> void { | proc read_positional_args = [&]() -> void { | ||||
| for (int i = 0; i < function->positional_arguments->next_index; ++i) { | |||||
| for (int i = 0; i < function->args.positional.symbols.next_index; ++i) { | |||||
| if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { | if (Memory::get_type(arguments) != Lisp_Object_Type::Pair) { | ||||
| create_wrong_number_of_arguments_error(function->positional_arguments->next_index, i); | |||||
| create_wrong_number_of_arguments_error(function->args.positional.symbols.next_index, i); | |||||
| return; | return; | ||||
| } | } | ||||
| // NOTE(Felix): We have to copy all the arguments, otherwise | // NOTE(Felix): We have to copy all the arguments, otherwise | ||||
| // we change the program code. | // we change the program code. | ||||
| try_void sym = function->positional_arguments->symbols[i]; | |||||
| try_void sym = function->args.positional.symbols.data[i]; | |||||
| define_symbol( | define_symbol( | ||||
| sym, | sym, | ||||
| Memory::copy_lisp_object_except_pairs(arguments->value.pair.first)); | Memory::copy_lisp_object_except_pairs(arguments->value.pair.first)); | ||||
| @@ -41,8 +41,8 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| return; | return; | ||||
| // find out how many keyword args we /have/ to read | // find out how many keyword args we /have/ to read | ||||
| for (int i = 0; i < function->keyword_arguments->values->next_index; ++i) { | |||||
| if (function->keyword_arguments->values->data[i] == nullptr) | |||||
| for (int i = 0; i < function->args.keyword.values.next_index; ++i) { | |||||
| if (function->args.keyword.values.data[i] == nullptr) | |||||
| ++obligatory_keywords_count; | ++obligatory_keywords_count; | ||||
| else | else | ||||
| break; | break; | ||||
| @@ -52,10 +52,10 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| while (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { | while (Memory::get_type(arguments->value.pair.first) == Lisp_Object_Type::Keyword) { | ||||
| // check if this one is even an accepted keyword | // check if this one is even an accepted keyword | ||||
| bool accepted = false; | bool accepted = false; | ||||
| for (int i = 0; i < function->keyword_arguments->values->next_index; ++i) { | |||||
| for (int i = 0; i < function->args.keyword.values.next_index; ++i) { | |||||
| if (string_equal( | if (string_equal( | ||||
| arguments->value.pair.first->value.symbol.identifier, | arguments->value.pair.first->value.symbol.identifier, | ||||
| function->keyword_arguments->keywords->data[i]->value.symbol.identifier)) | |||||
| function->args.keyword.keywords.data[i]->value.symbol.identifier)) | |||||
| { | { | ||||
| accepted = true; | accepted = true; | ||||
| break; | break; | ||||
| @@ -77,10 +77,10 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| } | } | ||||
| // check if it was already read in | // check if it was already read in | ||||
| for (int i = 0; i < read_in_keywords->next_index; ++i) { | |||||
| for (int i = 0; i < read_in_keywords.next_index; ++i) { | |||||
| if (string_equal( | if (string_equal( | ||||
| arguments->value.pair.first->value.symbol.identifier, | arguments->value.pair.first->value.symbol.identifier, | ||||
| read_in_keywords->data[i])) | |||||
| read_in_keywords.data[i])) | |||||
| { | { | ||||
| // NOTE(Felix): if we are actually done with all the | // NOTE(Felix): if we are actually done with all the | ||||
| // necessary keywords then we have to count the rest | // necessary keywords then we have to count the rest | ||||
| @@ -112,7 +112,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| sym, | sym, | ||||
| Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first)); | Memory::copy_lisp_object_except_pairs(arguments->value.pair.rest->value.pair.first)); | ||||
| append_to_array_list(read_in_keywords, arguments->value.pair.first->value.symbol.identifier); | |||||
| append_to_array_list(&read_in_keywords, arguments->value.pair.first->value.symbol.identifier); | |||||
| ++read_obligatory_keywords_count; | ++read_obligatory_keywords_count; | ||||
| // overstep both for next one | // overstep both for next one | ||||
| @@ -126,20 +126,20 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| proc check_keyword_args = [&]() -> void { | proc check_keyword_args = [&]() -> void { | ||||
| // check if all necessary keywords have been read in | // check if all necessary keywords have been read in | ||||
| for (int i = 0; i < function->keyword_arguments->values->next_index; ++i) { | |||||
| String* defined_keyword = function->keyword_arguments->keywords->data[i]->value.symbol.identifier; | |||||
| for (int i = 0; i < function->args.keyword.values.next_index; ++i) { | |||||
| String* defined_keyword = function->args.keyword.keywords.data[i]->value.symbol.identifier; | |||||
| bool was_set = false; | bool was_set = false; | ||||
| for (int j = 0; j < read_in_keywords->next_index; ++j) { | |||||
| for (int j = 0; j < read_in_keywords.next_index; ++j) { | |||||
| // TODO(Felix): Later compare the keywords, not their strings!! | // TODO(Felix): Later compare the keywords, not their strings!! | ||||
| if (string_equal( | if (string_equal( | ||||
| read_in_keywords->data[j], | |||||
| read_in_keywords.data[j], | |||||
| defined_keyword)) | defined_keyword)) | ||||
| { | { | ||||
| was_set = true; | was_set = true; | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| if (function->keyword_arguments->values->data[i] == nullptr) { | |||||
| if (function->args.keyword.values.data[i] == nullptr) { | |||||
| // if this one does not have a default value | // if this one does not have a default value | ||||
| if (!was_set) { | if (!was_set) { | ||||
| create_generic_error( | create_generic_error( | ||||
| @@ -153,7 +153,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| // to use it or if the user supplied his own | // to use it or if the user supplied his own | ||||
| if (!was_set) { | if (!was_set) { | ||||
| try_void sym = Memory::get_or_create_lisp_object_symbol(defined_keyword); | try_void sym = Memory::get_or_create_lisp_object_symbol(defined_keyword); | ||||
| try_void val = Memory::copy_lisp_object_except_pairs(function->keyword_arguments->values->data[i]); | |||||
| try_void val = Memory::copy_lisp_object_except_pairs(function->args.keyword.values.data[i]); | |||||
| define_symbol(sym, val); | define_symbol(sym, val); | ||||
| } | } | ||||
| } | } | ||||
| @@ -162,13 +162,13 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| proc read_rest_arg = [&]() -> void { | proc read_rest_arg = [&]() -> void { | ||||
| if (arguments == Memory::nil) { | if (arguments == Memory::nil) { | ||||
| if (function->rest_argument) { | |||||
| define_symbol(function->rest_argument, Memory::nil); | |||||
| if (function->args.rest) { | |||||
| define_symbol(function->args.rest, Memory::nil); | |||||
| } | } | ||||
| } else { | } else { | ||||
| if (function->rest_argument) { | |||||
| if (function->args.rest) { | |||||
| define_symbol( | define_symbol( | ||||
| function->rest_argument, | |||||
| function->args.rest, | |||||
| // NOTE(Felix): arguments will be a list, and I THINK | // NOTE(Felix): arguments will be a list, and I THINK | ||||
| // we do not need to copy it... | // we do not need to copy it... | ||||
| arguments); | arguments); | ||||
| @@ -201,9 +201,9 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| */ | */ | ||||
| proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | ||||
| // first init the fields | // first init the fields | ||||
| function->positional_arguments = create_positional_argument_list(16); | |||||
| function->keyword_arguments = create_keyword_argument_list(16); | |||||
| function->rest_argument = nullptr; | |||||
| function->args.positional = create_positional_argument_list(16); | |||||
| function->args.keyword = create_keyword_argument_list(16); | |||||
| function->args.rest = nullptr; | |||||
| // okay let's try to read some positional arguments | // okay let's try to read some positional arguments | ||||
| while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { | while (Memory::get_type(arguments) == Lisp_Object_Type::Pair) { | ||||
| @@ -228,7 +228,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||||
| // okay wow we found an actual symbol | // okay wow we found an actual symbol | ||||
| append_to_positional_argument_list( | append_to_positional_argument_list( | ||||
| function->positional_arguments, | |||||
| &function->args.positional, | |||||
| arguments->value.pair.first); | arguments->value.pair.first); | ||||
| arguments = arguments->value.pair.rest; | arguments = arguments->value.pair.rest; | ||||
| @@ -294,7 +294,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||||
| pop_environment(); | pop_environment(); | ||||
| }; | }; | ||||
| try_void ret = eval_expr(next->value.pair.first); | try_void ret = eval_expr(next->value.pair.first); | ||||
| append_to_keyword_argument_list(function->keyword_arguments, | |||||
| append_to_keyword_argument_list(&function->args.keyword, | |||||
| arguments->value.pair.first, | arguments->value.pair.first, | ||||
| ret); | ret); | ||||
| arguments = next->value.pair.rest; | arguments = next->value.pair.rest; | ||||
| @@ -304,7 +304,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||||
| } | } | ||||
| } else { | } else { | ||||
| // No :defaults-to, so just add it to the list | // No :defaults-to, so just add it to the list | ||||
| append_to_keyword_argument_list(function->keyword_arguments, | |||||
| append_to_keyword_argument_list(&function->args.keyword, | |||||
| arguments->value.pair.first, | arguments->value.pair.first, | ||||
| nullptr); | nullptr); | ||||
| arguments = next; | arguments = next; | ||||
| @@ -331,7 +331,7 @@ proc parse_argument_list(Lisp_Object* arguments, Function* function) -> void { | |||||
| create_parsing_error("After the 'rest' marker there must follow a symbol."); | create_parsing_error("After the 'rest' marker there must follow a symbol."); | ||||
| return; | return; | ||||
| } | } | ||||
| function->rest_argument = arguments->value.pair.first; | |||||
| function->args.rest = arguments->value.pair.first; | |||||
| if (arguments->value.pair.rest != Memory::nil) { | if (arguments->value.pair.rest != Memory::nil) { | ||||
| create_parsing_error("The lambda list must end after the rest symbol"); | create_parsing_error("The lambda list must end after the rest symbol"); | ||||
| } | } | ||||
| @@ -362,6 +362,7 @@ proc list_length(Lisp_Object* node) -> int { | |||||
| } | } | ||||
| proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_Object* { | proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_Object* { | ||||
| profile_this; | |||||
| int my_out_arguments_length = 0; | int my_out_arguments_length = 0; | ||||
| if (arguments == Memory::nil) { | if (arguments == Memory::nil) { | ||||
| *(out_arguments_length) = 0; | *(out_arguments_length) = 0; | ||||
| @@ -396,15 +397,17 @@ proc eval_arguments(Lisp_Object* arguments, int *out_arguments_length) -> Lisp_O | |||||
| } | } | ||||
| proc eval_expr(Lisp_Object* node) -> Lisp_Object* { | proc eval_expr(Lisp_Object* node) -> Lisp_Object* { | ||||
| profile_this; | |||||
| using namespace Globals::Current_Execution; | using namespace Globals::Current_Execution; | ||||
| append_to_array_list(call_stack, node); | |||||
| append_to_array_list(&call_stack, node); | |||||
| defer { | defer { | ||||
| // NOTE(Felix): We only delete the current entry from the call | // NOTE(Felix): We only delete the current entry from the call | ||||
| // stack, if we did not encounter an error, otherwise we neet | // stack, if we did not encounter an error, otherwise we neet | ||||
| // to preserve the callstack to print it later. it will be | // to preserve the callstack to print it later. it will be | ||||
| // cleared in log_error(). | // cleared in log_error(). | ||||
| if (!Globals::error) | if (!Globals::error) | ||||
| --call_stack->next_index; | |||||
| --call_stack.next_index; | |||||
| }; | }; | ||||
| switch (Memory::get_type(node)) { | switch (Memory::get_type(node)) { | ||||
| @@ -39,14 +39,18 @@ namespace Parser { | |||||
| } | } | ||||
| namespace Globals { | namespace Globals { | ||||
| char* bin_path = nullptr; | |||||
| Log_Level log_level = Log_Level::Debug; | Log_Level log_level = Log_Level::Debug; | ||||
| namespace Current_Execution { | namespace Current_Execution { | ||||
| Lisp_Object_Array_List* call_stack = create_Lisp_Object_array_list(); | |||||
| Environment_Array_List* envi_stack = create_Environment_array_list(); | |||||
| Lisp_Object_Array_List call_stack = create_Lisp_Object_array_list(); | |||||
| Environment_Array_List envi_stack = create_Environment_array_list(); | |||||
| } | } | ||||
| #ifdef _DONT_BREAK_ON_ERRORS | |||||
| bool breaking_on_errors = false; | |||||
| #else | |||||
| bool breaking_on_errors = true; | bool breaking_on_errors = true; | ||||
| #endif | |||||
| Error* error = nullptr; | Error* error = nullptr; | ||||
| } | } | ||||
| @@ -3,10 +3,10 @@ namespace GC { | |||||
| int current_mark; | int current_mark; | ||||
| Lisp_Object_Array_List* marked_objects; | |||||
| String_Array_List* marked_strings; | |||||
| Environment_Array_List* marked_environments; | |||||
| Environment_Array_List* protected_environments; | |||||
| Lisp_Object_Array_List marked_objects; | |||||
| String_Array_List marked_strings; | |||||
| Environment_Array_List marked_environments; | |||||
| Environment_Array_List protected_environments; | |||||
| proc marked(Lisp_Object* node) -> bool { | proc marked(Lisp_Object* node) -> bool { | ||||
| return false; | return false; | ||||
| @@ -20,8 +20,14 @@ namespace GC { | |||||
| if (marked(node)) | if (marked(node)) | ||||
| return; | return; | ||||
| append_to_array_list(marked_objects, node); | |||||
| // mark object itself | |||||
| append_to_array_list(&marked_objects, node); | |||||
| // mark docstring | |||||
| if (node->docstring) | |||||
| append_to_array_list(&marked_strings, node->docstring); | |||||
| // mark type specific data | |||||
| switch (Memory::get_type(node)) { | switch (Memory::get_type(node)) { | ||||
| case Lisp_Object_Type::Pair: { | case Lisp_Object_Type::Pair: { | ||||
| for_lisp_list (node) { | for_lisp_list (node) { | ||||
| @@ -34,11 +40,18 @@ namespace GC { | |||||
| } | } | ||||
| } break; | } break; | ||||
| case Lisp_Object_Type::String: { | case Lisp_Object_Type::String: { | ||||
| append_to_array_list(marked_strings, node->value.string); | |||||
| append_to_array_list(&marked_strings, node->value.string); | |||||
| } break; | } break; | ||||
| case Lisp_Object_Type::Function: { | case Lisp_Object_Type::Function: { | ||||
| // NOTE(Felix): We dont have to mark the symbols, keywords | |||||
| // for parameter names, as symbols and keywords are never | |||||
| // garbage collected | |||||
| maybe_mark(node->value.function.parent_environment); | maybe_mark(node->value.function.parent_environment); | ||||
| maybe_mark(node->value.function.body); | maybe_mark(node->value.function.body); | ||||
| // mark the default arguemnt values: | |||||
| for_array_list (node->value.function.args.keyword.values) { | |||||
| if (it) maybe_mark(it); | |||||
| } | |||||
| } break; | } break; | ||||
| } | } | ||||
| @@ -48,7 +61,7 @@ namespace GC { | |||||
| if (marked(env)) | if (marked(env)) | ||||
| return; | return; | ||||
| append_to_array_list(marked_environments, env); | |||||
| append_to_array_list(&marked_environments, env); | |||||
| for_array_list (env->parents) { | for_array_list (env->parents) { | ||||
| maybe_mark(it); | maybe_mark(it); | ||||
| @@ -66,7 +79,6 @@ namespace GC { | |||||
| for_array_list (protected_environments) maybe_mark(it); | for_array_list (protected_environments) maybe_mark(it); | ||||
| for_array_list (Globals::Current_Execution::envi_stack) maybe_mark(it); | for_array_list (Globals::Current_Execution::envi_stack) maybe_mark(it); | ||||
| } | } | ||||
| proc gc_init_and_go() -> void { | proc gc_init_and_go() -> void { | ||||
| @@ -393,10 +393,10 @@ proc print_single_call(Lisp_Object* obj) -> void { | |||||
| proc print_call_stack() -> void { | proc print_call_stack() -> void { | ||||
| using Globals::Current_Execution::call_stack; | using Globals::Current_Execution::call_stack; | ||||
| printf("callstack [%d] (most recent call last):\n", call_stack->next_index); | |||||
| for (int i = 0; i < call_stack->next_index; ++i) { | |||||
| printf("callstack [%d] (most recent call last):\n", call_stack.next_index); | |||||
| for (int i = 0; i < call_stack.next_index; ++i) { | |||||
| printf("%2d -> ", i); | printf("%2d -> ", i); | ||||
| print_single_call(call_stack->data[i]); | |||||
| print_single_call(call_stack.data[i]); | |||||
| printf("\n"); | printf("\n"); | ||||
| } | } | ||||
| } | } | ||||
| @@ -410,5 +410,5 @@ proc log_error() -> void { | |||||
| print_call_stack(); | print_call_stack(); | ||||
| puts(console_normal); | puts(console_normal); | ||||
| Globals::Current_Execution::call_stack->next_index = 0; | |||||
| Globals::Current_Execution::call_stack.next_index = 0; | |||||
| } | } | ||||
| @@ -26,26 +26,20 @@ proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char* { | |||||
| return "unknown"; | return "unknown"; | ||||
| } | } | ||||
| proc create_positional_argument_list(int initial_capacity) -> Positional_Arguments* { | |||||
| Positional_Arguments* ret = new(Positional_Arguments); | |||||
| ret->symbols = (Lisp_Object**)malloc(initial_capacity * sizeof(Lisp_Object*)); | |||||
| ret->next_index = 0; | |||||
| ret->length = initial_capacity; | |||||
| proc create_positional_argument_list(int initial_capacity) -> Positional_Arguments { | |||||
| Positional_Arguments ret; | |||||
| ret.symbols = create_Lisp_Object_array_list(initial_capacity); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| proc append_to_positional_argument_list(Positional_Arguments* args, Lisp_Object* sym) -> void { | proc append_to_positional_argument_list(Positional_Arguments* args, Lisp_Object* sym) -> void { | ||||
| if (args->next_index == args->length) { | |||||
| args->length *= 2; | |||||
| args->symbols = (Lisp_Object**)realloc(args->symbols, args->length * sizeof(Lisp_Object*)); | |||||
| } | |||||
| args->symbols[args->next_index++] = sym; | |||||
| append_to_array_list(&args->symbols, sym); | |||||
| } | } | ||||
| proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments* { | |||||
| Keyword_Arguments* ret = new(Keyword_Arguments); | |||||
| ret->keywords = create_Lisp_Object_array_list(initial_capacity); | |||||
| ret->values = create_Lisp_Object_array_list(initial_capacity); | |||||
| proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments { | |||||
| Keyword_Arguments ret; | |||||
| ret.keywords = create_Lisp_Object_array_list(initial_capacity); | |||||
| ret.values = create_Lisp_Object_array_list(initial_capacity); | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -53,6 +47,6 @@ proc append_to_keyword_argument_list(Keyword_Arguments* args, | |||||
| Lisp_Object* keyword, | Lisp_Object* keyword, | ||||
| Lisp_Object* default_value) -> void | Lisp_Object* default_value) -> void | ||||
| { | { | ||||
| append_to_array_list(args->keywords, keyword); | |||||
| append_to_array_list(args->values, default_value); | |||||
| append_to_array_list(&args->keywords, keyword); | |||||
| append_to_array_list(&args->values, default_value); | |||||
| } | } | ||||
| @@ -3,7 +3,9 @@ | |||||
| 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")) { | if (Slime::string_equal(argv[1], "--run-tests")) { | ||||
| return Slime::run_all_tests() ? 0 : 1; | |||||
| int res = Slime::run_all_tests(); | |||||
| Slime::interprete_file("generate-docs.slime"); | |||||
| return res ? 0 : 1; | |||||
| } | } | ||||
| Slime::interprete_file(argv[1]); | Slime::interprete_file(argv[1]); | ||||
| @@ -4,7 +4,7 @@ namespace Memory { | |||||
| // lisp_objects | // lisp_objects | ||||
| // ------------------ | // ------------------ | ||||
| int object_memory_size; | int object_memory_size; | ||||
| Int_Array_List* free_spots_in_object_memory; | |||||
| Int_Array_List free_spots_in_object_memory; | |||||
| Lisp_Object* object_memory; | Lisp_Object* object_memory; | ||||
| int next_index_in_object_memory = 0; | int next_index_in_object_memory = 0; | ||||
| @@ -12,7 +12,7 @@ namespace Memory { | |||||
| // environments | // environments | ||||
| // ------------------ | // ------------------ | ||||
| int environment_memory_size; | int environment_memory_size; | ||||
| Int_Array_List* free_spots_in_environment_memory; | |||||
| Int_Array_List free_spots_in_environment_memory; | |||||
| Environment* environment_memory; | Environment* environment_memory; | ||||
| int next_index_in_environment_memory = 0; | int next_index_in_environment_memory = 0; | ||||
| @@ -23,7 +23,7 @@ namespace Memory { | |||||
| // free_spots_in_string_memory is an arraylist of pointers into | // free_spots_in_string_memory is an arraylist of pointers into | ||||
| // the string_memory, where dead String objects live (which give | // the string_memory, where dead String objects live (which give | ||||
| // information about their size) | // information about their size) | ||||
| Void_Ptr_Array_List* free_spots_in_string_memory; | |||||
| Void_Ptr_Array_List free_spots_in_string_memory; | |||||
| String* string_memory; | String* string_memory; | ||||
| String* next_free_spot_in_string_memory; | String* next_free_spot_in_string_memory; | ||||
| @@ -38,15 +38,15 @@ namespace Memory { | |||||
| " - %f%% of the object_memory is used\n" | " - %f%% of the object_memory is used\n" | ||||
| " - %d of %d total Lisp_Objects are in use\n" | " - %d of %d total Lisp_Objects are in use\n" | ||||
| " - %d holes in used memory (fragmentation)\n", | " - %d holes in used memory (fragmentation)\n", | ||||
| (1.0*next_index_in_object_memory - free_spots_in_object_memory->next_index)/object_memory_size, | |||||
| next_index_in_object_memory - free_spots_in_object_memory->next_index, object_memory_size, | |||||
| free_spots_in_object_memory->next_index); | |||||
| (1.0*next_index_in_object_memory - free_spots_in_object_memory.next_index)/object_memory_size, | |||||
| next_index_in_object_memory - free_spots_in_object_memory.next_index, object_memory_size, | |||||
| free_spots_in_object_memory.next_index); | |||||
| printf("Memory Status:\n" | printf("Memory Status:\n" | ||||
| " - %f%% of the string_memory is used\n" | " - %f%% of the string_memory is used\n" | ||||
| " - %d holes in used memory (fragmentation)\n", | " - %d holes in used memory (fragmentation)\n", | ||||
| (1.0*(size_t)next_free_spot_in_string_memory - (size_t)string_memory)/string_memory_size, | (1.0*(size_t)next_free_spot_in_string_memory - (size_t)string_memory)/string_memory_size, | ||||
| free_spots_in_string_memory->next_index); | |||||
| free_spots_in_string_memory.next_index); | |||||
| } | } | ||||
| inline proc get_c_str(String* str) -> char* { | inline proc get_c_str(String* str) -> char* { | ||||
| @@ -106,7 +106,7 @@ namespace Memory { | |||||
| } | } | ||||
| proc delete_string(String* str) { | proc delete_string(String* str) { | ||||
| append_to_array_list(free_spots_in_string_memory, (void*)str); | |||||
| append_to_array_list(&free_spots_in_string_memory, (void*)str); | |||||
| } | } | ||||
| proc duplicate_string(String* str) -> String* { | proc duplicate_string(String* str) -> String* { | ||||
| @@ -136,7 +136,7 @@ namespace Memory { | |||||
| proc create_lisp_object() -> Lisp_Object* { | proc create_lisp_object() -> Lisp_Object* { | ||||
| int index; | int index; | ||||
| // if we have no free spots then append at the end | // if we have no free spots then append at the end | ||||
| if (free_spots_in_object_memory->next_index == 0) { | |||||
| if (free_spots_in_object_memory.next_index == 0) { | |||||
| // if we still have space | // if we still have space | ||||
| if (object_memory_size == next_index_in_object_memory) { | if (object_memory_size == next_index_in_object_memory) { | ||||
| create_out_of_memory_error( | create_out_of_memory_error( | ||||
| @@ -149,7 +149,7 @@ namespace Memory { | |||||
| index = next_index_in_object_memory++; | index = next_index_in_object_memory++; | ||||
| } else { | } else { | ||||
| // else fill a free spot, and remove the free spot | // else fill a free spot, and remove the free spot | ||||
| index = free_spots_in_object_memory->data[free_spots_in_object_memory->next_index--]; | |||||
| index = free_spots_in_object_memory.data[free_spots_in_object_memory.next_index--]; | |||||
| } | } | ||||
| Lisp_Object* object = object_memory+index; | Lisp_Object* object = object_memory+index; | ||||
| object->flags = 0; | object->flags = 0; | ||||
| @@ -184,22 +184,22 @@ namespace Memory { | |||||
| try_void Parser::standard_in = create_string("stdin"); | try_void Parser::standard_in = create_string("stdin"); | ||||
| try_void Globals::Current_Execution::envi_stack->data[0] = create_built_ins_environment(); | |||||
| try_void Globals::Current_Execution::envi_stack->next_index = 1; | |||||
| try_void Globals::Current_Execution::envi_stack.data[0] = create_built_ins_environment(); | |||||
| try_void Globals::Current_Execution::envi_stack.next_index = 1; | |||||
| } | } | ||||
| proc reset() -> void { | proc reset() -> void { | ||||
| free_spots_in_object_memory->next_index = 0; | |||||
| free_spots_in_environment_memory->next_index = 0; | |||||
| free_spots_in_string_memory->next_index = 0; | |||||
| free_spots_in_object_memory.next_index = 0; | |||||
| free_spots_in_environment_memory.next_index = 0; | |||||
| free_spots_in_string_memory.next_index = 0; | |||||
| // because t and nil are always there we start the index at 2 | // because t and nil are always there we start the index at 2 | ||||
| next_index_in_object_memory = 2; | next_index_in_object_memory = 2; | ||||
| next_index_in_environment_memory = 0; | next_index_in_environment_memory = 0; | ||||
| next_free_spot_in_string_memory = string_memory; | next_free_spot_in_string_memory = string_memory; | ||||
| try_void Globals::Current_Execution::envi_stack->data[0] = create_built_ins_environment(); | |||||
| try_void Globals::Current_Execution::envi_stack->next_index = 1; | |||||
| try_void Globals::Current_Execution::envi_stack.data[0] = create_built_ins_environment(); | |||||
| try_void Globals::Current_Execution::envi_stack.next_index = 1; | |||||
| } | } | ||||
| proc create_lisp_object_number(double number) -> Lisp_Object* { | proc create_lisp_object_number(double number) -> Lisp_Object* { | ||||
| @@ -353,7 +353,7 @@ namespace Memory { | |||||
| int index; | int index; | ||||
| // if we have no free spots then append at the end | // if we have no free spots then append at the end | ||||
| if (free_spots_in_environment_memory->next_index == 0) { | |||||
| if (free_spots_in_environment_memory.next_index == 0) { | |||||
| // if we still have space | // if we still have space | ||||
| if (environment_memory_size == next_index_in_environment_memory) { | if (environment_memory_size == next_index_in_environment_memory) { | ||||
| create_out_of_memory_error( | create_out_of_memory_error( | ||||
| @@ -366,7 +366,7 @@ namespace Memory { | |||||
| index = next_index_in_environment_memory++; | index = next_index_in_environment_memory++; | ||||
| } else { | } else { | ||||
| // else fill a free spot, and remove the free spot | // else fill a free spot, and remove the free spot | ||||
| index = free_spots_in_environment_memory->data[free_spots_in_environment_memory->next_index--]; | |||||
| index = free_spots_in_environment_memory.data[free_spots_in_environment_memory.next_index--]; | |||||
| } | } | ||||
| @@ -376,7 +376,7 @@ namespace Memory { | |||||
| env->parents = create_Environment_array_list(); | env->parents = create_Environment_array_list(); | ||||
| if (parent) | if (parent) | ||||
| append_to_array_list(env->parents, parent); | |||||
| append_to_array_list(&env->parents, parent); | |||||
| env->capacity = start_capacity; | env->capacity = start_capacity; | ||||
| env->next_index = 0; | env->next_index = 0; | ||||
| @@ -402,17 +402,17 @@ namespace Memory { | |||||
| load_built_ins_into_environment(); | load_built_ins_into_environment(); | ||||
| // save the current working directory | |||||
| char* cwd = get_cwd(); | |||||
| defer { | |||||
| change_cwd(cwd); | |||||
| free(cwd); | |||||
| }; | |||||
| // get the direction of the exe | |||||
| char* exe_path = get_exe_dir(); | |||||
| change_cwd(exe_path); | |||||
| free(exe_path); | |||||
| // // save the current working directory | |||||
| // char* cwd = get_cwd(); | |||||
| // defer { | |||||
| // change_cwd(cwd); | |||||
| // free(cwd); | |||||
| // }; | |||||
| // // get the direction of the exe | |||||
| // char* exe_path = get_exe_dir(); | |||||
| // change_cwd(exe_path); | |||||
| // free(exe_path); | |||||
| built_in_load(Memory::create_string("pre.slime")); | built_in_load(Memory::create_string("pre.slime")); | ||||
| @@ -403,9 +403,9 @@ namespace Parser { | |||||
| try assert_type(arguments, Lisp_Object_Type::Pair); | try assert_type(arguments, Lisp_Object_Type::Pair); | ||||
| try parse_argument_list(arguments, ¯o->value.function); | try parse_argument_list(arguments, ¯o->value.function); | ||||
| } else { | } else { | ||||
| macro->value.function.positional_arguments = create_positional_argument_list(1); | |||||
| macro->value.function.keyword_arguments = create_keyword_argument_list(1); | |||||
| macro->value.function.rest_argument = nullptr; | |||||
| macro->value.function.args.positional = create_positional_argument_list(1); | |||||
| macro->value.function.args.keyword = create_keyword_argument_list(1); | |||||
| macro->value.function.args.rest = nullptr; | |||||
| } | } | ||||
| // arguments = arguments->value.pair.rest; | // arguments = arguments->value.pair.rest; | ||||
| @@ -556,7 +556,7 @@ namespace Parser { | |||||
| } | } | ||||
| proc write_expanded_file(String* file_name, Lisp_Object_Array_List* program) -> void { | |||||
| proc write_expanded_file(String* file_name, Lisp_Object_Array_List program) -> void { | |||||
| const char* ext = ".expanded"; | const char* ext = ".expanded"; | ||||
| char* newName = (char*)calloc(10 + file_name->length, sizeof(char)); | char* newName = (char*)calloc(10 + file_name->length, sizeof(char)); | ||||
| strcpy(newName, Memory::get_c_str(file_name)); | strcpy(newName, Memory::get_c_str(file_name)); | ||||
| @@ -573,21 +573,21 @@ namespace Parser { | |||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| for (int i = 0; i < program->next_index; ++i) { | |||||
| for (int i = 0; i < program.next_index; ++i) { | |||||
| // a macro will parse as nil for now, so we skip those | // a macro will parse as nil for now, so we skip those | ||||
| if (program->data[i] == Memory::nil) | |||||
| if (program.data[i] == Memory::nil) | |||||
| continue; | continue; | ||||
| print(program->data[i], true, f); | |||||
| print(program.data[i], true, f); | |||||
| fprintf(f, "\n\n"); | fprintf(f, "\n\n"); | ||||
| } | } | ||||
| } | } | ||||
| proc parse_program(String* file_name, char* text) -> Lisp_Object_Array_List* { | |||||
| proc parse_program(String* file_name, char* text) -> Lisp_Object_Array_List { | |||||
| parser_file = file_name; | parser_file = file_name; | ||||
| parser_line = 1; | parser_line = 1; | ||||
| parser_col = 0; | parser_col = 0; | ||||
| Lisp_Object_Array_List* program = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List program = create_Lisp_Object_array_list(); | |||||
| int index_in_text = 0; | int index_in_text = 0; | ||||
| @@ -595,10 +595,10 @@ namespace Parser { | |||||
| switch (text[index_in_text]) { | switch (text[index_in_text]) { | ||||
| case '(': { | case '(': { | ||||
| Lisp_Object* parsed; | Lisp_Object* parsed; | ||||
| try { | |||||
| try_struct { | |||||
| parsed = parse_expression(text, &index_in_text); | parsed = parse_expression(text, &index_in_text); | ||||
| } | } | ||||
| append_to_array_list(program, parsed); | |||||
| append_to_array_list(&program, parsed); | |||||
| } break; | } break; | ||||
| case ';': | case ';': | ||||
| case ' ': | case ' ': | ||||
| @@ -611,7 +611,7 @@ namespace Parser { | |||||
| /* syntax error */ | /* syntax error */ | ||||
| create_parsing_error("Garbage in file scope at %s:%d:%d", | create_parsing_error("Garbage in file scope at %s:%d:%d", | ||||
| parser_file, parser_line, parser_col); | parser_file, parser_line, parser_col); | ||||
| return nullptr; | |||||
| return {}; | |||||
| } | } | ||||
| } | } | ||||
| @@ -32,7 +32,6 @@ namespace Slime { | |||||
| # include "./platform.cpp" | # include "./platform.cpp" | ||||
| # include "./structs.cpp" | # include "./structs.cpp" | ||||
| # include "./forward_decls.cpp" | # include "./forward_decls.cpp" | ||||
| # include "./profiler.cpp" | |||||
| # include "./memory.cpp" | # include "./memory.cpp" | ||||
| # include "./gc.cpp" | # include "./gc.cpp" | ||||
| # include "./lisp_object.cpp" | # include "./lisp_object.cpp" | ||||
| @@ -8,7 +8,6 @@ define_array_list(String*, String); | |||||
| define_array_list(int, Int); | define_array_list(int, Int); | ||||
| define_array_list(void*, Void_Ptr); | define_array_list(void*, Void_Ptr); | ||||
| enum struct Thread_Type { | enum struct Thread_Type { | ||||
| Main, | Main, | ||||
| GarbageCollection | GarbageCollection | ||||
| @@ -91,37 +90,40 @@ struct Vector { | |||||
| }; | }; | ||||
| struct Positional_Arguments { | struct Positional_Arguments { | ||||
| Lisp_Object** symbols; // Array of Pointers to Lisp_Object<Symbol> | |||||
| int next_index; | |||||
| int length; | |||||
| Lisp_Object_Array_List symbols; | |||||
| }; | }; | ||||
| struct Keyword_Arguments { | struct Keyword_Arguments { | ||||
| // Array of Pointers to Lisp_Object<Keyword> | // Array of Pointers to Lisp_Object<Keyword> | ||||
| Lisp_Object_Array_List* keywords; | |||||
| Lisp_Object_Array_List keywords; | |||||
| // NOTE(Felix): values[i] will be nullptr if no defalut value was | // NOTE(Felix): values[i] will be nullptr if no defalut value was | ||||
| // declared for key identifiers[i] | // declared for key identifiers[i] | ||||
| Lisp_Object_Array_List* values; | |||||
| Lisp_Object_Array_List values; | |||||
| }; | }; | ||||
| struct Arguments { | struct Arguments { | ||||
| Positional_Arguments positional; | |||||
| Keyword_Arguments keyword; | |||||
| // NOTE(Felix): rest_argument will be nullptr if no rest argument | // NOTE(Felix): rest_argument will be nullptr if no rest argument | ||||
| // is declared otherwise its a symbol | // is declared otherwise its a symbol | ||||
| Lisp_Object* rest_argument; | |||||
| Keyword_Arguments keyword_arguments; | |||||
| Positional_Arguments positional_arguments; | |||||
| Lisp_Object* rest; | |||||
| }; | }; | ||||
| struct Environment { | |||||
| Environment_Array_List parents; | |||||
| int capacity; | |||||
| int next_index; | |||||
| // TODO(Felix): Use a hashmap here. | |||||
| char** keys; | |||||
| Lisp_Object** values; | |||||
| }; | |||||
| struct Function { | struct Function { | ||||
| Function_Type type; | Function_Type type; | ||||
| Positional_Arguments* positional_arguments; | |||||
| Keyword_Arguments* keyword_arguments; | |||||
| // NOTE(Felix): rest_argument will be nullptr if no rest argument | |||||
| // is declared otherwise its a symbol | |||||
| Lisp_Object* rest_argument; | |||||
| Arguments args; | |||||
| Lisp_Object* body; // implicit begin | Lisp_Object* body; // implicit begin | ||||
| Environment* parent_environment; // we are doing closures now!! | |||||
| Environment* parent_environment; // we are doing closures now!! | |||||
| }; | }; | ||||
| struct cFunction { | struct cFunction { | ||||
| @@ -131,7 +133,7 @@ struct cFunction { | |||||
| struct Lisp_Object { | struct Lisp_Object { | ||||
| Source_Code_Location* sourceCodeLocation; | Source_Code_Location* sourceCodeLocation; | ||||
| u64 flags; | u64 flags; | ||||
| Lisp_Object* userType; | |||||
| Lisp_Object* userType; // keyword | |||||
| String* docstring; | String* docstring; | ||||
| union { | union { | ||||
| Symbol symbol; // used for symbols and keywords | Symbol symbol; // used for symbols and keywords | ||||
| @@ -145,16 +147,6 @@ struct Lisp_Object { | |||||
| } value; | } value; | ||||
| }; | }; | ||||
| struct Environment { | |||||
| Environment_Array_List* parents; | |||||
| int capacity; | |||||
| int next_index; | |||||
| // TODO(Felix): Use a hashmap here. | |||||
| char** keys; | |||||
| Lisp_Object** values; | |||||
| }; | |||||
| struct Error { | struct Error { | ||||
| Lisp_Object* position; | Lisp_Object* position; | ||||
| // type has to be a keyword | // type has to be a keyword | ||||
| @@ -115,79 +115,79 @@ | |||||
| proc test_array_lists_adding_and_removing() -> testresult { | proc test_array_lists_adding_and_removing() -> testresult { | ||||
| // test adding and removing | // test adding and removing | ||||
| Int_Array_List* list = create_Int_array_list(); | |||||
| append_to_array_list(list, 1); | |||||
| append_to_array_list(list, 2); | |||||
| append_to_array_list(list, 3); | |||||
| append_to_array_list(list, 4); | |||||
| Int_Array_List list = create_Int_array_list(); | |||||
| append_to_array_list(&list, 1); | |||||
| append_to_array_list(&list, 2); | |||||
| append_to_array_list(&list, 3); | |||||
| append_to_array_list(&list, 4); | |||||
| assert_equal_int(list->next_index, 4); | |||||
| assert_equal_int(list.next_index, 4); | |||||
| remove_index_from_array_list(list, 0); | |||||
| remove_index_from_array_list(&list, 0); | |||||
| assert_equal_int(list->next_index, 3); | |||||
| assert_equal_int(list->data[0], 4); | |||||
| assert_equal_int(list->data[1], 2); | |||||
| assert_equal_int(list->data[2], 3); | |||||
| assert_equal_int(list.next_index, 3); | |||||
| assert_equal_int(list.data[0], 4); | |||||
| assert_equal_int(list.data[1], 2); | |||||
| assert_equal_int(list.data[2], 3); | |||||
| remove_index_from_array_list(list, 2); | |||||
| remove_index_from_array_list(&list, 2); | |||||
| assert_equal_int(list->next_index, 2); | |||||
| assert_equal_int(list->data[0], 4); | |||||
| assert_equal_int(list->data[1], 2); | |||||
| assert_equal_int(list.next_index, 2); | |||||
| assert_equal_int(list.data[0], 4); | |||||
| assert_equal_int(list.data[1], 2); | |||||
| return pass; | return pass; | ||||
| } | } | ||||
| proc test_array_lists_sorting() -> testresult { | proc test_array_lists_sorting() -> testresult { | ||||
| // test adding and removing | // test adding and removing | ||||
| Int_Array_List* list = create_Int_array_list(); | |||||
| append_to_array_list(list, 1); | |||||
| append_to_array_list(list, 2); | |||||
| append_to_array_list(list, 3); | |||||
| append_to_array_list(list, 4); | |||||
| Int_Array_List list = create_Int_array_list(); | |||||
| append_to_array_list(&list, 1); | |||||
| append_to_array_list(&list, 2); | |||||
| append_to_array_list(&list, 3); | |||||
| append_to_array_list(&list, 4); | |||||
| sort_array_list(list); | |||||
| sort_array_list(&list); | |||||
| assert_equal_int(list->next_index, 4); | |||||
| assert_equal_int(list.next_index, 4); | |||||
| assert_equal_int(list->data[0], 1); | |||||
| assert_equal_int(list->data[1], 2); | |||||
| assert_equal_int(list->data[2], 3); | |||||
| assert_equal_int(list->data[3], 4); | |||||
| assert_equal_int(list.data[0], 1); | |||||
| assert_equal_int(list.data[1], 2); | |||||
| assert_equal_int(list.data[2], 3); | |||||
| assert_equal_int(list.data[3], 4); | |||||
| append_to_array_list(list, 0); | |||||
| append_to_array_list(list, 5); | |||||
| append_to_array_list(&list, 0); | |||||
| append_to_array_list(&list, 5); | |||||
| assert_equal_int(list->next_index, 6); | |||||
| assert_equal_int(list.next_index, 6); | |||||
| sort_array_list(list); | |||||
| sort_array_list(&list); | |||||
| assert_equal_int(list->data[0], 0); | |||||
| assert_equal_int(list->data[1], 1); | |||||
| assert_equal_int(list->data[2], 2); | |||||
| assert_equal_int(list->data[3], 3); | |||||
| assert_equal_int(list->data[4], 4); | |||||
| assert_equal_int(list->data[5], 5); | |||||
| assert_equal_int(list.data[0], 0); | |||||
| assert_equal_int(list.data[1], 1); | |||||
| assert_equal_int(list.data[2], 2); | |||||
| assert_equal_int(list.data[3], 3); | |||||
| assert_equal_int(list.data[4], 4); | |||||
| assert_equal_int(list.data[5], 5); | |||||
| return pass; | return pass; | ||||
| } | } | ||||
| proc test_array_lists_searching() -> testresult { | proc test_array_lists_searching() -> testresult { | ||||
| Int_Array_List* list = create_Int_array_list(); | |||||
| append_to_array_list(list, 1); | |||||
| append_to_array_list(list, 2); | |||||
| append_to_array_list(list, 3); | |||||
| append_to_array_list(list, 4); | |||||
| Int_Array_List list = create_Int_array_list(); | |||||
| append_to_array_list(&list, 1); | |||||
| append_to_array_list(&list, 2); | |||||
| append_to_array_list(&list, 3); | |||||
| append_to_array_list(&list, 4); | |||||
| int index = sorted_array_list_find(list, 3); | |||||
| int index = sorted_array_list_find(&list, 3); | |||||
| assert_equal_int(index, 2); | assert_equal_int(index, 2); | ||||
| index = sorted_array_list_find(list, 1); | |||||
| index = sorted_array_list_find(&list, 1); | |||||
| assert_equal_int(index, 0); | assert_equal_int(index, 0); | ||||
| index = sorted_array_list_find(list, 5); | |||||
| index = sorted_array_list_find(&list, 5); | |||||
| assert_equal_int(index, -1); | assert_equal_int(index, -1); | ||||
| return pass; | return pass; | ||||
| @@ -595,14 +595,6 @@ proc test_file(const char* file) -> testresult { | |||||
| } | } | ||||
| proc run_all_tests() -> bool { | proc run_all_tests() -> bool { | ||||
| Memory::init(4096 * 2000, 1024 * 32, 4096 * 16 * 10); | |||||
| // get the direction of the exe | |||||
| char* exe_path = get_exe_dir(); | |||||
| // switch to the exe directory for loading pre.slime | |||||
| change_cwd(exe_path); | |||||
| free(exe_path); | |||||
| bool result = true; | bool result = true; | ||||
| @@ -611,6 +603,8 @@ proc run_all_tests() -> bool { | |||||
| invoke_test(test_array_lists_sorting); | invoke_test(test_array_lists_sorting); | ||||
| invoke_test(test_array_lists_searching); | invoke_test(test_array_lists_searching); | ||||
| Memory::init(4096 * 2000, 1024 * 32, 4096 * 16 * 10); | |||||
| printf("\n -- Parsing --\n"); | printf("\n -- Parsing --\n"); | ||||
| invoke_test(test_parse_atom); | invoke_test(test_parse_atom); | ||||
| invoke_test(test_parse_expression); | invoke_test(test_parse_expression); | ||||
| @@ -305,8 +305,8 @@ proc visualize_lisp_machine() -> void { | |||||
| draw_new_line(); | draw_new_line(); | ||||
| int free_string_memory = (int)(Memory::next_free_spot_in_string_memory - Memory::string_memory); | int free_string_memory = (int)(Memory::next_free_spot_in_string_memory - Memory::string_memory); | ||||
| for (int i = 0; i < Memory::free_spots_in_string_memory->next_index; ++i) { | |||||
| free_string_memory += ((String*)(Memory::free_spots_in_string_memory->data[i]))->length; | |||||
| for (int i = 0; i < Memory::free_spots_in_string_memory.next_index; ++i) { | |||||
| free_string_memory += ((String*)(Memory::free_spots_in_string_memory.data[i]))->length; | |||||
| } | } | ||||
| int used_string_memory = Memory::string_memory_size - free_string_memory; | int used_string_memory = Memory::string_memory_size - free_string_memory; | ||||
| @@ -334,8 +334,8 @@ proc visualize_lisp_machine() -> void { | |||||
| // Object Memory | // Object Memory | ||||
| // ------------------- | // ------------------- | ||||
| int free_object_memory_cells = Memory::object_memory_size - (Memory::next_index_in_object_memory - Memory::free_spots_in_object_memory->next_index); | |||||
| int used_object_memory_cells = Memory::next_index_in_object_memory - Memory::free_spots_in_object_memory->next_index; | |||||
| int free_object_memory_cells = Memory::object_memory_size - (Memory::next_index_in_object_memory - Memory::free_spots_in_object_memory.next_index); | |||||
| int used_object_memory_cells = Memory::next_index_in_object_memory - Memory::free_spots_in_object_memory.next_index; | |||||
| write_x += draw_text("Object Memory:").width; | write_x += draw_text("Object Memory:").width; | ||||
| draw_margin(); | draw_margin(); | ||||
| @@ -359,26 +359,26 @@ proc visualize_lisp_machine() -> void { | |||||
| draw_new_line(3); | draw_new_line(3); | ||||
| }; | }; | ||||
| proc draw_symbols_keywords_and_numbers = [&]() { | proc draw_symbols_keywords_and_numbers = [&]() { | ||||
| Lisp_Object_Array_List* symbols = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List* keywords = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List* numbers = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List* strings = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List* pairs = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List* lists = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List symbols = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List keywords = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List numbers = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List strings = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List pairs = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List lists = create_Lisp_Object_array_list(); | |||||
| // loop over all used memory | // loop over all used memory | ||||
| for (int i = 0; i < Memory::next_index_in_object_memory; ++i) { | for (int i = 0; i < Memory::next_index_in_object_memory; ++i) { | ||||
| for (int j = 0; j < Memory::free_spots_in_object_memory->next_index; ++j) { | |||||
| if (i == Memory::free_spots_in_object_memory->data[j]) | |||||
| for (int j = 0; j < Memory::free_spots_in_object_memory.next_index; ++j) { | |||||
| if (i == Memory::free_spots_in_object_memory.data[j]) | |||||
| goto next; | goto next; | ||||
| } | } | ||||
| switch (Memory::get_type(Memory::object_memory+i)) { | switch (Memory::get_type(Memory::object_memory+i)) { | ||||
| case Lisp_Object_Type::Symbol: append_to_array_list(symbols, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::String: append_to_array_list(strings, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Keyword: append_to_array_list(keywords, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Number : append_to_array_list(numbers, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Pair : append_to_array_list(pairs, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Symbol: append_to_array_list(&symbols, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::String: append_to_array_list(&strings, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Keyword: append_to_array_list(&keywords, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Number : append_to_array_list(&numbers, Memory::object_memory+i); break; | |||||
| case Lisp_Object_Type::Pair : append_to_array_list(&pairs, Memory::object_memory+i); break; | |||||
| default: break; | default: break; | ||||
| } | } | ||||
| @@ -386,36 +386,36 @@ proc visualize_lisp_machine() -> void { | |||||
| } | } | ||||
| // create the lists-list by filtering the pairs-list. | // create the lists-list by filtering the pairs-list. | ||||
| Lisp_Object_Array_List* pairs_to_filter = create_Lisp_Object_array_list(); | |||||
| Lisp_Object_Array_List pairs_to_filter = create_Lisp_Object_array_list(); | |||||
| // helper lambda: | // helper lambda: | ||||
| proc remove_doubles_from_lisp_object_array_list = [&](Lisp_Object_Array_List* list) -> void { | |||||
| if (list->next_index == 0) | |||||
| proc remove_doubles_from_lisp_object_array_list = [&](Lisp_Object_Array_List list) -> void { | |||||
| if (list.next_index == 0) | |||||
| return; | return; | ||||
| sort_array_list(list); | |||||
| Int_Array_List* indices_to_filter = create_Int_array_list(); | |||||
| sort_array_list(&list); | |||||
| Int_Array_List indices_to_filter = create_Int_array_list(); | |||||
| size_t last = (size_t)list->data[0]; | |||||
| for (int i = 1; i < list->next_index; ++i) { | |||||
| if ((size_t)list->data[i] == last) | |||||
| append_to_array_list(indices_to_filter, i); | |||||
| size_t last = (size_t)list.data[0]; | |||||
| for (int i = 1; i < list.next_index; ++i) { | |||||
| if ((size_t)list.data[i] == last) | |||||
| append_to_array_list(&indices_to_filter, i); | |||||
| else | else | ||||
| last = (size_t)list->data[i]; | |||||
| last = (size_t)list.data[i]; | |||||
| } | } | ||||
| for (int i = indices_to_filter->next_index; i >= 0; --i) { | |||||
| remove_index_from_array_list(list, indices_to_filter->data[i]); | |||||
| for (int i = indices_to_filter.next_index; i >= 0; --i) { | |||||
| remove_index_from_array_list(&list, indices_to_filter.data[i]); | |||||
| } | } | ||||
| // sort again as removing items destroys the order | // sort again as removing items destroys the order | ||||
| sort_array_list(list); | |||||
| sort_array_list(&list); | |||||
| }; | }; | ||||
| // recursive lambda | // recursive lambda | ||||
| std::function<void(Lisp_Object*)> filter_pair_and_children; | std::function<void(Lisp_Object*)> filter_pair_and_children; | ||||
| filter_pair_and_children = [&](Lisp_Object* pair) { | filter_pair_and_children = [&](Lisp_Object* pair) { | ||||
| append_to_array_list(pairs_to_filter, pair); | |||||
| append_to_array_list(&pairs_to_filter, pair); | |||||
| if (Memory::get_type(pair->value.pair.first) == Lisp_Object_Type::Pair) | if (Memory::get_type(pair->value.pair.first) == Lisp_Object_Type::Pair) | ||||
| filter_pair_and_children(pair->value.pair.first); | filter_pair_and_children(pair->value.pair.first); | ||||
| @@ -423,12 +423,12 @@ proc visualize_lisp_machine() -> void { | |||||
| if (Memory::get_type(pair->value.pair.rest) == Lisp_Object_Type::Pair) | if (Memory::get_type(pair->value.pair.rest) == Lisp_Object_Type::Pair) | ||||
| filter_pair_and_children(pair->value.pair.rest); | filter_pair_and_children(pair->value.pair.rest); | ||||
| }; | }; | ||||
| for (int i = 0; i < pairs->next_index; ++i) { | |||||
| if (Memory::get_type(pairs->data[i]->value.pair.first) == Lisp_Object_Type::Pair) | |||||
| filter_pair_and_children(pairs->data[i]->value.pair.first); | |||||
| for (int i = 0; i < pairs.next_index; ++i) { | |||||
| if (Memory::get_type(pairs.data[i]->value.pair.first) == Lisp_Object_Type::Pair) | |||||
| filter_pair_and_children(pairs.data[i]->value.pair.first); | |||||
| if (Memory::get_type(pairs->data[i]->value.pair.rest) == Lisp_Object_Type::Pair) | |||||
| filter_pair_and_children(pairs->data[i]->value.pair.rest); | |||||
| if (Memory::get_type(pairs.data[i]->value.pair.rest) == Lisp_Object_Type::Pair) | |||||
| filter_pair_and_children(pairs.data[i]->value.pair.rest); | |||||
| } | } | ||||
| @@ -436,9 +436,9 @@ proc visualize_lisp_machine() -> void { | |||||
| // fprintf(stderr, "removing %d pairs\n", pairs_to_filter->next_index); | // fprintf(stderr, "removing %d pairs\n", pairs_to_filter->next_index); | ||||
| // okay, so pairs_to_filter now only the pairs once each that | // okay, so pairs_to_filter now only the pairs once each that | ||||
| // we want to filter from the pairs list | // we want to filter from the pairs list | ||||
| for (int i = 0; i < pairs->next_index; ++i) { | |||||
| if (sorted_array_list_find(pairs_to_filter, pairs->data[i]) == -1) { | |||||
| append_to_array_list(lists, pairs->data[i]); | |||||
| for (int i = 0; i < pairs.next_index; ++i) { | |||||
| if (sorted_array_list_find(&pairs_to_filter, pairs.data[i]) == -1) { | |||||
| append_to_array_list(&lists, pairs.data[i]); | |||||
| } | } | ||||
| } | } | ||||
| @@ -450,15 +450,15 @@ proc visualize_lisp_machine() -> void { | |||||
| start_y = write_y; | start_y = write_y; | ||||
| write_x += draw_text("Symbols: ").width; | write_x += draw_text("Symbols: ").width; | ||||
| draw_integer(symbols->next_index); | |||||
| draw_integer(symbols.next_index); | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x; | write_x = start_x; | ||||
| for (int i = 0; i < symbols->next_index; ++i) { | |||||
| for (int i = 0; i < symbols.next_index; ++i) { | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x; | write_x = start_x; | ||||
| draw_text(&symbols->data[i]->value.symbol.identifier->data); | |||||
| draw_text(&symbols.data[i]->value.symbol.identifier->data); | |||||
| } | } | ||||
| @@ -466,15 +466,15 @@ proc visualize_lisp_machine() -> void { | |||||
| write_y = start_y; | write_y = start_y; | ||||
| write_x += draw_text("Keywords: ").width; | write_x += draw_text("Keywords: ").width; | ||||
| draw_integer(keywords->next_index); | |||||
| draw_integer(keywords.next_index); | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 300; | write_x = start_x + 300; | ||||
| for (int i = 0; i < keywords->next_index; ++i) { | |||||
| for (int i = 0; i < keywords.next_index; ++i) { | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 300; | write_x = start_x + 300; | ||||
| draw_lisp_object(keywords->data[i]); | |||||
| draw_lisp_object(keywords.data[i]); | |||||
| } | } | ||||
| @@ -483,30 +483,30 @@ proc visualize_lisp_machine() -> void { | |||||
| write_y = start_y; | write_y = start_y; | ||||
| write_x += draw_text("Numbers: ").width; | write_x += draw_text("Numbers: ").width; | ||||
| draw_integer(numbers->next_index); | |||||
| draw_integer(numbers.next_index); | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 600; | write_x = start_x + 600; | ||||
| for (int i = 0; i < numbers->next_index; ++i) { | |||||
| for (int i = 0; i < numbers.next_index; ++i) { | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 600; | write_x = start_x + 600; | ||||
| draw_float((float)(numbers->data[i]->value.number)); | |||||
| draw_float((float)(numbers.data[i]->value.number)); | |||||
| } | } | ||||
| write_x = start_x + 900; | write_x = start_x + 900; | ||||
| write_y = start_y; | write_y = start_y; | ||||
| write_x += draw_text("Strings: ").width; | write_x += draw_text("Strings: ").width; | ||||
| draw_integer(strings->next_index); | |||||
| draw_integer(strings.next_index); | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 900; | write_x = start_x + 900; | ||||
| for (int i = 0; i < strings->next_index; ++i) { | |||||
| for (int i = 0; i < strings.next_index; ++i) { | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 900; | write_x = start_x + 900; | ||||
| draw_text(&strings->data[i]->value.string->data, "#2aa198", true, 75); | |||||
| draw_text(&strings.data[i]->value.string->data, "#2aa198", true, 75); | |||||
| } | } | ||||
| @@ -514,17 +514,17 @@ proc visualize_lisp_machine() -> void { | |||||
| write_y = start_y; | write_y = start_y; | ||||
| write_x += draw_text("Lists, Pairs: ").width; | write_x += draw_text("Lists, Pairs: ").width; | ||||
| write_x += draw_integer(lists->next_index).width; | |||||
| write_x += draw_integer(lists.next_index).width; | |||||
| draw_margin(); | draw_margin(); | ||||
| draw_integer(pairs->next_index); | |||||
| draw_integer(pairs.next_index); | |||||
| draw_new_line(); | draw_new_line(); | ||||
| write_x = start_x + 2000; | write_x = start_x + 2000; | ||||
| for (int i = 0; i < lists->next_index; ++i) { | |||||
| for (int i = 0; i < lists.next_index; ++i) { | |||||
| draw_new_line(3); | draw_new_line(3); | ||||
| write_x = start_x + 2000; | write_x = start_x + 2000; | ||||
| write_y += draw_pair(lists->data[i]).height; | |||||
| write_y += draw_pair(lists.data[i]).height; | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -96,6 +96,9 @@ | |||||
| <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | ||||
| </ImportGroup> | </ImportGroup> | ||||
| <PropertyGroup Label="UserMacros" /> | <PropertyGroup Label="UserMacros" /> | ||||
| <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='run tests|x64'"> | |||||
| <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> | |||||
| </PropertyGroup> | |||||
| <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> | ||||
| <ClCompile> | <ClCompile> | ||||
| <WarningLevel>Level3</WarningLevel> | <WarningLevel>Level3</WarningLevel> | ||||
| @@ -135,6 +138,7 @@ | |||||
| <SDLCheck>true</SDLCheck> | <SDLCheck>true</SDLCheck> | ||||
| <CompileAs>Default</CompileAs> | <CompileAs>Default</CompileAs> | ||||
| <LanguageStandard>stdcpplatest</LanguageStandard> | <LanguageStandard>stdcpplatest</LanguageStandard> | ||||
| <PreprocessorDefinitions>_PROFILING;%(PreprocessorDefinitions)</PreprocessorDefinitions> | |||||
| </ClCompile> | </ClCompile> | ||||
| <Link> | <Link> | ||||
| <Profile>true</Profile> | <Profile>true</Profile> | ||||