diff --git a/src/built_ins.cpp b/src/built_ins.cpp index 396859b..60af1ea 100644 --- a/src/built_ins.cpp +++ b/src/built_ins.cpp @@ -29,9 +29,7 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { create_error(Error_Type::Not_Yet_Implemented, n1->sourceCodeLocation); return false; case Lisp_Object_Type::String: - return string_equal( - n1->value.string->value, - n2->value.string->value); + return string_equal(n1->value.string, n2->value.string); case Lisp_Object_Type::Symbol: return string_equal( n1->value.symbol->identifier, @@ -270,8 +268,8 @@ proc built_in_exponentiate(Lisp_Object* arguments, Environment* env) -> Lisp_Obj } -proc built_in_load(const char* file_name, Environment* env) -> Lisp_Object* { - char* file_content = read_entire_file(file_name); +proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { + char* file_content = read_entire_file(Memory::get_c_str(file_name)); if (file_content) { Lisp_Object* result = Memory::create_lisp_object_nil(); Lisp_Object_Array_List* program; @@ -670,7 +668,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { arguments = arguments->value.pair->rest; // if there is a docstring, use it if (arguments->value.pair->first->type == Lisp_Object_Type::String) { - function->docstring = arguments->value.pair->first->value.string->value; + function->docstring = arguments->value.pair->first->value.string; arguments = arguments->value.pair->rest; } else { function->docstring = nullptr; @@ -720,7 +718,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { arguments = arguments->value.pair->rest; // if there is a docstring, use it if (arguments->value.pair->first->type == Lisp_Object_Type::String) { - function->docstring = arguments->value.pair->first->value.string->value; + function->docstring = arguments->value.pair->first->value.string; arguments = arguments->value.pair->rest; } else { function->docstring = nullptr; @@ -876,29 +874,33 @@ proc load_built_ins_into_environment(Environment* env) -> void { Lisp_Object* fun = eval_expr(arguments->value.pair->first, env); if (fun->value.function->docstring) - printf("Docstring:\n==========\n%s\n\n", fun->value.function->docstring); + printf("Docstring:\n==========\n%s\n\n", Memory::get_c_str(fun->value.function->docstring)); else printf("No docstring avaliable\n"); printf("Arguments:\n==========\n"); printf("Postitional: {"); if (fun->value.function->positional_arguments->next_index != 0) { - printf("%s", fun->value.function->positional_arguments->identifiers[0]); + printf("%s", + Memory::get_c_str(fun->value.function->positional_arguments->identifiers[0])); for (int i = 1; i < fun->value.function->positional_arguments->next_index; ++i) { - printf(", %s", fun->value.function->positional_arguments->identifiers[i]); + printf(", %s", + Memory::get_c_str(fun->value.function->positional_arguments->identifiers[i])); } } printf("}\n"); printf("Keyword: {"); if (fun->value.function->keyword_arguments->next_index != 0) { - printf("%s", fun->value.function->keyword_arguments->identifiers[0]); + printf("%s", + Memory::get_c_str(fun->value.function->keyword_arguments->identifiers[0])); if (fun->value.function->keyword_arguments->values->data[0]) { printf(" ("); print(fun->value.function->keyword_arguments->values->data[0]); printf(")"); } for (int i = 1; i < fun->value.function->keyword_arguments->next_index; ++i) { - printf(", %s", fun->value.function->keyword_arguments->identifiers[i]); + printf(", %s", + Memory::get_c_str(fun->value.function->keyword_arguments->identifiers[i])); if (fun->value.function->keyword_arguments->values->data[i]) { printf(" ("); print(fun->value.function->keyword_arguments->values->data[i]); @@ -909,7 +911,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { printf("}\n"); printf("Rest: {"); if (fun->value.function->rest_argument) - printf("%s", fun->value.function->rest_argument); + printf("%s", + Memory::get_c_str(fun->value.function->rest_argument)); printf("}\n"); } @@ -948,7 +951,9 @@ proc load_built_ins_into_environment(Environment* env) -> void { print(evaluated_arguments->value.pair->first); } char* line = read_line(); - return Memory::create_lisp_object_string(line, (int)strlen(line)); + String* strLine = Memory::create_string(line); + free(line); + return Memory::create_lisp_object_string(strLine); }); defun("exit", cLambda { try { @@ -1012,8 +1017,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { Lisp_Object* result; try { - result = built_in_load( - evaluated_arguments->value.pair->first->value.string->value, env); + result = built_in_load(evaluated_arguments->value.pair->first->value.string, env); } return result; @@ -1070,7 +1074,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { report_error(Error_Type::Type_Missmatch); } - return Memory::create_lisp_object_symbol(_strdup(source->value.string->value)); + return Memory::create_lisp_object_symbol(Memory::duplicate_string(source->value.string)); }); defun("symbol->string", cLambda { try { @@ -1086,9 +1090,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { if (source->type != Lisp_Object_Type::Symbol) { report_error(Error_Type::Type_Missmatch); } - - // TODO(Felix): this is not really fast what we are doing here: - return Memory::create_lisp_object_string(_strdup(source->value.symbol->identifier), (int)strlen(source->value.symbol->identifier)); + return Memory::create_lisp_object_string(Memory::duplicate_string(source->value.symbol->identifier)); }); defun("concat-strings", cLambda { try { @@ -1114,18 +1116,17 @@ proc load_built_ins_into_environment(Environment* env) -> void { head = evaluated_arguments; - char* resulting_string = (char*)malloc(resulting_string_len * sizeof(char)) + 1; + String* resulting_string = Memory::create_string("", resulting_string_len); int index_in_string = 0; while (head->type == Lisp_Object_Type::Pair) { - strcpy(resulting_string+index_in_string, head->value.pair->first->value.string->value); + strcpy((&resulting_string->data)+index_in_string, + Memory::get_c_str(head->value.pair->first->value.string)); index_in_string += head->value.pair->first->value.string->length; head = head->value.pair->rest; } - resulting_string[index_in_string] = '\0'; - - return Memory::create_lisp_object_string(resulting_string, resulting_string_len); + return Memory::create_lisp_object_string(resulting_string); }); #undef report_error diff --git a/src/env.cpp b/src/env.cpp index e814264..35b377e 100644 --- a/src/env.cpp +++ b/src/env.cpp @@ -11,14 +11,14 @@ proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> env->values = (Lisp_Object**)realloc(env->values, env->capacity * sizeof(Lisp_Object*)); } - env->keys [env->next_index] = symbol->value.symbol->identifier; + env->keys [env->next_index] = Memory::get_c_str(symbol->value.symbol->identifier); env->values[env->next_index] = value; ++env->next_index; } proc lookup_symbol_in_this_envt(Symbol* sym, Environment* env) -> Lisp_Object* { for (int i = env->next_index - 1; i >= 0; --i) - if (string_equal(env->keys[i], sym->identifier)) + if (string_equal(env->keys[i], Memory::get_c_str(sym->identifier))) return env->values[i]; return nullptr; } @@ -38,15 +38,15 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { return result; } - if (string_equal(sym->identifier, "nil")) { + if (string_equal(Memory::get_c_str(sym->identifier), "nil")) { return Memory::create_lisp_object_nil(); } - if (string_equal(sym->identifier, "t")) { + if (string_equal(Memory::get_c_str(sym->identifier), "t")) { return Memory::create_lisp_object_t(); } create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); - printf("%s\n", sym->identifier); + printf("%s\n", Memory::get_c_str(sym->identifier)); return nullptr; } diff --git a/src/eval.cpp b/src/eval.cpp index 97b8d39..4a37b8f 100644 --- a/src/eval.cpp +++ b/src/eval.cpp @@ -18,7 +18,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> arguments = arguments->value.pair->rest; } - String_Array_List* read_in_keywords = create_String_array_list(16); + String_Array_List* read_in_keywords = create_String_array_list(); if (arguments->type == Lisp_Object_Type::Nil) goto checks; @@ -86,7 +86,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> checks: // check if all necessary keywords have been read in for (int i = 0; i < function->keyword_arguments->next_index; ++i) { - char* defined_keyword = function->keyword_arguments->identifiers[i]; + String* defined_keyword = function->keyword_arguments->identifiers[i]; bool was_set = false; for (int j = 0; j < read_in_keywords->next_index; ++j) { if (string_equal( @@ -439,12 +439,13 @@ proc interprete_file (char* file_name) -> Lisp_Object* { load_built_ins_into_environment(env); try { - built_in_load("pre.slime", env); + built_in_load(Memory::create_string("pre.slime"), env); } Lisp_Object_Array_List* program; try { - program = Parser::parse_program(file_name, file_content); + program = Parser::parse_program( + Memory::create_string(file_name), file_content); } Lisp_Object* result = Memory::create_lisp_object_nil(); @@ -466,8 +467,8 @@ proc interprete_stdin() -> void { char* line; - built_in_load("pre.slime", env); - built_in_load("test.slime", env); + built_in_load(Memory::create_string("pre.slime"), env); + built_in_load(Memory::create_string("test.slime"), env); if (error) { log_error(); @@ -479,6 +480,7 @@ proc interprete_stdin() -> void { printf(">"); line = read_expression(); parsed = Parser::parse_single_expression(line); + free(line); if (error) { log_error(); delete_error(); diff --git a/src/forward_decls.cpp b/src/forward_decls.cpp index f3b0e61..3653a7c 100644 --- a/src/forward_decls.cpp +++ b/src/forward_decls.cpp @@ -5,3 +5,4 @@ proc is_truthy (Lisp_Object*, Environment*) -> bool; proc list_length(Lisp_Object*) -> int; proc load_built_ins_into_environment(Environment*) -> void; proc parse_argument_list(Lisp_Object*, Function*) -> void; +proc create_error(Error_Type type, Source_Code_Location* location) -> void; diff --git a/src/io.cpp b/src/io.cpp index 02a917c..4156450 100644 --- a/src/io.cpp +++ b/src/io.cpp @@ -8,6 +8,18 @@ proc string_equal(const char input[], const char check[]) -> bool { return true; } +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 { + return string_equal(Memory::get_c_str(str), check); +} + +proc string_equal(String* str1, String* str2) -> bool { + return string_equal(Memory::get_c_str(str1), Memory::get_c_str(str2)); +} + proc get_nibble(char c) -> char { if (c >= 'A' && c <= 'F') return (c - 'a') + 10; @@ -67,7 +79,7 @@ proc unescape_string(char* in) -> bool { return true; } -proc read_entire_file (const char* filename) -> char* { +proc read_entire_file(char* filename) -> char* { char *fileContent = nullptr; FILE *fp = fopen(filename, "r"); if (fp) { @@ -106,7 +118,8 @@ proc read_entire_file (const char* filename) -> char* { } proc read_expression() -> char* { - char* line = (char*)malloc(100), * linep = line; + char* line = (char*)malloc(100); + char* linep = line; size_t lenmax = 100, len = lenmax; int c; @@ -132,20 +145,20 @@ proc read_expression() -> char* { linep = linen; } - line++; - if((*line = (char)c) == '(') + *line = (char)c; + if(*line == '(') ++nesting; - else if((*line = (char)c) == ')') + else if(*line == ')') --nesting; - else if((*line = (char)c) == '\n') + else if(*line == '\n') if (nesting == 0) break; + line++; } (*line)--; // we dont want the \n actually *line = '\0'; - // BUG(Felix): Why do we have to add 1 here? - return linep + 1; + return linep; } proc read_line() -> char* { @@ -175,19 +188,20 @@ proc read_line() -> char* { linep = linen; } - line++; - if((*line = (char)c) == '(') + *line = (char)c; + if(*line == '(') ++nesting; - else if((*line = (char)c) == ')') + else if(*line == ')') --nesting; - else if((*line = (char)c) == '\n') + else if(*line == '\n') if (nesting == 0) break; + line++; } (*line)--; // we dont want the \n actually *line = '\0'; - // BUG(Felix): Why do we have to add 1 here? - return linep + 1; + + return linep; } @@ -225,13 +239,13 @@ proc print(Lisp_Object* node) -> void { printf("%f", node->value.number->value); } break; case (Lisp_Object_Type::String): { - printf("\"%s\"", node->value.string->value); + printf("\"%s\"", Memory::get_c_str(node->value.string)); } break; case (Lisp_Object_Type::Symbol): { - printf("%s", node->value.symbol->identifier); + printf("%s", Memory::get_c_str(node->value.symbol->identifier)); } break; case (Lisp_Object_Type::Keyword): { - printf(":%s", node->value.keyword->identifier); + printf(":%s", Memory::get_c_str(node->value.keyword->identifier)); } break; case (Lisp_Object_Type::Function): { if (node->value.function->type == Function_Type::Lambda) @@ -286,13 +300,13 @@ proc fprint(FILE* f, Lisp_Object* node) -> void { fprintf(f, "%f", node->value.number->value); } break; case (Lisp_Object_Type::String): { - fprintf(f, "\"%s\"", node->value.string->value); + fprintf(f, "\"%s\"", Memory::get_c_str(node->value.string)); } break; case (Lisp_Object_Type::Symbol): { - fprintf(f, "%s", node->value.symbol->identifier); + fprintf(f, "%s", Memory::get_c_str(node->value.symbol->identifier)); } break; case (Lisp_Object_Type::Keyword): { - fprintf(f, ":%s", node->value.keyword->identifier); + fprintf(f, ":%s", Memory::get_c_str(node->value.keyword->identifier)); } break; case (Lisp_Object_Type::Function): { if (node->value.function->type == Function_Type::Lambda) @@ -337,7 +351,7 @@ proc fprint(FILE* f, Lisp_Object* node) -> void { proc print_error_location() -> void { if (error->location) { printf("%s (line %d, position %d)", - error->location->file, + Memory::get_c_str(error->location->file), error->location->line, error->location->column); } else { diff --git a/src/lisp_object.cpp b/src/lisp_object.cpp index 0876ce3..cc2d5bb 100644 --- a/src/lisp_object.cpp +++ b/src/lisp_object.cpp @@ -1,4 +1,4 @@ -proc create_source_code_location(const char* file, int line, int col) -> Source_Code_Location* { +proc create_source_code_location(String* file, int line, int col) -> Source_Code_Location* { if (!file) return nullptr; @@ -26,23 +26,23 @@ proc Lisp_Object_Type_to_string(Lisp_Object_Type type) -> const char* { proc create_positional_argument_list(int initial_capacity) -> Positional_Arguments* { Positional_Arguments* ret = new(Positional_Arguments); - ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); + ret->identifiers = (String**)malloc(initial_capacity * sizeof(String*)); ret->next_index = 0; ret->length = initial_capacity; return ret; } -proc append_to_positional_argument_list(Positional_Arguments* args, char* identifier) -> void { +proc append_to_positional_argument_list(Positional_Arguments* args, String* identifier) -> void { if (args->next_index == args->length) { args->length *= 2; - args->identifiers = (char**)realloc(args->identifiers, args->length * sizeof(char*)); + args->identifiers = (String**)realloc(args->identifiers, args->length * sizeof(String*)); } args->identifiers[args->next_index++] = identifier; } proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments* { Keyword_Arguments* ret = new(Keyword_Arguments); - ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); + ret->identifiers = (String**)malloc(initial_capacity * sizeof(String*)); ret->values = create_Lisp_Object_array_list(initial_capacity); ret->next_index = 0; ret->length = initial_capacity; @@ -50,12 +50,12 @@ proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments* { } proc append_to_keyword_argument_list(Keyword_Arguments* args, - char* identifier, - struct Lisp_Object* default_value) -> void + String* identifier, + Lisp_Object* default_value) -> void { if (args->next_index == args->length) { args->length *= 2; - args->identifiers = (char**)realloc(args->identifiers, args->length * sizeof(char*)); + args->identifiers = (String**)realloc(args->identifiers, args->length * sizeof(String*)); } args->identifiers[args->next_index++] = identifier; diff --git a/src/memory.cpp b/src/memory.cpp index 0a4447a..e85725c 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -1,40 +1,100 @@ namespace Memory { - constexpr int maxLispObjects = 4096 * 1024; // == 98304kb == 96mb - Int_Array_List* freeSpots; - Lisp_Object* memory; - int nextFreeSpot = 0; - - proc init() -> void { - memory = (Lisp_Object*)malloc(maxLispObjects * sizeof(Lisp_Object)); - freeSpots = create_Int_array_list(); + // ------------------ + // lisp_object + // ------------------ + constexpr int object_memory_size = 4096 * 1024; // == 98304kb == 96mb + Int_Array_List* free_spots_in_object_memory; + Lisp_Object* object_memory; + int next_index_in_object_memory = 0; + + // ------------------ + // strings + // ------------------ + constexpr 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) + Void_Ptr_Array_List* free_spots_in_string_memory; + String* string_memory; + String* next_free_spot_in_string_memory; + + proc init() { + free_spots_in_object_memory = create_Int_array_list(); + free_spots_in_string_memory = create_Void_Ptr_array_list(); + + object_memory = (Lisp_Object*)malloc(object_memory_size * sizeof(Lisp_Object)); + string_memory = (String*)malloc(object_memory_size * sizeof(Lisp_Object)); + + next_free_spot_in_string_memory = string_memory; } - proc print_status() -> void { + proc print_status() { printf("Memory Status:\n" - " - %f%% of the memory is used\n" + " - %f%% of the object_memory is used\n" " - %d of %d total Lisp_Objects are in use\n" " - %d holes in used memory (fragmentation)\n", - (1.0*nextFreeSpot - freeSpots->next_index)/maxLispObjects, - nextFreeSpot - freeSpots->next_index, maxLispObjects, - freeSpots->next_index); + (1.0*next_index_in_object_memory - free_spots_in_object_memory->next_index)/object_memory_size, + next_index_in_object_memory - free_spots_in_object_memory->next_index, object_memory_size, + free_spots_in_object_memory->next_index); + + printf("Memory Status:\n" + " - %f%% of the string_memory is used\n" + " - %d holes in used memory (fragmentation)\n", + (1.0*(size_t)next_free_spot_in_string_memory - (size_t)string_memory)/string_memory_size, + free_spots_in_string_memory->next_index); + } + + inline proc get_c_str(String* str) -> char* { + return &str->data; + } + + 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) { + append_to_Void_Ptr_array_list(free_spots_in_string_memory, (void*)str); + } + + 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_lisp_object() -> Lisp_Object* { int index; // if we have no free spots then append at the end - if (freeSpots->next_index == 0) { + if (free_spots_in_object_memory->next_index == 0) { // if we still have space - if (maxLispObjects == nextFreeSpot) { + if (object_memory_size == next_index_in_object_memory) { create_error(Error_Type::Out_Of_Memory, nullptr); return nullptr; } - index = nextFreeSpot++; + index = next_index_in_object_memory++; } else { // else fill a free spot - index = freeSpots->data[freeSpots->next_index--]; + index = free_spots_in_object_memory->data[free_spots_in_object_memory->next_index--]; } - Lisp_Object* object = memory+index; + Lisp_Object* object = object_memory+index; object->sourceCodeLocation = nullptr; return object; } @@ -61,31 +121,39 @@ namespace Memory { return node; } - proc create_lisp_object_string(char* str, int length) -> Lisp_Object* { + proc create_lisp_object_string(String* str) -> Lisp_Object* { Lisp_Object* node = create_lisp_object(); node->type = Lisp_Object_Type::String; - node->value.string = new(String); - node->value.string->value = str; - node->value.string->length = length; + node->value.string = str; return node; } - proc create_lisp_object_symbol(const char* identifier) -> Lisp_Object* { + proc create_lisp_object_symbol(String* identifier) -> Lisp_Object* { Lisp_Object* node = create_lisp_object(); node->type = Lisp_Object_Type::Symbol; node->value.symbol = new(Symbol); - node->value.symbol->identifier = (char*) identifier; + node->value.symbol->identifier = identifier; return node; } - proc create_lisp_object_keyword(const char* keyword) -> Lisp_Object* { + proc create_lisp_object_symbol(const char* identifier) -> Lisp_Object* { + return create_lisp_object_symbol( + Memory::create_string(identifier)); + } + + proc create_lisp_object_keyword(String* keyword) -> Lisp_Object* { Lisp_Object* node = create_lisp_object(); node->type = Lisp_Object_Type::Keyword; node->value.keyword = new(Keyword); - node->value.keyword->identifier = (char*) keyword; + node->value.keyword->identifier = keyword; return node; } + proc create_lisp_object_keyword(const char* keyword) -> Lisp_Object* { + return create_lisp_object_keyword( + Memory::create_string(keyword)); + } + proc create_lisp_object_cfunction(std::function function) -> Lisp_Object* { Lisp_Object* node = create_lisp_object(); node->type = Lisp_Object_Type::CFunction; @@ -132,5 +200,4 @@ namespace Memory { load_built_ins_into_environment(ret); return ret; } - } diff --git a/src/parse.cpp b/src/parse.cpp index 4deeb31..af1c4a9 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,15 +1,8 @@ namespace Parser { -#define inject_scl(_ret) \ - _ret->sourceCodeLocation = new(Source_Code_Location); \ - _ret->sourceCodeLocation->file = parser_file; \ - _ret->sourceCodeLocation->line = parser_line; \ - _ret->sourceCodeLocation->column = parser_col - - const char* parser_file; + String* parser_file; int parser_line; int parser_col; - // NOTE(Felix): In this environment, the build in functions will // be loaded, and the macros will be stroed in form of // special-lambdas, that get executed in this environment at @@ -28,6 +21,13 @@ namespace Parser { environment_for_macros = env; } + proc inject_scl(Lisp_Object* lo) -> void { + lo->sourceCodeLocation = new(Source_Code_Location); + lo->sourceCodeLocation->file = parser_file; + lo->sourceCodeLocation->line = parser_line; + lo->sourceCodeLocation->column = parser_col; + } + void eat_comment_line(char* text, int* index_in_text) { // safety check if we are actually starting a comment here if (text[*index_in_text] != ';') @@ -68,7 +68,7 @@ namespace Parser { } while (position_before != *index_in_text); } - char* read_atom(char* text, int* index_in_text) { + String* read_atom(char* text, int* index_in_text) { int atom_length = 0; while (text[*index_in_text+atom_length] != ' ' && text[*index_in_text+atom_length] != ')' && @@ -88,8 +88,9 @@ namespace Parser { text[*index_in_text+atom_length] = '\0'; // get the atom - char* atom = (char*)malloc(atom_length*sizeof(char)+1); // plus null char - strcpy(atom, text+(*index_in_text)); + 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 text[*index_in_text+atom_length] = before; @@ -98,14 +99,17 @@ namespace Parser { // ended *index_in_text += atom_length; - return atom; + return ret; } Lisp_Object* parse_number(char* text, int* index_in_text) { double number; - char* str_number = read_atom(text, index_in_text); - sscanf(str_number, "%lf", &number); + // TODO(Felix): parse the number direcrly from the string and + // dont create a String first + String* str_number = read_atom(text, index_in_text); + sscanf(Memory::get_c_str(str_number), "%lf", &number); Lisp_Object* ret = Memory::create_lisp_object_number(number); + inject_scl(ret); return ret; } @@ -114,15 +118,16 @@ namespace Parser { // we are now on the colon ++(*index_in_text); ++parser_col; - char* str_keyword = read_atom(text, index_in_text); + String* str_keyword = read_atom(text, index_in_text); Lisp_Object* ret = Memory::create_lisp_object_keyword(str_keyword); + inject_scl(ret); return ret; } Lisp_Object* parse_symbol(char* text, int* index_in_text) { // we are now at the first char of the symbol - char* str_symbol = read_atom(text, index_in_text); + String* str_symbol = read_atom(text, index_in_text); Lisp_Object* ret = Memory::create_lisp_object_symbol(str_symbol); inject_scl(ret); return ret; @@ -136,9 +141,8 @@ namespace Parser { // now we are at the first letter, if this is the closing '"' then // it's easy if (text[*index_in_text] == '"') { - char* str = new(char); - *str = '\0'; - Lisp_Object* ret = Memory::create_lisp_object_string(str, 0); + Lisp_Object* ret = Memory::create_lisp_object_string( + Memory::create_string("", 0)); inject_scl(ret); // plus one because we want to go after the quotes @@ -158,7 +162,7 @@ namespace Parser { // we found the end of the string text[*index_in_text+string_length] = '\0'; - char* string = (char*)malloc(string_length*sizeof(char)+1); // plus null char + String* string = Memory::create_string("", string_length); if (!unescape_string(text+(*index_in_text))) { create_error( @@ -166,7 +170,7 @@ namespace Parser { create_source_code_location(parser_file, parser_line, parser_col)); return nullptr; } - strcpy(string, text+(*index_in_text)); + strcpy(&string->data, text+(*index_in_text)); /* manually copy to parse control sequences correctly */ /* int temp_index = 0; */ /* while (text+(temp_index+(*index_in_text)) != '\0') { */ @@ -179,7 +183,7 @@ namespace Parser { *index_in_text += string_length +1; // plus one because we want to // go after the quotes - Lisp_Object* ret = Memory::create_lisp_object_string(string, string_length); + Lisp_Object* ret = Memory::create_lisp_object_string(string); inject_scl(ret); return ret; } @@ -371,7 +375,7 @@ namespace Parser { arguments = arguments->value.pair->rest; // if there is a docstring, use it if (arguments->value.pair->first->type == Lisp_Object_Type::String) { - function->docstring = arguments->value.pair->first->value.string->value; + function->docstring = arguments->value.pair->first->value.string; arguments = arguments->value.pair->rest; } else { function->docstring = nullptr; @@ -437,7 +441,7 @@ namespace Parser { } Lisp_Object* parse_single_expression(char* text) { - parser_file = "stdin"; + parser_file = Memory::create_string("stdin"); parser_line = 1; parser_col = 1; @@ -466,10 +470,10 @@ namespace Parser { return nullptr; } - void write_expanded_file(const char* file_name, Lisp_Object_Array_List* program) { + void write_expanded_file(String* file_name, Lisp_Object_Array_List* program) { const char* ext = ".expanded"; - char* newName = (char*)calloc(4 + strlen(file_name), sizeof(char)); - strcpy(newName, file_name); + char* newName = (char*)calloc(10 + file_name->length, sizeof(char)); + strcpy(newName, Memory::get_c_str(file_name)); strcat(newName, ext); FILE *f = fopen(newName, "w"); @@ -487,15 +491,15 @@ namespace Parser { } fclose(f); + free(newName); } - Lisp_Object_Array_List* parse_program(const char* file_name, char* text) { - parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1); - strcpy((char *)parser_file, file_name); + Lisp_Object_Array_List* parse_program(String* file_name, char* text) { + parser_file = file_name; parser_line = 1; parser_col = 0; - Lisp_Object_Array_List* program = create_Lisp_Object_array_list(16); + Lisp_Object_Array_List* program = create_Lisp_Object_array_list(); int index_in_text = 0; @@ -526,6 +530,4 @@ namespace Parser { return program; } - -#undef inject_scl } diff --git a/src/slime.h b/src/slime.h index 920c7ab..c21751e 100644 --- a/src/slime.h +++ b/src/slime.h @@ -6,10 +6,10 @@ #include "./defines.cpp" #include "./structs.cpp" #include "./forward_decls.cpp" +#include "./memory.cpp" #include "./lisp_object.cpp" #include "./error.cpp" #include "./io.cpp" -#include "./memory.cpp" #include "./env.cpp" #include "./parse.cpp" #include "./built_ins.cpp" diff --git a/src/structs.cpp b/src/structs.cpp index 1327612..a905f18 100644 --- a/src/structs.cpp +++ b/src/structs.cpp @@ -1,9 +1,11 @@ struct Lisp_Object; +struct String; struct Environment; define_array_list(Lisp_Object*, Lisp_Object); -define_array_list(char*, String); +define_array_list(String*, String); define_array_list(int, Int); +define_array_list(void*, Void_Ptr); enum struct Lisp_Object_Type { Nil, @@ -49,29 +51,29 @@ enum struct Log_Level { Debug, }; +struct String { + int length; + char data; +}; + struct Source_Code_Location { - const char* file; + String* file; int line; int column; }; struct Symbol { - char* identifier; + String* identifier; }; struct Keyword { - char* identifier; + String* identifier; }; struct Number { double value; }; -struct String { - int length; - char* value; -}; - struct Pair { Lisp_Object* first; Lisp_Object* rest; @@ -80,13 +82,13 @@ struct Pair { struct Positional_Arguments { // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have // to convert them to strings and back to symbols - char** identifiers; + String** identifiers; // Array of Pointers to String int next_index; int length; }; struct Keyword_Arguments { - char** identifiers; + String** identifiers; // Array of Pointers to String // NOTE(Felix): values[i] will be nullptr if no defalut value was // declared for key identifiers[i] Lisp_Object_Array_List* values; @@ -96,11 +98,11 @@ struct Keyword_Arguments { struct Function { Function_Type type; - char* docstring; + String* docstring; Positional_Arguments* positional_arguments; Keyword_Arguments* keyword_arguments; // rest_argument will be nullptr if no rest argument is declared - char* rest_argument; + String* rest_argument; Lisp_Object* body; // implicit prog Environment* parent_environment; // we are doing closures now!! }; diff --git a/src/testing.cpp b/src/testing.cpp index af4eb29..4099533 100644 --- a/src/testing.cpp +++ b/src/testing.cpp @@ -50,7 +50,7 @@ #define assert_equal_string(variable, value) \ if (!string_equal(variable, value)) { \ - print_assert_equal_fail(variable, value, char*, "%s"); \ + print_assert_equal_fail(&variable->data, value, char*, "%s"); \ return fail; \ } @@ -108,7 +108,7 @@ proc test_eval_operands() -> testresult { assert_equal_type(operands, Lisp_Object_Type::Pair); assert_equal_type(operands->value.pair->first, Lisp_Object_Type::String); - assert_equal_string(operands->value.pair->first->value.string->value, "okay"); + assert_equal_string(operands->value.pair->first->value.string, "okay"); operands = operands->value.pair->rest; @@ -144,7 +144,7 @@ proc test_parse_atom() -> testresult { result = Parser::parse_atom(string, &index_in_text); assert_equal_type(result, Lisp_Object_Type::String); - assert_equal_string(result->value.string->value, "asd"); + assert_equal_string(result->value.string, "asd"); // test keywords ++index_in_text;