Browse Source

trying not to leak memory

master
FelixBrendel 6 years ago
parent
commit
a790a38655
22 changed files with 203 additions and 77 deletions
  1. +1
    -1
      3rd/ftb
  2. +4
    -0
      bin/import1.slime
  3. +8
    -0
      bin/import2.slime
  4. +1
    -1
      bin/pre.slime.expanded
  5. BIN
     
  6. +8
    -8
      bin/tests/alists.slime
  7. +17
    -0
      bin/tests/singular_imports.slime
  8. +7
    -1
      build.bat
  9. +21
    -0
      include/define_macros.hpp
  10. +5
    -0
      include/libslime.h
  11. +36
    -0
      me-management.org
  12. +24
    -12
      src/built_ins.cpp
  13. +21
    -0
      src/define_macros.hpp
  14. +0
    -35
      src/defines.cpp
  15. +3
    -3
      src/eval.cpp
  16. +3
    -0
      src/libslime.cpp
  17. +6
    -0
      src/lisp_object.cpp
  18. +3
    -0
      src/main.cpp
  19. +18
    -6
      src/memory.cpp
  20. +7
    -8
      src/parse.cpp
  21. +8
    -1
      src/structs.cpp
  22. +2
    -1
      src/testing.cpp

+ 1
- 1
3rd/ftb

@@ -1 +1 @@
Subproject commit a20539587c9547084629fb730e12dab21ea8ccca
Subproject commit 43da71f8094e24c544c12352e02eb76c746e1c93

+ 4
- 0
bin/import1.slime View File

@@ -0,0 +1,4 @@
(define a 10)

(define (get-a-1)
a)

+ 8
- 0
bin/import2.slime View File

@@ -0,0 +1,8 @@
(import "import1.slime")


(define (set-a-2 s)
(set! a s))

(define (get-a-2)
a)

+ 1
- 1
bin/pre.slime.expanded View File

@@ -88,7 +88,7 @@

(define (range (:from 0) :to) :doc "Returns a sequence of numbers starting with the number defined\nby the key =from= and ends with the number defined in =to=." (when (< from to) (pair from (range :from (+ 1 from) :to to))))

(define (range-while (:from 0) to) :doc "Returns a sequence of numbers starting with the number defined\nby the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (mutate from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (mutate from (increment from)))) result)
(define (range-while (:from 0) :to) :doc "Returns a sequence of numbers starting with the number defined\nby the key 'from' and ends with the number defined in 'to'." (define result (list (copy from))) (define head result) (set! from (increment from)) (while (< from to) (begin (mutate head (pair (first head) (pair (copy from) nil))) (define head (rest head)) (set! from (increment from)))) result)

(define (map fun seq) :doc "Takes a function and a sequence as arguments and returns a new\nsequence which contains the results of using the first sequences\nelemens as argument to that function." (if (null? seq) seq (pair (fun (first seq)) (map fun (rest seq)))))



BIN
View File


+ 8
- 8
bin/tests/alists.slime View File

@@ -89,13 +89,13 @@
;; :key2 value2,
;; :key1 value1))

