| @@ -1 +1 @@ | |||||
| Subproject commit 98aa1450d8e63046d3260ea7fb4ff12c9c7e2629 | |||||
| Subproject commit e5cb9ce81d822fee56bdef1f44b3f8d1a29618de | |||||
| @@ -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/set! hash-map-set!) | ||||
| (define hm/get hash-map-get) | (define hm/get hash-map-get) | ||||
| @@ -5,12 +12,12 @@ | |||||
| (mytry (hm/get hm key) ())) | (mytry (hm/get hm key) ())) | ||||
| (define-syntax (pe expr) | (define-syntax (pe expr) | ||||
| `((begin | |||||
| `(begin | |||||
| (print :end " " ',expr "evaluates to") | (print :end " " ',expr "evaluates to") | ||||
| ((lambda (e) | ((lambda (e) | ||||
| (print e) | (print e) | ||||
| e) ,expr)) | e) ,expr)) | ||||
| )) | |||||
| ) | |||||
| (define the-empty-stream ()) | (define the-empty-stream ()) | ||||
| @@ -175,11 +182,6 @@ condition is false." | |||||
| (rec body)) | (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-syntax (define-typed args . body) | ||||
| (define (get-arg-names args) | (define (get-arg-names args) | ||||
| (when args | (when args | ||||
| @@ -33,8 +33,8 @@ | |||||
| do { \ | do { \ | ||||
| if (Memory::get_type(_node) != _type) { \ | if (Memory::get_type(_node) != _type) { \ | ||||
| create_type_missmatch_error( \ | 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) | } while(0) | ||||
| @@ -178,7 +178,7 @@ namespace Slime { | |||||
| inline void push_environment(Environment*); | inline void push_environment(Environment*); | ||||
| inline void pop_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 visualize_lisp_machine(); | ||||
| void generate_docs(String* path); | void generate_docs(String* path); | ||||
| @@ -35,8 +35,8 @@ | |||||
| char* t = lisp_object_to_string(_node); \ | char* t = lisp_object_to_string(_node); \ | ||||
| defer { free(t); }; \ | defer { free(t); }; \ | ||||
| create_type_missmatch_error( \ | 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); \ | t); \ | ||||
| } \ | } \ | ||||
| } while(0) | } while(0) | ||||
| @@ -64,12 +64,12 @@ namespace Slime { | |||||
| proc add_to_load_path(const char* path) -> void { | proc add_to_load_path(const char* path) -> void { | ||||
| using Globals::load_path; | using Globals::load_path; | ||||
| load_path.append((void*)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* file_content; | ||||
| char fullpath[4096]; | char fullpath[4096]; | ||||
| sprintf(fullpath, "%s", Memory::get_c_str(file_name)); | sprintf(fullpath, "%s", Memory::get_c_str(file_name)); | ||||
| @@ -98,7 +98,11 @@ namespace Slime { | |||||
| Lisp_Object* result = Memory::nil; | Lisp_Object* result = Memory::nil; | ||||
| Array_List<Lisp_Object*>* program; | Array_List<Lisp_Object*>* program; | ||||
| try program = Parser::parse_program(Memory::create_string(fullpath), file_content); | |||||
| 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 | // NOTE(Felix): deferred so even if the eval failes, it will | ||||
| // run | // run | ||||
| @@ -114,7 +118,7 @@ namespace Slime { | |||||
| return result; | return result; | ||||
| } | } | ||||
| proc built_in_import(String* file_name) -> Lisp_Object* { | |||||
| proc built_in_import(String file_name) -> Lisp_Object* { | |||||
| profile_this(); | profile_this(); | ||||
| Environment* new_env; | Environment* new_env; | ||||
| @@ -142,8 +146,16 @@ namespace Slime { | |||||
| proc load_built_ins_into_environment() -> void* { | proc load_built_ins_into_environment() -> void* { | ||||
| profile_this(); | 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") { | define_macro((apply fun fun_args), "TODO") { | ||||
| // NOTE(Felix): is has to be a macro because apply by | // NOTE(Felix): is has to be a macro because apply by | ||||
| // itself cannot return the result, we have to invoke eval | // itself cannot return the result, we have to invoke eval | ||||
| @@ -199,7 +211,7 @@ namespace Slime { | |||||
| define_symbol( | define_symbol( | ||||
| Memory::get_symbol("c"), | Memory::get_symbol("c"), | ||||
| Memory::create_lisp_object((double)0)); | 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), "") { | define((lambda), "") { | ||||
| fetch(c); | fetch(c); | ||||
| c->value.number++; | c->value.number++; | ||||
| @@ -314,7 +326,8 @@ namespace Slime { | |||||
| thing_cons->value.pair.rest != Memory::nil) | thing_cons->value.pair.rest != Memory::nil) | ||||
| { | { | ||||
| // extract docs | // 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; | thing_cons = thing_cons->value.pair.rest; | ||||
| } | } | ||||
| func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons); | func->value.function->body.lisp_body = maybe_wrap_body_in_begin(thing_cons); | ||||
| @@ -580,15 +593,10 @@ namespace Slime { | |||||
| free(string); | free(string); | ||||
| return nullptr; | return nullptr; | ||||
| }; | }; | ||||
| define_special((define-syntax form (:doc "") . body), "TODO") { | |||||
| define_special((define-syntax form . body), "TODO") { | |||||
| profile_with_name("(define-syntax)"); | 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) { | if (Memory::get_type(form) != Lisp_Object_Type::Pair) { | ||||
| create_parsing_error("You can only create function macros."); | create_parsing_error("You can only create function macros."); | ||||
| @@ -601,8 +609,6 @@ namespace Slime { | |||||
| // creating new lisp object and setting type | // creating new lisp object and setting type | ||||
| Lisp_Object* func; | Lisp_Object* func; | ||||
| try func = Memory::create_lisp_object_function(Lisp_Function_Type::Macro); | try func = Memory::create_lisp_object_function(Lisp_Function_Type::Macro); | ||||
| if (doc) func->docstring = doc->value.string; | |||||
| in_caller_env { | in_caller_env { | ||||
| // setting parent env | // setting parent env | ||||
| func->value.function->parent_environment = get_current_environment(); | func->value.function->parent_environment = get_current_environment(); | ||||
| @@ -1017,13 +1023,15 @@ namespace Slime { | |||||
| printf(" is of type "); | printf(" is of type "); | ||||
| print(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: "); | printf("\nand is printed as: "); | ||||
| print(val); | print(val); | ||||
| printf("\n\ndocs:\n=====\n %s\n\n", | 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) | if (Memory::get_type(val) == Lisp_Object_Type::Function) | ||||
| { | { | ||||
| @@ -1125,7 +1133,7 @@ namespace Slime { | |||||
| defer { | defer { | ||||
| free(line); | free(line); | ||||
| }; | }; | ||||
| String* strLine = Memory::create_string(line); | |||||
| String strLine = Memory::create_string(line); | |||||
| return Memory::create_lisp_object(strLine); | return Memory::create_lisp_object(strLine); | ||||
| }; | }; | ||||
| define((exit (:code 0)), "TODO") { | define((exit (:code 0)), "TODO") { | ||||
| @@ -1240,16 +1248,16 @@ namespace Slime { | |||||
| int resulting_string_len = 0; | int resulting_string_len = 0; | ||||
| for_lisp_list (strings) { | for_lisp_list (strings) { | ||||
| try assert_type(it, Lisp_Object_Type::String); | 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; | int index_in_string = 0; | ||||
| for_lisp_list (strings) { | 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)); | 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); | return Memory::create_lisp_object(resulting_string); | ||||
| @@ -42,7 +42,7 @@ | |||||
| #endif | #endif | ||||
| #define try_struct try_or_else_return({}) | #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 try try_or_else_return(0) | ||||
| #define dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) | #define dont_break_on_errors fluid_let(Globals::breaking_on_errors, false) | ||||
| @@ -105,15 +105,14 @@ | |||||
| #endif | #endif | ||||
| // NOTE(Felix): we have to copy the string because we need it to be | // 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_file = file_name_built_ins; \ | ||||
| Parser::parser_line = __LINE__; \ | Parser::parser_line = __LINE__; \ | ||||
| Parser::parser_col = 0; \ | 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); \ | if_error_log_location_and_return(nullptr); \ | ||||
| assert_type(label(params,__LINE__), Lisp_Object_Type::Pair); \ | assert_type(label(params,__LINE__), Lisp_Object_Type::Pair); \ | ||||
| assert_type(label(params,__LINE__)->value.pair.first, Lisp_Object_Type::Symbol); \ | 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); \ | 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__)); \ | create_arguments_from_lambda_list_and_inject(label(params,__LINE__)->value.pair.rest, label(sfun,__LINE__)); \ | ||||
| if_error_log_location_and_return(nullptr); \ | 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(); \ | label(sfun,__LINE__)->value.function->parent_environment = get_current_environment(); \ | ||||
| define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ | define_symbol(label(sym,__LINE__), label(sfun,__LINE__)); \ | ||||
| label(sfun,__LINE__)->value.function->body. ending | label(sfun,__LINE__)->value.function->body. ending | ||||
| @@ -154,3 +153,7 @@ | |||||
| for (Lisp_Object* head = l, *it; \ | for (Lisp_Object* head = l, *it; \ | ||||
| Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \ | Memory::get_type(head) == Lisp_Object_Type::Pair && (it = head->value.pair.first); \ | ||||
| head = head->value.pair.rest, ++it_index) | head = head->value.pair.rest, ++it_index) | ||||
| #define dbg(thing, format) \ | |||||
| printf("%s = " format "\n", #thing, thing) | |||||
| @@ -1,5 +1,5 @@ | |||||
| namespace Slime { | namespace Slime { | ||||
| proc generate_docs(String* path) -> void { | |||||
| proc generate_docs(String path) -> void { | |||||
| FILE *f = fopen(Memory::get_c_str(path), "w"); | FILE *f = fopen(Memory::get_c_str(path), "w"); | ||||
| if (!f) { | if (!f) { | ||||
| create_generic_error("The file for writing the documentation (%s) " | create_generic_error("The file for writing the documentation (%s) " | ||||
| @@ -124,10 +124,11 @@ namespace Slime { | |||||
| } | } | ||||
| } | } | ||||
| fprintf(f, "\n - docu :: "); | 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"); | fprintf(f, "none\n"); | ||||
| } | } | ||||
| } | } | ||||
| @@ -1,11 +1,11 @@ | |||||
| namespace Slime { | namespace Slime { | ||||
| proc define_symbol(Lisp_Object* symbol, Lisp_Object* value) -> void { | 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()); | define_symbol(symbol, value, get_current_environment()); | ||||
| } | } | ||||
| proc define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) -> void { | 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); | env->hm.set_object((void*)symbol, value); | ||||
| } | } | ||||
| @@ -76,7 +76,7 @@ namespace Slime { | |||||
| } | } | ||||
| proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | 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); | // print(node); | ||||
| assert_type(node, Lisp_Object_Type::Symbol); | assert_type(node, Lisp_Object_Type::Symbol); | ||||
| @@ -85,10 +85,10 @@ namespace Slime { | |||||
| if (result) | if (result) | ||||
| return result; | return result; | ||||
| String* identifier = node->value.symbol; | |||||
| String identifier = node->value.symbol; | |||||
| print_environment(env); | print_environment(env); | ||||
| printf("\n"); | 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; | return nullptr; | ||||
| } | } | ||||
| @@ -108,7 +108,7 @@ namespace Slime { | |||||
| for_hash_map (env->hm) { | for_hash_map (env->hm) { | ||||
| print_indent(indent); | print_indent(indent); | ||||
| printf("-> %s :: ", &(((Lisp_Object*)key)->value.symbol->data)); | |||||
| printf("-> %s :: ", (((Lisp_Object*)key)->value.symbol.data)); | |||||
| print((Lisp_Object*)value); | print((Lisp_Object*)value); | ||||
| printf(" (0x%016llx)", (unsigned long long)value); | printf(" (0x%016llx)", (unsigned long long)value); | ||||
| puts(""); | puts(""); | ||||
| @@ -7,7 +7,7 @@ namespace Slime { | |||||
| error = nullptr; | 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(); | delete_error(); | ||||
| if (Globals::breaking_on_errors) { | if (Globals::breaking_on_errors) { | ||||
| debug_break(); | 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 { | 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; | using Globals::error; | ||||
| // TODO(Felix): is the length even used?? | |||||
| int length = 200; | int length = 200; | ||||
| String* formatted_string = Memory::create_string("", length); | |||||
| String formatted_string = Memory::create_string("", length); | |||||
| if (error) { | if (error) { | ||||
| error = new(Error); | error = new(Error); | ||||
| error->type = type; | error->type = type; | ||||
| @@ -49,8 +50,8 @@ namespace Slime { | |||||
| written_length = vasprintf(&out_msg, format, args); | written_length = vasprintf(&out_msg, format, args); | ||||
| va_end(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); | free(out_msg); | ||||
| create_error(c_func_name, c_file_name, c_file_line, type, formatted_string); | create_error(c_func_name, c_file_name, c_file_line, type, formatted_string); | ||||
| } | } | ||||
| @@ -31,7 +31,7 @@ namespace Slime { | |||||
| "Not enough positional args supplied. Needed: %d suppied, %d.\n" | "Not enough positional args supplied. Needed: %d suppied, %d.\n" | ||||
| "Next missing arg is '%s'", | "Next missing arg is '%s'", | ||||
| arg_spec->positional.symbols.next_index, arg_end-index_of_next_arg, | 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; | return nullptr; | ||||
| } | } | ||||
| // NOTE(Felix): We have to copy all the arguments, | // 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" | "The function does not take the keyword argument ':%s'\n" | ||||
| "and not all required keyword arguments have been read\n" | "and not all required keyword arguments have been read\n" | ||||
| "in to potentially count it as the rest argument.", | "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; | return nullptr; | ||||
| } | } | ||||
| // This is an accepted kwarg; check if it was already | // This is an accepted kwarg; check if it was already | ||||
| @@ -92,7 +92,7 @@ namespace Slime { | |||||
| // in, it is an error | // in, it is an error | ||||
| create_generic_error( | create_generic_error( | ||||
| "The function already read the keyword argument ':%s'", | "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; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| @@ -102,7 +102,7 @@ namespace Slime { | |||||
| if (index_of_next_arg+1 == arg_end) { | if (index_of_next_arg+1 == arg_end) { | ||||
| create_generic_error( | create_generic_error( | ||||
| "Attempting to set the keyword argument ':%s', but no value was supplied.", | "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; | return nullptr; | ||||
| } | } | ||||
| @@ -145,7 +145,7 @@ namespace Slime { | |||||
| create_generic_error( | create_generic_error( | ||||
| "There was no value supplied for the required " | "There was no value supplied for the required " | ||||
| "keyword argument ':%s'.", | "keyword argument ':%s'.", | ||||
| &defined_keyword->value.symbol->data); | |||||
| defined_keyword->value.symbol.data); | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| } else { | } else { | ||||
| @@ -240,7 +240,7 @@ namespace Slime { | |||||
| create_parsing_error("Only symbols and keywords " | create_parsing_error("Only symbols and keywords " | ||||
| "(with or without default args) " | "(with or without default args) " | ||||
| "can be parsed here, but found '%s'", | "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; | return; | ||||
| } | } | ||||
| @@ -444,7 +444,7 @@ namespace Slime { | |||||
| free(t); | free(t); | ||||
| }; | }; | ||||
| create_generic_error("The first element of the pair was not a function but: %s in %s", | 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; | return nullptr; | ||||
| } | } | ||||
| } | } | ||||
| @@ -515,7 +515,7 @@ namespace Slime { | |||||
| } | } | ||||
| proc interprete_file (char* file_name) -> Lisp_Object* { | proc interprete_file (char* file_name) -> Lisp_Object* { | ||||
| try Memory::init(4096 * 256); | |||||
| try Memory::init(); | |||||
| Lisp_Object* result; | Lisp_Object* result; | ||||
| @@ -525,7 +525,7 @@ namespace Slime { | |||||
| } | } | ||||
| proc interprete_stdin() -> void { | 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); | printf("Welcome to the lispy interpreter.\n%s\n", version_string); | ||||
| @@ -1,11 +1,11 @@ | |||||
| namespace Slime { | namespace Slime { | ||||
| void add_to_load_path(const char*); | void add_to_load_path(const char*); | ||||
| bool lisp_object_equal(Lisp_Object*,Lisp_Object*); | 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 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, 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); | 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_arguments(Lisp_Object*); | ||||
| Lisp_Object* eval_expr(Lisp_Object*); | Lisp_Object* eval_expr(Lisp_Object*); | ||||
| @@ -28,23 +28,23 @@ namespace Slime { | |||||
| inline void push_environment(Environment*); | inline void push_environment(Environment*); | ||||
| inline void pop_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 visualize_lisp_machine(); | ||||
| void generate_docs(String* path); | |||||
| void generate_docs(String path); | |||||
| void log_error(); | void log_error(); | ||||
| namespace Memory { | namespace Memory { | ||||
| Environment* create_built_ins_environment(); | Environment* create_built_ins_environment(); | ||||
| Lisp_Object* create_lisp_object_cfunction(bool is_special); | Lisp_Object* create_lisp_object_cfunction(bool is_special); | ||||
| inline Lisp_Object_Type get_type(Lisp_Object* node); | 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(); | 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_symbol(const char*); | ||||
| Lisp_Object* get_keyword(String* identifier); | |||||
| Lisp_Object* get_keyword(String identifier); | |||||
| Lisp_Object* get_keyword(const char*); | Lisp_Object* get_keyword(const char*); | ||||
| Lisp_Object* create_lisp_object(double); | Lisp_Object* create_lisp_object(double); | ||||
| Lisp_Object* create_lisp_object(const char*); | Lisp_Object* create_lisp_object(const char*); | ||||
| @@ -63,12 +63,13 @@ namespace Slime { | |||||
| namespace Parser { | namespace Parser { | ||||
| // extern Environment* environment_for_macros; | // 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_line; | ||||
| extern int parser_col; | extern int parser_col; | ||||
| Lisp_Object* parse_expression(char* text, int* index_in_text); | 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(char* text); | ||||
| Lisp_Object* parse_single_expression(wchar_t* text); | Lisp_Object* parse_single_expression(wchar_t* text); | ||||
| } | } | ||||
| @@ -4,7 +4,7 @@ namespace Slime::GC { | |||||
| int current_mark; | int current_mark; | ||||
| Array_List<Lisp_Object*> marked_objects; | Array_List<Lisp_Object*> marked_objects; | ||||
| Array_List<String*> marked_strings; | |||||
| Array_List<String> marked_strings; | |||||
| Array_List<Environment*> marked_environments; | Array_List<Environment*> marked_environments; | ||||
| Array_List<Environment*> protected_environments; | Array_List<Environment*> protected_environments; | ||||
| @@ -24,8 +24,9 @@ namespace Slime::GC { | |||||
| marked_objects.append(node); | marked_objects.append(node); | ||||
| // mark docstring | // mark docstring | ||||
| if (node->docstring) | |||||
| marked_strings.append(node->docstring); | |||||
| // TODO(Felix): | |||||
| // if (node->docstring) | |||||
| // marked_strings.append(node->docstring); | |||||
| // mark type specific data | // mark type specific data | ||||
| switch (Memory::get_type(node)) { | switch (Memory::get_type(node)) { | ||||
| @@ -10,18 +10,15 @@ namespace Slime { | |||||
| return false; | 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); | 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); | 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)); | 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)); | Lisp_Object* name = (Lisp_Object*)(get_root_environment()->hm.search_key_to_object(node)); | ||||
| if (name) { | if (name) { | ||||
| switch (node->value.function->type.c_function_type) { | 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-??]"); | default: return strdup("[c-??]"); | ||||
| } | } | ||||
| } else { | } else { | ||||
| @@ -435,7 +432,7 @@ namespace Slime { | |||||
| // first check if it is a quotation form, in that case we want | // first check if it is a quotation form, in that case we want | ||||
| // to print it prettier | // to print it prettier | ||||
| if (Memory::get_type(head->value.pair.first) == Lisp_Object_Type::Symbol) { | 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; | auto symbol = head->value.pair.first; | ||||
| @@ -47,15 +47,15 @@ unsigned int hm_hash(Slime::Lisp_Object* obj); | |||||
| # include "forward_decls.cpp" | # 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; | 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; | 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); | return Slime::lisp_object_equal(a, b); | ||||
| } | } | ||||
| @@ -88,7 +88,7 @@ unsigned int hm_hash(Slime::Lisp_Object* obj) { | |||||
| // different, they cauld be equivalent: | // different, they cauld be equivalent: | ||||
| case Lisp_Object_Type::Pointer: return hm_hash((void*) obj->value.pointer); | 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::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: { | case Lisp_Object_Type::Pair: { | ||||
| u32 hash = 1; | u32 hash = 1; | ||||
| for_lisp_list (obj) { | for_lisp_list (obj) { | ||||
| @@ -1,6 +1,6 @@ | |||||
| namespace Slime { | 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; | return nullptr; | ||||
| Source_Code_Location* ret = (Source_Code_Location*)malloc(sizeof(Source_Code_Location)); | Source_Code_Location* ret = (Source_Code_Location*)malloc(sizeof(Source_Code_Location)); | ||||
| @@ -10,7 +10,7 @@ namespace Slime { | |||||
| return ret; | 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) { | switch (type) { | ||||
| case(Lisp_Object_Type::Nil): return "nil"; | case(Lisp_Object_Type::Nil): return "nil"; | ||||
| case(Lisp_Object_Type::T): return "t"; | case(Lisp_Object_Type::T): return "t"; | ||||
| @@ -28,18 +28,4 @@ namespace Slime { | |||||
| return "unknown"; | 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; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| @@ -16,7 +16,7 @@ int main(int argc, char* argv[]) { | |||||
| int res = Slime::run_all_tests(); | int res = Slime::run_all_tests(); | ||||
| return res ? 0 : 1; | return res ? 0 : 1; | ||||
| } else if (Slime::string_equal(argv[1], "--generate-docs")) { | } else if (Slime::string_equal(argv[1], "--generate-docs")) { | ||||
| Slime::Memory::init(4096 * 256* 100); | |||||
| Slime::Memory::init(); | |||||
| if (Slime::Globals::error) return 1; | if (Slime::Globals::error) return 1; | ||||
| Slime::built_in_load(Slime::Memory::create_string("generate-docs.slime")); | Slime::built_in_load(Slime::Memory::create_string("generate-docs.slime")); | ||||
| } else { | } else { | ||||
| @@ -28,5 +28,4 @@ int main(int argc, char* argv[]) { | |||||
| } | } | ||||
| if (Slime::Globals::error) return 1; | if (Slime::Globals::error) return 1; | ||||
| } | } | ||||
| @@ -28,26 +28,11 @@ namespace Slime::Memory { | |||||
| // ------------------ | // ------------------ | ||||
| Bucket_Allocator<Hash_Map<Lisp_Object*, Lisp_Object*>> hashmap_memory; | Bucket_Allocator<Hash_Map<Lisp_Object*, Lisp_Object*>> 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<void*> free_spots_in_string_memory; | |||||
| String* string_memory; | |||||
| String* next_free_spot_in_string_memory; | |||||
| // ------------------ | // ------------------ | ||||
| // immutables | // immutables | ||||
| // ------------------ | // ------------------ | ||||
| Lisp_Object* nil = nullptr; | Lisp_Object* nil = nullptr; | ||||
| Lisp_Object* t = nullptr; | Lisp_Object* t = nullptr; | ||||
| Lisp_Object* _if = nullptr; | |||||
| Lisp_Object* _define = nullptr; | |||||
| Lisp_Object* _begin = nullptr; | |||||
| proc print_status() { | proc print_status() { | ||||
| @@ -66,8 +51,8 @@ namespace Slime::Memory { | |||||
| // free_spots_in_string_memory.next_index); | // 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* { | inline proc get_c_str(Lisp_Object* str) -> char* { | ||||
| @@ -89,49 +74,35 @@ namespace Slime::Memory { | |||||
| node->flags = (u64)(node->flags) | bitmask; | 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 | // TODO(Felix): When parsing symbols or keywords, compute the | ||||
| // hash while reading them in. | // 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 = (1000003 * value) ^ c; | ||||
| } | } | ||||
| value ^= str->length; | |||||
| value ^= str.length; | |||||
| return value; | 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* { | proc create_lisp_object() -> Lisp_Object* { | ||||
| @@ -139,14 +110,28 @@ namespace Slime::Memory { | |||||
| object->flags = 0; | object->flags = 0; | ||||
| object->sourceCodeLocation = nullptr; | object->sourceCodeLocation = nullptr; | ||||
| object->userType = nullptr; | object->userType = nullptr; | ||||
| object->docstring = nullptr; | |||||
| return object; | return object; | ||||
| } | } | ||||
| proc free_everything() -> void { | proc free_everything() -> void { | ||||
| free(string_memory); | |||||
| object_memory.for_each([](Lisp_Object* lo){ | 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){ | environment_memory.for_each([](Environment* env){ | ||||
| env->parents.dealloc(); | env->parents.dealloc(); | ||||
| @@ -155,6 +140,7 @@ namespace Slime::Memory { | |||||
| hashmap_memory.for_each([](Hash_Map<Lisp_Object*, Lisp_Object*>* hm){ | hashmap_memory.for_each([](Hash_Map<Lisp_Object*, Lisp_Object*>* hm){ | ||||
| hm->dealloc(); | hm->dealloc(); | ||||
| }); | }); | ||||
| // free the exe dir: | // free the exe dir: | ||||
| free(Globals::load_path.data[0]); | free(Globals::load_path.data[0]); | ||||
| Globals::load_path.dealloc(); | Globals::load_path.dealloc(); | ||||
| @@ -166,6 +152,8 @@ namespace Slime::Memory { | |||||
| Globals::Current_Execution::ats.dealloc(); | Globals::Current_Execution::ats.dealloc(); | ||||
| Globals::Current_Execution::mes.dealloc(); | Globals::Current_Execution::mes.dealloc(); | ||||
| free(Parser::standard_in.data); | |||||
| object_memory.dealloc(); | object_memory.dealloc(); | ||||
| environment_memory.dealloc(); | environment_memory.dealloc(); | ||||
| hashmap_memory.dealloc(); | hashmap_memory.dealloc(); | ||||
| @@ -197,7 +185,7 @@ namespace Slime::Memory { | |||||
| return ret; | return ret; | ||||
| } | } | ||||
| proc init(int sms) -> void { | |||||
| proc init() -> void { | |||||
| profile_this(); | profile_this(); | ||||
| object_memory.alloc(1024, 8); | object_memory.alloc(1024, 8); | ||||
| @@ -228,10 +216,6 @@ namespace Slime::Memory { | |||||
| add_to_load_path(exe_path); | add_to_load_path(exe_path); | ||||
| add_to_load_path("../bin/"); | 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 | // init nil | ||||
| try_void nil = create_lisp_object(); | try_void nil = create_lisp_object(); | ||||
| @@ -279,7 +263,7 @@ namespace Slime::Memory { | |||||
| return node; | return node; | ||||
| } | } | ||||
| proc create_lisp_object(String* str) -> Lisp_Object* { | |||||
| proc create_lisp_object(String str) -> Lisp_Object* { | |||||
| Lisp_Object* node; | Lisp_Object* node; | ||||
| try node = create_lisp_object(); | try node = create_lisp_object(); | ||||
| set_type(node, Lisp_Object_Type::String); | set_type(node, Lisp_Object_Type::String); | ||||
| @@ -368,53 +352,68 @@ namespace Slime::Memory { | |||||
| return node; | 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(); | try node = create_lisp_object(); | ||||
| set_type(node, Lisp_Object_Type::Symbol); | 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; | 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(); | try node = create_lisp_object(); | ||||
| set_type(node, Lisp_Object_Type::Keyword); | 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; | 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* { | proc create_lisp_object_cfunction(C_Function_Type type) -> Lisp_Object* { | ||||
| Lisp_Object* node; | Lisp_Object* node; | ||||
| try node = create_lisp_object(); | try node = create_lisp_object(); | ||||
| @@ -455,19 +454,29 @@ namespace Slime::Memory { | |||||
| // TODO(Felix): If argument is a list (pair), do a FULL copy, | // TODO(Felix): If argument is a list (pair), do a FULL copy, | ||||
| // we don't copy singleton objects | // 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; | 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* { | 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 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; | return ret; | ||||
| } | } | ||||
| inline proc create_list(Lisp_Object* o1) -> Lisp_Object* { | inline proc create_list(Lisp_Object* o1) -> Lisp_Object* { | ||||
| Lisp_Object* ret; | Lisp_Object* ret; | ||||
| try ret = create_lisp_object_pair(o1, nil); | try ret = create_lisp_object_pair(o1, nil); | ||||
| @@ -1,6 +1,6 @@ | |||||
| namespace Slime::Parser { | namespace Slime::Parser { | ||||
| String* standard_in; | |||||
| String* parser_file; | |||||
| String standard_in; | |||||
| String parser_file; | |||||
| int parser_line; | int parser_line; | ||||
| int parser_col; | int parser_col; | ||||
| @@ -126,15 +126,15 @@ namespace Slime::Parser { | |||||
| text[*index_in_text+atom_length] = '\0'; | 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) { | if (keyword) { | ||||
| try ret = Memory::get_keyword(str_keyword); | |||||
| try ret = Memory::get_keyword(text+*index_in_text); | |||||
| } else { | } 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; | int new_len; | ||||
| try new_len = unescape_string(text+(*index_in_text)); | 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); | // printf("------ %s\n", &string->data); | ||||
| text[*index_in_text+string_length] = '"'; | text[*index_in_text+string_length] = '"'; | ||||
| @@ -359,10 +359,20 @@ namespace Slime::Parser { | |||||
| proc parse_single_expression(wchar_t* text) -> Lisp_Object* { | proc parse_single_expression(wchar_t* text) -> Lisp_Object* { | ||||
| char* res = wchar_to_char(text); | char* res = wchar_to_char(text); | ||||
| defer {free(res);}; | |||||
| defer_free(res); | |||||
| return parse_single_expression(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* { | proc parse_single_expression(char* text) -> Lisp_Object* { | ||||
| parser_file = standard_in; | parser_file = standard_in; | ||||
| parser_line = 1; | parser_line = 1; | ||||
| @@ -375,7 +385,7 @@ namespace Slime::Parser { | |||||
| } | } | ||||
| proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*>* { | |||||
| proc parse_program(String file_name, char* text) -> Array_List<Lisp_Object*>* { | |||||
| profile_this(); | profile_this(); | ||||
| parser_file = file_name; | parser_file = file_name; | ||||
| parser_line = 1; | parser_line = 1; | ||||
| @@ -71,12 +71,12 @@ namespace Slime { | |||||
| }; | }; | ||||
| struct String { | struct String { | ||||
| int length; | |||||
| char data; | |||||
| int length; | |||||
| char* data; | |||||
| }; | }; | ||||
| struct Source_Code_Location { | struct Source_Code_Location { | ||||
| String* file; | |||||
| String file; | |||||
| int line; | int line; | ||||
| int column; | int column; | ||||
| }; | }; | ||||
| @@ -135,11 +135,10 @@ namespace Slime { | |||||
| Source_Code_Location* sourceCodeLocation; | Source_Code_Location* sourceCodeLocation; | ||||
| u64 flags; | u64 flags; | ||||
| Lisp_Object* userType; // keyword | Lisp_Object* userType; // keyword | ||||
| String* docstring; | |||||
| union value { | union value { | ||||
| String* symbol; // used for symbols and keywords | |||||
| String symbol; // used for symbols and keywords | |||||
| double number; | double number; | ||||
| String* string; | |||||
| String string; | |||||
| Pair pair; | Pair pair; | ||||
| Vector vector; | Vector vector; | ||||
| Function* function; | Function* function; | ||||
| @@ -148,13 +147,12 @@ namespace Slime { | |||||
| Hash_Map<Lisp_Object*, Lisp_Object*>* hashMap; | Hash_Map<Lisp_Object*, Lisp_Object*>* hashMap; | ||||
| ~value() {} | ~value() {} | ||||
| } value; | } value; | ||||
| ~Lisp_Object(); | |||||
| }; | }; | ||||
| struct Error { | struct Error { | ||||
| Lisp_Object* position; | Lisp_Object* position; | ||||
| // type has to be a keyword | // type has to be a keyword | ||||
| Lisp_Object* type; | Lisp_Object* type; | ||||
| String* message; | |||||
| String message; | |||||
| }; | }; | ||||
| } | } | ||||
| @@ -60,15 +60,15 @@ namespace Slime { | |||||
| #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->data, value, char*, "%s"); \ | |||||
| print_assert_equal_fail(variable.data, value, char*, "%s"); \ | |||||
| return fail; \ | return fail; \ | ||||
| } | } | ||||
| #define assert_equal_type(node, _type) \ | #define assert_equal_type(node, _type) \ | ||||
| if (Memory::get_type(node) != _type) { \ | if (Memory::get_type(node) != _type) { \ | ||||
| print_assert_equal_fail( \ | 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; \ | return fail; \ | ||||
| } \ | } \ | ||||
| @@ -555,8 +555,15 @@ namespace Slime { | |||||
| proc test_singular_symbols() -> testresult { | proc test_singular_symbols() -> testresult { | ||||
| auto cc_s_aa = Memory::get_symbol("aa"); | auto cc_s_aa = Memory::get_symbol("aa"); | ||||
| auto cc_s_aa2 = Memory::get_symbol("aa2"); | 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_aa, s_s_aa); | ||||
| assert_equal_int(cc_s_aa2, s_s_aa2); | assert_equal_int(cc_s_aa2, s_s_aa2); | ||||
| @@ -571,7 +578,9 @@ namespace Slime { | |||||
| // assert_no_error(); | // assert_no_error(); | ||||
| push_environment(Memory::create_child_environment(get_current_environment())); | 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(); | assert_no_error(); | ||||
| pop_environment(); | pop_environment(); | ||||
| @@ -582,7 +591,7 @@ namespace Slime { | |||||
| profile_this(); | profile_this(); | ||||
| bool result = true; | bool result = true; | ||||
| try Memory::init(409600); | |||||
| try Memory::init(); | |||||
| push_environment(Memory::create_child_environment( | push_environment(Memory::create_child_environment( | ||||
| get_current_environment())); | get_current_environment())); | ||||