| @@ -0,0 +1,45 @@ | |||
| default: | |||
| artifacts: | |||
| paths: | |||
| - ./bin/slime | |||
| - ./bin/slime_d | |||
| expire_in: 1 week | |||
| variables: | |||
| GIT_SUBMODULE_STRATEGY: recursive | |||
| stages: | |||
| - build_debug | |||
| - build_release | |||
| - test | |||
| build_clang++_d: | |||
| image: warchantua/dev-essential | |||
| stage: build_debug | |||
| script: clang++ -D_DEBUG -D_DONT_BREAK_ON_ERRORS src/main.cpp -gfull -gdwarf -o ./bin/slime_d --std=c++17 -I3rd/ | |||
| build_g++_d: | |||
| stage: build_debug | |||
| script: g++ -D_DEBUG -D_DONT_BREAK_ON_ERRORS src/main.cpp -g -o ./bin/slime_d --std=c++17 -I3rd/ | |||
| build_clang++_r: | |||
| image: warchantua/dev-essential | |||
| stage: build_release | |||
| script: clang++ -D_DONT_BREAK_ON_ERRORS -O3 src/main.cpp -g -o ./bin/slime --std=c++17 -I3rd/ || exit 1 | |||
| build_g++_r: | |||
| stage: build_release | |||
| script: g++ -D_DONT_BREAK_ON_ERRORS -O3 src/main.cpp -g -o ./bin/slime --std=c++17 -I3rd/ || exit 1 | |||
| tests_d: | |||
| stage: test | |||
| script: ./bin/slime_d --run-tests | |||
| tests_r: | |||
| stage: test | |||
| script: ./bin/slime --run-tests | |||
| valgrind: | |||
| image: warchantua/dev-essential | |||
| stage: test | |||
| script: valgrind --error-exitcode=123 -q --track-origins=yes --leak-check=full --show-leak-kinds=all ./bin/slime_d --run-tests | |||
| @@ -0,0 +1,29 @@ | |||
| BSD 3-Clause License | |||
| Copyright (c) 2020, Felix Brendel | |||
| All rights reserved. | |||
| Redistribution and use in source and binary forms, with or without | |||
| modification, are permitted provided that the following conditions are met: | |||
| * Redistributions of source code must retain the above copyright notice, this | |||
| list of conditions and the following disclaimer. | |||
| * Redistributions in binary form must reproduce the above copyright notice, | |||
| this list of conditions and the following disclaimer in the documentation | |||
| and/or other materials provided with the distribution. | |||
| * Neither the name of the copyright holder nor the names of its | |||
| contributors may be used to endorse or promote products derived from | |||
| this software without specific prior written permission. | |||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | |||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | |||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
| @@ -18,13 +18,13 @@ time clang++ -D_DEBUG -D_DONT_BREAK_ON_ERRORS \ | |||
| src/main.cpp -gfull -gdwarf -o ./bin/slime_d --std=c++17 \ | |||
| -I3rd/ || exit 1 | |||
| # echo "" | |||
| # echo "--------------------------------" | |||
| # echo " compiling fullslime (release) " | |||
| # echo "--------------------------------" | |||
| # time clang++ -D_DONT_BREAK_ON_ERRORS -O3 \ | |||
| # src/main.cpp -g -o ./bin/slime --std=c++17 \ | |||
| # -I3rd/ || exit 1 | |||
| echo "" | |||
| echo "--------------------------------" | |||
| echo " compiling fullslime (release) " | |||
| echo "--------------------------------" | |||
| time clang++ -D_DONT_BREAK_ON_ERRORS -O3 \ | |||
| src/main.cpp -g -o ./bin/slime --std=c++17 \ | |||
| -I3rd/ || exit 1 | |||
| echo "" | |||
| echo "------------------------------" | |||
| @@ -71,10 +71,10 @@ namespace Slime { | |||
| proc built_in_load(String file_name) -> Lisp_Object* { | |||
| profile_with_comment(file_name.data); | |||
| char* file_content; | |||
| path_char fullpath[MAX_PATH]; | |||
| path_char fullpath[max_path_len]; | |||
| #ifdef UNICODE | |||
| path_char* temp = char_to_path_char(Memory::get_c_str(file_name)); | |||
| swprintf(fullpath, MAX_PATH,L"%s", temp); | |||
| swprintf(fullpath, max_path_len,L"%s", temp); | |||
| file_content = read_entire_file(temp); | |||
| free(temp); | |||
| #else | |||
| @@ -89,7 +89,7 @@ namespace Slime { | |||
| #ifdef UNICODE | |||
| fullpath[0] = L'\0'; | |||
| path_char* temp = char_to_path_char(Memory::get_c_str(file_name)); | |||
| swprintf(fullpath, MAX_PATH, L"%s%s", it, temp); | |||
| swprintf(fullpath, max_path_len, L"%s%s", it, temp); | |||
| free(temp); | |||
| #else | |||
| fullpath[0] = '\0'; | |||
| @@ -171,9 +171,6 @@ namespace Slime { | |||
| proc load_built_ins_into_environment() -> void* { | |||
| profile_this(); | |||
| String file_name_built_ins = Memory::create_string(__FILE__); | |||
| defer_free(file_name_built_ins.data); | |||
| define_macro((call/cc fun), "TODO") { | |||
| profile_with_name("(call/cc)"); | |||
| @@ -1364,7 +1361,9 @@ namespace Slime { | |||
| // example, numbers are not valid symbols. | |||
| try assert_type(str, Lisp_Object_Type::String); | |||
| return Memory::get_symbol(Memory::duplicate_string(str->value.string)); | |||
| // TODO(Felix): It was like this: why did we have to copy it? | |||
| // return Memory::get_symbol(Memory::duplicate_string(str->value.string)); | |||
| return Memory::get_symbol(str->value.string); | |||
| }; | |||
| define((concat-strings . strings), "TODO") { | |||
| profile_with_name("(concat-strings)"); | |||
| @@ -109,7 +109,7 @@ | |||
| // because the parser relys on being able to temporaily put in markers | |||
| // in the code and also it will fill out the source code location | |||
| #define _define_helper(def, docstring, type, ending) \ | |||
| Parser::parser_file = file_name_built_ins; \ | |||
| Parser::parser_file = Memory::create_string_no_alloc((char*)__FILE__); \ | |||
| Parser::parser_line = __LINE__; \ | |||
| Parser::parser_col = 0; \ | |||
| auto label(params,__LINE__) = Parser::parse_single_expression(#def); \ | |||
| @@ -129,7 +129,7 @@ | |||
| #define define_special(def, docs) _define_helper(def, docs, Slime::C_Function_Type::cSpecial, c_body = []() -> Lisp_Object*) | |||
| #define define_macro(def, docs) _define_helper(def, docs, Slime::C_Function_Type::cMacro, c_macro_body = []() -> void) | |||
| #define in_caller_env fluid_let( \ | |||
| #define in_caller_env fluid_let( \ | |||
| Globals::Current_Execution.envi_stack.next_index, \ | |||
| Globals::Current_Execution.envi_stack.next_index-1) | |||
| @@ -53,6 +53,7 @@ namespace Slime { | |||
| char* get_c_str(String); | |||
| void free_everything(); | |||
| String create_string(const char*); | |||
| String create_string_no_alloc(const char*); | |||
| Lisp_Object* get_symbol(String identifier); | |||
| Lisp_Object* get_symbol(const char*); | |||
| Lisp_Object* get_keyword(String identifier); | |||
| @@ -17,6 +17,7 @@ | |||
| # include <direct.h> | |||
| # include <windows.h> | |||
| #else | |||
| # include <limits.h> | |||
| # include <unistd.h> | |||
| # include <signal.h> | |||
| #endif | |||
| @@ -74,6 +74,14 @@ namespace Slime::Memory { | |||
| } | |||
| proc create_string_no_alloc(char* str) -> String { | |||
| String s = { | |||
| (u32)strlen(str), | |||
| str | |||
| }; | |||
| return s; | |||
| } | |||
| proc create_string(const char* str, u32 len) -> String { | |||
| String s = { | |||
| len, | |||
| @@ -100,6 +108,20 @@ namespace Slime::Memory { | |||
| proc free_everything() -> void { | |||
| object_memory.for_each([](Lisp_Object* lo){ | |||
| switch (lo->type) { | |||
| case Lisp_Object_Type::Continuation: { | |||
| lo->value.continuation->cs.dealloc(); | |||
| lo->value.continuation->pcs.dealloc(); | |||
| lo->value.continuation->ams.dealloc(); | |||
| lo->value.continuation->ats.dealloc(); | |||
| lo->value.continuation->mes.dealloc(); | |||
| lo->value.continuation->envi_stack.dealloc(); | |||
| for (auto it : lo->value.continuation->nass) { | |||
| it.dealloc(); | |||
| } | |||
| lo->value.continuation->nass.dealloc(); | |||
| free(lo->value.continuation); | |||
| } break; | |||
| case Lisp_Object_Type::Function: { | |||
| lo->value.function->args.positional.symbols.dealloc(); | |||
| lo->value.function->args.keyword.keywords.dealloc(); | |||
| @@ -126,8 +148,12 @@ namespace Slime::Memory { | |||
| free(value); | |||
| } | |||
| // free the exe dir: | |||
| free(Globals::load_path.data[0]); | |||
| // free paths in load path | |||
| for (u32 i = 0; i < Globals::load_path.next_index; ++i) { | |||
| free(Globals::load_path.data[i]); | |||
| } | |||
| Globals::load_path.dealloc(); | |||
| Globals::user_types.dealloc(); | |||
| Globals::docs.dealloc(); | |||
| @@ -136,6 +162,9 @@ namespace Slime::Memory { | |||
| Globals::Current_Execution.ams.dealloc(); | |||
| Globals::Current_Execution.pcs.dealloc(); | |||
| Globals::Current_Execution.nass.dealloc(); | |||
| for (auto it: Globals::Current_Execution.nass) { | |||
| it.dealloc(); | |||
| } | |||
| Globals::Current_Execution.ats.dealloc(); | |||
| Globals::Current_Execution.mes.dealloc(); | |||
| @@ -280,24 +309,28 @@ namespace Slime::Memory { | |||
| return node; | |||
| } | |||
| inline proc full_clone_continuation(Continuation* c) -> Continuation* { | |||
| Continuation* res = (Continuation*)malloc(sizeof(Continuation)); | |||
| res->cs = c->cs.clone(); | |||
| res->pcs = c->pcs.clone(); | |||
| res->ams = c->ams.clone(); | |||
| res->ats = c->ats.clone(); | |||
| res->mes = c->mes.clone(); | |||
| res->envi_stack = c->envi_stack.clone(); | |||
| res->nass = c->nass.clone(); | |||
| for (u32 i = 0; i < res->nass.next_index; ++i) { | |||
| res->nass.data[i] = c->nass.data[i].clone(); | |||
| } | |||
| return res; | |||
| } | |||
| proc create_lisp_object_continuation() -> Lisp_Object* { | |||
| using Globals::Current_Execution; | |||
| Lisp_Object* node; | |||
| try node = create_lisp_object(); | |||
| node->type = Lisp_Object_Type::Continuation; | |||
| node->value.continuation = (Continuation*)malloc(sizeof(Continuation)); | |||
| node->value.continuation->cs = Current_Execution.cs.clone(); | |||
| node->value.continuation->pcs = Current_Execution.pcs.clone(); | |||
| node->value.continuation->ams = Current_Execution.ams.clone(); | |||
| node->value.continuation->ats = Current_Execution.ats.clone(); | |||
| node->value.continuation->mes = Current_Execution.mes.clone(); | |||
| node->value.continuation->envi_stack = Current_Execution.envi_stack.clone(); | |||
| node->value.continuation->nass = Current_Execution.nass.clone(); | |||
| for (u32 i = 0; i < node->value.continuation->nass.next_index; ++i) { | |||
| node->value.continuation->nass.data[i] = node->value.continuation->nass.data[i].clone(); | |||
| } | |||
| node->value.continuation = full_clone_continuation(&Globals::Current_Execution); | |||
| return node; | |||
| } | |||
| @@ -460,25 +493,32 @@ namespace Slime::Memory { | |||
| if (n == Memory::nil || n == Memory::t) { | |||
| return n; | |||
| } else { | |||
| Lisp_Object_Type type = n->type; | |||
| if (type == Lisp_Object_Type::Symbol || | |||
| type == Lisp_Object_Type::Keyword || | |||
| type == Lisp_Object_Type::Function) | |||
| { | |||
| switch(n->type) { | |||
| case Lisp_Object_Type::Symbol: | |||
| case Lisp_Object_Type::Keyword: | |||
| case Lisp_Object_Type::Function: | |||
| return n; | |||
| } else if (type == Lisp_Object_Type::String) { | |||
| case Lisp_Object_Type::String: { | |||
| Lisp_Object* target; | |||
| try target = create_lisp_object(); | |||
| *target = *n; | |||
| target->value.string = create_string(target->value.string.data); | |||
| return target; | |||
| } else { | |||
| } | |||
| case Lisp_Object_Type::Continuation: | |||
| Lisp_Object* target; | |||
| try target = create_lisp_object(); | |||
| *target = *n; | |||
| target->value.continuation = full_clone_continuation(n->value.continuation); | |||
| return target; | |||
| default: { | |||
| Lisp_Object* target; | |||
| try target = create_lisp_object(); | |||
| *target = *n; | |||
| return target; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -1,5 +1,12 @@ | |||
| namespace Slime { | |||
| #ifdef SLIME_WINDOWS | |||
| constexpr u32 max_path_len = MAX_PATH; | |||
| #else | |||
| constexpr u32 max_path_len = PATH_MAX; | |||
| #endif | |||
| inline proc get_cwd() -> char* { | |||
| const u32 buf_size = 2048; | |||
| char* res = (char*)malloc(buf_size * sizeof(char)); | |||
| @@ -46,13 +46,13 @@ namespace Slime { | |||
| } \ | |||
| #define assert_equal_f64(variable, value) \ | |||
| if (fabs((f64)variable - (f64)value) > epsilon) { \ | |||
| if (fabsl((f64)variable - (f64)value) > epsilon) { \ | |||
| print_assert_equal_fail(variable, value, f64, "%Lf"); \ | |||
| return fail; \ | |||
| } | |||
| #define assert_not_equal_f64(variable, value) \ | |||
| if (fabs((f64)variable - (f64)value) <= epsilon) { \ | |||
| if (fabsl((f64)variable - (f64)value) <= epsilon) { \ | |||
| print_assert_not_equal_fail(variable, value, f64, "L%f"); \ | |||
| return fail; \ | |||
| } | |||