(assert (= (length (first p)) 6))
(assert (= (ds::plist::get p :key1) 'value4))
;; (assert (= (length (first p)) 6))
;; (assert (= (ds::plist::get p :key1) 'value4))

(ds::plist::remove! p :key1)
;; p == ((:key2 value2,
;; :key1 value1))
;; (ds::plist::remove! p :key1)
;; ;; p == ((:key2 value2,
;; ;; :key1 value1))

(assert (= (length (first p)) 4))
(assert (= (ds::plist::get p :key1) 'value1))
(assert (= (ds::plist::get p :key2) 'value2))
;; (assert (= (length (first p)) 4))
;; (assert (= (ds::plist::get p :key1) 'value1))
;; (assert (= (ds::plist::get p :key2) 'value2))

+ 17
- 0
bin/tests/singular_imports.slime View File

@@ -0,0 +1,17 @@
(import "import1.slime")

(assert (= a 10))
(assert (= (get-a-1) 10))


(import "import2.slime")

(assert (= a 10))
(assert (= (get-a-1) 10))
(assert (= (get-a-2) 10))

(set-a-2 11)

(assert (= a 11))
(assert (= (get-a-1) 11))
(assert (= (get-a-2) 11))

+ 7
- 1
build.bat View File

@@ -7,7 +7,13 @@ set exeName=slime.exe
taskkill /F /IM %exeName% > NUL 2> NUL

echo ---------- Compiling ----------
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
call ..\timecmd cl ^
../src/main.cpp ^
/I../3rd/ ^
/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

if %errorlevel% == 0 (


+ 21
- 0
include/define_macros.hpp View File

@@ -128,3 +128,24 @@
#define in_caller_env fluid_let( \
Globals::Current_Execution::envi_stack.next_index, \
Globals::Current_Execution::envi_stack.next_index-1)


/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))

/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)

+ 5
- 0
include/libslime.h View File

@@ -1,3 +1,5 @@
#pragma once

#include <functional>
#include "ftb/arraylist.hpp"
#include "ftb/hashmap.hpp"
@@ -182,11 +184,13 @@ namespace Slime {

void visualize_lisp_machine();
void generate_docs(String* path);
void log_error();

namespace Memory {
extern Lisp_Object* nil;
extern Lisp_Object* t;

Environment* create_child_environment(Environment* parent);
Environment* create_built_ins_environment();
Lisp_Object* create_lisp_object_cfunction(bool is_special);
Lisp_Object* get_or_create_lisp_object_keyword(const char* identifier);
@@ -196,6 +200,7 @@ namespace Slime {
void free_everything();
String* create_string(const char*);
Lisp_Object* create_lisp_object_number(double);
Lisp_Object* create_lisp_object_pointer(void*);
Lisp_Object* get_or_create_lisp_object_symbol(String* identifier);
Lisp_Object* get_or_create_lisp_object_symbol(const char*);
Lisp_Object* get_or_create_lisp_object_keyword(String* identifier);


+ 36
- 0
me-management.org View File

@@ -0,0 +1,36 @@
* mallocs

|------------------------------------------+------------------------|
| location | always freed |
|------------------------------------------+------------------------|
| [[file:3rd\ftb\arraylist.hpp::11]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::17]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::44]]: | yes |
| [[file:.\3rd\ftb\bucket_allocator.hpp::46]]: | yes |
| [[file:.\src\io.cpp::49]]: | yes |
| [[file:.\src\io.cpp::164]]: | yes |
| [[file:.\src\io.cpp::209]]: | yes |
| [[file:.\src\io.cpp::285]]: | yes |
| [[file:.\src\memory.cpp::158]]: | yes in free_everything |
| [[file:.\src\platform.cpp::3]]: | yes |
| [[file:.\src\platform.cpp::27]]: | yes |
| [[file:.\src\platform.cpp::47]]: | yes |
| [[file:.\src\platform.cpp::81]]: | yes |
|------------------------------------------+------------------------|

* news

|----------------------------------+-------------------------------------------------------------------------------------|
| location | always deleted |
|----------------------------------+-------------------------------------------------------------------------------------|
| [[file:.\src\eval.cpp::262]]: | ::new (&(result->positional.symbols)) Array_List<Lisp_Object*>; |
| [[file:.\src\eval.cpp::263]]: | ::new (&(result->keyword.keywords)) Array_List<Lisp_Object*>; |
| [[file:.\src\eval.cpp:264]]: | ::new (&(result->keyword.values)) Array_List<Lisp_Object*>; |
| [[file:.\src\io.cpp:284]]: | // allocate a new block of memory size char (1 byte) instead of wide char (2 bytes) |
| [[file:.\src\io.cpp:306]]: | wchar_t* wc = new wchar_t[cSize]; |
| [[file:.\src\memory.cpp:336]]: | // node->value.lambdaWrapper = new Lambda_Wrapper(function); |
| [[file:.\src\memory.cpp:383]]: | // inject a new array list; |
| [[file:.\src\parse.cpp:195]]: | // better for keeping track of the encountered new lines and |
| [[file:.\src\parse.cpp:196]]: | // characters since last new line so we can update the parser |
| [[file:.\src\parse.cpp:208]]: | /* new col = (count chars since last \n) + 1 */ |
|----------------------------------+-------------------------------------------------------------------------------------|

+ 24
- 12
src/built_ins.cpp View File

@@ -69,35 +69,47 @@ proc built_in_load(String* file_name) -> Lisp_Object* {
}
create_generic_error("The file to load '%s' was not found in the load path.",
Memory::get_c_str(file_name));
return nullptr;
}

}


Lisp_Object* result = Memory::nil;
Array_List<Lisp_Object*> program;
Array_List<Lisp_Object*>* program;
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]);
}
delete program;

return result;
}

proc built_in_import(String* file_name) -> Lisp_Object* {
// create new empty environment
Environment* new_env;
try new_env = Memory::create_child_environment(get_root_environment());
get_current_environment()->parents.append(new_env);

push_environment(new_env);
defer {
pop_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());
// TODO(Felix): check absoulute paths in the map, not just
// relative ones
Memory::file_to_env_map.set_object(Memory::get_c_str(file_name), new_env);
push_environment(new_env);
defer {
pop_environment();
};

Lisp_Object* res;
try res = built_in_load(file_name);
}

Lisp_Object* res = built_in_load(file_name);
get_current_environment()->parents.append(new_env);

return res;
return Memory::nil;
}

proc load_built_ins_into_environment() -> void {


+ 21
- 0
src/define_macros.hpp View File

@@ -128,3 +128,24 @@
#define in_caller_env fluid_let( \
Globals::Current_Execution::envi_stack.next_index, \
Globals::Current_Execution::envi_stack.next_index-1)


/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))

/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)

