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"); if (!f) { create_generic_error("The file for writing the documentation " "could not be opened for writing."); return; } defer { fclose(f); }; Environment_Array_List* visited = create_Environment_array_list(); std::function print_this_env; print_this_env = [&](Environment* env, char* prefix) -> void { bool we_already_printed = false; // TODO(Felix): Make a generic array_list_contains function for (int i = 0; i < visited->next_index; ++i) { if (visited->data[i] == env) { we_already_printed = true; break; } } if (!we_already_printed) { append_to_array_list(visited, env); for (int i = 0; i < env->next_index; ++i) { fprintf(f, "\\hrule\n* =%s%s= \n" // " :PROPERTIES:\n" // " :UNNUMBERED: t\n" // " :END:" ,prefix, env->keys[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); } /* * type */ Lisp_Object_Type type = Memory::get_type(env->values[i]); Lisp_Object* LOtype; try_void LOtype = eval_expr(Memory::create_list( Memory::get_or_create_lisp_object_symbol("type"), env->values[i])); fprintf(f, "\n - type :: ="); print(LOtype, true, f); fprintf(f, "="); /* * if printable value -> print it */ switch (type) { case(Lisp_Object_Type::Nil): case(Lisp_Object_Type::T): case(Lisp_Object_Type::Number): case(Lisp_Object_Type::String): case(Lisp_Object_Type::Pair): case(Lisp_Object_Type::Symbol): case(Lisp_Object_Type::Keyword): { fprintf(f, "\n - value :: ="); print(env->values[i], true, f); fprintf(f, "="); } break; default: break; } /* * if function then print arguments */ if (type == Lisp_Object_Type::Function) { Lisp_Object* fun = env->values[i]; bool printed_at_least_some_args = false; fprintf(f, "\n - arguments :: "); if (fun->value.function.positional_arguments->next_index != 0) { if (!printed_at_least_some_args) fprintf(f, ":"); 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)); } } if (fun->value.function.keyword_arguments->next_index != 0) { if (!printed_at_least_some_args) fprintf(f, ":"); fprintf(f, "\n - keyword :: "); fprintf(f, "=%s=", Memory::get_c_str(fun->value.function.keyword_arguments->keywords[0]->value.symbol.identifier)); if (fun->value.function.keyword_arguments->values->data[0]) { fprintf(f, " =("); print(fun->value.function.keyword_arguments->values->data[0], true, f); fprintf(f, ")="); } for (int i = 1; i < fun->value.function.keyword_arguments->next_index; ++i) { fprintf(f, ", =%s=", Memory::get_c_str(fun->value.function.keyword_arguments->keywords[i]->value.symbol.identifier)); if (fun->value.function.keyword_arguments->values->data[i]) { fprintf(f, " =("); print(fun->value.function.keyword_arguments->values->data[i], true, f); fprintf(f, ")="); } } } if (fun->value.function.rest_argument) { if (!printed_at_least_some_args) fprintf(f, ":"); fprintf(f, "\n - rest :: =%s=", Memory::get_c_str(fun->value.function.rest_argument)); } // if no args at all if (fun->value.function.positional_arguments->next_index == 0 && fun->value.function.keyword_arguments->next_index == 0 && !fun->value.function.rest_argument) { fprintf(f, "none."); } } fprintf(f, "\n - docu :: "); if (env->values[i]->docstring) fprintf(f, "\n #+BEGIN:\n%s\n #+END:\n", Memory::get_c_str(env->values[i]->docstring)); else 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); } } } for (int i = 0; i < env->parents->next_index; ++i) { print_this_env(env->parents->data[i], prefix); } }; print_this_env(get_current_environment(), (char*)""); }