From ffc576eae3aa2d585438e05a3b51962e8c1780b6 Mon Sep 17 00:00:00 2001 From: FelixBrendel Date: Sun, 5 Apr 2020 23:06:46 +0200 Subject: [PATCH] UNICODE support and fixed a bug where top level imports did noit work --- .dir-locals.el | 2 +- 3rd/ftb | 2 +- bin/math.slime | 12 ++++++++---- bin/slime.rdbg | Bin 408 -> 419 bytes build.bat | 2 +- info.org | 5 +++++ src/assert.hpp | 4 ++-- src/built_ins.cpp | 33 +++++++++++++++++++++++++++++---- src/defines.cpp | 3 +++ src/env.cpp | 15 +++++++++------ src/eval.cpp | 2 ++ src/forward_decls.cpp | 9 +++++++-- src/globals.cpp | 2 +- src/io.cpp | 27 ++++++++++++++++++++++++--- src/main.cpp | 2 ++ src/memory.cpp | 21 ++++++++++++++------- src/platform.cpp | 10 +++++----- src/testing.cpp | 3 +-- src/visualization.cpp | 2 +- todo.org | 8 +++++++- 20 files changed, 123 insertions(+), 41 deletions(-) create mode 100644 info.org diff --git a/.dir-locals.el b/.dir-locals.el index 6b3fa20..fa67836 100644 --- a/.dir-locals.el +++ b/.dir-locals.el @@ -29,7 +29,7 @@ (font-lock-add-keywords 'c++-mode - '(("\\<\\(if_debug\\|if_windows\\|if_linux\\|defer\\|proc\\|try\\|try_void\\|for_array_list\\|for_hash_map\\|for_lisp_list\\|for_lisp_vector\\|in_caller_env\\|ignore_logging\\|dont_break_on_errors\\)\\>" . + '(("\\<\\(if_debug\\|if_unicode\\|if_windows\\|if_linux\\|defer\\|proc\\|try\\|try_void\\|for_array_list\\|for_hash_map\\|for_lisp_list\\|for_lisp_vector\\|in_caller_env\\|ignore_logging\\|dont_break_on_errors\\)\\>" . font-lock-keyword-face))))))) (c++-mode . ((eval . (company-clang-set-prefix "slime.h")) diff --git a/3rd/ftb b/3rd/ftb index 07e89f3..39dbfa3 160000 --- a/3rd/ftb +++ b/3rd/ftb @@ -1 +1 @@ -Subproject commit 07e89f384155abd4ec231edc173ce0d03244b1cf +Subproject commit 39dbfa3db926c78eda8ab086b93e8be8c2828b99 diff --git a/bin/math.slime b/bin/math.slime index 7196041..a35cf1c 100644 --- a/bin/math.slime +++ b/bin/math.slime @@ -1,17 +1,21 @@ (define-module math :imports ("oo.slime") - :exports (pi abs sqrt make-vector3) + :exports (pi tau abs sqrt make-vector3) (define pi - :doc "Tha famous circle constant." + "The famous circle constant." 3.14159265) + (define tau + "The second famous circle constant." + (* 2 pi)) + (define (abs x) - :doc "Accepts one argument and returns the absoulte value of it" + "Accepts one argument and returns the absoulte value of it" (if (> x 0) x (- x))) (define (sqrt x) - :doc "Accepts one argument and returns the square root of it" + "Accepts one argument and returns the square root of it" (** x 0.5)) (define-class (vector3 x y z) diff --git a/bin/slime.rdbg b/bin/slime.rdbg index ebc2d7d316b5d35128879769e9119bf40bdc6dec..98e2ceeb3eb7d198476a869150aa80df8c0fd16d 100644 GIT binary patch delta 83 zcmbQiyqH-#$i>N>n}LBrFQzyrGdEQ)wIUV7)zvL3&C@MOEiNer@)+2GSZ$($%w!El i-iePjChk|6I8l#LaiW4Ob6H}}L`Ut3@@kV!8Iu8b{uUho delta 98 zcmZ3?JcC&w$i>N>n}LBrFQzyrGdEQ)wIUVB0|Ry-sWfq+1ZQzka!hJbQGU_H_u7n# mKoJhGNLgae#5qQc3P1sNus~kf!~h*eH6VYYv*2V0#$*5o6dbJp diff --git a/build.bat b/build.bat index 698c1a0..93a0e27 100644 --- a/build.bat +++ b/build.bat @@ -7,7 +7,7 @@ set exeName=slime.exe taskkill /F /IM %exeName% > NUL 2> NUL echo ---------- Compiling ---------- -call clang-cl ^ +call cl ^ ../src/main.cpp^ /I../3rd/ ^ /D_PROFILING /D_DEBUG /D_DONT_BREAK_ON_ERRORS ^ diff --git a/info.org b/info.org new file mode 100644 index 0000000..f646bc0 --- /dev/null +++ b/info.org @@ -0,0 +1,5 @@ +* Steps to init the system + 1. call =Memory::init= + 2. call =add_to_load_path= as often as wanted + 3. call =Memory::load_pre= + 4. call =Memory::push_user_environment= diff --git a/src/assert.hpp b/src/assert.hpp index 7998d0e..6cef360 100644 --- a/src/assert.hpp +++ b/src/assert.hpp @@ -33,7 +33,7 @@ do { \ if (_node->type != _type) { \ char* t = lisp_object_to_string(_node); \ - defer { free(t); }; \ + defer_free(t); \ create_type_missmatch_error( \ lisp_object_type_to_string(_type), \ lisp_object_type_to_string(_node->type), \ @@ -47,7 +47,7 @@ do { \ if (!(condition)) { \ create_generic_error("Assertion-error: %s\n" \ - " for: %s\n" \ + " condition: %s\n" \ " in: %s:%d", \ message, #condition, __FILE__, __LINE__); \ } \ diff --git a/src/built_ins.cpp b/src/built_ins.cpp index 4d49dac..498c1d3 100644 --- a/src/built_ins.cpp +++ b/src/built_ins.cpp @@ -62,23 +62,39 @@ namespace Slime { return false; } - proc add_to_load_path(const char* path) -> void { + proc add_to_load_path(const path_char* path) -> void { using Globals::load_path; - load_path.append((void*)path); + load_path.append((path_char*)path); } proc built_in_load(String file_name) -> Lisp_Object* { profile_with_comment(file_name.data); char* file_content; - char fullpath[4096]; + path_char fullpath[MAX_PATH]; +#ifdef UNICODE + path_char* temp = char_to_path_char(Memory::get_c_str(file_name)); + swprintf(fullpath, L"%s", temp); + file_content = read_entire_file(temp); + free(temp); +#else sprintf(fullpath, "%s", Memory::get_c_str(file_name)); file_content = read_entire_file(Memory::get_c_str(file_name)); +#endif + + if (!file_content) { for (auto it: Globals::load_path) { +#ifdef UNICODE + fullpath[0] = L'\0'; + path_char* temp = char_to_path_char(Memory::get_c_str(file_name)); + swprintf(fullpath, L"%s%s", it, temp); + free(temp); +#else fullpath[0] = '\0'; - sprintf(fullpath, "%s%s", (char*)it, Memory::get_c_str(file_name)); + sprintf(fullpath, "%s%s", it, Memory::get_c_str(file_name)); +#endif file_content = read_entire_file(fullpath); if (file_content) break; @@ -98,7 +114,13 @@ namespace Slime { Lisp_Object* result = Memory::nil; Array_List* program; +#ifdef UNICODE + char* temp_c = path_char_to_char(fullpath); + String spath = Memory::create_string(temp_c); + free(temp_c); +#else String spath = Memory::create_string(fullpath); +#endif defer { free(spath.data); }; @@ -121,9 +143,12 @@ namespace Slime { proc built_in_import(String file_name) -> Lisp_Object* { profile_this(); Environment* new_env; + try assert("You cannot use import inside of the root-env (parent cycle)", + get_root_environment() != get_current_environment()); new_env = Memory::file_to_env_map.get_object(Memory::get_c_str(file_name)); + if (!new_env) { // create new empty environment try new_env = Memory::create_child_environment(get_root_environment()); diff --git a/src/defines.cpp b/src/defines.cpp index 5ef2a1c..95b152f 100644 --- a/src/defines.cpp +++ b/src/defines.cpp @@ -1,12 +1,15 @@ #define proc auto #ifdef _DEBUG +# define SLIME_DEBUG # define if_debug if constexpr (true) #else # define if_debug if constexpr (false) #endif + #ifdef _MSC_VER +# define SLIME_WINDOWS # define debug_break() if_debug __debugbreak() # define if_windows if constexpr (true) # define if_linux if constexpr (false) diff --git a/src/env.cpp b/src/env.cpp index 6e81979..2707c05 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -37,7 +37,10 @@ namespace Slime { if (result) return result; - for (u32 i = 0; i < env->parents.next_index; ++i) { + // NOTE(Felix): We have to traverse the parents in reverse + // order of adding them. The thing we imported last, should + // overshadow the things imported earlier + for (s32 i = (s32)env->parents.next_index-1; i >= 0; --i) { result = try_lookup_symbol(node, env->parents.data[i]); if (result) @@ -95,11 +98,11 @@ namespace Slime { } }; - if(env == get_root_environment()) { - print_indent(); - printf("[built-ins]-Environment (0x%p)\n", env); - return; - } + // if(env == get_root_environment()) { + // print_indent(); + // printf("[built-ins]-Environment (0x%p)\n", env); + // return; + // } for_hash_map (env->hm) { print_indent(); diff --git a/src/eval.cpp b/src/eval.cpp index 997aeef..37e19a5 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -566,6 +566,7 @@ namespace Slime { proc interprete_file (char* file_name) -> Lisp_Object* { try Memory::init(); try Memory::load_pre(); + try Memory::push_user_environment(); defer { if_debug { Slime::Memory::free_everything(); @@ -582,6 +583,7 @@ namespace Slime { proc interprete_stdin() -> void { try_void Memory::init(); try_void Memory::load_pre(); + try_void Memory::push_user_environment(); defer { if_debug { Slime::Memory::free_everything(); diff --git a/src/forward_decls.cpp b/src/forward_decls.cpp index 602c70f..29e49f1 100644 --- a/src/forward_decls.cpp +++ b/src/forward_decls.cpp @@ -1,5 +1,5 @@ namespace Slime { - void add_to_load_path(const char*); + void add_to_load_path(const path_char*); bool lisp_object_equal(Lisp_Object*,Lisp_Object*); Lisp_Object* built_in_load(String); Lisp_Object* built_in_import(String); @@ -21,6 +21,11 @@ namespace Slime { void print(Lisp_Object* node, bool print_repr = false, FILE* file = stdout); void print_environment(Environment*); + char* char_to_wchar(const wchar_t* c); + wchar_t* char_to_wchar(const char* c); + path_char* char_to_path_char(const char* c); + char* path_char_to_char(const path_char* c); + inline char* duplicate_c_string(const char* str); bool run_all_tests(); @@ -81,7 +86,7 @@ namespace Slime { extern bool debug_log; extern char* bin_path; extern Log_Level log_level; - extern Array_List load_path; + extern Array_List load_path; // namespace Current_Execution { // extern Array_List call_stack; // extern Array_List envi_stack; diff --git a/src/globals.cpp b/src/globals.cpp index 9ddb8ce..7d3eaaa 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -18,7 +18,7 @@ namespace Slime::Globals { char* bin_path = nullptr; Log_Level log_level = Log_Level::Debug; bool debug_log = false; - Array_List load_path; + Array_List load_path; Hash_Map docs; Hash_Map source_code_locations; diff --git a/src/io.cpp b/src/io.cpp index afccd40..31ccd2b 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -117,10 +117,14 @@ namespace Slime { return (s32)(out - in); } - proc read_entire_file(char* filename) -> char* { - profile_with_comment(filename); + proc read_entire_file(path_char* filename) -> char* { + profile_this(); char *fileContent = nullptr; +#if defined(UNICODE) && defined(SLIME_WINDOWS) + FILE *fp = _wfopen(filename, L"r"); +#else FILE *fp = fopen(filename, "r"); +#endif if (fp) { /* Go to the end of the file. */ if (fseek(fp, 0L, SEEK_END) == 0) { @@ -292,7 +296,7 @@ namespace Slime { return filePathC; } - const wchar_t* char_to_wchar(const char* c) { + wchar_t* char_to_wchar(const char* c) { const size_t cSize = strlen(c)+1; wchar_t* wc = new wchar_t[cSize]; mbstowcs (wc, c, cSize); @@ -300,6 +304,23 @@ namespace Slime { return wc; } + path_char* char_to_path_char(const char* c) { +#ifdef UNICODE + return char_to_wchar(c); +#else + return duplicate_c_string(c); +#endif + } + + char* path_char_to_char(const path_char* c) { +#ifdef UNICODE + return wchar_to_char(c); +#else + return duplicate_c_string(c); +#endif + } + + proc string_buider_to_string(Array_List string_builder) -> char* { size_t len = 1; for (auto str : string_builder) { diff --git a/src/main.cpp b/src/main.cpp index 543a27e..dfc603b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,8 @@ s32 main(s32 argc, char* argv[]) { return res ? 0 : 1; } else if (Slime::string_equal(argv[1], "--generate-docs-file")) { Slime::Memory::init(); + Slime::Memory::load_pre(); + Slime::Memory::push_user_environment(); defer { if_debug { Slime::Memory::free_everything(); diff --git a/src/memory.cpp b/src/memory.cpp index 2ef5c2b..54a7b8e 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -128,7 +128,7 @@ namespace Slime::Memory { // free the exe dir: free(Globals::load_path.data[0]); - // Globals::load_path.dealloc(); + Globals::load_path.dealloc(); Globals::user_types.dealloc(); Globals::docs.dealloc(); Globals::Current_Execution.envi_stack.dealloc(); @@ -172,12 +172,21 @@ namespace Slime::Memory { return ret; } - proc load_pre() -> void { + inline proc load_pre() -> void { String file_name = Memory::create_string("pre.slime"); defer_free(file_name.data); try_void built_in_load(file_name); } + inline proc push_user_environment() -> void { + // NOTE(Felix): We create a user environment, so when the user + // imports stuff, they don't import in the root env, because + // that leads to a parent-cycle + Environment* env; + try_void env = create_child_environment(get_current_environment()); + push_environment(env); + } + proc init() -> void { profile_this(); @@ -185,7 +194,7 @@ namespace Slime::Memory { environment_memory.alloc(1024, 8); hashmap_memory.alloc(256, 8); - char* exe_path = get_exe_dir(); + path_char* exe_path = get_exe_dir(); global_symbol_table.alloc(); @@ -202,9 +211,9 @@ namespace Slime::Memory { Globals::docs.alloc(); Globals::user_types.alloc(); - // Globals::load_path.alloc(); + Globals::load_path.alloc(); add_to_load_path(exe_path); - add_to_load_path("../bin/"); + add_to_load_path((path_char*)char_to_path_char("../bin/")); // init nil @@ -221,8 +230,6 @@ namespace Slime::Memory { Environment* env; try_void env = create_built_ins_environment(); push_environment(env); - - } diff --git a/src/platform.cpp b/src/platform.cpp index 10d1df1..6fafce2 100644 --- a/src/platform.cpp +++ b/src/platform.cpp @@ -61,12 +61,12 @@ namespace Slime { } #endif - proc get_exe_dir() -> char* { + proc get_exe_dir() -> path_char* { #ifdef _MSC_VER DWORD last_error; DWORD result; - DWORD path_size = 1024; - char* path = (char*)malloc(1024); + DWORD path_size = MAX_PATH; + path_char* path = (path_char*)malloc(sizeof(path_char)*path_size); while (true) { memset(path, 0, path_size); @@ -86,7 +86,7 @@ namespace Slime { break; } path_size = path_size * 2; - path = (char*)malloc(path_size); + path = (path_char*)malloc((sizeof(path_char)) * path_size); } else break; @@ -102,7 +102,7 @@ namespace Slime { s32 index_in_path = -1; s32 last_backslash = -1; - char c; + path_char c; while ((c = path[++index_in_path]) != '\0') { if (c == '\\') last_backslash = index_in_path; diff --git a/src/testing.cpp b/src/testing.cpp index 611e7e9..a98868d 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -537,8 +537,6 @@ namespace Slime { proc test_file(const char* file) -> testresult { profile_with_name(file); - // Memory::reset(); - // assert_no_error(); push_environment(Memory::create_child_environment(get_current_environment())); String name = Memory::create_string(file); @@ -556,6 +554,7 @@ namespace Slime { bool result = true; try Memory::init(); try Memory::load_pre(); + try Memory::push_user_environment(); defer { if_debug { Slime::Memory::free_everything(); diff --git a/src/visualization.cpp b/src/visualization.cpp index 773b1f0..7e132f6 100644 --- a/src/visualization.cpp +++ b/src/visualization.cpp @@ -5,7 +5,7 @@ namespace Slime { // char* cwd = get_cwd(); // // get the direction of the exe - // char* exe_path = get_exe_dir(); + // path_char* exe_path = get_exe_dir(); // // switch to the exe directory for loading pre.slime // change_cwd(exe_path); diff --git a/todo.org b/todo.org index 4de6ecb..13a6e09 100644 --- a/todo.org +++ b/todo.org @@ -37,8 +37,14 @@ CLOSED: [2020-03-31 Di 11:58] * DONE update header files CLOSED: [2020-03-31 Di 11:58] +* TODO incorporate the print library for slime objects + - define a =%lo= to print =Lisp_Objects= + print("The value of node is: %lo", node); // 이렇게 + * TODO Make specific SLIME macros +- =SLIME_UNICODE= - =SLIME_WINDOWS= +- =SLIME_LINUX= - =SLIME_DEBUG= - =SLIME_RELEASE= - =SLIME_DISTRIBUTE= @@ -49,7 +55,7 @@ * TODO define-syntax-shorthand (define-syntax-shorthand [ vector ] ) (define-syntax-shorthand { hash-map } ) -* TODO revert ats to use funciton pointers if capturs are not working anyways +* TODO revert ats to use function pointers if capturs are not working anyways use the stack to store immediate results, so no captures are necessary * TODO continuation test2 let a cont have a not expanded macro in cs and before calling the cont, expand the macro and let it