+ 0
- 35
src/defines.cpp View File

@@ -16,41 +16,6 @@
# define if_linux if constexpr (true)
#endif

/*
* iterate over lisp vectors
*/
#define for_lisp_vector(v) \
if (!v); else \
if (int it_index = 0); else \
for (auto it = v->value.vector.data; \
it_index < v->value.vector.length; \
it=v->value.vector.data+(++it_index))

/*
* iterate over lisp lists
*/
#define for_lisp_list(l) \
if (!l); else \
if (int it_index = 0); else \
for (Lisp_Object* head = l, *it; \
Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \
head = head->value.pair.rest, ++it_index)



/*
#define assert(cond) \
if_debug { \
if (!cond) { \
if (log_level == Log_Level::Debug) { \
printf("Assertion failed: %s %d", __FILE__, __LINE__); \
} \
debug_break(); \
} \
} else {} \
*/


#define console_normal "\x1B[0m"
#define console_red "\x1B[31m"
#define console_green "\x1B[32m"


+ 3
- 3
src/eval.cpp View File

@@ -259,9 +259,9 @@ proc create_arguments_from_lambda_list_and_inject(Lisp_Object* arguments, Lisp_O
result = &function->value.function.args;
}

::new (&(result->positional.symbols)) Array_List<Lisp_Object*>;
::new (&(result->keyword.keywords)) Array_List<Lisp_Object*>;
::new (&(result->keyword.values)) Array_List<Lisp_Object*>;
::new (&result->positional.symbols) Array_List<Lisp_Object*>;
::new (&result->keyword.keywords) Array_List<Lisp_Object*>;
::new (&result->keyword.values) Array_List<Lisp_Object*>;

// first init the fields
// result->positional = create_positional_argument_list(16);


+ 3
- 0
src/libslime.cpp View File

@@ -1,7 +1,10 @@
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE

#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>

#include <stdio.h>
#include <time.h>
#include <string.h>


+ 6
- 0
src/lisp_object.cpp View File

@@ -39,3 +39,9 @@ proc append_to_keyword_argument_list(Keyword_Arguments* args,
args->keywords.append(keyword);
args->values.append(default_value);
}

Lisp_Object::~Lisp_Object() {
if (Memory::get_type(this) == Lisp_Object_Type::HashMap) {
this->value.hashMap.~Hash_Map();
}
}

+ 3
- 0
src/main.cpp View File

@@ -1,10 +1,13 @@
#include "libslime.cpp"


