| @@ -8,3 +8,4 @@ | |||
| *.vspx | |||
| todo.html | |||
| *.expanded | |||
| /bin/vgcore.* | |||
| @@ -1 +1,3 @@ | |||
| (define variable "Hello World!") | |||
| (define variable "imported") | |||
| (define (get-imported-variable) variable) | |||
| @@ -1,3 +1,9 @@ | |||
| (import "tests/import.slime") | |||
| (print variable) | |||
| (assert (= variable "imported")) | |||
| (assert (= (get-imported-variable) "imported")) | |||
| (load "tests/load.slime") | |||
| (assert (= variable "loaded")) | |||
| (assert (= (get-imported-variable) "imported")) | |||
| @@ -0,0 +1 @@ | |||
| (define variable "loaded") | |||
| @@ -48,7 +48,8 @@ proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { | |||
| proc built_in_import(String* file_name, Environment* env) -> Lisp_Object* { | |||
| // create new empty environment | |||
| Environment* new_env = Memory::create_child_environment(Globals::root_environment); | |||
| Environment* new_env; | |||
| try new_env = Memory::create_child_environment(Globals::root_environment); | |||
| Environment* old_macro_env = Parser::environment_for_macros; | |||
| Parser::environment_for_macros = new_env; | |||
| @@ -537,7 +538,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||
| try arguments_length = list_length(arguments); | |||
| try assert_arguments_length_greater_equal(1, arguments_length); | |||
| Environment* let_env = Memory::create_child_environment(env); | |||
| Environment* let_env; | |||
| try let_env = Memory::create_child_environment(env); | |||
| Lisp_Object* bindings = arguments->value.pair.first; | |||
| while (true) { | |||
| if (bindings == Memory::nil) { | |||
| @@ -8,12 +8,13 @@ proc delete_error() -> void { | |||
| } | |||
| proc create_error(const char* c_file_name, int c_file_line, Lisp_Object* type, String* message) -> void { | |||
| visualize_lisp_machine(); | |||
| printf("Error created in:\n%s:%d\n", c_file_name, c_file_line); | |||
| delete_error(); | |||
| debug_break(); | |||
| // visualize_lisp_machine(); | |||
| using Globals::error; | |||
| error = new(Error); | |||
| error->type = type; | |||
| @@ -1,5 +1,7 @@ | |||
| proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> Lisp_Object* { | |||
| Environment* new_env = Memory::create_child_environment(function->parent_environment); | |||
| Environment* new_env; | |||
| try new_env = Memory::create_child_environment(function->parent_environment); | |||
| Lisp_Object* sym, *val; // used as temp storage to use `try` | |||
| // positional arguments | |||
| @@ -427,9 +429,10 @@ proc is_truthy(Lisp_Object* expression, Environment* env) -> bool { | |||
| } | |||
| proc interprete_file (char* file_name) -> Lisp_Object* { | |||
| Memory::init(4096 * 256, 4096 * 256); | |||
| Memory::init(4096 * 256, 1024, 4096 * 256); | |||
| Environment* root_env = Globals::root_environment; | |||
| Environment* user_env = Memory::create_child_environment(root_env); | |||
| Environment* user_env; | |||
| try user_env = Memory::create_child_environment(root_env); | |||
| Parser::environment_for_macros = user_env; | |||
| // char* file_content; | |||
| @@ -450,9 +453,15 @@ proc interprete_file (char* file_name) -> Lisp_Object* { | |||
| } | |||
| proc interprete_stdin() -> void { | |||
| Memory::init(4096 * 256, 4096 * 256); | |||
| Memory::init(4096 * 256, 1024, 4096 * 256); | |||
| Environment* root_env = Globals::root_environment; | |||
| Environment* user_env = Memory::create_child_environment(root_env); | |||
| if (Globals::error) { | |||
| log_error(); | |||
| delete_error(); | |||
| return; | |||
| } | |||
| Parser::environment_for_macros = user_env; | |||
| printf("Welcome to the lispy interpreter.\n"); | |||
| @@ -470,8 +479,10 @@ proc interprete_stdin() -> void { | |||
| while (true) { | |||
| printf(">"); | |||
| line = read_expression(); | |||
| defer { | |||
| free(line); | |||
| }; | |||
| parsed = Parser::parse_single_expression(line); | |||
| free(line); | |||
| if (Globals::error) { | |||
| log_error(); | |||
| delete_error(); | |||
| @@ -1,13 +1,12 @@ | |||
| proc string_equal(const char input[], const char check[]) -> bool { | |||
| if (input == check) return true; | |||
| int i; | |||
| for(i = 0; input[i] != '\0' || check[i] != '\0'; i++) { | |||
| if(input[i] != check[i]) { | |||
| return false; | |||
| } | |||
| for(int i = 0; input[i] == check[i]; i++) { | |||
| if (input[i] == '\0') | |||
| return true; | |||
| } | |||
| return true; | |||
| return false; | |||
| } | |||
| proc string_equal(String* str, const char check[]) -> bool { | |||
| @@ -21,7 +20,7 @@ proc string_equal(const char check[], String* str) -> bool { | |||
| proc string_equal(String* str1, String* str2) -> bool { | |||
| if (str1 == str2) | |||
| return true; | |||
| return string_equal(Memory::get_c_str(str1), Memory::get_c_str(str2)); | |||
| } | |||
| @@ -91,8 +90,8 @@ proc read_entire_file(char* filename) -> char* { | |||
| /* Go to the end of the file. */ | |||
| if (fseek(fp, 0L, SEEK_END) == 0) { | |||
| /* Get the size of the file. */ | |||
| long bufsize = ftell(fp); | |||
| if (bufsize == -1) { | |||
| long bufsize = ftell(fp) + 1; | |||
| if (bufsize == 0) { | |||
| fputs("Empty file", stderr); | |||
| goto closeFile; | |||
| } | |||
| @@ -13,7 +13,7 @@ namespace Memory { | |||
| // ------------------ | |||
| int environment_memory_size; | |||
| Int_Array_List* free_spots_in_environment_memory; | |||
| Lisp_Object* environment_memory; | |||
| Environment* environment_memory; | |||
| int next_index_in_environment_memory = 0; | |||
| // ------------------ | |||
| @@ -135,7 +135,7 @@ namespace Memory { | |||
| } | |||
| index = next_index_in_object_memory++; | |||
| } else { | |||
| // else fill a free spot | |||
| // else fill a free spot, and remove the free spot | |||
| index = free_spots_in_object_memory->data[free_spots_in_object_memory->next_index--]; | |||
| } | |||
| Lisp_Object* object = object_memory+index; | |||
| @@ -145,15 +145,18 @@ namespace Memory { | |||
| return object; | |||
| } | |||
| proc init(int oms, int sms) { | |||
| object_memory_size = oms; | |||
| string_memory_size = sms; | |||
| proc init(int oms, int ems, int sms) { | |||
| object_memory_size = oms; | |||
| environment_memory_size = ems; | |||
| string_memory_size = sms; | |||
| free_spots_in_object_memory = create_Int_array_list(); | |||
| free_spots_in_string_memory = create_Void_Ptr_array_list(); | |||
| free_spots_in_object_memory = create_Int_array_list(); | |||
| free_spots_in_environment_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(string_memory_size * sizeof(char)); | |||
| object_memory = (Lisp_Object*)malloc(object_memory_size * sizeof(Lisp_Object)); | |||
| environment_memory = (Environment*)malloc(environment_memory_size * sizeof(Environment)); | |||
| string_memory = (String*)malloc(string_memory_size * sizeof(char)); | |||
| next_free_spot_in_string_memory = string_memory; | |||
| @@ -165,15 +168,19 @@ namespace Memory { | |||
| try_void t = create_lisp_object(); | |||
| set_type(t, Lisp_Object_Type::T); | |||
| Globals::root_environment = create_built_ins_environment(); | |||
| Parser::standard_in = create_string("stdin"); | |||
| try_void Globals::root_environment = create_built_ins_environment(); | |||
| try_void Parser::standard_in = create_string("stdin"); | |||
| } | |||
| proc reset() -> void { | |||
| free_spots_in_object_memory->next_index = 0; | |||
| free_spots_in_string_memory->next_index = 0; | |||
| next_index_in_object_memory = 2; // because t and nil are always there | |||
| next_free_spot_in_string_memory = string_memory; | |||
| free_spots_in_object_memory->next_index = 0; | |||
| free_spots_in_environment_memory->next_index = 0; | |||
| free_spots_in_string_memory->next_index = 0; | |||
| // because t and nil are always there we start the index at 2 | |||
| next_index_in_object_memory = 2; | |||
| next_index_in_environment_memory = 0; | |||
| next_free_spot_in_string_memory = string_memory; | |||
| Globals::root_environment = create_built_ins_environment(); | |||
| } | |||
| @@ -268,8 +275,27 @@ namespace Memory { | |||
| } | |||
| proc create_child_environment(Environment* parent) -> Environment* { | |||
| Environment* env = new(Environment); | |||
| int index; | |||
| // if we have no free spots then append at the end | |||
| if (free_spots_in_environment_memory->next_index == 0) { | |||
| // if we still have space | |||
| if (environment_memory_size == next_index_in_environment_memory) { | |||
| create_out_of_memory_error( | |||
| "There is not enough space in the environment" | |||
| "memory to allocate additional environments. " | |||
| "Maybe try increasing the Memory size when " | |||
| "calling Memory::init()"); | |||
| return nullptr; | |||
| } | |||
| index = next_index_in_environment_memory++; | |||
| } else { | |||
| // else fill a free spot, and remove the free spot | |||
| index = free_spots_in_environment_memory->data[free_spots_in_environment_memory->next_index--]; | |||
| } | |||
| Environment* env = environment_memory+index; | |||
| int start_capacity = 16; | |||
| env->parents = create_Environment_array_list(); | |||
| @@ -286,11 +312,14 @@ namespace Memory { | |||
| } | |||
| proc create_empty_environment() -> Environment* { | |||
| return create_child_environment(nullptr); | |||
| Environment* ret; | |||
| try ret = create_child_environment(nullptr); | |||
| return ret; | |||
| } | |||
| proc create_built_ins_environment() -> Environment* { | |||
| Environment* ret = create_child_environment(nullptr); | |||
| Environment* ret; | |||
| try ret = create_child_environment(nullptr); | |||
| load_built_ins_into_environment(ret); | |||
| return ret; | |||
| } | |||
| @@ -197,7 +197,7 @@ proc test_eval_operands() -> testresult { | |||
| char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; | |||
| Lisp_Object* operands = Parser::parse_single_expression(operands_string); | |||
| int operands_length; | |||
| operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length); | |||
| try operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length); | |||
| assert_no_error(); | |||
| assert_equal_int(list_length(operands), 4); | |||
| @@ -341,7 +341,8 @@ proc test_parse_expression() -> testresult { | |||
| proc test_built_in_add() -> testresult { | |||
| char exp_string[] = "(+ 10 4)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -354,7 +355,8 @@ proc test_built_in_add() -> testresult { | |||
| proc test_built_in_substract() -> testresult { | |||
| char exp_string[] = "(- 10 4)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -368,7 +370,8 @@ proc test_built_in_substract() -> testresult { | |||
| proc test_built_in_multiply() -> testresult { | |||
| char exp_string[] = "(* 10 4)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -382,7 +385,8 @@ proc test_built_in_multiply() -> testresult { | |||
| proc test_built_in_divide() -> testresult { | |||
| char exp_string[] = "(/ 20 4)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -396,7 +400,8 @@ proc test_built_in_divide() -> testresult { | |||
| proc test_built_in_if() -> testresult { | |||
| char exp_string1[] = "(if 1 4 5)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -405,7 +410,7 @@ proc test_built_in_if() -> testresult { | |||
| char exp_string2[] = "(if () 4 5)"; | |||
| expression = Parser::parse_single_expression(exp_string2); | |||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -418,7 +423,8 @@ proc test_built_in_if() -> testresult { | |||
| proc test_built_in_and() -> testresult { | |||
| char exp_string1[] = "(and 1 \"asd\" 4)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -427,7 +433,7 @@ proc test_built_in_and() -> testresult { | |||
| // a false case | |||
| char exp_string2[] = "(and () \"asd\" 4)"; | |||
| expression = Parser::parse_single_expression(exp_string2); | |||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -439,7 +445,8 @@ proc test_built_in_and() -> testresult { | |||
| proc test_built_in_or() -> testresult { | |||
| char exp_string1[] = "(or \"asd\" nil)"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -448,7 +455,7 @@ proc test_built_in_or() -> testresult { | |||
| // a false case | |||
| char exp_string2[] = "(or () ())"; | |||
| expression = Parser::parse_single_expression(exp_string2); | |||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -461,7 +468,8 @@ proc test_built_in_or() -> testresult { | |||
| proc test_built_in_not() -> testresult { | |||
| char exp_string1[] = "(not ())"; | |||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| Lisp_Object* result; | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| // a true case | |||
| assert_no_error(); | |||
| @@ -471,7 +479,7 @@ proc test_built_in_not() -> testresult { | |||
| // a false case | |||
| char exp_string2[] = "(not \"asd xD\")"; | |||
| expression = Parser::parse_single_expression(exp_string2); | |||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| try result = eval_expr(expression, Memory::create_built_ins_environment()); | |||
| assert_no_error(); | |||
| assert_not_null(result); | |||
| @@ -481,7 +489,8 @@ proc test_built_in_not() -> testresult { | |||
| } | |||
| proc test_built_in_type() -> testresult { | |||
| Environment* env = Memory::create_built_ins_environment(); | |||
| Environment* env; | |||
| try env = Memory::create_built_ins_environment(); | |||
| // normal type testing | |||
| char exp_string1[] = "(prog (define a 10)(type a))"; | |||
| @@ -528,7 +537,8 @@ proc test_built_in_type() -> testresult { | |||
| } | |||
| proc test_singular_t_and_nil() -> testresult { | |||
| Environment* env = Memory::create_built_ins_environment(); | |||
| Environment* env; | |||
| try env = Memory::create_built_ins_environment(); | |||
| // nil testing | |||
| char exp_string1[] = "()"; | |||
| @@ -562,12 +572,15 @@ proc test_singular_t_and_nil() -> testresult { | |||
| } | |||
| proc test_file(const char* file) -> testresult { | |||
| Environment* root_env; | |||
| Environment* user_env; | |||
| Memory::reset(); | |||
| assert_no_error(); | |||
| Environment* root_env = Memory::create_built_ins_environment(); | |||
| root_env = Memory::create_built_ins_environment(); | |||
| assert_no_error(); | |||
| Environment* user_env = Memory::create_child_environment(root_env); | |||
| user_env = Memory::create_child_environment(root_env); | |||
| assert_no_error(); | |||
| Parser::environment_for_macros = user_env; | |||
| @@ -582,7 +595,7 @@ proc test_file(const char* file) -> testresult { | |||
| } | |||
| proc run_all_tests() -> bool { | |||
| Memory::init(4096 * 2000, 4096 * 16); | |||
| Memory::init(4096 * 2000, 1024, 4096 * 16); | |||
| Parser::environment_for_macros = Globals::root_environment; | |||
| bool result = true; | |||