| @@ -1,6 +0,0 @@ | |||||
| void assert_type (Lisp_Object* node, Lisp_Object_Type type) { | |||||
| if (!node) | |||||
| create_error(Error_Type::Unknown_Error, nullptr); | |||||
| if (node->type == type) return; | |||||
| create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation); | |||||
| } | |||||
| @@ -1,9 +1,3 @@ | |||||
| Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length); | |||||
| int list_length(Lisp_Object* node); | |||||
| Lisp_Object* eval_expr(Lisp_Object* node, Environment* env); | |||||
| bool is_truthy (Lisp_Object* expression, Environment* env); | |||||
| void parse_argument_list(Lisp_Object* arguments, Function* function); | |||||
| bool lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) { | bool lisp_object_equal(Lisp_Object* n1, Lisp_Object* n2) { | ||||
| if (n1 == n2) | if (n1 == n2) | ||||
| return true; | return true; | ||||
| @@ -55,17 +49,17 @@ Lisp_Object* built_in_equals(Lisp_Object* arguments, Environment* env) { | |||||
| } | } | ||||
| if (arguments->type == Lisp_Object_Type::Nil) | if (arguments->type == Lisp_Object_Type::Nil) | ||||
| return create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_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 create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -82,13 +76,13 @@ Lisp_Object* built_in_greater(Lisp_Object* arguments, Environment* env) { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value >= last_number) | if (arguments->value.pair->first->value.number->value >= last_number) | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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 create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -105,13 +99,13 @@ Lisp_Object* built_in_greater_equal(Lisp_Object* arguments, Environment* env) { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value > last_number) | if (arguments->value.pair->first->value.number->value > last_number) | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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 create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -128,13 +122,13 @@ Lisp_Object* built_in_less(Lisp_Object* arguments, Environment* env) { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value <= last_number) | if (arguments->value.pair->first->value.number->value <= last_number) | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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 create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -151,13 +145,13 @@ Lisp_Object* built_in_less_equal(Lisp_Object* arguments, Environment* env) { | |||||
| } | } | ||||
| if (arguments->value.pair->first->value.number->value < last_number) | if (arguments->value.pair->first->value.number->value < last_number) | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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 create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -175,7 +169,7 @@ Lisp_Object* built_in_add(Lisp_Object* arguments, Environment* env) { | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return create_lisp_object_number(sum); | |||||
| return Memory::create_lisp_object_number(sum); | |||||
| } | } | ||||
| Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -198,7 +192,7 @@ Lisp_Object* built_in_substract(Lisp_Object* arguments, Environment* env) { | |||||
| difference -= arguments->value.pair->first->value.number->value; | difference -= arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return create_lisp_object_number(difference); | |||||
| return Memory::create_lisp_object_number(difference); | |||||
| } | } | ||||
| Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -221,7 +215,7 @@ Lisp_Object* built_in_multiply(Lisp_Object* arguments, Environment* env) { | |||||
| product *= arguments->value.pair->first->value.number->value; | product *= arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return create_lisp_object_number(product); | |||||
| return Memory::create_lisp_object_number(product); | |||||
| } | } | ||||
| Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -244,7 +238,7 @@ Lisp_Object* built_in_divide(Lisp_Object* arguments, Environment* env) { | |||||
| quotient /= arguments->value.pair->first->value.number->value; | quotient /= arguments->value.pair->first->value.number->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } | } | ||||
| return create_lisp_object_number(quotient); | |||||
| return Memory::create_lisp_object_number(quotient); | |||||
| } | } | ||||
| Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) { | Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) { | ||||
| @@ -272,14 +266,14 @@ Lisp_Object* built_in_exponentiate(Lisp_Object* arguments, Environment* env) { | |||||
| double exponent = arguments->value.pair->first->value.number->value; | double exponent = arguments->value.pair->first->value.number->value; | ||||
| return create_lisp_object_number(pow(base, exponent)); | |||||
| return Memory::create_lisp_object_number(pow(base, exponent)); | |||||
| } | } | ||||
| Lisp_Object* built_in_load(char* file_name, Environment* env) { | Lisp_Object* built_in_load(char* file_name, Environment* env) { | ||||
| char* file_content = read_entire_file(file_name); | char* file_content = read_entire_file(file_name); | ||||
| if (file_content) { | if (file_content) { | ||||
| Lisp_Object* result = create_lisp_object_nil(); | |||||
| Lisp_Object* result = Memory::create_lisp_object_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); | ||||
| @@ -308,8 +302,8 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| auto defun = [&](char* name, std::function<Lisp_Object*(Lisp_Object*, Environment*)> fun) { | auto defun = [&](char* name, std::function<Lisp_Object*(Lisp_Object*, Environment*)> fun) { | ||||
| define_symbol( | define_symbol( | ||||
| create_lisp_object_symbol(name), | |||||
| create_lisp_object_cfunction(fun), | |||||
| Memory::create_lisp_object_symbol(name), | |||||
| Memory::create_lisp_object_cfunction(fun), | |||||
| env); | env); | ||||
| }; | }; | ||||
| @@ -436,7 +430,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| try { | try { | ||||
| result = eval_expr(else_part->value.pair->first, env); | result = eval_expr(else_part->value.pair->first, env); | ||||
| } | } | ||||
| else return create_lisp_object_nil(); | |||||
| else return Memory::create_lisp_object_nil(); | |||||
| return result; | return result; | ||||
| }); | }); | ||||
| defun("quote", cLambda { | defun("quote", cLambda { | ||||
| @@ -466,7 +460,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| unquoteSomeExpressions = [&unquoteSomeExpressions, &env] (Lisp_Object* expr) -> Lisp_Object* { | unquoteSomeExpressions = [&unquoteSomeExpressions, &env] (Lisp_Object* expr) -> Lisp_Object* { | ||||
| // if it is an atom, return it | // if it is an atom, return it | ||||
| if (expr->type != Lisp_Object_Type::Pair) | if (expr->type != Lisp_Object_Type::Pair) | ||||
| return copy_lisp_object(expr); | |||||
| return Memory::copy_lisp_object(expr); | |||||
| // it is a pair! | // it is a pair! | ||||
| Lisp_Object* originalPair = expr->value.pair->first; | Lisp_Object* originalPair = expr->value.pair->first; | ||||
| @@ -486,7 +480,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| // funciton, we can't jsut modify it because otherwise | // funciton, we can't jsut modify it because otherwise | ||||
| // we modify the body of the function and would bake | // we modify the body of the function and would bake | ||||
| // in the result... | // in the result... | ||||
| Lisp_Object* newPair = create_lisp_object_pair(nullptr, nullptr); | |||||
| Lisp_Object* newPair = Memory::create_lisp_object_pair(nullptr, nullptr); | |||||
| Lisp_Object* newPairHead = newPair; | Lisp_Object* newPairHead = newPair; | ||||
| Lisp_Object* head = expr; | Lisp_Object* head = expr; | ||||
| while (head->type == Lisp_Object_Type::Pair) { | while (head->type == Lisp_Object_Type::Pair) { | ||||
| @@ -495,12 +489,12 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| if (head->value.pair->rest->type != Lisp_Object_Type::Pair) | if (head->value.pair->rest->type != Lisp_Object_Type::Pair) | ||||
| break; | break; | ||||
| newPairHead->value.pair->rest = create_lisp_object_pair(nullptr, nullptr); | |||||
| newPairHead->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr); | |||||
| newPairHead = newPairHead->value.pair->rest; | newPairHead = newPairHead->value.pair->rest; | ||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| } | } | ||||
| newPairHead->value.pair->rest = create_lisp_object_nil(); | |||||
| newPairHead->value.pair->rest = Memory::create_lisp_object_nil(); | |||||
| return newPair; | return newPair; | ||||
| }; | }; | ||||
| @@ -522,10 +516,10 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| } | } | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (!result) return create_lisp_object_nil(); | |||||
| if (!result) return Memory::create_lisp_object_nil(); | |||||
| } | } | ||||
| return create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| }); | }); | ||||
| defun("or", cLambda { | defun("or", cLambda { | ||||
| bool result = false; | bool result = false; | ||||
| @@ -538,10 +532,10 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| } | } | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (result) return create_lisp_object_t(); | |||||
| if (result) return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| }); | }); | ||||
| defun("not", cLambda { | defun("not", cLambda { | ||||
| try { | try { | ||||
| @@ -556,8 +550,8 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| truthy = is_truthy(arguments->value.pair->first, env); | truthy = is_truthy(arguments->value.pair->first, env); | ||||
| } | } | ||||
| if (truthy) | if (truthy) | ||||
| return create_lisp_object_nil(); | |||||
| return create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| }); | }); | ||||
| defun("while", cLambda { | defun("while", cLambda { | ||||
| try { | try { | ||||
| @@ -570,7 +564,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| 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 = create_lisp_object_nil(); | |||||
| Lisp_Object* result = Memory::create_lisp_object_nil(); | |||||
| while (true) { | while (true) { | ||||
| try { | try { | ||||
| @@ -595,7 +589,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| if (arguments_length < 1) | if (arguments_length < 1) | ||||
| report_error(Error_Type::Wrong_Number_Of_Arguments); | report_error(Error_Type::Wrong_Number_Of_Arguments); | ||||
| Environment* let_env = create_child_environment(env); | |||||
| Environment* let_env = Memory::create_child_environment(env); | |||||
| Lisp_Object* bindings = arguments->value.pair->first; | Lisp_Object* bindings = arguments->value.pair->first; | ||||
| while (true) { | while (true) { | ||||
| if (bindings->type == Lisp_Object_Type::Nil) { | if (bindings->type == Lisp_Object_Type::Nil) { | ||||
| @@ -684,11 +678,11 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| // 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 = create_lisp_object_pair( | |||||
| create_lisp_object_symbol("prog"), | |||||
| function->body = Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* ret = new(Lisp_Object); | |||||
| Lisp_Object* ret = Memory::create_lisp_object(); | |||||
| ret->type = Lisp_Object_Type::Function; | ret->type = Lisp_Object_Type::Function; | ||||
| ret->value.function = function; | ret->value.function = function; | ||||
| return ret; | return ret; | ||||
| @@ -734,11 +728,11 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| // 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 = create_lisp_object_pair( | |||||
| create_lisp_object_symbol("prog"), | |||||
| function->body = Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* ret = new(Lisp_Object); | |||||
| Lisp_Object* ret = Memory::create_lisp_object(); | |||||
| ret->type = Lisp_Object_Type::Function; | ret->type = Lisp_Object_Type::Function; | ||||
| ret->value.function = function; | ret->value.function = function; | ||||
| return ret; | return ret; | ||||
| @@ -790,7 +784,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| if (arguments_length != 2) { | if (arguments_length != 2) { | ||||
| report_error(Error_Type::Wrong_Number_Of_Arguments); | report_error(Error_Type::Wrong_Number_Of_Arguments); | ||||
| } | } | ||||
| return create_lisp_object_pair(evaluated_arguments->value.pair->first, evaluated_arguments->value.pair->rest->value.pair->first); | |||||
| return Memory::create_lisp_object_pair(evaluated_arguments->value.pair->first, evaluated_arguments->value.pair->rest->value.pair->first); | |||||
| }); | }); | ||||
| defun("first", cLambda { | defun("first", cLambda { | ||||
| try { | try { | ||||
| @@ -800,7 +794,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| 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 create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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); | ||||
| @@ -814,7 +808,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| 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 create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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); | ||||
| @@ -830,26 +824,26 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| 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 create_lisp_object_keyword("cfunction"); | |||||
| case Lisp_Object_Type::CFunction: return Memory::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 create_lisp_object_keyword("lambda"); | |||||
| return Memory::create_lisp_object_keyword("lambda"); | |||||
| else if (fun->type == Function_Type::Special_Lambda) | else if (fun->type == Function_Type::Special_Lambda) | ||||
| return create_lisp_object_keyword("special-lambda"); | |||||
| return Memory::create_lisp_object_keyword("special-lambda"); | |||||
| else if (fun->type == Function_Type::Macro) | else if (fun->type == Function_Type::Macro) | ||||
| return create_lisp_object_keyword("macro"); | |||||
| else return create_lisp_object_keyword("unknown"); | |||||
| } | |||||
| case Lisp_Object_Type::Keyword: return create_lisp_object_keyword("keyword"); | |||||
| case Lisp_Object_Type::Nil: return create_lisp_object_keyword("nil"); | |||||
| case Lisp_Object_Type::T: return create_lisp_object_keyword("t"); | |||||
| case Lisp_Object_Type::Number: return create_lisp_object_keyword("number"); | |||||
| case Lisp_Object_Type::Pair: return create_lisp_object_keyword("pair"); | |||||
| case Lisp_Object_Type::String: return create_lisp_object_keyword("string"); | |||||
| case Lisp_Object_Type::Symbol: return create_lisp_object_keyword("symbol"); | |||||
| } | |||||
| return create_lisp_object_keyword("unknown"); | |||||
| 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"); | |||||
| }); | }); | ||||
| defun("info", cLambda { | defun("info", cLambda { | ||||
| try { | try { | ||||
| @@ -863,9 +857,9 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| print(arguments->value.pair->first); | print(arguments->value.pair->first); | ||||
| Lisp_Object* type = eval_expr( | Lisp_Object* type = eval_expr( | ||||
| create_lisp_object_pair( | |||||
| create_lisp_object_symbol("type"), | |||||
| create_lisp_object_pair(arguments->value.pair->first, create_lisp_object_nil())), | |||||
| 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())), | |||||
| env); | env); | ||||
| if (type) { | if (type) { | ||||
| @@ -924,7 +918,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| delete_error(); | delete_error(); | ||||
| } | } | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| }); | }); | ||||
| defun("print", cLambda { | defun("print", cLambda { | ||||
| try { | try { | ||||
| @@ -935,7 +929,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| } | } | ||||
| print(evaluated_arguments->value.pair->first); | print(evaluated_arguments->value.pair->first); | ||||
| // printf("\n"); | // printf("\n"); | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| }); | }); | ||||
| defun("read", cLambda { | defun("read", cLambda { | ||||
| try { | try { | ||||
| @@ -954,7 +948,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| print(evaluated_arguments->value.pair->first); | print(evaluated_arguments->value.pair->first); | ||||
| } | } | ||||
| char* line = read_line(); | char* line = read_line(); | ||||
| return create_lisp_object_string(line, (int)strlen(line)); | |||||
| return Memory::create_lisp_object_string(line, (int)strlen(line)); | |||||
| }); | }); | ||||
| defun("exit", cLambda { | defun("exit", cLambda { | ||||
| try { | try { | ||||
| @@ -979,7 +973,11 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| if_debug { | if_debug { | ||||
| __debugbreak(); | __debugbreak(); | ||||
| } | } | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| }); | |||||
| defun("memstat", cLambda { | |||||
| Memory::print_status(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| }); | }); | ||||
| defun("try", cLambda { | defun("try", cLambda { | ||||
| try { | try { | ||||
| @@ -1039,7 +1037,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| report_error(Error_Type::Type_Missmatch); | report_error(Error_Type::Type_Missmatch); | ||||
| } | } | ||||
| Lisp_Object* target = new(Lisp_Object); | |||||
| Lisp_Object* target = Memory::create_lisp_object(); | |||||
| Lisp_Object* source = evaluated_arguments->value.pair->first; | Lisp_Object* source = evaluated_arguments->value.pair->first; | ||||
| *target = *source; | *target = *source; | ||||
| @@ -1074,7 +1072,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| report_error(Error_Type::Type_Missmatch); | report_error(Error_Type::Type_Missmatch); | ||||
| } | } | ||||
| return create_lisp_object_symbol(_strdup(source->value.string->value)); | |||||
| return Memory::create_lisp_object_symbol(_strdup(source->value.string->value)); | |||||
| }); | }); | ||||
| defun("symbol->string", cLambda { | defun("symbol->string", cLambda { | ||||
| try { | try { | ||||
| @@ -1092,7 +1090,7 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| } | } | ||||
| // TODO(Felix): this is not really fast what we are doing here: | // TODO(Felix): this is not really fast what we are doing here: | ||||
| return create_lisp_object_string(_strdup(source->value.symbol->identifier), (int)strlen(source->value.symbol->identifier)); | |||||
| return Memory::create_lisp_object_string(_strdup(source->value.symbol->identifier), (int)strlen(source->value.symbol->identifier)); | |||||
| }); | }); | ||||
| defun("concat-strings", cLambda { | defun("concat-strings", cLambda { | ||||
| try { | try { | ||||
| @@ -1129,15 +1127,9 @@ void load_built_ins_into_environment(Environment* env) { | |||||
| resulting_string[index_in_string] = '\0'; | resulting_string[index_in_string] = '\0'; | ||||
| return create_lisp_object_string(resulting_string, resulting_string_len); | |||||
| return Memory::create_lisp_object_string(resulting_string, resulting_string_len); | |||||
| }); | }); | ||||
| #undef report_error | #undef report_error | ||||
| #undef cLambda | #undef cLambda | ||||
| } | } | ||||
| Environment* create_built_ins_environment() { | |||||
| Environment* ret = create_child_environment(nullptr); | |||||
| load_built_ins_into_environment(ret); | |||||
| return ret; | |||||
| } | |||||
| @@ -1,30 +1,3 @@ | |||||
| struct Environment { | |||||
| struct Environment* parent; | |||||
| int capacity; | |||||
| int next_index; | |||||
| // TODO(Felix): Use a hashmap here. | |||||
| char** keys; | |||||
| Lisp_Object** values; | |||||
| }; | |||||
| Environment* create_child_environment(Environment* parent) { | |||||
| Environment* env = new(Environment); | |||||
| int start_capacity = 16; | |||||
| env->parent = parent; | |||||
| env->capacity = start_capacity; | |||||
| env->next_index = 0; | |||||
| env->keys = (char**)malloc(start_capacity * sizeof(char*)); | |||||
| env->values = (Lisp_Object**)malloc(start_capacity * sizeof(Lisp_Object*)); | |||||
| return env; | |||||
| } | |||||
| Environment* create_empty_environment() { | |||||
| return create_child_environment(nullptr); | |||||
| } | |||||
| void define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) { | void define_symbol(Lisp_Object* symbol, Lisp_Object* value, Environment* env) { | ||||
| // NOTE(Felix): right now we are simply adding the symol at the | // NOTE(Felix): right now we are simply adding the symol at the | ||||
| @@ -68,10 +41,10 @@ Lisp_Object* lookup_symbol(Lisp_Object* node, Environment* env) { | |||||
| } | } | ||||
| if (string_equal(sym->identifier, "nil")) { | if (string_equal(sym->identifier, "nil")) { | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| } | } | ||||
| if (string_equal(sym->identifier, "t")) { | if (string_equal(sym->identifier, "t")) { | ||||
| return create_lisp_object_t(); | |||||
| return Memory::create_lisp_object_t(); | |||||
| } | } | ||||
| create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | ||||
| @@ -87,8 +60,8 @@ void print_indent(int indent) { | |||||
| void print_environment_indent(Environment* env, int indent) { | void print_environment_indent(Environment* env, int indent) { | ||||
| for (int i = 0; i < env->next_index; ++i) { | for (int i = 0; i < env->next_index; ++i) { | ||||
| print_indent(indent); | print_indent(indent); | ||||
| printf("%s -> ", env->keys[i]); | |||||
| print(env->values[i]); | print(env->values[i]); | ||||
| printf(" %s", env->keys[i]); | |||||
| printf("\n"); | printf("\n"); | ||||
| } | } | ||||
| if (env->parent) { | if (env->parent) { | ||||
| @@ -1,25 +1,3 @@ | |||||
| enum struct Error_Type { | |||||
| Ill_Formed_Arguments, | |||||
| Ill_Formed_Lambda_List, | |||||
| Ill_Formed_List, | |||||
| Not_A_Function, | |||||
| Not_Yet_Implemented, | |||||
| Symbol_Not_Defined, | |||||
| Syntax_Error, | |||||
| Trailing_Garbage, | |||||
| Type_Missmatch, | |||||
| Unbalanced_Parenthesis, | |||||
| Unexpected_Eof, | |||||
| Unknown_Error, | |||||
| Unknown_Keyword_Argument, | |||||
| Wrong_Number_Of_Arguments, | |||||
| }; | |||||
| struct Error { | |||||
| Error_Type type; | |||||
| Source_Code_Location* location; | |||||
| }; | |||||
| Error* error; | Error* error; | ||||
| void delete_error() { | void delete_error() { | ||||
| @@ -52,6 +30,14 @@ char* Error_Type_to_string(Error_Type type) { | |||||
| case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF"; | case Error_Type::Unexpected_Eof: return "Parsing-error: Unexpected EOF"; | ||||
| case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument"; | case Error_Type::Unknown_Keyword_Argument: return "Evaluation-error: Unknown keyword argument"; | ||||
| case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments"; | case Error_Type::Wrong_Number_Of_Arguments: return "Evaluation-error: Wrong number of arguments"; | ||||
| case Error_Type::Out_Of_Memory: return "Runtime-error: Out of memory"; | |||||
| default: return "Unknown Error"; | default: return "Unknown Error"; | ||||
| } | } | ||||
| } | } | ||||
| void assert_type(Lisp_Object* node, Lisp_Object_Type type) { | |||||
| if (!node) | |||||
| create_error(Error_Type::Unknown_Error, nullptr); | |||||
| if (node->type == type) return; | |||||
| create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation); | |||||
| } | |||||
| @@ -1,7 +1,7 @@ | |||||
| Lisp_Object* eval_expr(Lisp_Object*, Environment*); | Lisp_Object* eval_expr(Lisp_Object*, Environment*); | ||||
| Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* function) { | Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* function) { | ||||
| Environment* new_env = create_child_environment(function->parent_environment); | |||||
| Environment* new_env = Memory::create_child_environment(function->parent_environment); | |||||
| // positional arguments | // positional arguments | ||||
| for (int i = 0; i < function->positional_arguments->next_index; ++i) { | for (int i = 0; i < function->positional_arguments->next_index; ++i) { | ||||
| @@ -10,7 +10,7 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct | |||||
| // 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( | ||||
| create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||||
| Memory::create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||||
| arguments->value.pair->first, new_env); | arguments->value.pair->first, new_env); | ||||
| } else { | } else { | ||||
| @@ -71,7 +71,7 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct | |||||
| // 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( | ||||
| create_lisp_object_symbol(arguments->value.pair->first->value.keyword->identifier), | |||||
| Memory::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); | ||||
| @@ -110,8 +110,8 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct | |||||
| // 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( | ||||
| create_lisp_object_symbol(defined_keyword), | |||||
| copy_lisp_object(function->keyword_arguments->values->data[i]), new_env); | |||||
| Memory::create_lisp_object_symbol(defined_keyword), | |||||
| Memory::copy_lisp_object(function->keyword_arguments->values->data[i]), new_env); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| @@ -120,13 +120,13 @@ Lisp_Object* apply_arguments_to_function(Lisp_Object* arguments, Function* funct | |||||
| 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( | ||||
| create_lisp_object_symbol(function->rest_argument), | |||||
| create_lisp_object_nil(), new_env); | |||||
| Memory::create_lisp_object_symbol(function->rest_argument), | |||||
| Memory::create_lisp_object_nil(), new_env); | |||||
| } | } | ||||
| } else { | } else { | ||||
| if (function->rest_argument) { | if (function->rest_argument) { | ||||
| define_symbol( | define_symbol( | ||||
| create_lisp_object_symbol(function->rest_argument), | |||||
| Memory::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 | ||||
| @@ -326,7 +326,7 @@ Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_a | |||||
| return arguments; | return arguments; | ||||
| } | } | ||||
| Lisp_Object* evaluated_arguments = create_lisp_object_pair(nullptr, nullptr); | |||||
| Lisp_Object* evaluated_arguments = Memory::create_lisp_object_pair(nullptr, nullptr); | |||||
| Lisp_Object* evaluated_arguments_head = evaluated_arguments; | Lisp_Object* evaluated_arguments_head = evaluated_arguments; | ||||
| Lisp_Object* current_head = arguments; | Lisp_Object* current_head = arguments; | ||||
| while (current_head->type == Lisp_Object_Type::Pair) { | while (current_head->type == Lisp_Object_Type::Pair) { | ||||
| @@ -337,7 +337,7 @@ Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_a | |||||
| current_head = current_head->value.pair->rest; | current_head = current_head->value.pair->rest; | ||||
| if (current_head->type == Lisp_Object_Type::Pair) { | if (current_head->type == Lisp_Object_Type::Pair) { | ||||
| evaluated_arguments_head->value.pair->rest = create_lisp_object_pair(nullptr, nullptr); | |||||
| evaluated_arguments_head->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr); | |||||
| evaluated_arguments_head = evaluated_arguments_head->value.pair->rest; | evaluated_arguments_head = evaluated_arguments_head->value.pair->rest; | ||||
| } else if (current_head->type == Lisp_Object_Type::Nil) { | } else if (current_head->type == Lisp_Object_Type::Nil) { | ||||
| evaluated_arguments_head->value.pair->rest = current_head; | evaluated_arguments_head->value.pair->rest = current_head; | ||||
| @@ -360,7 +360,6 @@ Lisp_Object* eval_expr(Lisp_Object* node, Environment* env) { | |||||
| if (error) | if (error) | ||||
| return nullptr; | return nullptr; | ||||
| Lisp_Object* ret = new(Lisp_Object); | |||||
| 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: | ||||
| @@ -0,0 +1,6 @@ | |||||
| Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length); | |||||
| Lisp_Object* eval_expr(Lisp_Object*, Environment*); | |||||
| bool is_truthy (Lisp_Object* expression, Environment* env); | |||||
| int list_length(Lisp_Object*); | |||||
| void load_built_ins_into_environment(Environment*); | |||||
| void parse_argument_list(Lisp_Object*, Function*); | |||||
| @@ -60,7 +60,7 @@ constexpr bool is_debug_build = false; | |||||
| } \ | } \ | ||||
| \ | \ | ||||
| \ | \ | ||||
| name##_Array_List* create_##name##_array_list(int initial_capacity) { \ | |||||
| name##_Array_List* create_##name##_array_list(int initial_capacity = 16) { \ | |||||
| name##_Array_List* ret = new(name##_Array_List); \ | name##_Array_List* ret = new(name##_Array_List); \ | ||||
| ret->data = (type*)malloc(initial_capacity * sizeof(type)); \ | ret->data = (type*)malloc(initial_capacity * sizeof(type)); \ | ||||
| ret->next_index = 0; \ | ret->next_index = 0; \ | ||||
| @@ -68,12 +68,6 @@ constexpr bool is_debug_build = false; | |||||
| return ret; \ | return ret; \ | ||||
| } | } | ||||
| define_array_list(char*, String); | |||||
| // int string_equal(char* a, char* b) { | |||||
| // return !strcmp(a, b); | |||||
| // } | |||||
| int string_equal(char input[],char check[]) | int string_equal(char input[],char check[]) | ||||
| { | { | ||||
| int i,result=1; | int i,result=1; | ||||
| @@ -8,14 +8,6 @@ | |||||
| #define console_green "" | #define console_green "" | ||||
| #define console_cyan "" | #define console_cyan "" | ||||
| enum struct Log_Level { | |||||
| None, | |||||
| Critical, | |||||
| Warning, | |||||
| Info, | |||||
| Debug, | |||||
| }; | |||||
| Log_Level log_level = Log_Level::Debug; | Log_Level log_level = Log_Level::Debug; | ||||
| void log_message(Log_Level type, char* message) { | void log_message(Log_Level type, char* message) { | ||||
| @@ -1,19 +1,3 @@ | |||||
| struct Lisp_Object; | |||||
| define_array_list(Lisp_Object*, Lisp_Object); | |||||
| enum struct Lisp_Object_Type { | |||||
| Nil, | |||||
| T, | |||||
| Symbol, | |||||
| Keyword, | |||||
| Number, | |||||
| String, | |||||
| Pair, | |||||
| Function, | |||||
| CFunction, | |||||
| }; | |||||
| char* Lisp_Object_Type_to_string(Lisp_Object_Type type) { | char* Lisp_Object_Type_to_string(Lisp_Object_Type type) { | ||||
| switch (type) { | switch (type) { | ||||
| case(Lisp_Object_Type::Nil): return "nil"; | case(Lisp_Object_Type::Nil): return "nil"; | ||||
| @@ -29,46 +13,6 @@ char* Lisp_Object_Type_to_string(Lisp_Object_Type type) { | |||||
| return "unknown"; | return "unknown"; | ||||
| } | } | ||||
| struct Symbol { | |||||
| char* identifier; | |||||
| }; | |||||
| struct Keyword { | |||||
| char* identifier; | |||||
| }; | |||||
| struct Number { | |||||
| double value; | |||||
| }; | |||||
| struct String { | |||||
| char* value; | |||||
| int length; | |||||
| }; | |||||
| struct Pair { | |||||
| Lisp_Object* first; | |||||
| Lisp_Object* rest; | |||||
| }; | |||||
| struct Positional_Arguments { | |||||
| // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have | |||||
| // to convert them to strings and back to symbols | |||||
| char** identifiers; | |||||
| int next_index; | |||||
| int length; | |||||
| }; | |||||
| struct Keyword_Arguments { | |||||
| char** identifiers; | |||||
| // NOTE(Felix): values[i] will be nullptr if no defalut value was | |||||
| // declared for key identifiers[i] | |||||
| Lisp_Object_Array_List* values; | |||||
| int next_index; | |||||
| int length; | |||||
| }; | |||||
| Positional_Arguments* create_positional_argument_list(int initial_capacity) { | Positional_Arguments* create_positional_argument_list(int initial_capacity) { | ||||
| Positional_Arguments* ret = new(Positional_Arguments); | Positional_Arguments* ret = new(Positional_Arguments); | ||||
| ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); | ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); | ||||
| @@ -106,125 +50,3 @@ void append_to_keyword_argument_list(Keyword_Arguments* args, | |||||
| args->identifiers[args->next_index++] = identifier; | args->identifiers[args->next_index++] = identifier; | ||||
| append_to_Lisp_Object_array_list(args->values, default_value); | append_to_Lisp_Object_array_list(args->values, default_value); | ||||
| } | } | ||||
| struct Environment; | |||||
| enum struct Function_Type { | |||||
| Lambda, | |||||
| Special_Lambda, | |||||
| Macro | |||||
| }; | |||||
| struct Function { | |||||
| Function_Type type; | |||||
| char* docstring; | |||||
| Positional_Arguments* positional_arguments; | |||||
| Keyword_Arguments* keyword_arguments; | |||||
| // rest_argument will be nullptr if no rest argument is declared | |||||
| char* rest_argument; | |||||
| Lisp_Object* body; // implicit prog | |||||
| Environment* parent_environment; // we are doing closures now!! | |||||
| }; | |||||
| struct CFunction { | |||||
| std::function<Lisp_Object* (Lisp_Object*, Environment*)> function; | |||||
| }; | |||||
| struct Lisp_Object { | |||||
| Source_Code_Location* sourceCodeLocation; | |||||
| Lisp_Object_Type type; | |||||
| union { | |||||
| Symbol* symbol; | |||||
| Keyword* keyword; | |||||
| Number* number; | |||||
| String* string; | |||||
| Pair* pair; | |||||
| Function* function; | |||||
| CFunction* cfunction; | |||||
| } value; | |||||
| }; | |||||
| struct Parsed_Arguments { | |||||
| Lisp_Object_Array_List* positional_arguments; | |||||
| // TODO(Felix): Really use hashmap (keyword[sting] -> | |||||
| // value[Lisp_Object*]) here | |||||
| Lisp_Object_Array_List* keyword_keys; | |||||
| Lisp_Object_Array_List* keyword_values; | |||||
| }; | |||||
| Lisp_Object* create_lisp_object() { | |||||
| Lisp_Object* node = new(Lisp_Object); | |||||
| node->sourceCodeLocation = nullptr; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_nil() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Nil; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_t() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::T; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_number(double number) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Number; | |||||
| node->value.number = new(Number); | |||||
| node->value.number->value = number; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_string(char* str, int length) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::String; | |||||
| node->value.string = new(String); | |||||
| node->value.string->value = str; | |||||
| node->value.string->length = length; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_symbol(char* identifier) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Symbol; | |||||
| node->value.symbol = new(Symbol); | |||||
| node->value.symbol->identifier = identifier; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_keyword(char* keyword) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Keyword; | |||||
| node->value.keyword = new(Keyword); | |||||
| node->value.keyword->identifier = keyword; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_cfunction(std::function<Lisp_Object*(Lisp_Object*, Environment*)> function) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::CFunction; | |||||
| node->value.cfunction = new(CFunction); | |||||
| node->value.cfunction->function = function; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Pair; | |||||
| node->value.pair = new(Pair); | |||||
| node->value.pair->first = first; | |||||
| node->value.pair->rest = rest; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* copy_lisp_object(Lisp_Object* n) { | |||||
| Lisp_Object* target = create_lisp_object(); | |||||
| *target = *n; | |||||
| return target; | |||||
| } | |||||
| @@ -9,10 +9,12 @@ | |||||
| #include <functional> | #include <functional> | ||||
| #include "./helpers.cpp" | #include "./helpers.cpp" | ||||
| #include "./structs.cpp" | |||||
| #include "./forward_decls.cpp" | |||||
| #include "./lisp_object.cpp" | #include "./lisp_object.cpp" | ||||
| #include "./error.cpp" | #include "./error.cpp" | ||||
| #include "./io.cpp" | #include "./io.cpp" | ||||
| #include "./assert.cpp" | |||||
| #include "./memory.cpp" | |||||
| #include "./env.cpp" | #include "./env.cpp" | ||||
| #include "./parse.cpp" | #include "./parse.cpp" | ||||
| #include "./built_ins.cpp" | #include "./built_ins.cpp" | ||||
| @@ -20,16 +22,17 @@ | |||||
| #include "./testing.cpp" | #include "./testing.cpp" | ||||
| Lisp_Object* interprete_file (char* file_name) { | Lisp_Object* interprete_file (char* file_name) { | ||||
| Memory::init(); | |||||
| Environment* env = Memory::create_empty_environment(); | |||||
| Parser::init(env); | |||||
| char* file_content = read_entire_file(file_name); | char* file_content = read_entire_file(file_name); | ||||
| if (!file_content) { | if (!file_content) { | ||||
| create_error(Error_Type::Unknown_Error, nullptr); | create_error(Error_Type::Unknown_Error, nullptr); | ||||
| } | } | ||||
| Environment* env = create_empty_environment(); | |||||
| load_built_ins_into_environment(env); | load_built_ins_into_environment(env); | ||||
| Parser::init(env); | |||||
| try { | try { | ||||
| built_in_load("pre.slime", env); | built_in_load("pre.slime", env); | ||||
| } | } | ||||
| @@ -39,7 +42,7 @@ Lisp_Object* interprete_file (char* file_name) { | |||||
| program = Parser::parse_program(file_name, file_content); | program = Parser::parse_program(file_name, file_content); | ||||
| } | } | ||||
| Lisp_Object* result = create_lisp_object_nil(); | |||||
| Lisp_Object* result = Memory::create_lisp_object_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); | ||||
| @@ -50,11 +53,13 @@ Lisp_Object* interprete_file (char* file_name) { | |||||
| } | } | ||||
| int interprete_stdin () { | int interprete_stdin () { | ||||
| Memory::init(); | |||||
| Environment* env = Memory::create_built_ins_environment(); | |||||
| Parser::init(env); | |||||
| printf("Welcome to the lispy interpreter.\n"); | printf("Welcome to the lispy interpreter.\n"); | ||||
| char* line; | |||||
| Environment* env = create_built_ins_environment(); | |||||
| Parser::init(env); | |||||
| char* line; | |||||
| built_in_load("pre.slime", env); | built_in_load("pre.slime", env); | ||||
| built_in_load("test.slime", env); | built_in_load("test.slime", env); | ||||
| @@ -94,7 +99,7 @@ int main (int argc, char *argv[]) { | |||||
| return 1; | return 1; | ||||
| } | } | ||||
| } else { | } else { | ||||
| run_all_tests(); | |||||
| // run_all_tests(); | |||||
| return interprete_stdin(); | return interprete_stdin(); | ||||
| } | } | ||||
| } | } | ||||
| @@ -0,0 +1,138 @@ | |||||
| namespace Memory { | |||||
| constexpr int maxLispObjects = 4096 * 1024; // == 98304kb == 96mb | |||||
| Int_Array_List* freeSpots; | |||||
| Lisp_Object* memory; | |||||
| int nextFreeSpot = 0; | |||||
| void init() { | |||||
| memory = (Lisp_Object*)malloc(maxLispObjects * sizeof(Lisp_Object)); | |||||
| freeSpots = create_Int_array_list(); | |||||
| } | |||||
| void print_status() { | |||||
| printf("Memory Status:\n" | |||||
| " - %f%% of the memory is used\n" | |||||
| " - %d of %d total Lisp_Objects are in use\n" | |||||
| " - %d holes in used memory (fragmentation)\n", | |||||
| (1.0*nextFreeSpot - freeSpots->next_index)/maxLispObjects, | |||||
| nextFreeSpot - freeSpots->next_index, maxLispObjects, | |||||
| freeSpots->next_index); | |||||
| } | |||||
| Lisp_Object* create_lisp_object() { | |||||
| int index; | |||||
| // if we have no free spots then append at the end | |||||
| if (freeSpots->next_index == 0) { | |||||
| // if we still have space | |||||
| if (maxLispObjects == nextFreeSpot) { | |||||
| create_error(Error_Type::Out_Of_Memory, nullptr); | |||||
| return nullptr; | |||||
| } | |||||
| index = nextFreeSpot++; | |||||
| } else { | |||||
| // else fill a free spot | |||||
| index = freeSpots->data[freeSpots->next_index--]; | |||||
| } | |||||
| Lisp_Object* object = memory+index; | |||||
| object->sourceCodeLocation = nullptr; | |||||
| return object; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_nil() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Nil; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_t() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::T; | |||||
| node->value.pair = nullptr; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_number(double number) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Number; | |||||
| node->value.number = new(Number); | |||||
| node->value.number->value = number; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_string(char* str, int length) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::String; | |||||
| node->value.string = new(String); | |||||
| node->value.string->value = str; | |||||
| node->value.string->length = length; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_symbol(char* identifier) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Symbol; | |||||
| node->value.symbol = new(Symbol); | |||||
| node->value.symbol->identifier = identifier; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_keyword(char* keyword) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Keyword; | |||||
| node->value.keyword = new(Keyword); | |||||
| node->value.keyword->identifier = keyword; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_cfunction(std::function<Lisp_Object*(Lisp_Object*, Environment*)> function) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::CFunction; | |||||
| node->value.cfunction = new(CFunction); | |||||
| node->value.cfunction->function = function; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* create_lisp_object_pair(Lisp_Object* first, Lisp_Object* rest) { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Pair; | |||||
| node->value.pair = new(Pair); | |||||
| node->value.pair->first = first; | |||||
| node->value.pair->rest = rest; | |||||
| return node; | |||||
| } | |||||
| Lisp_Object* copy_lisp_object(Lisp_Object* n) { | |||||
| Lisp_Object* target = create_lisp_object(); | |||||
| *target = *n; | |||||
| return target; | |||||
| } | |||||
| // environments | |||||
| Environment* create_child_environment(Environment* parent) { | |||||
| Environment* env = new(Environment); | |||||
| int start_capacity = 16; | |||||
| env->parent = parent; | |||||
| env->capacity = start_capacity; | |||||
| env->next_index = 0; | |||||
| env->keys = (char**)malloc(start_capacity * sizeof(char*)); | |||||
| env->values = (Lisp_Object**)malloc(start_capacity * sizeof(Lisp_Object*)); | |||||
| return env; | |||||
| } | |||||
| Environment* create_empty_environment() { | |||||
| return create_child_environment(nullptr); | |||||
| } | |||||
| Environment* create_built_ins_environment() { | |||||
| Environment* ret = create_child_environment(nullptr); | |||||
| load_built_ins_into_environment(ret); | |||||
| return ret; | |||||
| } | |||||
| } | |||||
| @@ -1,11 +1,3 @@ | |||||
| // forward decls -- start | |||||
| void load_built_ins_into_environment(Environment*); | |||||
| Lisp_Object* eval_expr(Lisp_Object*, Environment*); | |||||
| void parse_argument_list(Lisp_Object*, Function*); | |||||
| int list_length(Lisp_Object*); | |||||
| // forward decls -- end | |||||
| namespace Parser { | namespace Parser { | ||||
| #define inject_scl(_ret) \ | #define inject_scl(_ret) \ | ||||
| @@ -113,7 +105,7 @@ namespace Parser { | |||||
| double number; | double number; | ||||
| char* str_number = read_atom(text, index_in_text); | char* str_number = read_atom(text, index_in_text); | ||||
| sscanf(str_number, "%lf", &number); | sscanf(str_number, "%lf", &number); | ||||
| Lisp_Object* ret = create_lisp_object_number(number); | |||||
| Lisp_Object* ret = Memory::create_lisp_object_number(number); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -123,7 +115,7 @@ namespace Parser { | |||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| char* str_keyword = read_atom(text, index_in_text); | char* str_keyword = read_atom(text, index_in_text); | ||||
| Lisp_Object* ret = create_lisp_object_keyword(str_keyword); | |||||
| Lisp_Object* ret = Memory::create_lisp_object_keyword(str_keyword); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -131,7 +123,7 @@ namespace Parser { | |||||
| Lisp_Object* parse_symbol(char* text, int* index_in_text) { | Lisp_Object* parse_symbol(char* text, int* index_in_text) { | ||||
| // we are now at the first char of the symbol | // we are now at the first char of the symbol | ||||
| char* str_symbol = read_atom(text, index_in_text); | char* str_symbol = read_atom(text, index_in_text); | ||||
| Lisp_Object* ret = create_lisp_object_symbol(str_symbol); | |||||
| Lisp_Object* ret = Memory::create_lisp_object_symbol(str_symbol); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -146,7 +138,7 @@ namespace Parser { | |||||
| if (text[*index_in_text] == '"') { | if (text[*index_in_text] == '"') { | ||||
| char* str = new(char); | char* str = new(char); | ||||
| *str = '\0'; | *str = '\0'; | ||||
| Lisp_Object* ret = create_lisp_object_string(str, 0); | |||||
| Lisp_Object* ret = Memory::create_lisp_object_string(str, 0); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| // plus one because we want to go after the quotes | // plus one because we want to go after the quotes | ||||
| @@ -187,7 +179,7 @@ namespace Parser { | |||||
| *index_in_text += string_length +1; // plus one because we want to | *index_in_text += string_length +1; // plus one because we want to | ||||
| // go after the quotes | // go after the quotes | ||||
| Lisp_Object* ret = create_lisp_object_string(string, string_length); | |||||
| Lisp_Object* ret = Memory::create_lisp_object_string(string, string_length); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| @@ -246,17 +238,17 @@ namespace Parser { | |||||
| } | } | ||||
| if (quoteType == '\'') | if (quoteType == '\'') | ||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("quote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| return Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("quote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| else if (quoteType == '`') | else if (quoteType == '`') | ||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("quasiquote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| return Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("quasiquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| // it has to be an unquote | // it has to be an unquote | ||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("unquote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| return Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("unquote"), | |||||
| Memory::create_lisp_object_pair(result, Memory::create_lisp_object_nil())); | |||||
| } | } | ||||
| @@ -271,11 +263,11 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| return create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_nil(); | |||||
| } | } | ||||
| // okay there is something | // okay there is something | ||||
| Lisp_Object* head = new(Lisp_Object); | |||||
| Lisp_Object* head = Memory::create_lisp_object(); | |||||
| head->type = Lisp_Object_Type::Pair; | head->type = Lisp_Object_Type::Pair; | ||||
| head->value.pair = new(Pair); | head->value.pair = new(Pair); | ||||
| Lisp_Object* expression = head; | Lisp_Object* expression = head; | ||||
| @@ -303,7 +295,7 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| head->value.pair->rest = create_lisp_object_nil(); | |||||
| head->value.pair->rest = Memory::create_lisp_object_nil(); | |||||
| ++parser_col; | ++parser_col; | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| break; | break; | ||||
| @@ -325,7 +317,7 @@ namespace Parser { | |||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| break; | break; | ||||
| } else { | } else { | ||||
| head->value.pair->rest = create_lisp_object_pair(nullptr, nullptr); | |||||
| head->value.pair->rest = Memory::create_lisp_object_pair(nullptr, nullptr); | |||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| } | } | ||||
| } | } | ||||
| @@ -387,17 +379,17 @@ 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 = create_lisp_object_pair( | |||||
| create_lisp_object_symbol("prog"), | |||||
| function->body = Memory::create_lisp_object_pair( | |||||
| Memory::create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Lisp_Object* macro = new(Lisp_Object); | |||||
| Lisp_Object* macro = Memory::create_lisp_object(); | |||||
| macro->type = Lisp_Object_Type::Function; | macro->type = Lisp_Object_Type::Function; | ||||
| macro->value.function = function; | macro->value.function = function; | ||||
| 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 create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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 --- */ | ||||
| @@ -453,7 +445,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 create_lisp_object_nil(); | |||||
| return Memory::create_lisp_object_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] == '`' || | ||||
| @@ -536,5 +528,4 @@ namespace Parser { | |||||
| } | } | ||||
| #undef inject_scl | #undef inject_scl | ||||
| } | } | ||||
| @@ -0,0 +1,142 @@ | |||||
| struct Lisp_Object; | |||||
| struct Environment; | |||||
| define_array_list(Lisp_Object*, Lisp_Object); | |||||
| define_array_list(char*, String); | |||||
| define_array_list(int, Int); | |||||
| enum struct Lisp_Object_Type { | |||||
| Nil, | |||||
| T, | |||||
| Symbol, | |||||
| Keyword, | |||||
| Number, | |||||
| String, | |||||
| Pair, | |||||
| Function, | |||||
| CFunction, | |||||
| }; | |||||
| enum struct Log_Level { | |||||
| None, | |||||
| Critical, | |||||
| Warning, | |||||
| Info, | |||||
| Debug, | |||||
| }; | |||||
| struct Symbol { | |||||
| char* identifier; | |||||
| }; | |||||
| struct Keyword { | |||||
| char* identifier; | |||||
| }; | |||||
| struct Number { | |||||
| double value; | |||||
| }; | |||||
| struct String { | |||||
| char* value; | |||||
| int length; | |||||
| }; | |||||
| struct Pair { | |||||
| Lisp_Object* first; | |||||
| Lisp_Object* rest; | |||||
| }; | |||||
| struct Positional_Arguments { | |||||
| // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have | |||||
| // to convert them to strings and back to symbols | |||||
| char** identifiers; | |||||
| int next_index; | |||||
| int length; | |||||
| }; | |||||
| struct Keyword_Arguments { | |||||
| char** identifiers; | |||||
| // NOTE(Felix): values[i] will be nullptr if no defalut value was | |||||
| // declared for key identifiers[i] | |||||
| Lisp_Object_Array_List* values; | |||||
| int next_index; | |||||
| int length; | |||||
| }; | |||||
| enum struct Function_Type { | |||||
| Lambda, | |||||
| Special_Lambda, | |||||
| Macro | |||||
| }; | |||||
| struct Function { | |||||
| Function_Type type; | |||||
| char* docstring; | |||||
| Positional_Arguments* positional_arguments; | |||||
| Keyword_Arguments* keyword_arguments; | |||||
| // rest_argument will be nullptr if no rest argument is declared | |||||
| char* rest_argument; | |||||
| Lisp_Object* body; // implicit prog | |||||
| Environment* parent_environment; // we are doing closures now!! | |||||
| }; | |||||
| struct CFunction { | |||||
| std::function<Lisp_Object* (Lisp_Object*, Environment*)> function; | |||||
| }; | |||||
| struct Lisp_Object { | |||||
| Source_Code_Location* sourceCodeLocation; | |||||
| Lisp_Object_Type type; | |||||
| union { | |||||
| Symbol* symbol; | |||||
| Keyword* keyword; | |||||
| Number* number; | |||||
| String* string; | |||||
| Pair* pair; | |||||
| Function* function; | |||||
| CFunction* cfunction; | |||||
| } value; | |||||
| }; | |||||
| struct Parsed_Arguments { | |||||
| Lisp_Object_Array_List* positional_arguments; | |||||
| // TODO(Felix): Really use hashmap (keyword[sting] -> | |||||
| // value[Lisp_Object*]) here | |||||
| Lisp_Object_Array_List* keyword_keys; | |||||
| Lisp_Object_Array_List* keyword_values; | |||||
| }; | |||||
| struct Environment { | |||||
| Environment* parent; | |||||
| int capacity; | |||||
| int next_index; | |||||
| // TODO(Felix): Use a hashmap here. | |||||
| char** keys; | |||||
| Lisp_Object** values; | |||||
| }; | |||||
| enum struct Error_Type { | |||||
| Ill_Formed_Arguments, | |||||
| Ill_Formed_Lambda_List, | |||||
| Ill_Formed_List, | |||||
| Not_A_Function, | |||||
| Not_Yet_Implemented, | |||||
| Symbol_Not_Defined, | |||||
| Syntax_Error, | |||||
| Trailing_Garbage, | |||||
| Type_Missmatch, | |||||
| Unbalanced_Parenthesis, | |||||
| Unexpected_Eof, | |||||
| Unknown_Error, | |||||
| Unknown_Keyword_Argument, | |||||
| Wrong_Number_Of_Arguments, | |||||
| Out_Of_Memory, | |||||
| }; | |||||
| struct Error { | |||||
| Error_Type type; | |||||
| Source_Code_Location* location; | |||||
| }; | |||||
| @@ -89,7 +89,7 @@ testresult test_eval_operands() { | |||||
| char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; | char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; | ||||
| Lisp_Object* operands = Parser::parse_single_expression(operands_string); | Lisp_Object* operands = Parser::parse_single_expression(operands_string); | ||||
| int operands_length; | int operands_length; | ||||
| operands = eval_arguments(operands, create_built_ins_environment(), &operands_length); | |||||
| operands = eval_arguments(operands, Memory::create_built_ins_environment(), &operands_length); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_equal_int(list_length(operands), 4); | assert_equal_int(list_length(operands), 4); | ||||
| @@ -233,7 +233,7 @@ testresult test_parse_expression() { | |||||
| testresult test_built_in_add() { | testresult test_built_in_add() { | ||||
| char exp_string[] = "(+ 10 4)"; | char exp_string[] = "(+ 10 4)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | Lisp_Object* expression = Parser::parse_single_expression(exp_string); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -246,7 +246,7 @@ testresult test_built_in_add() { | |||||
| testresult test_built_in_substract() { | testresult test_built_in_substract() { | ||||
| char exp_string[] = "(- 10 4)"; | char exp_string[] = "(- 10 4)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | Lisp_Object* expression = Parser::parse_single_expression(exp_string); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -260,7 +260,7 @@ testresult test_built_in_substract() { | |||||
| testresult test_built_in_multiply() { | testresult test_built_in_multiply() { | ||||
| char exp_string[] = "(* 10 4)"; | char exp_string[] = "(* 10 4)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | Lisp_Object* expression = Parser::parse_single_expression(exp_string); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -274,7 +274,7 @@ testresult test_built_in_multiply() { | |||||
| testresult test_built_in_divide() { | testresult test_built_in_divide() { | ||||
| char exp_string[] = "(/ 20 4)"; | char exp_string[] = "(/ 20 4)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | Lisp_Object* expression = Parser::parse_single_expression(exp_string); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_null(error); | assert_null(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -288,7 +288,7 @@ testresult test_built_in_divide() { | |||||
| testresult test_built_in_if() { | testresult test_built_in_if() { | ||||
| char exp_string1[] = "(if 1 4 5)"; | char exp_string1[] = "(if 1 4 5)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -297,7 +297,7 @@ testresult test_built_in_if() { | |||||
| char exp_string2[] = "(if () 4 5)"; | char exp_string2[] = "(if () 4 5)"; | ||||
| expression = Parser::parse_single_expression(exp_string2); | expression = Parser::parse_single_expression(exp_string2); | ||||
| result = eval_expr(expression, create_built_ins_environment()); | |||||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -310,7 +310,7 @@ testresult test_built_in_if() { | |||||
| testresult test_built_in_and() { | testresult test_built_in_and() { | ||||
| char exp_string1[] = "(and 1 \"asd\" 4)"; | char exp_string1[] = "(and 1 \"asd\" 4)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -319,7 +319,7 @@ testresult test_built_in_and() { | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(and () \"asd\" 4)"; | char exp_string2[] = "(and () \"asd\" 4)"; | ||||
| expression = Parser::parse_single_expression(exp_string2); | expression = Parser::parse_single_expression(exp_string2); | ||||
| result = eval_expr(expression, create_built_ins_environment()); | |||||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -331,7 +331,7 @@ testresult test_built_in_and() { | |||||
| testresult test_built_in_or() { | testresult test_built_in_or() { | ||||
| char exp_string1[] = "(or \"asd\" nil)"; | char exp_string1[] = "(or \"asd\" nil)"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -340,7 +340,7 @@ testresult test_built_in_or() { | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(or () ())"; | char exp_string2[] = "(or () ())"; | ||||
| expression = Parser::parse_single_expression(exp_string2); | expression = Parser::parse_single_expression(exp_string2); | ||||
| result = eval_expr(expression, create_built_ins_environment()); | |||||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -353,7 +353,7 @@ testresult test_built_in_or() { | |||||
| testresult test_built_in_not() { | testresult test_built_in_not() { | ||||
| char exp_string1[] = "(not ())"; | char exp_string1[] = "(not ())"; | ||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | ||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| // a true case | // a true case | ||||
| assert_no_error(error); | assert_no_error(error); | ||||
| @@ -363,7 +363,7 @@ testresult test_built_in_not() { | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(not \"asd xD\")"; | char exp_string2[] = "(not \"asd xD\")"; | ||||
| expression = Parser::parse_single_expression(exp_string2); | expression = Parser::parse_single_expression(exp_string2); | ||||
| result = eval_expr(expression, create_built_ins_environment()); | |||||
| result = eval_expr(expression, Memory::create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| @@ -374,7 +374,8 @@ testresult test_built_in_not() { | |||||
| void run_all_tests() { | void run_all_tests() { | ||||
| log_level = Log_Level::None; | log_level = Log_Level::None; | ||||
| Parser::init(create_built_ins_environment()); | |||||
| Memory::init(); | |||||
| Parser::init(Memory::create_built_ins_environment()); | |||||
| printf("-- Parsing --\n"); | printf("-- Parsing --\n"); | ||||
| invoke_test(test_parse_atom); | invoke_test(test_parse_atom); | ||||