int main(int argc, char* argv[]) {
if (argc > 1) {
if (Slime::string_equal(argv[1], "--run-tests")) {
int res = Slime::run_all_tests();
// Slime::interprete_file((char*)"generate-docs.slime");

_CrtDumpMemoryLeaks();
return res ? 0 : 1;
}



+ 18
- 6
src/memory.cpp View File

@@ -6,6 +6,8 @@ namespace Memory {
Hash_Map<char*, Lisp_Object*> global_symbol_table;
Hash_Map<char*, Lisp_Object*> global_keyword_table;


Hash_Map<char*, Environment*> file_to_env_map;
// ------------------
// lisp_objects
// ------------------
@@ -177,13 +179,23 @@ namespace Memory {
free_spots_in_string_memory.next_index = 0;


::new((&global_symbol_table)) Hash_Map<char*, Lisp_Object*>;
::new((&global_keyword_table)) Hash_Map<char*, Lisp_Object*>;
global_symbol_table.~Hash_Map();
global_keyword_table.~Hash_Map();
file_to_env_map.~Hash_Map();

::new(&global_symbol_table) Hash_Map<char*, Lisp_Object*>;
::new(&global_keyword_table) Hash_Map<char*, Lisp_Object*>;
::new(&file_to_env_map) Hash_Map<char*, Lisp_Object*>;

try_void Parser::standard_in = create_string("stdin");

object_memory.reset();
environment_memory.reset();

object_memory.~Bucket_Allocator();
// environment_memory.~Bucket_Allocator();

::new(&object_memory) Bucket_Allocator<Lisp_Object, 1024>;
::new(&environment_memory) Bucket_Allocator<Environment, 1024>;

next_free_spot_in_string_memory = string_memory;


@@ -373,7 +385,7 @@ namespace Memory {
return copy_lisp_object(n);
}

proc create_child_environment(Environment* parent) -> Environment* {
proc create_child_environment(Environment* parent) -> Environment* {

Environment* env = environment_memory.allocate();

@@ -404,7 +416,7 @@ namespace Memory {

try load_built_ins_into_environment();

built_in_load(Memory::create_string("pre.slime"));
try built_in_load(Memory::create_string("pre.slime"));

return ret;
}


+ 7
- 8
src/parse.cpp View File

@@ -98,7 +98,6 @@ namespace Parser {

// get the atom
String* ret = Memory::create_string("", atom_length);
// char* atom = (char*)malloc(atom_length*sizeof(char)+1); // plus null char
strcpy(&ret->data, text+(*index_in_text));

// restore the original string
@@ -448,7 +447,7 @@ namespace Parser {

}

proc write_expanded_file(String* file_name, Array_List<Lisp_Object*> program) -> void {
proc write_expanded_file(String* file_name, Array_List<Lisp_Object*>* program) -> void {
const char* ext = ".expanded";
char* newName = (char*)calloc(10 + file_name->length, sizeof(char));
strcpy(newName, Memory::get_c_str(file_name));
@@ -465,21 +464,21 @@ namespace Parser {
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
if (program.data[i] == Memory::nil)
if (program->data[i] == Memory::nil)
continue;
print(program.data[i], true, f);
print(program->data[i], true, f);
fprintf(f, "\n\n");
}
}

proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*> {
proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*>* {
parser_file = file_name;
parser_line = 1;
parser_col = 0;

Array_List<Lisp_Object*> program;
Array_List<Lisp_Object*>* program = new Array_List<Lisp_Object*>;

int index_in_text = 0;

@@ -490,7 +489,7 @@ namespace Parser {
try_struct {
parsed = parse_expression(text, &index_in_text);
}
program.append(parsed);
program->append(parsed);
} break;
case ';':
case ' ':


+ 8
- 1
src/structs.cpp View File

@@ -103,6 +103,11 @@ struct Arguments {
struct Environment {
Array_List<Environment*> parents;
Hash_Map<void*, Lisp_Object*> hm;

~Environment() {
parents.~Array_List();
hm.~Hash_Map();
}
};

struct Function {
@@ -123,7 +128,7 @@ struct Lisp_Object {
u64 flags;
Lisp_Object* userType; // keyword
String* docstring;
union {
union value {
Symbol symbol; // used for symbols and keywords
double number;
String* string;
@@ -134,7 +139,9 @@ struct Lisp_Object {
void* pointer;
Continuation continuation;
Hash_Map<Lisp_Object*, Lisp_Object*> hashMap;
~value() {}
} value;
~Lisp_Object();
};

struct Error {


+ 2
- 1
src/testing.cpp View File

@@ -596,7 +596,7 @@ proc test_file(const char* file) -> testresult {
pop_environment();
};

built_in_load(Memory::create_string(file));
try built_in_load(Memory::create_string(file));
assert_no_error();

return pass;
@@ -654,6 +654,7 @@ proc run_all_tests() -> bool {
invoke_test_script("automata");
invoke_test_script("sicp");
invoke_test_script("hashmaps");
invoke_test_script("singular_imports");

// Memory::print_status();



Loading…
Cancel
Save