From 9295d57a8e7d55ba550c02cf7ad0c74b670c01aa Mon Sep 17 00:00:00 2001 From: Felix Brendel Date: Wed, 18 Mar 2020 22:56:40 +0100 Subject: [PATCH] Big String refacor: now len+pointer, no String storage anymore --- 3rd/ftb | 2 +- bin/pre.slime | 16 ++-- include/assert.hpp | 4 +- include/libslime.h | 2 +- src/assert.hpp | 4 +- src/built_ins.cpp | 64 +++++++------ src/define_macros.hpp | 19 ++-- src/docgeneration.cpp | 11 ++- src/env.cpp | 12 +-- src/error.cpp | 9 +- src/eval.cpp | 18 ++-- src/forward_decls.cpp | 25 ++--- src/gc.cpp | 7 +- src/io.cpp | 17 ++-- src/libslime.cpp | 8 +- src/lisp_object.cpp | 20 +--- src/main.cpp | 3 +- src/memory.cpp | 211 ++++++++++++++++++++++-------------------- src/parse.cpp | 34 ++++--- src/structs.cpp | 14 ++- src/testing.cpp | 23 +++-- 21 files changed, 275 insertions(+), 248 deletions(-) diff --git a/3rd/ftb b/3rd/ftb index 98aa145..e5cb9ce 160000 --- a/3rd/ftb +++ b/3rd/ftb @@ -1 +1 @@ -Subproject commit 98aa1450d8e63046d3260ea7fb4ff12c9c7e2629 +Subproject commit e5cb9ce81d822fee56bdef1f44b3f8d1a29618de diff --git a/bin/pre.slime b/bin/pre.slime index f073d43..9f0cc94 100644 --- a/bin/pre.slime +++ b/bin/pre.slime @@ -1,3 +1,10 @@ +;; (remove_when_double_free_is_fixed) +;; (remove_when_double_free_is_fixed_2) +;; (define (kk (:key ())) +;; ()) + +;; (kk) + (define hm/set! hash-map-set!) (define hm/get hash-map-get) @@ -5,12 +12,12 @@ (mytry (hm/get hm key) ())) (define-syntax (pe expr) - `((begin + `(begin (print :end " " ',expr "evaluates to") ((lambda (e) (print e) e) ,expr)) - )) + ) (define the-empty-stream ()) @@ -175,11 +182,6 @@ condition is false." (rec body)) -;; (define-syntax (apply fun seq) -;; "Applies the function to the sequence, as in calls the function with -;; ithe sequence as arguemens." -;; `(eval (pair ,fun ,seq))) - (define-syntax (define-typed args . body) (define (get-arg-names args) (when args diff --git a/include/assert.hpp b/include/assert.hpp index 5d6a148..168ef96 100644 --- a/include/assert.hpp +++ b/include/assert.hpp @@ -33,8 +33,8 @@ do { \ if (Memory::get_type(_node) != _type) { \ create_type_missmatch_error( \ - Lisp_Object_Type_to_string(_type), \ - Lisp_Object_Type_to_string(Memory::get_type(_node))); \ + lisp_object_type_to_string(_type), \ + lisp_object_type_to_string(Memory::get_type(_node))); \ } \ } while(0) diff --git a/include/libslime.h b/include/libslime.h index f0f6173..4f85ff5 100644 --- a/include/libslime.h +++ b/include/libslime.h @@ -178,7 +178,7 @@ namespace Slime { inline void push_environment(Environment*); inline void pop_environment(); - const char* Lisp_Object_Type_to_string(Lisp_Object_Type type); + const char* lisp_object_type_to_string(Lisp_Object_Type type); void visualize_lisp_machine(); void generate_docs(String* path); diff --git a/src/assert.hpp b/src/assert.hpp index 8038d9d..527e643 100644 --- a/src/assert.hpp +++ b/src/assert.hpp @@ -35,8 +35,8 @@ char* t = lisp_object_to_string(_node); \ defer { free(t); }; \ create_type_missmatch_error( \ - Lisp_Object_Type_to_string(_type), \ - Lisp_Object_Type_to_string(Memory::get_type(_node)), \ + lisp_object_type_to_string(_type), \ + lisp_object_type_to_string(Memory::get_type(_node)), \ t); \ } \ } while(0) diff --git a/src/built_ins.cpp b/src/built_ins.cpp index c8e7a0c..3d57cc0 100644 --- a/src/built_ins.cpp +++ b/src/built_ins.cpp @@ -64,12 +64,12 @@ namespace Slime { proc add_to_load_path(const char* path) -> void { using Globals::load_path; - + load_path.append((void*)path); } - proc built_in_load(String* file_name) -> Lisp_Object* { - profile_with_comment(&file_name->data); + proc built_in_load(String file_name) -> Lisp_Object* { + profile_with_comment(file_name.data); char* file_content; char fullpath[4096]; sprintf(fullpath, "%s", Memory::get_c_str(file_name)); @@ -98,7 +98,11 @@ namespace Slime { Lisp_Object* result = Memory::nil; Array_List* program; - try program = Parser::parse_program(Memory::create_string(fullpath), file_content); + String spath = Memory::create_string(fullpath); + defer { + free(spath.data); + }; + try program = Parser::parse_program(spath, file_content); // NOTE(Felix): deferred so even if the eval failes, it will // run @@ -114,7 +118,7 @@ namespace Slime { return result; } - proc built_in_import(String* file_name) -> Lisp_Object* { + proc built_in_import(String file_name) -> Lisp_Object* { profile_this(); Environment* new_env; @@ -142,8 +146,16 @@ namespace Slime { proc load_built_ins_into_environment() -> void* { profile_this(); - String* file_name_built_ins = Memory::create_string(__FILE__); - + String file_name_built_ins = Memory::create_string(__FILE__); + defer { + free(file_name_built_ins.data); + }; + define((remove_when_double_free_is_fixed (:k1 ()) (:k2 ()) . rest), "") { + return Memory::nil; + }; + define((remove_when_double_free_is_fixed_2 (:k1 ()) (:k2 ()) . rest), "") { + return Memory::nil; + }; define_macro((apply fun fun_args), "TODO") { // NOTE(Felix): is has to be a macro because apply by // itself cannot return the result, we have to invoke eval @@ -199,7 +211,7 @@ namespace Slime { define_symbol( Memory::get_symbol("c"), Memory::create_lisp_object((double)0)); - String* file_name_built_ins = Memory::create_string(__FILE__); + String file_name_built_ins = Memory::create_string(__FILE__); define((lambda), "") { fetch(c); c->value.number++; @@ -314,7 +326,8 @@ namespace Slime { thing_cons->value.pair.rest != Memory::nil) { // extract docs - func->docstring = thing_cons->value.pair.first->value.string; + //TODO(Felix): make docs as HM lookup + // func->docstring = thing_cons->value.pair.first->value.string; thing_cons = thing_cons->value.pair.rest; } func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons); @@ -580,15 +593,10 @@ namespace Slime { free(string); return nullptr; }; - define_special((define-syntax form (:doc "") . body), "TODO") { + define_special((define-syntax form . body), "TODO") { profile_with_name("(define-syntax)"); - fetch(form, doc, body); - - try assert_type(doc, Lisp_Object_Type::String); - // if no doc string, we dont have to store it - if (Memory::get_c_str(doc)[0] == '\0') { - doc = nullptr; - } + fetch(form, body); + // TODO(Felix): Macros cannot have docs now if (Memory::get_type(form) != Lisp_Object_Type::Pair) { create_parsing_error("You can only create function macros."); @@ -601,8 +609,6 @@ namespace Slime { // creating new lisp object and setting type Lisp_Object* func; try func = Memory::create_lisp_object_function(Lisp_Function_Type::Macro); - if (doc) func->docstring = doc->value.string; - in_caller_env { // setting parent env func->value.function->parent_environment = get_current_environment(); @@ -1017,13 +1023,15 @@ namespace Slime { printf(" is of type "); print(type); - printf(" (internal: %s)", Lisp_Object_Type_to_string(Memory::get_type(val))); + printf(" (internal: %s)", lisp_object_type_to_string(Memory::get_type(val))); printf("\nand is printed as: "); print(val); printf("\n\ndocs:\n=====\n %s\n\n", - (val->docstring) - ? Memory::get_c_str(val->docstring) - : "No docs avaliable"); + // TODO(felix): Doc HM lookup + // (val->docstring) + // ? Memory::get_c_str(val->docstring) + // : + "No docs avaliable"); if (Memory::get_type(val) == Lisp_Object_Type::Function) { @@ -1125,7 +1133,7 @@ namespace Slime { defer { free(line); }; - String* strLine = Memory::create_string(line); + String strLine = Memory::create_string(line); return Memory::create_lisp_object(strLine); }; define((exit (:code 0)), "TODO") { @@ -1240,16 +1248,16 @@ namespace Slime { int resulting_string_len = 0; for_lisp_list (strings) { try assert_type(it, Lisp_Object_Type::String); - resulting_string_len += it->value.string->length; + resulting_string_len += it->value.string.length; } - String* resulting_string = Memory::create_string("", resulting_string_len); + String resulting_string = Memory::create_string("", resulting_string_len); int index_in_string = 0; for_lisp_list (strings) { - strcpy((&resulting_string->data)+index_in_string, + strcpy(resulting_string.data+index_in_string, Memory::get_c_str(it->value.string)); - index_in_string += it->value.string->length; + index_in_string += it->value.string.length; } return Memory::create_lisp_object(resulting_string); diff --git a/src/define_macros.hpp b/src/define_macros.hpp index 5683dde..046fb9f 100644 --- a/src/define_macros.hpp +++ b/src/define_macros.hpp @@ -42,7 +42,7 @@ #endif #define try_struct try_or_else_return({}) -#define try_void try_or_else_return() +#define try_void try_or_else_return(;) #define try try_or_else_return(0) #define dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) @@ -105,15 +105,14 @@ #endif // NOTE(Felix): we have to copy the string because we need it to be -// mutable for the parser to work, 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, docs, type, ending) \ +// mutable for the parser to work, (#def gives us a const char) +// 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, docs, type, ending) \ Parser::parser_file = file_name_built_ins; \ Parser::parser_line = __LINE__; \ Parser::parser_col = 0; \ - auto label(params,__LINE__) = Parser::parse_single_expression( \ - Memory::get_c_str(Memory::create_string(#def))); \ + auto label(params,__LINE__) = Parser::parse_single_expression(#def); \ if_error_log_location_and_return(nullptr); \ assert_type(label(params,__LINE__), Lisp_Object_Type::Pair); \ assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \ @@ -121,7 +120,7 @@ auto label(sfun,__LINE__) = Memory::create_lisp_object_cfunction(type); \ create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ if_error_log_location_and_return(nullptr); \ - label(sfun,__LINE__)->docstring = Memory::create_string(docs); \ + /* TODO(Felix): label(sfun,__LINE__)->docstring = Memory::create_string(docs); */ \ label(sfun,__LINE__)->value.function->parent_environment = get_current_environment(); \ define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ label(sfun,__LINE__)->value.function->body. ending @@ -154,3 +153,7 @@ 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 dbg(thing, format) \ + printf("%s = " format "\n", #thing, thing) diff --git a/src/docgeneration.cpp b/src/docgeneration.cpp index 433a5d0..e038006 100644 --- a/src/docgeneration.cpp +++ b/src/docgeneration.cpp @@ -1,5 +1,5 @@ namespace Slime { - proc generate_docs(String* path) -> void { + proc generate_docs(String path) -> void { FILE *f = fopen(Memory::get_c_str(path), "w"); if (!f) { create_generic_error("The file for writing the documentation (%s) " @@ -124,10 +124,11 @@ namespace Slime { } } fprintf(f, "\n - docu :: "); - if (value->docstring) - fprintf(f, "\n #+BEGIN:\n%s\n #+END:\n", - Memory::get_c_str(value->docstring)); - else + // TODO(Felix): make docsting a hashmap lookup + // if (value->docstring) + // fprintf(f, "\n #+BEGIN:\n%s\n #+END:\n", + // Memory::get_c_str(value->docstring)); + // else fprintf(f, "none\n"); } } diff --git a/src/env.cpp b/src/env.cpp index ab603f9..36777c8 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -1,11 +1,11 @@ namespace Slime { proc define_symbol(Lisp_Object* symbol, Lisp_Object* value) -> void { - profile_with_comment(&symbol->value.symbol->data); + profile_with_comment(symbol->value.symbol.data); define_symbol(symbol, value, get_current_environment()); } proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> void { - profile_with_comment(&symbol->value.symbol->data); + profile_with_comment(symbol->value.symbol.data); env->hm.set_object((void*)symbol, value); } @@ -76,7 +76,7 @@ namespace Slime { } proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { - profile_with_comment(&node->value.symbol->data); + profile_with_comment(node->value.symbol.data); // print(node); assert_type(node, Lisp_Object_Type::Symbol); @@ -85,10 +85,10 @@ namespace Slime { if (result) return result; - String* identifier = node->value.symbol; + String identifier = node->value.symbol; print_environment(env); printf("\n"); - create_symbol_undefined_error("The symbol '%s' is not defined.", &identifier->data); + create_symbol_undefined_error("The symbol '%s' is not defined.", identifier.data); return nullptr; } @@ -108,7 +108,7 @@ namespace Slime { for_hash_map (env->hm) { print_indent(indent); - printf("-> %s :: ", &(((Lisp_Object*)key)->value.symbol->data)); + printf("-> %s :: ", (((Lisp_Object*)key)->value.symbol.data)); print((Lisp_Object*)value); printf(" (0x%016llx)", (unsigned long long)value); puts(""); diff --git a/src/error.cpp b/src/error.cpp index 02537eb..b1ba966 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -7,7 +7,7 @@ namespace Slime { error = nullptr; } - proc create_error(const char* c_func_name,const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { + proc create_error(const char* c_func_name,const char* c_file_name, int c_file_line, Lisp_Object* type, String message) -> void { delete_error(); if (Globals::breaking_on_errors) { debug_break(); @@ -36,8 +36,9 @@ namespace Slime { proc create_error(const char* c_func_name, const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...) -> void { using Globals::error; + // TODO(Felix): is the length even used?? int length = 200; - String* formatted_string = Memory::create_string("", length); + String formatted_string = Memory::create_string("", length); if (error) { error = new(Error); error->type = type; @@ -49,8 +50,8 @@ namespace Slime { written_length = vasprintf(&out_msg, format, args); va_end(args); - formatted_string->length = written_length; - strcpy(&formatted_string->data, out_msg); + formatted_string.length = written_length; + strcpy(formatted_string.data, out_msg); free(out_msg); create_error(c_func_name, c_file_name, c_file_line, type, formatted_string); } diff --git a/src/eval.cpp b/src/eval.cpp index 48557ef..9bde9c0 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -31,7 +31,7 @@ namespace Slime { "Not enough positional args supplied. Needed: %d suppied, %d.\n" "Next missing arg is '%s'", arg_spec->positional.symbols.next_index, arg_end-index_of_next_arg, - &arg_spec->positional.symbols.data[i]->value.symbol->data); + arg_spec->positional.symbols.data[i]->value.symbol.data); return nullptr; } // NOTE(Felix): We have to copy all the arguments, @@ -75,7 +75,7 @@ namespace Slime { "The function does not take the keyword argument ':%s'\n" "and not all required keyword arguments have been read\n" "in to potentially count it as the rest argument.", - &(cs.data[index_of_next_arg]->value.symbol->data)); + cs.data[index_of_next_arg]->value.symbol.data); return nullptr; } // This is an accepted kwarg; check if it was already @@ -92,7 +92,7 @@ namespace Slime { // in, it is an error create_generic_error( "The function already read the keyword argument ':%s'", - &(cs.data[index_of_next_arg]->value.symbol->data)); + cs.data[index_of_next_arg]->value.symbol.data); return nullptr; } } @@ -102,7 +102,7 @@ namespace Slime { if (index_of_next_arg+1 == arg_end) { create_generic_error( "Attempting to set the keyword argument ':%s', but no value was supplied.", - &(cs.data[index_of_next_arg]->value.symbol->data)); + cs.data[index_of_next_arg]->value.symbol.data); return nullptr; } @@ -145,7 +145,7 @@ namespace Slime { create_generic_error( "There was no value supplied for the required " "keyword argument ':%s'.", - &defined_keyword->value.symbol->data); + defined_keyword->value.symbol.data); return nullptr; } } else { @@ -240,7 +240,7 @@ namespace Slime { create_parsing_error("Only symbols and keywords " "(with or without default args) " "can be parsed here, but found '%s'", - Lisp_Object_Type_to_string(Memory::get_type(arguments->value.pair.first))); + lisp_object_type_to_string(Memory::get_type(arguments->value.pair.first))); return; } @@ -444,7 +444,7 @@ namespace Slime { free(t); }; create_generic_error("The first element of the pair was not a function but: %s in %s", - Lisp_Object_Type_to_string(type), t); + lisp_object_type_to_string(type), t); return nullptr; } } @@ -515,7 +515,7 @@ namespace Slime { } proc interprete_file (char* file_name) -> Lisp_Object* { - try Memory::init(4096 * 256); + try Memory::init(); Lisp_Object* result; @@ -525,7 +525,7 @@ namespace Slime { } proc interprete_stdin() -> void { - try_void Memory::init(4096 * 256* 100); + try_void Memory::init(); printf("Welcome to the lispy interpreter.\n%s\n", version_string); diff --git a/src/forward_decls.cpp b/src/forward_decls.cpp index 52b485a..0b8bd90 100644 --- a/src/forward_decls.cpp +++ b/src/forward_decls.cpp @@ -1,11 +1,11 @@ namespace Slime { void add_to_load_path(const char*); bool lisp_object_equal(Lisp_Object*,Lisp_Object*); - Lisp_Object* built_in_load(String*); - Lisp_Object* built_in_import(String*); + Lisp_Object* built_in_load(String); + Lisp_Object* built_in_import(String); void delete_error(); void create_error(const char* c_func_name, const char* c_file_name, int c_file_line, Lisp_Object* type, const char* format, ...); - void create_error(const char* c_func_name, const char* c_file_name, int c_file_line, Lisp_Object* type, String* message); + void create_error(const char* c_func_name, const char* c_file_name, int c_file_line, Lisp_Object* type, String message); void create_error(Lisp_Object* type, const char* message, const char* c_file_name, int c_file_line); Lisp_Object* eval_arguments(Lisp_Object*); Lisp_Object* eval_expr(Lisp_Object*); @@ -28,23 +28,23 @@ namespace Slime { inline void push_environment(Environment*); inline void pop_environment(); - const char* Lisp_Object_Type_to_string(Lisp_Object_Type type); + const char* lisp_object_type_to_string(Lisp_Object_Type type); void visualize_lisp_machine(); - void generate_docs(String* path); + void generate_docs(String path); void log_error(); namespace Memory { Environment* create_built_ins_environment(); Lisp_Object* create_lisp_object_cfunction(bool is_special); inline Lisp_Object_Type get_type(Lisp_Object* node); - void init(int); - char* get_c_str(String*); + void init(); + char* get_c_str(String); void free_everything(); - String* create_string(const char*); - Lisp_Object* get_symbol(String* identifier); + String create_string(const char*); + Lisp_Object* get_symbol(String identifier); Lisp_Object* get_symbol(const char*); - Lisp_Object* get_keyword(String* identifier); + Lisp_Object* get_keyword(String identifier); Lisp_Object* get_keyword(const char*); Lisp_Object* create_lisp_object(double); Lisp_Object* create_lisp_object(const char*); @@ -63,12 +63,13 @@ namespace Slime { namespace Parser { // extern Environment* environment_for_macros; - extern String* standard_in; - extern String* parser_file; + extern String standard_in; + extern String parser_file; extern int parser_line; extern int parser_col; Lisp_Object* parse_expression(char* text, int* index_in_text); + Lisp_Object* parse_single_expression(const char* text); Lisp_Object* parse_single_expression(char* text); Lisp_Object* parse_single_expression(wchar_t* text); } diff --git a/src/gc.cpp b/src/gc.cpp index e62fd29..f08b841 100644 --- a/src/gc.cpp +++ b/src/gc.cpp @@ -4,7 +4,7 @@ namespace Slime::GC { int current_mark; Array_List marked_objects; - Array_List marked_strings; + Array_List marked_strings; Array_List marked_environments; Array_List protected_environments; @@ -24,8 +24,9 @@ namespace Slime::GC { marked_objects.append(node); // mark docstring - if (node->docstring) - marked_strings.append(node->docstring); + // TODO(Felix): + // if (node->docstring) + // marked_strings.append(node->docstring); // mark type specific data switch (Memory::get_type(node)) { diff --git a/src/io.cpp b/src/io.cpp index 510a113..3cd90ff 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -10,18 +10,15 @@ namespace Slime { return false; } - proc string_equal(String* str, const char check[]) -> bool { + proc string_equal(String str, const char check[]) -> bool { return string_equal(Memory::get_c_str(str), check); } - proc string_equal(const char check[], String* str) -> bool { + proc string_equal(const char check[], String str) -> bool { return string_equal(Memory::get_c_str(str), check); } - proc string_equal(String* str1, String* str2) -> bool { - if (str1 == str2) - return true; - + proc string_equal(String str1, String str2) -> bool { return string_equal(Memory::get_c_str(str1), Memory::get_c_str(str2)); } @@ -401,9 +398,9 @@ namespace Slime { Lisp_Object* name = (Lisp_Object*)(get_root_environment()->hm.search_key_to_object(node)); if (name) { switch (node->value.function->type.c_function_type) { - case C_Function_Type::cFunction: asprintf(&temp, "[c-function %s]",&((Lisp_Object*)name)->value.symbol->data); break; - case C_Function_Type::cSpecial: asprintf(&temp, "[c-special %s]", &((Lisp_Object*)name)->value.symbol->data); break; - case C_Function_Type::cMacro: asprintf(&temp, "[c-macro %s]", &((Lisp_Object*)name)->value.symbol->data); break; + case C_Function_Type::cFunction: asprintf(&temp, "[c-function %s]",name->value.symbol.data); break; + case C_Function_Type::cSpecial: asprintf(&temp, "[c-special %s]", name->value.symbol.data); break; + case C_Function_Type::cMacro: asprintf(&temp, "[c-macro %s]", name->value.symbol.data); break; default: return strdup("[c-??]"); } } else { @@ -435,7 +432,7 @@ namespace Slime { // first check if it is a quotation form, in that case we want // to print it prettier if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) { - String* identifier = head->value.pair.first->value.symbol; + String identifier = head->value.pair.first->value.symbol; auto symbol = head->value.pair.first; diff --git a/src/libslime.cpp b/src/libslime.cpp index 7796210..3bd2d8d 100644 --- a/src/libslime.cpp +++ b/src/libslime.cpp @@ -47,15 +47,15 @@ unsigned int hm_hash(Slime::Lisp_Object* obj); # include "forward_decls.cpp" -bool hm_objects_match(char* a, char* b) { +inline bool hm_objects_match(char* a, char* b) { return strcmp(a, b) == 0; } -bool hm_objects_match(void* a, void* b) { +inline bool hm_objects_match(void* a, void* b) { return a == b; } -bool hm_objects_match(Slime::Lisp_Object* a, Slime::Lisp_Object* b) { +inline bool hm_objects_match(Slime::Lisp_Object* a, Slime::Lisp_Object* b) { return Slime::lisp_object_equal(a, b); } @@ -88,7 +88,7 @@ unsigned int hm_hash(Slime::Lisp_Object* obj) { // 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::String: return hm_hash((char*) obj->value.string.data); case Lisp_Object_Type::Pair: { u32 hash = 1; for_lisp_list (obj) { diff --git a/src/lisp_object.cpp b/src/lisp_object.cpp index 7347f71..3164dbd 100644 --- a/src/lisp_object.cpp +++ b/src/lisp_object.cpp @@ -1,6 +1,6 @@ namespace Slime { - proc create_source_code_location(String* file, int line, int col) -> Source_Code_Location* { - if (!file) + proc create_source_code_location(String file, int line, int col) -> Source_Code_Location* { + if (!file.data) return nullptr; Source_Code_Location* ret = (Source_Code_Location*)malloc(sizeof(Source_Code_Location)); @@ -10,7 +10,7 @@ namespace Slime { return ret; } - proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char* { + proc lisp_object_type_to_string(Lisp_Object_Type type) -> const char* { switch (type) { case(Lisp_Object_Type::Nil): return "nil"; case(Lisp_Object_Type::T): return "t"; @@ -28,18 +28,4 @@ namespace Slime { return "unknown"; } - Lisp_Object::~Lisp_Object() { - free(sourceCodeLocation); - sourceCodeLocation = 0; - - switch (Memory::get_type(this)) { - case Lisp_Object_Type::Function:{ - this->value.function->args.positional.symbols.dealloc(); - this->value.function->args.keyword.keywords.dealloc(); - this->value.function->args.keyword.values.dealloc(); - free(this->value.function); - } break; - default: break; - } - } } diff --git a/src/main.cpp b/src/main.cpp index 617deec..84c99de 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,7 +16,7 @@ int main(int argc, char* argv[]) { int res = Slime::run_all_tests(); return res ? 0 : 1; } else if (Slime::string_equal(argv[1], "--generate-docs")) { - Slime::Memory::init(4096 * 256* 100); + Slime::Memory::init(); if (Slime::Globals::error) return 1; Slime::built_in_load(Slime::Memory::create_string("generate-docs.slime")); } else { @@ -28,5 +28,4 @@ int main(int argc, char* argv[]) { } if (Slime::Globals::error) return 1; - } diff --git a/src/memory.cpp b/src/memory.cpp index cf73397..b543bb4 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -28,26 +28,11 @@ namespace Slime::Memory { // ------------------ Bucket_Allocator> hashmap_memory; - // ------------------ - // strings - // ------------------ - int string_memory_size; // = 4096 * 1024; // == 98304kb == 96mb - // free_spots_in_string_memory is an arraylist of pointers into - // the string_memory, where dead String objects live (which give - // information about their size) - Array_List free_spots_in_string_memory; - String* string_memory; - String* next_free_spot_in_string_memory; - // ------------------ // immutables // ------------------ Lisp_Object* nil = nullptr; Lisp_Object* t = nullptr; - Lisp_Object* _if = nullptr; - Lisp_Object* _define = nullptr; - Lisp_Object* _begin = nullptr; - proc print_status() { @@ -66,8 +51,8 @@ namespace Slime::Memory { // free_spots_in_string_memory.next_index); } - inline proc get_c_str(String* str) -> char* { - return &str->data; + inline proc get_c_str(String str) -> char* { + return str.data; } inline proc get_c_str(Lisp_Object* str) -> char* { @@ -89,49 +74,35 @@ namespace Slime::Memory { node->flags = (u64)(node->flags) | bitmask; } - proc hash(String* str) -> u64 { + proc hash(String str) -> u64 { // TODO(Felix): When parsing symbols or keywords, compute the // hash while reading them in. - u64 value = str->data << 7; - for (int i = 1; i < str->length; ++i) { - char c = ((char*)&str->data)[i]; + u64 value = str.data[0] << 7; + for (int i = 1; i < str.length; ++i) { + char c = str.data[i]; value = (1000003 * value) ^ c; } - value ^= str->length; + value ^= str.length; return value; } - proc create_string(const char* str, int len) -> String* { - // TODO(Felix): check the holes first, not just always append - // at the end - - String* ret = next_free_spot_in_string_memory; - ret->length = len; - strcpy(&ret->data, str); - - // now update the next_free_spot_in_string_memory pointer: - // overstrep the counter and the first char (thik of it as if - // we were overstepping the last ('\0') char) and then we only - // need to overstep 'len' more chars - next_free_spot_in_string_memory += 1; - - // overstep the other chars - next_free_spot_in_string_memory = ((String*)((char*)next_free_spot_in_string_memory)+len); - return ret; - } - - proc delete_string(String* str) { - free_spots_in_string_memory.append((void*)str); + proc create_string(const char* str, int len) -> String { + String s = { + len, + (char*)malloc(sizeof(char) * len + 1) + }; + strcpy(s.data, str); + return s; } - proc duplicate_string(String* str) -> String* { - return create_string(get_c_str(str), str->length); + proc create_string (const char* str) -> String { + return create_string(str, (int)strlen(str)); } - proc create_string (const char* str) -> String* { - return create_string(str, (int)strlen(str)); + proc duplicate_string(String str) -> String { + return create_string(str.data, str.length); } proc create_lisp_object() -> Lisp_Object* { @@ -139,14 +110,28 @@ namespace Slime::Memory { object->flags = 0; object->sourceCodeLocation = nullptr; object->userType = nullptr; - object->docstring = nullptr; return object; } proc free_everything() -> void { - free(string_memory); object_memory.for_each([](Lisp_Object* lo){ - lo->~Lisp_Object(); + free(lo->sourceCodeLocation); + lo->sourceCodeLocation = 0; + + switch (Memory::get_type(lo)) { + case Lisp_Object_Type::Function: { + lo->value.function->args.positional.symbols.dealloc(); + lo->value.function->args.keyword.keywords.dealloc(); + lo->value.function->args.keyword.values.dealloc(); + free(lo->value.function); + } break; + case Lisp_Object_Type::Symbol: + case Lisp_Object_Type::Keyword: + case Lisp_Object_Type::String: { + free(lo->value.string.data); + } break; + default: break; + } }); environment_memory.for_each([](Environment* env){ env->parents.dealloc(); @@ -155,6 +140,7 @@ namespace Slime::Memory { hashmap_memory.for_each([](Hash_Map* hm){ hm->dealloc(); }); + // free the exe dir: free(Globals::load_path.data[0]); Globals::load_path.dealloc(); @@ -166,6 +152,8 @@ namespace Slime::Memory { Globals::Current_Execution::ats.dealloc(); Globals::Current_Execution::mes.dealloc(); + free(Parser::standard_in.data); + object_memory.dealloc(); environment_memory.dealloc(); hashmap_memory.dealloc(); @@ -197,7 +185,7 @@ namespace Slime::Memory { return ret; } - proc init(int sms) -> void { + proc init() -> void { profile_this(); object_memory.alloc(1024, 8); @@ -228,10 +216,6 @@ namespace Slime::Memory { add_to_load_path(exe_path); add_to_load_path("../bin/"); - string_memory_size = sms; - string_memory = (String*)malloc(string_memory_size * sizeof(char)); - - next_free_spot_in_string_memory = string_memory; // init nil try_void nil = create_lisp_object(); @@ -279,7 +263,7 @@ namespace Slime::Memory { return node; } - proc create_lisp_object(String* str) -> Lisp_Object* { + proc create_lisp_object(String str) -> Lisp_Object* { Lisp_Object* node; try node = create_lisp_object(); set_type(node, Lisp_Object_Type::String); @@ -368,53 +352,68 @@ namespace Slime::Memory { return node; } - - - proc get_symbol(String* identifier) -> Lisp_Object* { - Lisp_Object* node = global_symbol_table.get_object(get_c_str(identifier)); - if (node) - return (Lisp_Object*)node; - + inline proc _create_symbol(char* identifier) -> Lisp_Object* { + Lisp_Object* node; try node = create_lisp_object(); set_type(node, Lisp_Object_Type::Symbol); - node->value.symbol = identifier; - global_symbol_table.set_object(get_c_str(identifier), node); + node->value.symbol = create_string(identifier); + global_symbol_table.set_object((char*)node->value.symbol.data, node); return node; } - proc get_symbol(const char* identifier) -> Lisp_Object* { - if (auto ret = global_symbol_table.get_object((char*)identifier)) - return (Lisp_Object*)ret; - else { - String* str; - try str = Memory::create_string(identifier); - return get_symbol(str); - } + inline proc get_symbol(String identifier) -> Lisp_Object* { + return get_symbol(identifier.data); } - proc get_keyword(String* keyword) -> Lisp_Object* { - Lisp_Object* node = global_keyword_table.get_object(get_c_str(keyword)); - if (node) - return (Lisp_Object*)node; + inline proc get_symbol(const char* identifier) -> Lisp_Object* { + if (Lisp_Object* ret = global_symbol_table.get_object((char*)identifier)) + return (Lisp_Object*)ret; + return _create_symbol((char*)identifier); + } + inline proc _create_keyword(char* identifier) -> Lisp_Object* { + Lisp_Object* node; try node = create_lisp_object(); set_type(node, Lisp_Object_Type::Keyword); - node->value.symbol = keyword; - global_keyword_table.set_object(get_c_str(keyword), node); + node->value.symbol = create_string(identifier); + global_keyword_table.set_object((char*)node->value.symbol.data, node); return node; } + inline proc get_keyword(String identifier) -> Lisp_Object* { + return get_keyword(identifier.data); + } - proc get_keyword(const char* keyword) -> Lisp_Object* { - if (auto ret = global_keyword_table.get_object((char*)keyword)) - return (Lisp_Object*)ret; - else { - String* str; - try str = Memory::create_string(keyword); - return get_keyword(str); - } + inline proc get_keyword(const char* identifier) -> Lisp_Object* { + if (Lisp_Object* ret = global_keyword_table.get_object((char*)identifier)) + return ret; + return _create_keyword((char*)identifier); } + + // proc get_keyword(String keyword) -> Lisp_Object* { + // Lisp_Object* node = global_keyword_table.get_object(get_c_str(keyword)); + // if (node) + // return (Lisp_Object*)node; + + // try node = create_lisp_object(); + // set_type(node, Lisp_Object_Type::Keyword); + // node->value.symbol = duplicate_string(keyword); + // global_keyword_table.set_object(get_c_str(keyword), node); + // return node; + // } + + + // proc get_keyword(const char* keyword) -> Lisp_Object* { + // if (auto ret = global_keyword_table.get_object((char*)keyword)) + // return (Lisp_Object*)ret; + // else { + // String str; + // try str = Memory::create_string(keyword); + // return get_keyword(str); + // } + // } + proc create_lisp_object_cfunction(C_Function_Type type) -> Lisp_Object* { Lisp_Object* node; try node = create_lisp_object(); @@ -455,19 +454,29 @@ namespace Slime::Memory { // TODO(Felix): If argument is a list (pair), do a FULL copy, // we don't copy singleton objects - if (n == Memory::nil || n == Memory::t || - Memory::get_type(n) == Lisp_Object_Type::Symbol || - Memory::get_type(n) == Lisp_Object_Type::Keyword || - Memory::get_type(n) == Lisp_Object_Type::Function) - { + if (n == Memory::nil || n == Memory::t) { return n; + } else { + Lisp_Object_Type type = Memory::get_type(n); + if (type == Lisp_Object_Type::Symbol || + type == Lisp_Object_Type::Keyword || + type == Lisp_Object_Type::Function) + { + return n; + } else if (type == 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 { + Lisp_Object* target; + try target = create_lisp_object(); + *target = *n; + + return target; + } } - - Lisp_Object* target; - try target = create_lisp_object(); - *target = *n; - - return target; } proc copy_lisp_object_except_pairs(Lisp_Object* n) -> Lisp_Object* { @@ -485,11 +494,13 @@ namespace Slime::Memory { }; try load_built_ins_into_environment(); - try built_in_load(Memory::create_string("pre.slime")); + String file_name = Memory::create_string("pre.slime"); + try built_in_load(file_name); + free(file_name.data); return ret; } - + inline proc create_list(Lisp_Object* o1) -> Lisp_Object* { Lisp_Object* ret; try ret = create_lisp_object_pair(o1, nil); diff --git a/src/parse.cpp b/src/parse.cpp index 55c0fe0..e1826ab 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,6 +1,6 @@ namespace Slime::Parser { - String* standard_in; - String* parser_file; + String standard_in; + String parser_file; int parser_line; int parser_col; @@ -126,15 +126,15 @@ namespace Slime::Parser { text[*index_in_text+atom_length] = '\0'; - String* str_keyword; - Lisp_Object* ret; - try str_keyword = Memory::create_string("", atom_length); - strcpy(&str_keyword->data, text+*index_in_text); + // String str_keyword; + // try str_keyword = Memory::create_string("", atom_length); + // strcpy(str_keyword.data, text+*index_in_text); + Lisp_Object* ret; if (keyword) { - try ret = Memory::get_keyword(str_keyword); + try ret = Memory::get_keyword(text+*index_in_text); } else { - try ret = Memory::get_symbol(str_keyword); + try ret = Memory::get_symbol(text+*index_in_text); } @@ -184,9 +184,9 @@ namespace Slime::Parser { int new_len; try new_len = unescape_string(text+(*index_in_text)); - String* string = Memory::create_string("", new_len); + String string = Memory::create_string("", new_len); - strcpy(&string->data, text+(*index_in_text)); + strcpy(string.data, text+(*index_in_text)); // printf("------ %s\n", &string->data); text[*index_in_text+string_length] = '"'; @@ -359,10 +359,20 @@ namespace Slime::Parser { proc parse_single_expression(wchar_t* text) -> Lisp_Object* { char* res = wchar_to_char(text); - defer {free(res);}; + defer_free(res); + return parse_single_expression(res); } + proc parse_single_expression(const char* text) -> Lisp_Object* { + String s = Memory::create_string(text); + defer_free(s.data); + + Lisp_Object* ret; + try ret = parse_single_expression(s.data); + return ret; + } + proc parse_single_expression(char* text) -> Lisp_Object* { parser_file = standard_in; parser_line = 1; @@ -375,7 +385,7 @@ namespace Slime::Parser { } - proc parse_program(String* file_name, char* text) -> Array_List* { + proc parse_program(String file_name, char* text) -> Array_List* { profile_this(); parser_file = file_name; parser_line = 1; diff --git a/src/structs.cpp b/src/structs.cpp index 29ee577..060856a 100644 --- a/src/structs.cpp +++ b/src/structs.cpp @@ -71,12 +71,12 @@ namespace Slime { }; struct String { - int length; - char data; + int length; + char* data; }; struct Source_Code_Location { - String* file; + String file; int line; int column; }; @@ -135,11 +135,10 @@ namespace Slime { Source_Code_Location* sourceCodeLocation; u64 flags; Lisp_Object* userType; // keyword - String* docstring; union value { - String* symbol; // used for symbols and keywords + String symbol; // used for symbols and keywords double number; - String* string; + String string; Pair pair; Vector vector; Function* function; @@ -148,13 +147,12 @@ namespace Slime { Hash_Map* hashMap; ~value() {} } value; - ~Lisp_Object(); }; struct Error { Lisp_Object* position; // type has to be a keyword Lisp_Object* type; - String* message; + String message; }; } diff --git a/src/testing.cpp b/src/testing.cpp index a8fa2da..ae69763 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -60,15 +60,15 @@ namespace Slime { #define assert_equal_string(variable, value) \ if (!string_equal(variable, value)) { \ - print_assert_equal_fail(&variable->data, value, char*, "%s"); \ + print_assert_equal_fail(variable.data, value, char*, "%s"); \ return fail; \ } #define assert_equal_type(node, _type) \ if (Memory::get_type(node) != _type) { \ print_assert_equal_fail( \ - Lisp_Object_Type_to_string(Memory::get_type(node)), \ - Lisp_Object_Type_to_string(_type), char*, "%s"); \ + lisp_object_type_to_string(Memory::get_type(node)), \ + lisp_object_type_to_string(_type), char*, "%s"); \ return fail; \ } \ @@ -555,8 +555,15 @@ namespace Slime { proc test_singular_symbols() -> testresult { auto cc_s_aa = Memory::get_symbol("aa"); auto cc_s_aa2 = Memory::get_symbol("aa2"); - auto s_s_aa = Memory::get_symbol(Memory::create_string("aa")); - auto s_s_aa2 = Memory::get_symbol(Memory::create_string("aa2")); + + String s1 = Memory::create_string("aa"); + String s2 = Memory::create_string("aa2"); + + auto s_s_aa = Memory::get_symbol(s1); + auto s_s_aa2 = Memory::get_symbol(s2); + + free(s1.data); + free(s2.data); assert_equal_int(cc_s_aa, s_s_aa); assert_equal_int(cc_s_aa2, s_s_aa2); @@ -571,7 +578,9 @@ namespace Slime { // assert_no_error(); push_environment(Memory::create_child_environment(get_current_environment())); - built_in_load(Memory::create_string(file)); + String name = Memory::create_string(file); + built_in_load(name); + free(name.data); assert_no_error(); pop_environment(); @@ -582,7 +591,7 @@ namespace Slime { profile_this(); bool result = true; - try Memory::init(409600); + try Memory::init(); push_environment(Memory::create_child_environment( get_current_environment()));