| @@ -1,12 +1,13 @@ | |||||
| TIMEFORMAT=%3lR | |||||
| SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" | SCRIPTPATH="$( cd "$(dirname "$0")" ; pwd -P )" | ||||
| pushd $SCRIPTPATH/src > /dev/null | |||||
| pushd $SCRIPTPATH > /dev/null | |||||
| clang++ main.cpp -g -o ../bin/slime --std=c++17 || exit 1 | |||||
| time clang++ src/main.cpp -g -o ./bin/slime --std=c++17 || exit 1 | |||||
| echo "" | echo "" | ||||
| echo "--- Output Start ---" | |||||
| pushd ../bin > /dev/null | |||||
| ./slime --run-tests | |||||
| pushd ./bin > /dev/null | |||||
| time ./slime --run-tests | |||||
| popd > /dev/null | popd > /dev/null | ||||
| echo "--- Output End ---" | |||||
| popd > /dev/null | popd > /dev/null | ||||
| unset TIMEFORMAT | |||||
| @@ -43,7 +43,7 @@ proc lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) -> bool { | |||||
| proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { | proc built_in_load(String* file_name, Environment* env) -> Lisp_Object* { | ||||
| char* file_content = read_entire_file(Memory::get_c_str(file_name)); | 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::nil; | |||||
| Lisp_Object_Array_List* program; | Lisp_Object_Array_List* program; | ||||
| try { | try { | ||||
| program = Parser::parse_program(file_name, file_content); | program = Parser::parse_program(file_name, file_content); | ||||
| @@ -72,7 +72,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| proc defun = [&](const char* name, auto fun) { | proc defun = [&](const char* name, auto fun) { | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(name), | |||||
| Memory::get_or_create_lisp_object_symbol(name), | |||||
| Memory::create_lisp_object_cfunction(fun), | Memory::create_lisp_object_cfunction(fun), | ||||
| env); | env); | ||||
| }; | }; | ||||
| @@ -84,17 +84,17 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| if (arguments->type == Lisp_Object_Type::Nil) | if (arguments->type == Lisp_Object_Type::Nil) | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| Lisp_Object* first = arguments->value.pair->first; | Lisp_Object* first = arguments->value.pair->first; | ||||
| while (arguments->type == Lisp_Object_Type::Pair) { | while (arguments->type == Lisp_Object_Type::Pair) { | ||||
| if (!lisp_object_equal(arguments->value.pair->first, first)) | if (!lisp_object_equal(arguments->value.pair->first, first)) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun(">", cLambda { | defun(">", cLambda { | ||||
| int arguments_length; | int arguments_length; | ||||
| @@ -110,13 +110,13 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value >= last_number) | if (arguments->value.pair->first->value.number->value >= last_number) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| last_number = arguments->value.pair->first->value.number->value; | last_number = arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun(">=", cLambda { | defun(">=", cLambda { | ||||
| int arguments_length; | int arguments_length; | ||||
| @@ -132,13 +132,13 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value > last_number) | if (arguments->value.pair->first->value.number->value > last_number) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| last_number = arguments->value.pair->first->value.number->value; | last_number = arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("<", cLambda { | defun("<", cLambda { | ||||
| int arguments_length; | int arguments_length; | ||||
| @@ -154,13 +154,13 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value <= last_number) | if (arguments->value.pair->first->value.number->value <= last_number) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| last_number = arguments->value.pair->first->value.number->value; | last_number = arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("<=", cLambda { | defun("<=", cLambda { | ||||
| int arguments_length; | int arguments_length; | ||||
| @@ -176,13 +176,13 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value < last_number) | if (arguments->value.pair->first->value.number->value < last_number) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| last_number = arguments->value.pair->first->value.number->value; | last_number = arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("+", cLambda { | defun("+", cLambda { | ||||
| int arguments_length; | int arguments_length; | ||||
| @@ -407,7 +407,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| try { | try { | ||||
| result = eval_expr(else_part->value.pair->first, env); | result = eval_expr(else_part->value.pair->first, env); | ||||
| } | } | ||||
| else return Memory::create_lisp_object_nil(); | |||||
| else return Memory::nil; | |||||
| return result; | return result; | ||||
| }); | }); | ||||
| defun("quote", cLambda { | defun("quote", cLambda { | ||||
| @@ -474,7 +474,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| newPairHead = newPairHead->value.pair->rest; | newPairHead = newPairHead->value.pair->rest; | ||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| } | } | ||||
| newPairHead->value.pair->rest = Memory::create_lisp_object_nil(); | |||||
| newPairHead->value.pair->rest = Memory::nil; | |||||
| return newPair; | return newPair; | ||||
| }; | }; | ||||
| @@ -496,10 +496,10 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (!result) return Memory::create_lisp_object_nil(); | |||||
| if (!result) return Memory::nil; | |||||
| } | } | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("or", cLambda { | defun("or", cLambda { | ||||
| bool result = false; | bool result = false; | ||||
| @@ -512,10 +512,10 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (result) return Memory::create_lisp_object_t(); | |||||
| if (result) return Memory::t; | |||||
| } | } | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| }); | }); | ||||
| defun("not", cLambda { | defun("not", cLambda { | ||||
| try { | try { | ||||
| @@ -530,8 +530,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| truthy = is_truthy(arguments->value.pair->first, env); | truthy = is_truthy(arguments->value.pair->first, env); | ||||
| } | } | ||||
| if (truthy) | if (truthy) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::nil; | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("while", cLambda { | defun("while", cLambda { | ||||
| try { | try { | ||||
| @@ -544,7 +544,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| Lisp_Object* condition_part = arguments->value.pair->first; | Lisp_Object* condition_part = arguments->value.pair->first; | ||||
| Lisp_Object* condition; | Lisp_Object* condition; | ||||
| Lisp_Object* then_part = arguments->value.pair->rest; | Lisp_Object* then_part = arguments->value.pair->rest; | ||||
| Lisp_Object* result = Memory::create_lisp_object_nil(); | |||||
| Lisp_Object* result = Memory::nil; | |||||
| while (true) { | while (true) { | ||||
| try { | try { | ||||
| @@ -659,7 +659,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| // we are now in the function body, just wrap it in an | // we are now in the function body, just wrap it in an | ||||
| // implicit prog | // implicit prog | ||||
| function->body = Memory::create_lisp_object_pair( | function->body = Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| Memory::get_or_create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* ret = Memory::create_lisp_object(); | Lisp_Object* ret = Memory::create_lisp_object(); | ||||
| @@ -709,7 +709,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| // we are now in the function body, just wrap it in an | // we are now in the function body, just wrap it in an | ||||
| // implicit prog | // implicit prog | ||||
| function->body = Memory::create_lisp_object_pair( | function->body = Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| Memory::get_or_create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* ret = Memory::create_lisp_object(); | Lisp_Object* ret = Memory::create_lisp_object(); | ||||
| @@ -774,7 +774,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| report_error(Error_Type::Wrong_Number_Of_Arguments); | report_error(Error_Type::Wrong_Number_Of_Arguments); | ||||
| } | } | ||||
| if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil) | if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair) | if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair) | ||||
| report_error(Error_Type::Type_Missmatch); | report_error(Error_Type::Type_Missmatch); | ||||
| @@ -788,7 +788,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| report_error(Error_Type::Wrong_Number_Of_Arguments); | report_error(Error_Type::Wrong_Number_Of_Arguments); | ||||
| } | } | ||||
| if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil) | if (evaluated_arguments->value.pair->first->type == Lisp_Object_Type::Nil) | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair) | if (evaluated_arguments->value.pair->first->type != Lisp_Object_Type::Pair) | ||||
| report_error(Error_Type::Type_Missmatch); | report_error(Error_Type::Type_Missmatch); | ||||
| @@ -821,7 +821,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| report_error(Error_Type::Wrong_Number_Of_Arguments); | report_error(Error_Type::Wrong_Number_Of_Arguments); | ||||
| } | } | ||||
| evaluated_arguments->value.pair->first->userType = nullptr; | evaluated_arguments->value.pair->first->userType = nullptr; | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| }); | }); | ||||
| defun("type", cLambda { | defun("type", cLambda { | ||||
| try { | try { | ||||
| @@ -837,26 +837,26 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| Lisp_Object_Type type = evaluated_arguments->value.pair->first->type; | Lisp_Object_Type type = evaluated_arguments->value.pair->first->type; | ||||
| switch (type) { | switch (type) { | ||||
| case Lisp_Object_Type::CFunction: return Memory::create_lisp_object_keyword("cfunction"); | |||||
| case Lisp_Object_Type::CFunction: return Memory::get_or_create_lisp_object_keyword("cfunction"); | |||||
| case Lisp_Object_Type::Function: { | case Lisp_Object_Type::Function: { | ||||
| Function* fun = evaluated_arguments->value.pair->first->value.function; | Function* fun = evaluated_arguments->value.pair->first->value.function; | ||||
| if (fun->type == Function_Type::Lambda) | if (fun->type == Function_Type::Lambda) | ||||
| return Memory::create_lisp_object_keyword("lambda"); | |||||
| return Memory::get_or_create_lisp_object_keyword("lambda"); | |||||
| else if (fun->type == Function_Type::Special_Lambda) | else if (fun->type == Function_Type::Special_Lambda) | ||||
| return Memory::create_lisp_object_keyword("special-lambda"); | |||||
| return Memory::get_or_create_lisp_object_keyword("special-lambda"); | |||||
| else if (fun->type == Function_Type::Macro) | else if (fun->type == Function_Type::Macro) | ||||
| return Memory::create_lisp_object_keyword("macro"); | |||||
| else return Memory::create_lisp_object_keyword("unknown"); | |||||
| } | |||||
| case Lisp_Object_Type::Keyword: return Memory::create_lisp_object_keyword("keyword"); | |||||
| case Lisp_Object_Type::Nil: return Memory::create_lisp_object_keyword("nil"); | |||||
| case Lisp_Object_Type::T: return Memory::create_lisp_object_keyword("t"); | |||||
| case Lisp_Object_Type::Number: return Memory::create_lisp_object_keyword("number"); | |||||
| case Lisp_Object_Type::Pair: return Memory::create_lisp_object_keyword("pair"); | |||||
| case Lisp_Object_Type::String: return Memory::create_lisp_object_keyword("string"); | |||||
| case Lisp_Object_Type::Symbol: return Memory::create_lisp_object_keyword("symbol"); | |||||
| } | |||||
| return Memory::create_lisp_object_keyword("unknown"); | |||||
| return Memory::get_or_create_lisp_object_keyword("macro"); | |||||
| else return Memory::get_or_create_lisp_object_keyword("unknown"); | |||||
| } | |||||
| case Lisp_Object_Type::Keyword: return Memory::get_or_create_lisp_object_keyword("keyword"); | |||||
| case Lisp_Object_Type::Nil: return Memory::get_or_create_lisp_object_keyword("nil"); | |||||
| case Lisp_Object_Type::T: return Memory::get_or_create_lisp_object_keyword("t"); | |||||
| case Lisp_Object_Type::Number: return Memory::get_or_create_lisp_object_keyword("number"); | |||||
| case Lisp_Object_Type::Pair: return Memory::get_or_create_lisp_object_keyword("pair"); | |||||
| case Lisp_Object_Type::String: return Memory::get_or_create_lisp_object_keyword("string"); | |||||
| case Lisp_Object_Type::Symbol: return Memory::get_or_create_lisp_object_keyword("symbol"); | |||||
| } | |||||
| return Memory::get_or_create_lisp_object_keyword("unknown"); | |||||
| }); | }); | ||||
| defun("info", cLambda { | defun("info", cLambda { | ||||
| try { | try { | ||||
| @@ -871,8 +871,8 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| Lisp_Object* type = eval_expr( | Lisp_Object* type = eval_expr( | ||||
| Memory::create_lisp_object_pair( | Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("type"), | |||||
| Memory::create_lisp_object_pair(arguments->value.pair->first, Memory::create_lisp_object_nil())), | |||||
| Memory::get_or_create_lisp_object_symbol("type"), | |||||
| Memory::create_lisp_object_pair(arguments->value.pair->first, Memory::nil)), | |||||
| env); | env); | ||||
| if (type) { | if (type) { | ||||
| @@ -936,7 +936,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| delete_error(); | delete_error(); | ||||
| } | } | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| }); | }); | ||||
| defun("print", cLambda { | defun("print", cLambda { | ||||
| try { | try { | ||||
| @@ -947,7 +947,7 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| } | } | ||||
| print(evaluated_arguments->value.pair->first); | print(evaluated_arguments->value.pair->first); | ||||
| // printf("\n"); | // printf("\n"); | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| }); | }); | ||||
| defun("read", cLambda { | defun("read", cLambda { | ||||
| try { | try { | ||||
| @@ -991,11 +991,11 @@ proc load_built_ins_into_environment(Environment* env) -> void { | |||||
| defun("break", cLambda { | defun("break", cLambda { | ||||
| print_environment(env); | print_environment(env); | ||||
| debug_break(); | debug_break(); | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| }); | }); | ||||
| defun("memstat", cLambda { | defun("memstat", cLambda { | ||||
| Memory::print_status(); | Memory::print_status(); | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| }); | }); | ||||
| defun("try", cLambda { | defun("try", cLambda { | ||||
| try { | try { | ||||
| @@ -1089,7 +1089,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(Memory::duplicate_string(source->value.string)); | |||||
| return Memory::get_or_create_lisp_object_symbol(Memory::duplicate_string(source->value.string)); | |||||
| }); | }); | ||||
| defun("symbol->string", cLambda { | defun("symbol->string", cLambda { | ||||
| try { | try { | ||||
| @@ -39,10 +39,10 @@ proc lookup_symbol(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| } | } | ||||
| if (string_equal(Memory::get_c_str(sym->identifier), "nil")) { | if (string_equal(Memory::get_c_str(sym->identifier), "nil")) { | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| } | } | ||||
| if (string_equal(Memory::get_c_str(sym->identifier), "t")) { | if (string_equal(Memory::get_c_str(sym->identifier), "t")) { | ||||
| return Memory::create_lisp_object_t(); | |||||
| return Memory::t; | |||||
| } | } | ||||
| create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | ||||
| @@ -8,7 +8,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| // their identifiers but before we converted them to | // their identifiers but before we converted them to | ||||
| // strings from symbols... Wo maybe just use the symbols? | // strings from symbols... Wo maybe just use the symbols? | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||||
| Memory::get_or_create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||||
| arguments->value.pair->first, new_env); | arguments->value.pair->first, new_env); | ||||
| } else { | } else { | ||||
| @@ -69,7 +69,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| // if not set it and then add it to the array list | // if not set it and then add it to the array list | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier), | |||||
| Memory::get_or_create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier), | |||||
| arguments->value.pair->rest->value.pair->first, | arguments->value.pair->rest->value.pair->first, | ||||
| new_env); | new_env); | ||||
| @@ -108,7 +108,7 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| // to use it or if the user supplied his own | // to use it or if the user supplied his own | ||||
| if (!was_set) { | if (!was_set) { | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(defined_keyword), | |||||
| Memory::get_or_create_lisp_object_symbol(defined_keyword), | |||||
| Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env); | Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env); | ||||
| } | } | ||||
| } | } | ||||
| @@ -118,13 +118,13 @@ proc apply_arguments_to_function(Lisp_Object* arguments, Function* function) -> | |||||
| if (arguments->type == Lisp_Object_Type::Nil) { | if (arguments->type == Lisp_Object_Type::Nil) { | ||||
| if (function->rest_argument) { | if (function->rest_argument) { | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(function->rest_argument), | |||||
| Memory::create_lisp_object_nil(), new_env); | |||||
| Memory::get_or_create_lisp_object_symbol(function->rest_argument), | |||||
| Memory::nil, new_env); | |||||
| } | } | ||||
| } else { | } else { | ||||
| if (function->rest_argument) { | if (function->rest_argument) { | ||||
| define_symbol( | define_symbol( | ||||
| Memory::create_lisp_object_symbol(function->rest_argument), | |||||
| Memory::get_or_create_lisp_object_symbol(function->rest_argument), | |||||
| arguments, new_env); | arguments, new_env); | ||||
| } else { | } else { | ||||
| // rest was not declared but additional arguments were found | // rest was not declared but additional arguments were found | ||||
| @@ -353,12 +353,12 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| return nullptr; \ | return nullptr; \ | ||||
| } | } | ||||
| if (error) | |||||
| return nullptr; | |||||
| switch (node->type) { | switch (node->type) { | ||||
| case Lisp_Object_Type::T: | case Lisp_Object_Type::T: | ||||
| case Lisp_Object_Type::Nil: | case Lisp_Object_Type::Nil: | ||||
| case Lisp_Object_Type::Number: | |||||
| case Lisp_Object_Type::Keyword: | |||||
| case Lisp_Object_Type::String: | |||||
| return node; | return node; | ||||
| case Lisp_Object_Type::Symbol: { | case Lisp_Object_Type::Symbol: { | ||||
| Lisp_Object* symbol; | Lisp_Object* symbol; | ||||
| @@ -367,10 +367,6 @@ proc eval_expr(Lisp_Object* node, Environment* env) -> Lisp_Object* { | |||||
| } | } | ||||
| return symbol; | return symbol; | ||||
| } | } | ||||
| case Lisp_Object_Type::Number: | |||||
| case Lisp_Object_Type::Keyword: | |||||
| case Lisp_Object_Type::String: | |||||
| return node; | |||||
| case Lisp_Object_Type::Pair: { | case Lisp_Object_Type::Pair: { | ||||
| Lisp_Object* lispOperator; | Lisp_Object* lispOperator; | ||||
| if (node->value.pair->first->type != Lisp_Object_Type::CFunction && | if (node->value.pair->first->type != Lisp_Object_Type::CFunction && | ||||
| @@ -448,7 +444,7 @@ proc interprete_file (char* file_name) -> Lisp_Object* { | |||||
| Memory::create_string(file_name), file_content); | Memory::create_string(file_name), file_content); | ||||
| } | } | ||||
| Lisp_Object* result = Memory::create_lisp_object_nil(); | |||||
| Lisp_Object* result = Memory::nil; | |||||
| for (int i = 0; i < program->next_index; ++i) { | for (int i = 0; i < program->next_index; ++i) { | ||||
| try { | try { | ||||
| result = eval_expr(program->data[i], env); | result = eval_expr(program->data[i], env); | ||||
| @@ -19,15 +19,12 @@ namespace Memory { | |||||
| String* string_memory; | String* string_memory; | ||||
| String* next_free_spot_in_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; | |||||
| } | |||||
| // ------------------ | |||||
| // immutables | |||||
| // ------------------ | |||||
| Lisp_Object* nil = nullptr; | |||||
| Lisp_Object* t = nullptr; | |||||
| proc print_status() { | proc print_status() { | ||||
| printf("Memory Status:\n" | printf("Memory Status:\n" | ||||
| @@ -99,20 +96,40 @@ namespace Memory { | |||||
| return object; | return object; | ||||
| } | } | ||||
| proc create_lisp_object_nil() -> Lisp_Object* { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Nil; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| } | |||||
| proc init() { | |||||
| free_spots_in_object_memory = create_Int_array_list(); | |||||
| free_spots_in_string_memory = create_Void_Ptr_array_list(); | |||||
| proc create_lisp_object_t() -> Lisp_Object* { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::T; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| 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; | |||||
| // init nil | |||||
| nil = create_lisp_object(); | |||||
| nil->type = Lisp_Object_Type::Nil; | |||||
| nil->value.pair = nullptr; | |||||
| // init t | |||||
| t = create_lisp_object(); | |||||
| t->type = Lisp_Object_Type::T; | |||||
| t->value.pair = nullptr; | |||||
| } | } | ||||
| // proc get_lisp_object_nil() -> Lisp_Object* { | |||||
| // Lisp_Object* node = create_lisp_object(); | |||||
| // node->type = Lisp_Object_Type::Nil; | |||||
| // node->value.pair = nullptr; | |||||
| // return node; | |||||
| // } | |||||
| // proc get_lisp_object_t() -> Lisp_Object* { | |||||
| // Lisp_Object* node = create_lisp_object(); | |||||
| // node->type = Lisp_Object_Type::T; | |||||
| // node->value.pair = nullptr; | |||||
| // return node; | |||||
| // } | |||||
| proc create_lisp_object_number(double number) -> Lisp_Object* { | proc create_lisp_object_number(double number) -> Lisp_Object* { | ||||
| Lisp_Object* node = create_lisp_object(); | Lisp_Object* node = create_lisp_object(); | ||||
| node->type = Lisp_Object_Type::Number; | node->type = Lisp_Object_Type::Number; | ||||
| @@ -128,7 +145,9 @@ namespace Memory { | |||||
| return node; | return node; | ||||
| } | } | ||||
| proc create_lisp_object_symbol(String* identifier) -> Lisp_Object* { | |||||
| proc get_or_create_lisp_object_symbol(String* identifier) -> Lisp_Object* { | |||||
| // TODO(Felix): if we already have it stored somewhere then | |||||
| // reuse it and dont create new one | |||||
| 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); | ||||
| @@ -136,12 +155,14 @@ namespace Memory { | |||||
| return node; | return node; | ||||
| } | } | ||||
| proc create_lisp_object_symbol(const char* identifier) -> Lisp_Object* { | |||||
| return create_lisp_object_symbol( | |||||
| proc get_or_create_lisp_object_symbol(const char* identifier) -> Lisp_Object* { | |||||
| return get_or_create_lisp_object_symbol( | |||||
| Memory::create_string(identifier)); | Memory::create_string(identifier)); | ||||
| } | } | ||||
| proc create_lisp_object_keyword(String* keyword) -> Lisp_Object* { | |||||
| proc get_or_create_lisp_object_keyword(String* keyword) -> Lisp_Object* { | |||||
| // TODO(Felix): if we already have it stored somewhere then | |||||
| // reuse it and dont create new one | |||||
| 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); | ||||
| @@ -149,8 +170,8 @@ namespace Memory { | |||||
| return node; | return node; | ||||
| } | } | ||||
| proc create_lisp_object_keyword(const char* keyword) -> Lisp_Object* { | |||||
| return create_lisp_object_keyword( | |||||
| proc get_or_create_lisp_object_keyword(const char* keyword) -> Lisp_Object* { | |||||
| return get_or_create_lisp_object_keyword( | |||||
| Memory::create_string(keyword)); | Memory::create_string(keyword)); | ||||
| } | } | ||||
| @@ -119,7 +119,7 @@ namespace Parser { | |||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| String* 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::get_or_create_lisp_object_keyword(str_keyword); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| @@ -128,7 +128,7 @@ namespace Parser { | |||||
| proc parse_symbol(char* text, int* index_in_text) -> Lisp_Object* { | proc parse_symbol(char* text, int* index_in_text) -> Lisp_Object* { | ||||
| // we are now at the first char of the symbol | // we are now at the first char of the symbol | ||||
| String* 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::get_or_create_lisp_object_symbol(str_symbol); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -243,16 +243,16 @@ namespace Parser { | |||||
| if (quoteType == '\'') | if (quoteType == '\'') | ||||
| return Memory::create_lisp_object_pair( | return Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("quote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| Memory::get_or_create_lisp_object_symbol("quote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::nil)); | |||||
| else if (quoteType == '`') | else if (quoteType == '`') | ||||
| return Memory::create_lisp_object_pair( | return Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("quasiquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| Memory::get_or_create_lisp_object_symbol("quasiquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::nil)); | |||||
| // it has to be an unquote | // it has to be an unquote | ||||
| return Memory::create_lisp_object_pair( | return Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("unquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| Memory::get_or_create_lisp_object_symbol("unquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::nil)); | |||||
| } | } | ||||
| @@ -267,7 +267,7 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| } | } | ||||
| // okay there is something | // okay there is something | ||||
| @@ -299,7 +299,7 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| head->value.pair->rest = Memory::create_lisp_object_nil(); | |||||
| head->value.pair->rest = Memory::nil; | |||||
| ++parser_col; | ++parser_col; | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| break; | break; | ||||
| @@ -384,7 +384,7 @@ namespace Parser { | |||||
| // we are now in the function body, just wrap it in an | // we are now in the function body, just wrap it in an | ||||
| // implicit prog | // implicit prog | ||||
| function->body = Memory::create_lisp_object_pair( | function->body = Memory::create_lisp_object_pair( | ||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| Memory::get_or_create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* macro = Memory::create_lisp_object(); | Lisp_Object* macro = Memory::create_lisp_object(); | ||||
| @@ -393,7 +393,7 @@ namespace Parser { | |||||
| define_symbol(symbol_for_macro, macro, environment_for_macros); | define_symbol(symbol_for_macro, macro, environment_for_macros); | ||||
| // print_environment(environment_for_macros); | // print_environment(environment_for_macros); | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| } else if (string_equal("delete-syntax", expression->value.pair->first->value.symbol->identifier)) { | } else if (string_equal("delete-syntax", expression->value.pair->first->value.symbol->identifier)) { | ||||
| /* --- deleting an existing macro --- */ | /* --- deleting an existing macro --- */ | ||||
| @@ -449,7 +449,7 @@ namespace Parser { | |||||
| Lisp_Object* result; | Lisp_Object* result; | ||||
| eat_until_code(text, &index_in_text); | eat_until_code(text, &index_in_text); | ||||
| if (text[(index_in_text)] == '\0') | if (text[(index_in_text)] == '\0') | ||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::nil; | |||||
| if (text[index_in_text] == '(' || | if (text[index_in_text] == '(' || | ||||
| text[index_in_text] == '\'' || | text[index_in_text] == '\'' || | ||||
| text[index_in_text] == '`' || | text[index_in_text] == '`' || | ||||
| @@ -425,6 +425,41 @@ proc test_built_in_type() -> testresult { | |||||
| return pass; | return pass; | ||||
| } | } | ||||
| proc test_singular_t_and_nil() -> testresult { | |||||
| Environment* env = Memory::create_built_ins_environment(); | |||||
| // nil testing | |||||
| char exp_string1[] = "()"; | |||||
| char exp_string2[] = "nil"; | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||||
| Lisp_Object* result = eval_expr(expression, env); | |||||
| assert_no_error(); | |||||
| assert_not_null(result); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| assert_equal_int(expression, result); | |||||
| Lisp_Object* expression2 = Parser::parse_single_expression(exp_string2); | |||||
| Lisp_Object* result2 = eval_expr(expression2, env); | |||||
| assert_no_error(); | |||||
| assert_not_null(result); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| assert_equal_int(result, result2); | |||||
| assert_equal_int(expression, Memory::nil); | |||||
| // t testing | |||||
| char exp_string3[] = "t"; | |||||
| Lisp_Object* expression3 = Parser::parse_single_expression(exp_string3); | |||||
| Lisp_Object* result3 = eval_expr(expression3, env); | |||||
| assert_no_error(); | |||||
| assert_not_null(result3); | |||||
| assert_equal_int(result3, Memory::t); | |||||
| return pass; | |||||
| } | |||||
| proc run_all_tests() -> void { | proc run_all_tests() -> void { | ||||
| log_level = Log_Level::None; | log_level = Log_Level::None; | ||||
| Memory::init(); | Memory::init(); | ||||
| @@ -449,6 +484,8 @@ proc run_all_tests() -> void { | |||||
| invoke_test(test_built_in_type); | invoke_test(test_built_in_type); | ||||
| printf("\n-- Memory management --\n"); | printf("\n-- Memory management --\n"); | ||||
| invoke_test(test_singular_t_and_nil); | |||||
| printf("\n-- Lexical scope --\n"); | printf("\n-- Lexical scope --\n"); | ||||
| printf("\n-- Macros --\n"); | printf("\n-- Macros --\n"); | ||||