| @@ -29,9 +29,7 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { | |||||
| create_error(Error_Type::Not_Yet_Implemented, n1->sourceCodeLocation); | create_error(Error_Type::Not_Yet_Implemented, n1->sourceCodeLocation); | ||||
| return false; | return false; | ||||
| case Lisp_Object_Type::String: | 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: | case Lisp_Object_Type::Symbol: | ||||
| return string_equal( | return string_equal( | ||||
| n1->value.symbol->identifier, | 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) { | if (file_content) { | ||||
| Lisp_Object* result = Memory::create_lisp_object_nil(); | Lisp_Object* result = Memory::create_lisp_object_nil(); | ||||
| Lisp_Object_Array_List* program; | Lisp_Object_Array_List* program; | ||||
| @@ -670,7 +668,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| // if there is a docstring, use it | // if there is a docstring, use it | ||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::String) { | 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; | arguments = arguments->value.pair->rest; | ||||
| } else { | } else { | ||||
| function->docstring = nullptr; | function->docstring = nullptr; | ||||
| @@ -720,7 +718,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| // if there is a docstring, use it | // if there is a docstring, use it | ||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::String) { | 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; | arguments = arguments->value.pair->rest; | ||||
| } else { | } else { | ||||
| function->docstring = nullptr; | 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); | Lisp_Object* fun = eval_expr(arguments->value.pair->first, env); | ||||
| if (fun->value.function->docstring) | 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 | else | ||||
| printf("No docstring avaliable\n"); | printf("No docstring avaliable\n"); | ||||
| printf("Arguments:\n==========\n"); | printf("Arguments:\n==========\n"); | ||||
| printf("Postitional: {"); | printf("Postitional: {"); | ||||
| if (fun->value.function->positional_arguments->next_index != 0) { | 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) { | 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("}\n"); | ||||
| printf("Keyword: {"); | printf("Keyword: {"); | ||||
| if (fun->value.function->keyword_arguments->next_index != 0) { | 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]) { | if (fun->value.function->keyword_arguments->values->data[0]) { | ||||
| printf(" ("); | printf(" ("); | ||||
| print(fun->value.function->keyword_arguments->values->data[0]); | print(fun->value.function->keyword_arguments->values->data[0]); | ||||
| printf(")"); | printf(")"); | ||||
| } | } | ||||
| for (int i = 1; i < fun->value.function->keyword_arguments->next_index; ++i) { | 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]) { | if (fun->value.function->keyword_arguments->values->data[i]) { | ||||
| printf(" ("); | printf(" ("); | ||||
| print(fun->value.function->keyword_arguments->values->data[i]); | 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("}\n"); | ||||
| printf("Rest: {"); | printf("Rest: {"); | ||||
| if (fun->value.function->rest_argument) | 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"); | printf("}\n"); | ||||
| } | } | ||||
| @@ -948,7 +951,9 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| print(evaluated_arguments->value.pair->first); | print(evaluated_arguments->value.pair->first); | ||||
| } | } | ||||
| char* line = read_line(); | 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 { | defun("exit", cLambda { | ||||
| try { | try { | ||||
| @@ -1012,8 +1017,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| Lisp_Object* result; | Lisp_Object* result; | ||||
| try { | 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; | return result; | ||||
| @@ -1070,7 +1074,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| report_error(Error_Type::Type_Missmatch); | 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 { | defun("symbol->string", cLambda { | ||||
| try { | try { | ||||
| @@ -1086,9 +1090,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| if (source->type != Lisp_Object_Type::Symbol) { | if (source->type != Lisp_Object_Type::Symbol) { | ||||
| report_error(Error_Type::Type_Missmatch); | 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 { | defun("concat-strings", cLambda { | ||||
| try { | try { | ||||
| @@ -1114,18 +1116,17 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| head = evaluated_arguments; | 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; | int index_in_string = 0; | ||||
| while (head->type == Lisp_Object_Type::Pair) { | 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; | index_in_string += head->value.pair->first->value.string->length; | ||||
| head = head->value.pair->rest; | 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 | #undef report_error | ||||
| @@ -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->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->values[env->next_index] = value; | ||||
| ++env->next_index; | ++env->next_index; | ||||
| } | } | ||||
| proc lookup_symbol_in_this_envt(Symbol* sym, Environment* env) -> Lisp_Object* { | proc lookup_symbol_in_this_envt(Symbol* sym, Environment* env) -> Lisp_Object* { | ||||
| for (int i = env->next_index - 1; i >= 0; --i) | 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 env->values[i]; | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| @@ -38,15 +38,15 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| return result; | return result; | ||||
| } | } | ||||
| if (string_equal(sym->identifier, "nil")) { | |||||
| if (string_equal(Memory::get_c_str(sym->identifier), "nil")) { | |||||
| return Memory::create_lisp_object_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(); | return Memory::create_lisp_object_t(); | ||||
| } | } | ||||
| create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | 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; | return nullptr; | ||||
| } | } | ||||
| @@ -18,7 +18,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| arguments = arguments->value.pair->rest; | 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) | if (arguments->type == Lisp_Object_Type::Nil) | ||||
| goto checks; | goto checks; | ||||
| @@ -86,7 +86,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| checks: | checks: | ||||
| // check if all necessary keywords have been read in | // check if all necessary keywords have been read in | ||||
| for (int i = 0; i < function->keyword_arguments->next_index; ++i) { | 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; | bool was_set = false; | ||||
| for (int j = 0; j < read_in_keywords->next_index; ++j) { | for (int j = 0; j < read_in_keywords->next_index; ++j) { | ||||
| if (string_equal( | if (string_equal( | ||||
| @@ -439,12 +439,13 @@ proc interprete_file (char* file_name) -> Lisp_Object* { | |||||
| load_built_ins_into_environment(env); | load_built_ins_into_environment(env); | ||||
| try { | try { | ||||
| built_in_load("pre.slime", env); | |||||
| built_in_load(Memory::create_string("pre.slime"), env); | |||||
| } | } | ||||
| Lisp_Object_Array_List* program; | Lisp_Object_Array_List* program; | ||||
| try { | 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(); | Lisp_Object* result = Memory::create_lisp_object_nil(); | ||||
| @@ -466,8 +467,8 @@ proc interprete_stdin() -> void { | |||||
| char* line; | 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) { | if (error) { | ||||
| log_error(); | log_error(); | ||||
| @@ -479,6 +480,7 @@ proc interprete_stdin() -> void { | |||||
| printf(">"); | printf(">"); | ||||
| line = read_expression(); | line = read_expression(); | ||||
| parsed = Parser::parse_single_expression(line); | parsed = Parser::parse_single_expression(line); | ||||
| free(line); | |||||
| if (error) { | if (error) { | ||||
| log_error(); | log_error(); | ||||
| delete_error(); | delete_error(); | ||||
| @@ -5,3 +5,4 @@ proc is_truthy (Lisp_Object*, Environment*) -> bool; | |||||
| proc list_length(Lisp_Object*) -> int; | proc list_length(Lisp_Object*) -> int; | ||||
| proc load_built_ins_into_environment(Environment*) -> void; | proc load_built_ins_into_environment(Environment*) -> void; | ||||
| proc parse_argument_list(Lisp_Object*, Function*) -> void; | proc parse_argument_list(Lisp_Object*, Function*) -> void; | ||||
| proc create_error(Error_Type type, Source_Code_Location* location) -> void; | |||||
| @@ -8,6 +8,18 @@ proc string_equal(const char input[], const char check[]) -> bool { | |||||
| return true; | 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 { | proc get_nibble(char c) -> char { | ||||
| if (c >= 'A' && c <= 'F') | if (c >= 'A' && c <= 'F') | ||||
| return (c - 'a') + 10; | return (c - 'a') + 10; | ||||
| @@ -67,7 +79,7 @@ proc unescape_string(char* in) -> bool { | |||||
| return true; | return true; | ||||
| } | } | ||||
| proc read_entire_file (const char* filename) -> char* { | |||||
| proc read_entire_file(char* filename) -> char* { | |||||
| char *fileContent = nullptr; | char *fileContent = nullptr; | ||||
| FILE *fp = fopen(filename, "r"); | FILE *fp = fopen(filename, "r"); | ||||
| if (fp) { | if (fp) { | ||||
| @@ -106,7 +118,8 @@ proc read_entire_file (const char* filename) -> char* { | |||||
| } | } | ||||
| proc read_expression() -> 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; | size_t lenmax = 100, len = lenmax; | ||||
| int c; | int c; | ||||
| @@ -132,20 +145,20 @@ proc read_expression() -> char* { | |||||
| linep = linen; | linep = linen; | ||||
| } | } | ||||
| line++; | |||||
| if((*line = (char)c) == '(') | |||||
| *line = (char)c; | |||||
| if(*line == '(') | |||||
| ++nesting; | ++nesting; | ||||
| else if((*line = (char)c) == ')') | |||||
| else if(*line == ')') | |||||
| --nesting; | --nesting; | ||||
| else if((*line = (char)c) == '\n') | |||||
| else if(*line == '\n') | |||||
| if (nesting == 0) | if (nesting == 0) | ||||
| break; | break; | ||||
| line++; | |||||
| } | } | ||||
| (*line)--; // we dont want the \n actually | (*line)--; // we dont want the \n actually | ||||
| *line = '\0'; | *line = '\0'; | ||||
| // BUG(Felix): Why do we have to add 1 here? | |||||
| return linep + 1; | |||||
| return linep; | |||||
| } | } | ||||
| proc read_line() -> char* { | proc read_line() -> char* { | ||||
| @@ -175,19 +188,20 @@ proc read_line() -> char* { | |||||
| linep = linen; | linep = linen; | ||||
| } | } | ||||
| line++; | |||||
| if((*line = (char)c) == '(') | |||||
| *line = (char)c; | |||||
| if(*line == '(') | |||||
| ++nesting; | ++nesting; | ||||
| else if((*line = (char)c) == ')') | |||||
| else if(*line == ')') | |||||
| --nesting; | --nesting; | ||||
| else if((*line = (char)c) == '\n') | |||||
| else if(*line == '\n') | |||||
| if (nesting == 0) | if (nesting == 0) | ||||
| break; | break; | ||||
| line++; | |||||
| } | } | ||||
| (*line)--; // we dont want the \n actually | (*line)--; // we dont want the \n actually | ||||
| *line = '\0'; | *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); | printf("%f", node->value.number->value); | ||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::String): { | case (Lisp_Object_Type::String): { | ||||
| printf("\"%s\"", node->value.string->value); | |||||
| printf("\"%s\"", Memory::get_c_str(node->value.string)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Symbol): { | case (Lisp_Object_Type::Symbol): { | ||||
| printf("%s", node->value.symbol->identifier); | |||||
| printf("%s", Memory::get_c_str(node->value.symbol->identifier)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Keyword): { | case (Lisp_Object_Type::Keyword): { | ||||
| printf(":%s", node->value.keyword->identifier); | |||||
| printf(":%s", Memory::get_c_str(node->value.keyword->identifier)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Function): { | case (Lisp_Object_Type::Function): { | ||||
| if (node->value.function->type == Function_Type::Lambda) | 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); | fprintf(f, "%f", node->value.number->value); | ||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::String): { | case (Lisp_Object_Type::String): { | ||||
| fprintf(f, "\"%s\"", node->value.string->value); | |||||
| fprintf(f, "\"%s\"", Memory::get_c_str(node->value.string)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Symbol): { | case (Lisp_Object_Type::Symbol): { | ||||
| fprintf(f, "%s", node->value.symbol->identifier); | |||||
| fprintf(f, "%s", Memory::get_c_str(node->value.symbol->identifier)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Keyword): { | case (Lisp_Object_Type::Keyword): { | ||||
| fprintf(f, ":%s", node->value.keyword->identifier); | |||||
| fprintf(f, ":%s", Memory::get_c_str(node->value.keyword->identifier)); | |||||
| } break; | } break; | ||||
| case (Lisp_Object_Type::Function): { | case (Lisp_Object_Type::Function): { | ||||
| if (node->value.function->type == Function_Type::Lambda) | 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 { | proc print_error_location() -> void { | ||||
| if (error->location) { | if (error->location) { | ||||
| printf("%s (line %d, position %d)", | printf("%s (line %d, position %d)", | ||||
| error->location->file, | |||||
| Memory::get_c_str(error->location->file), | |||||
| error->location->line, | error->location->line, | ||||
| error->location->column); | error->location->column); | ||||
| } else { | } else { | ||||
| @@ -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) | if (!file) | ||||
| return nullptr; | 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* { | proc create_positional_argument_list(int initial_capacity) -> Positional_Arguments* { | ||||
| Positional_Arguments* ret = new(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->next_index = 0; | ||||
| ret->length = initial_capacity; | ret->length = initial_capacity; | ||||
| return ret; | 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) { | if (args->next_index == args->length) { | ||||
| args->length *= 2; | 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; | args->identifiers[args->next_index++] = identifier; | ||||
| } | } | ||||
| proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments* { | proc create_keyword_argument_list(int initial_capacity) -> Keyword_Arguments* { | ||||
| Keyword_Arguments* ret = new(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->values = create_Lisp_Object_array_list(initial_capacity); | ||||
| ret->next_index = 0; | ret->next_index = 0; | ||||
| ret->length = initial_capacity; | 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, | 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) { | if (args->next_index == args->length) { | ||||
| args->length *= 2; | 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; | args->identifiers[args->next_index++] = identifier; | ||||
| @@ -1,40 +1,100 @@ | |||||
| namespace Memory { | 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" | 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 of %d total Lisp_Objects are in use\n" | ||||
| " - %d holes in used memory (fragmentation)\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* { | proc create_lisp_object() -> Lisp_Object* { | ||||
| int index; | int index; | ||||
| // if we have no free spots then append at the end | // 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 we still have space | ||||
| if (maxLispObjects == nextFreeSpot) { | |||||
| if (object_memory_size == next_index_in_object_memory) { | |||||
| create_error(Error_Type::Out_Of_Memory, nullptr); | create_error(Error_Type::Out_Of_Memory, nullptr); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| index = nextFreeSpot++; | |||||
| index = next_index_in_object_memory++; | |||||
| } else { | } else { | ||||
| // else fill a free spot | // 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; | object->sourceCodeLocation = nullptr; | ||||
| return object; | return object; | ||||
| } | } | ||||
| @@ -61,31 +121,39 @@ namespace Memory { | |||||
| return node; | 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(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::String; | 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; | 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(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::Symbol; | node->type = Lisp_Object_Type::Symbol; | ||||
| node->value.symbol = new(Symbol); | node->value.symbol = new(Symbol); | ||||
| node->value.symbol->identifier = (char*) identifier; | |||||
| node->value.symbol->identifier = identifier; | |||||
| return node; | 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(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::Keyword; | node->type = Lisp_Object_Type::Keyword; | ||||
| node->value.keyword = new(Keyword); | node->value.keyword = new(Keyword); | ||||
| node->value.keyword->identifier = (char*) keyword; | |||||
| node->value.keyword->identifier = keyword; | |||||
| return node; | 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<Lisp_Object*(Lisp_Object*, Environment*)> function) -> Lisp_Object* { | proc create_lisp_object_cfunction(std::function<Lisp_Object*(Lisp_Object*, Environment*)> function) -> Lisp_Object* { | ||||
| Lisp_Object* node = create_lisp_object(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::CFunction; | node->type = Lisp_Object_Type::CFunction; | ||||
| @@ -132,5 +200,4 @@ namespace Memory { | |||||
| load_built_ins_into_environment(ret); | load_built_ins_into_environment(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,15 +1,8 @@ | |||||
| namespace Parser { | 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_line; | ||||
| int parser_col; | int parser_col; | ||||
| // NOTE(Felix): In this environment, the build in functions will | // NOTE(Felix): In this environment, the build in functions will | ||||
| // be loaded, and the macros will be stroed in form of | // be loaded, and the macros will be stroed in form of | ||||
| // special-lambdas, that get executed in this environment at | // special-lambdas, that get executed in this environment at | ||||
| @@ -28,6 +21,13 @@ namespace Parser { | |||||
| environment_for_macros = env; | 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) { | void eat_comment_line(char* text, int* index_in_text) { | ||||
| // safety check if we are actually starting a comment here | // safety check if we are actually starting a comment here | ||||
| if (text[*index_in_text] != ';') | if (text[*index_in_text] != ';') | ||||
| @@ -68,7 +68,7 @@ namespace Parser { | |||||
| } while (position_before != *index_in_text); | } 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; | int atom_length = 0; | ||||
| while (text[*index_in_text+atom_length] != ' ' && | while (text[*index_in_text+atom_length] != ' ' && | ||||
| 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'; | text[*index_in_text+atom_length] = '\0'; | ||||
| // get the atom | // 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 | // restore the original string | ||||
| text[*index_in_text+atom_length] = before; | text[*index_in_text+atom_length] = before; | ||||
| @@ -98,14 +99,17 @@ namespace Parser { | |||||
| // ended | // ended | ||||
| *index_in_text += atom_length; | *index_in_text += atom_length; | ||||
| return atom; | |||||
| return ret; | |||||
| } | } | ||||
| Lisp_Object* parse_number(char* text, int* index_in_text) { | Lisp_Object* parse_number(char* text, int* index_in_text) { | ||||
| double number; | 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); | Lisp_Object* ret = Memory::create_lisp_object_number(number); | ||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -114,15 +118,16 @@ namespace Parser { | |||||
| // we are now on the colon | // we are now on the colon | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++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); | Lisp_Object* ret = Memory::create_lisp_object_keyword(str_keyword); | ||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| Lisp_Object* parse_symbol(char* text, int* index_in_text) { | Lisp_Object* parse_symbol(char* text, int* index_in_text) { | ||||
| // we are now at the first char of the symbol | // 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); | Lisp_Object* ret = Memory::create_lisp_object_symbol(str_symbol); | ||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| @@ -136,9 +141,8 @@ namespace Parser { | |||||
| // now we are at the first letter, if this is the closing '"' then | // now we are at the first letter, if this is the closing '"' then | ||||
| // it's easy | // it's easy | ||||
| if (text[*index_in_text] == '"') { | 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); | inject_scl(ret); | ||||
| // plus one because we want to go after the quotes | // plus one because we want to go after the quotes | ||||
| @@ -158,7 +162,7 @@ namespace Parser { | |||||
| // we found the end of the string | // we found the end of the string | ||||
| text[*index_in_text+string_length] = '\0'; | 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))) { | if (!unescape_string(text+(*index_in_text))) { | ||||
| create_error( | create_error( | ||||
| @@ -166,7 +170,7 @@ namespace Parser { | |||||
| create_source_code_location(parser_file, parser_line, parser_col)); | create_source_code_location(parser_file, parser_line, parser_col)); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| strcpy(string, text+(*index_in_text)); | |||||
| strcpy(&string->data, text+(*index_in_text)); | |||||
| /* manually copy to parse control sequences correctly */ | /* manually copy to parse control sequences correctly */ | ||||
| /* int temp_index = 0; */ | /* int temp_index = 0; */ | ||||
| /* while (text+(temp_index+(*index_in_text)) != '\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 | *index_in_text += string_length +1; // plus one because we want to | ||||
| // go after the quotes | // 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); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -371,7 +375,7 @@ namespace Parser { | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| // if there is a docstring, use it | // if there is a docstring, use it | ||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::String) { | 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; | arguments = arguments->value.pair->rest; | ||||
| } else { | } else { | ||||
| function->docstring = nullptr; | function->docstring = nullptr; | ||||
| @@ -437,7 +441,7 @@ namespace Parser { | |||||
| } | } | ||||
| Lisp_Object* parse_single_expression(char* text) { | Lisp_Object* parse_single_expression(char* text) { | ||||
| parser_file = "stdin"; | |||||
| parser_file = Memory::create_string("stdin"); | |||||
| parser_line = 1; | parser_line = 1; | ||||
| parser_col = 1; | parser_col = 1; | ||||
| @@ -466,10 +470,10 @@ namespace Parser { | |||||
| return nullptr; | 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"; | 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); | strcat(newName, ext); | ||||
| FILE *f = fopen(newName, "w"); | FILE *f = fopen(newName, "w"); | ||||
| @@ -487,15 +491,15 @@ namespace Parser { | |||||
| } | } | ||||
| fclose(f); | 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_line = 1; | ||||
| parser_col = 0; | 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; | int index_in_text = 0; | ||||
| @@ -526,6 +530,4 @@ namespace Parser { | |||||
| return program; | return program; | ||||
| } | } | ||||
| #undef inject_scl | |||||
| } | } | ||||
| @@ -6,10 +6,10 @@ | |||||
| #include "./defines.cpp" | #include "./defines.cpp" | ||||
| #include "./structs.cpp" | #include "./structs.cpp" | ||||
| #include "./forward_decls.cpp" | #include "./forward_decls.cpp" | ||||
| #include "./memory.cpp" | |||||
| #include "./lisp_object.cpp" | #include "./lisp_object.cpp" | ||||
| #include "./error.cpp" | #include "./error.cpp" | ||||
| #include "./io.cpp" | #include "./io.cpp" | ||||
| #include "./memory.cpp" | |||||
| #include "./env.cpp" | #include "./env.cpp" | ||||
| #include "./parse.cpp" | #include "./parse.cpp" | ||||
| #include "./built_ins.cpp" | #include "./built_ins.cpp" | ||||
| @@ -1,9 +1,11 @@ | |||||
| struct Lisp_Object; | struct Lisp_Object; | ||||
| struct String; | |||||
| struct Environment; | struct Environment; | ||||
| define_array_list(Lisp_Object*, Lisp_Object); | 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(int, Int); | ||||
| define_array_list(void*, Void_Ptr); | |||||
| enum struct Lisp_Object_Type { | enum struct Lisp_Object_Type { | ||||
| Nil, | Nil, | ||||
| @@ -49,29 +51,29 @@ enum struct Log_Level { | |||||
| Debug, | Debug, | ||||
| }; | }; | ||||
| struct String { | |||||
| int length; | |||||
| char data; | |||||
| }; | |||||
| struct Source_Code_Location { | struct Source_Code_Location { | ||||
| const char* file; | |||||
| String* file; | |||||
| int line; | int line; | ||||
| int column; | int column; | ||||
| }; | }; | ||||
| struct Symbol { | struct Symbol { | ||||
| char* identifier; | |||||
| String* identifier; | |||||
| }; | }; | ||||
| struct Keyword { | struct Keyword { | ||||
| char* identifier; | |||||
| String* identifier; | |||||
| }; | }; | ||||
| struct Number { | struct Number { | ||||
| double value; | double value; | ||||
| }; | }; | ||||
| struct String { | |||||
| int length; | |||||
| char* value; | |||||
| }; | |||||
| struct Pair { | struct Pair { | ||||
| Lisp_Object* first; | Lisp_Object* first; | ||||
| Lisp_Object* rest; | Lisp_Object* rest; | ||||
| @@ -80,13 +82,13 @@ struct Pair { | |||||
| struct Positional_Arguments { | struct Positional_Arguments { | ||||
| // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have | // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have | ||||
| // to convert them to strings and back to symbols | // to convert them to strings and back to symbols | ||||
| char** identifiers; | |||||
| String** identifiers; // Array of Pointers to String | |||||
| int next_index; | int next_index; | ||||
| int length; | int length; | ||||
| }; | }; | ||||
| struct Keyword_Arguments { | struct Keyword_Arguments { | ||||
| char** identifiers; | |||||
| String** identifiers; // Array of Pointers to String | |||||
| // NOTE(Felix): values[i] will be nullptr if no defalut value was | // NOTE(Felix): values[i] will be nullptr if no defalut value was | ||||
| // declared for key identifiers[i] | // declared for key identifiers[i] | ||||
| Lisp_Object_Array_List* values; | Lisp_Object_Array_List* values; | ||||
| @@ -96,11 +98,11 @@ struct Keyword_Arguments { | |||||
| struct Function { | struct Function { | ||||
| Function_Type type; | Function_Type type; | ||||
| char* docstring; | |||||
| String* docstring; | |||||
| Positional_Arguments* positional_arguments; | Positional_Arguments* positional_arguments; | ||||
| Keyword_Arguments* keyword_arguments; | Keyword_Arguments* keyword_arguments; | ||||
| // rest_argument will be nullptr if no rest argument is declared | // rest_argument will be nullptr if no rest argument is declared | ||||
| char* rest_argument; | |||||
| String* rest_argument; | |||||
| Lisp_Object* body; // implicit prog | Lisp_Object* body; // implicit prog | ||||
| Environment* parent_environment; // we are doing closures now!! | Environment* parent_environment; // we are doing closures now!! | ||||
| }; | }; | ||||
| @@ -50,7 +50,7 @@ | |||||
| #define assert_equal_string(variable, value) \ | #define assert_equal_string(variable, value) \ | ||||
| if (!string_equal(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; \ | return fail; \ | ||||
| } | } | ||||
| @@ -108,7 +108,7 @@ proc test_eval_operands() -> testresult { | |||||
| assert_equal_type(operands, Lisp_Object_Type::Pair); | assert_equal_type(operands, Lisp_Object_Type::Pair); | ||||
| assert_equal_type(operands->value.pair->first, Lisp_Object_Type::String); | 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; | operands = operands->value.pair->rest; | ||||
| @@ -144,7 +144,7 @@ proc test_parse_atom() -> testresult { | |||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Lisp_Object_Type::String); | 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 | // test keywords | ||||
| ++index_in_text; | ++index_in_text; | ||||