// proc assert_type(Lisp_Object*, Lisp_Object_Type) -> void; proc add_to_load_path(const char*) -> void; proc lisp_object_equal(Lisp_Object*,Lisp_Object*) -> bool; proc built_in_load(String*) -> Lisp_Object*; proc built_in_import(String*) -> Lisp_Object*; 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, const char* format, ...) -> void; proc create_error(Lisp_Object* type, const char* message, const char* c_file_name, int c_file_line) -> void; proc eval_arguments(Lisp_Object*) -> Lisp_Object*; proc eval_expr(Lisp_Object*) -> Lisp_Object*; proc is_truthy (Lisp_Object*) -> bool; proc list_length(Lisp_Object*) -> int; proc load_built_ins_into_environment() -> void; proc create_arguments_from_lambda_list_and_inject(Lisp_Object* formal_arguments, Lisp_Object* function) -> void; proc print_environment(Environment*) -> void; inline proc get_root_environment() -> Environment*; inline proc get_current_environment() -> Environment*; inline proc push_environment(Environment*) -> void; inline proc pop_environment() -> void; proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char*; proc visualize_lisp_machine() -> void; proc generate_docs(String* path) -> void; namespace Memory { proc create_built_ins_environment() -> Environment*; proc get_or_create_lisp_object_keyword(const char* identifier) -> Lisp_Object*; inline proc get_type(Lisp_Object* node) -> Lisp_Object_Type; } namespace Parser { // extern Environment* environment_for_macros; extern String* standard_in; extern String* parser_file; extern int parser_line; extern int parser_col; proc parse_single_expression(char* text) -> Lisp_Object*; } namespace Globals { char* bin_path = nullptr; Log_Level log_level = Log_Level::Debug; Void_Ptr_Array_List load_path = create_Void_Ptr_array_list(); namespace Current_Execution { 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; #endif Error* error = nullptr; } inline bool hm_objects_match(char* a, char* b) { return strcmp(a, b) == 0; } inline bool hm_objects_match(void* a, void* b) { return a == b; } u32 hm_hash(void* ptr) { return ((unsigned long long)ptr * 2654435761) % 4294967296; } u32 hm_hash(char* str) { u32 value = str[0] << 7; int i = 0; while (str[i]) { value = (10000003 * value) ^ str[i++]; } return value ^ i; } inline bool hm_objects_match(Lisp_Object* a, Lisp_Object* b) { return lisp_object_equal(a, b); } u32 hm_hash(Lisp_Object* obj) { switch (Memory::get_type(obj)) { // hash from adress: if two objects of these types have // different addresses, they are different case Lisp_Object_Type::CFunction: case Lisp_Object_Type::Function: case Lisp_Object_Type::Symbol: case Lisp_Object_Type::Keyword: case Lisp_Object_Type::Continuation: case Lisp_Object_Type::Nil: case Lisp_Object_Type::T: return hm_hash((void*) obj); // hash from contents: even if objects are themselved // different, they cauld be equivalent: case Lisp_Object_Type::Pointer: return hm_hash((void*) obj->value.pointer); case Lisp_Object_Type::Number: return hm_hash((void*) (unsigned long long)obj->value.number); // HACK(Felix): yes case Lisp_Object_Type::String: return hm_hash((char*) &obj->value.string->data); case Lisp_Object_Type::Pair: { u32 hash = 1; for_lisp_list (obj) { hash <<= 1; hash += hm_hash(it); } return hash; } break; case Lisp_Object_Type::Vector: case Lisp_Object_Type::HashMap: default: create_not_yet_implemented_error(); return 0; } }