| @@ -1,4 +1,4 @@ | |||||
| void assert_type (Ast_Node* node, Ast_Node_Type type) { | |||||
| void assert_type (Lisp_Object* node, Lisp_Object_Type type) { | |||||
| if (!node) | if (!node) | ||||
| create_error(Error_Type::Unknown_Error, nullptr); | create_error(Error_Type::Unknown_Error, nullptr); | ||||
| if (node->type == type) return; | if (node->type == type) return; | ||||
| @@ -5,7 +5,7 @@ struct Environment { | |||||
| int next_index; | int next_index; | ||||
| // TODO(Felix): Use a hashmap here. | // TODO(Felix): Use a hashmap here. | ||||
| char** keys; | char** keys; | ||||
| Ast_Node** values; | |||||
| Lisp_Object** values; | |||||
| }; | }; | ||||
| Environment* create_child_environment(Environment* parent) { | Environment* create_child_environment(Environment* parent) { | ||||
| @@ -17,7 +17,7 @@ Environment* create_child_environment(Environment* parent) { | |||||
| env->capacity = start_capacity; | env->capacity = start_capacity; | ||||
| env->next_index = 0; | env->next_index = 0; | ||||
| env->keys = (char**)malloc(start_capacity * sizeof(char*)); | env->keys = (char**)malloc(start_capacity * sizeof(char*)); | ||||
| env->values = (Ast_Node**)malloc(start_capacity * sizeof(Ast_Node*)); | |||||
| env->values = (Lisp_Object**)malloc(start_capacity * sizeof(Lisp_Object*)); | |||||
| return env; | return env; | ||||
| } | } | ||||
| @@ -26,7 +26,7 @@ Environment* create_empty_environment() { | |||||
| return create_child_environment(nullptr); | return create_child_environment(nullptr); | ||||
| } | } | ||||
| void define_symbol(Ast_Node* symbol, Ast_Node* 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 | ||||
| // back of the list without checking if it already exists but are | // back of the list without checking if it already exists but are | ||||
| // also searching for thesymbol from the back, so we will find the | // also searching for thesymbol from the back, so we will find the | ||||
| @@ -35,7 +35,7 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { | |||||
| if (env->next_index == env->capacity) { | if (env->next_index == env->capacity) { | ||||
| env->capacity *= 2; | env->capacity *= 2; | ||||
| env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*)); | env->keys = (char**)realloc(env->keys, env->capacity * sizeof(char*)); | ||||
| env->values = (Ast_Node**)realloc(env->values, env->capacity * sizeof(Ast_Node*)); | |||||
| env->values = (Lisp_Object**)realloc(env->values, env->capacity * sizeof(Lisp_Object*)); | |||||
| } | } | ||||
| env->keys [env->next_index] = symbol->value.symbol->identifier; | env->keys [env->next_index] = symbol->value.symbol->identifier; | ||||
| @@ -45,17 +45,17 @@ void define_symbol(Ast_Node* symbol, Ast_Node* value, Environment* env) { | |||||
| void print_environment(Environment* env); | void print_environment(Environment* env); | ||||
| Ast_Node* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) { | |||||
| Lisp_Object* lookup_symbol_in_this_envt(Symbol* sym, Environment* env) { | |||||
| for (int i = env->next_index - 1; i >= 0; --i) | for (int i = env->next_index - 1; i >= 0; --i) | ||||
| if (string_equal(env->keys[i], sym->identifier)) | if (string_equal(env->keys[i], sym->identifier)) | ||||
| return env->values[i]; | return env->values[i]; | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| Ast_Node* lookup_symbol(Ast_Node* node, Environment* env) { | |||||
| Lisp_Object* lookup_symbol(Lisp_Object* node, Environment* env) { | |||||
| // first check current environment | // first check current environment | ||||
| Symbol* sym = node->value.symbol; | Symbol* sym = node->value.symbol; | ||||
| Ast_Node* result; | |||||
| Lisp_Object* result; | |||||
| result = lookup_symbol_in_this_envt(sym, env); | result = lookup_symbol_in_this_envt(sym, env); | ||||
| if (result) | if (result) | ||||
| return result; | return result; | ||||
| @@ -68,10 +68,10 @@ Ast_Node* lookup_symbol(Ast_Node* node, Environment* env) { | |||||
| } | } | ||||
| if (string_equal(sym->identifier, "nil")) { | if (string_equal(sym->identifier, "nil")) { | ||||
| return create_ast_node_nil(); | |||||
| return create_lisp_object_nil(); | |||||
| } | } | ||||
| if (string_equal(sym->identifier, "t")) { | if (string_equal(sym->identifier, "t")) { | ||||
| return create_ast_node_t(); | |||||
| return create_lisp_object_t(); | |||||
| } | } | ||||
| create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | create_error(Error_Type::Symbol_Not_Defined, node->sourceCodeLocation); | ||||
| @@ -1,16 +1,16 @@ | |||||
| Ast_Node* eval_expr(Ast_Node*, Environment*); | |||||
| Lisp_Object* eval_expr(Lisp_Object*, Environment*); | |||||
| Ast_Node* apply_arguments_to_function(Ast_Node* 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 = 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) { | ||||
| if (arguments->type == Ast_Node_Type::Pair) { | |||||
| // TODO(Felix): here we create new ast_node_symbols from | |||||
| if (arguments->type == Lisp_Object_Type::Pair) { | |||||
| // TODO(Felix): here we create new lisp_object_symbols from | |||||
| // 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_ast_node_symbol(function->positional_arguments->identifiers[i]), | |||||
| create_lisp_object_symbol(function->positional_arguments->identifiers[i]), | |||||
| arguments->value.pair->first, new_env); | arguments->value.pair->first, new_env); | ||||
| } else { | } else { | ||||
| @@ -22,14 +22,14 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function) { | |||||
| String_Array_List* read_in_keywords = create_String_array_list(16); | String_Array_List* read_in_keywords = create_String_array_list(16); | ||||
| if (arguments->type == Ast_Node_Type::Nil) | |||||
| if (arguments->type == Lisp_Object_Type::Nil) | |||||
| goto checks; | goto checks; | ||||
| // keyword arguments: use all given ones and keep track of the | // keyword arguments: use all given ones and keep track of the | ||||
| // added ones (array list), if end of parameters in encountered or | // added ones (array list), if end of parameters in encountered or | ||||
| // something that is not a keyword is encountered or a keyword | // something that is not a keyword is encountered or a keyword | ||||
| // that is not recognized is encoutered, jump out of the loop. | // that is not recognized is encoutered, jump out of the loop. | ||||
| while (arguments->value.pair->first->type == Ast_Node_Type::Keyword) { | |||||
| while (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) { | |||||
| // check if this one is even an accepted keyword | // check if this one is even an accepted keyword | ||||
| bool accepted = false; | bool accepted = false; | ||||
| for (int i = 0; i < function->keyword_arguments->next_index; ++i) { | for (int i = 0; i < function->keyword_arguments->next_index; ++i) { | ||||
| @@ -64,14 +64,14 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function) { | |||||
| // okay so we found a keyword that has to be read in and was | // okay so we found a keyword that has to be read in and was | ||||
| // not already read in, is there a next element to actually | // not already read in, is there a next element to actually | ||||
| // set it to? | // set it to? | ||||
| if (arguments->value.pair->rest->type != Ast_Node_Type::Pair) { | |||||
| if (arguments->value.pair->rest->type != Lisp_Object_Type::Pair) { | |||||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| // 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_ast_node_symbol(arguments->value.pair->first->value.keyword->identifier), | |||||
| 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); | ||||
| @@ -80,7 +80,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function) { | |||||
| // overstep both for next one | // overstep both for next one | ||||
| arguments = arguments->value.pair->rest->value.pair->rest; | arguments = arguments->value.pair->rest->value.pair->rest; | ||||
| if (arguments->type == Ast_Node_Type::Nil) { | |||||
| if (arguments->type == Lisp_Object_Type::Nil) { | |||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| @@ -110,23 +110,23 @@ Ast_Node* apply_arguments_to_function(Ast_Node* 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( | ||||
| create_ast_node_symbol(defined_keyword), | |||||
| copy_ast_node(function->keyword_arguments->values->data[i]), new_env); | |||||
| create_lisp_object_symbol(defined_keyword), | |||||
| copy_lisp_object(function->keyword_arguments->values->data[i]), new_env); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (arguments->type == Ast_Node_Type::Nil) { | |||||
| if (arguments->type == Lisp_Object_Type::Nil) { | |||||
| if (function->rest_argument) { | if (function->rest_argument) { | ||||
| define_symbol( | define_symbol( | ||||
| create_ast_node_symbol(function->rest_argument), | |||||
| create_ast_node_nil(), new_env); | |||||
| create_lisp_object_symbol(function->rest_argument), | |||||
| create_lisp_object_nil(), new_env); | |||||
| } | } | ||||
| } else { | } else { | ||||
| if (function->rest_argument) { | if (function->rest_argument) { | ||||
| define_symbol( | define_symbol( | ||||
| create_ast_node_symbol(function->rest_argument), | |||||
| 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 | ||||
| @@ -136,7 +136,7 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function) { | |||||
| } | } | ||||
| Ast_Node* result; | |||||
| Lisp_Object* result; | |||||
| try { | try { | ||||
| result = eval_expr(function->body, new_env); | result = eval_expr(function->body, new_env); | ||||
| } | } | ||||
| @@ -162,15 +162,15 @@ Ast_Node* apply_arguments_to_function(Ast_Node* arguments, Function* function) { | |||||
| positional_arguments, keyword_arguments and rest_argument and | positional_arguments, keyword_arguments and rest_argument and | ||||
| filling it in | filling it in | ||||
| */ | */ | ||||
| void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| void parse_argument_list(Lisp_Object* arguments, Function* function) { | |||||
| // first init the fields | // first init the fields | ||||
| function->positional_arguments = create_positional_argument_list(16); | function->positional_arguments = create_positional_argument_list(16); | ||||
| function->keyword_arguments = create_keyword_argument_list(16); | function->keyword_arguments = create_keyword_argument_list(16); | ||||
| function->rest_argument = nullptr; | function->rest_argument = nullptr; | ||||
| // okay let's try to read some positional arguments | // okay let's try to read some positional arguments | ||||
| while (arguments->type == Ast_Node_Type::Pair) { | |||||
| if (arguments->value.pair->first->type == Ast_Node_Type::Keyword) { | |||||
| while (arguments->type == Lisp_Object_Type::Pair) { | |||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) { | |||||
| if (string_equal(arguments->value.pair->first->value.keyword->identifier, "keys") || | if (string_equal(arguments->value.pair->first->value.keyword->identifier, "keys") || | ||||
| string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | ||||
| break; | break; | ||||
| @@ -180,7 +180,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| } | } | ||||
| } | } | ||||
| if (arguments->value.pair->first->type != Ast_Node_Type::Symbol) { | |||||
| if (arguments->value.pair->first->type != Lisp_Object_Type::Symbol) { | |||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -195,25 +195,25 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| // okay we are done with positional arguments, lets check for | // okay we are done with positional arguments, lets check for | ||||
| // keywords, | // keywords, | ||||
| if (arguments->type != Ast_Node_Type::Pair) { | |||||
| if (arguments->type != Ast_Node_Type::Nil) | |||||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||||
| if (arguments->type != Lisp_Object_Type::Nil) | |||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| if (arguments->value.pair->first->type == Ast_Node_Type::Keyword && | |||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword && | |||||
| string_equal(arguments->value.pair->first->value.keyword->identifier, "keys")) | string_equal(arguments->value.pair->first->value.keyword->identifier, "keys")) | ||||
| { | { | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (arguments->type != Ast_Node_Type::Pair || | |||||
| arguments->value.pair->first->type != Ast_Node_Type::Symbol) | |||||
| if (arguments->type != Lisp_Object_Type::Pair || | |||||
| arguments->value.pair->first->type != Lisp_Object_Type::Symbol) | |||||
| { | { | ||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| while (arguments->type == Ast_Node_Type::Pair) { | |||||
| if (arguments->value.pair->first->type == Ast_Node_Type::Keyword) { | |||||
| while (arguments->type == Lisp_Object_Type::Pair) { | |||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword) { | |||||
| if (string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | if (string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | ||||
| break; | break; | ||||
| else { | else { | ||||
| @@ -222,7 +222,7 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| } | } | ||||
| } | } | ||||
| if (arguments->value.pair->first->type != Ast_Node_Type::Symbol) { | |||||
| if (arguments->value.pair->first->type != Lisp_Object_Type::Symbol) { | |||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| @@ -230,16 +230,16 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| // we found a symbol (arguments->value.pair->first) for | // we found a symbol (arguments->value.pair->first) for | ||||
| // the keyword args! Let's check if the next arguement is | // the keyword args! Let's check if the next arguement is | ||||
| // :defaults-to | // :defaults-to | ||||
| Ast_Node* next = arguments->value.pair->rest; | |||||
| if (next->type == Ast_Node_Type::Pair && | |||||
| next->value.pair->first->type == Ast_Node_Type::Keyword && | |||||
| Lisp_Object* next = arguments->value.pair->rest; | |||||
| if (next->type == Lisp_Object_Type::Pair && | |||||
| next->value.pair->first->type == Lisp_Object_Type::Keyword && | |||||
| string_equal(next->value.pair->first->value.keyword->identifier, | string_equal(next->value.pair->first->value.keyword->identifier, | ||||
| "defaults-to")) | "defaults-to")) | ||||
| { | { | ||||
| // check if there is a next argument too, otherwise it | // check if there is a next argument too, otherwise it | ||||
| // would be an error | // would be an error | ||||
| next = next->value.pair->rest; | next = next->value.pair->rest; | ||||
| if (next->type == Ast_Node_Type::Pair) { | |||||
| if (next->type == Lisp_Object_Type::Pair) { | |||||
| append_to_keyword_argument_list(function->keyword_arguments, | append_to_keyword_argument_list(function->keyword_arguments, | ||||
| arguments->value.pair->first->value.symbol->identifier, | arguments->value.pair->first->value.symbol->identifier, | ||||
| next->value.pair->first); | next->value.pair->first); | ||||
| @@ -261,24 +261,24 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| // Now we are also done with keyword arguments, lets check for | // Now we are also done with keyword arguments, lets check for | ||||
| // if there is a rest argument | // if there is a rest argument | ||||
| if (arguments->type != Ast_Node_Type::Pair) { | |||||
| if (arguments->type != Ast_Node_Type::Nil) | |||||
| if (arguments->type != Lisp_Object_Type::Pair) { | |||||
| if (arguments->type != Lisp_Object_Type::Nil) | |||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| if (arguments->value.pair->first->type == Ast_Node_Type::Keyword && | |||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::Keyword && | |||||
| string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | string_equal(arguments->value.pair->first->value.keyword->identifier, "rest")) | ||||
| { | { | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| if (arguments->type != Ast_Node_Type::Pair || | |||||
| arguments->value.pair->first->type != Ast_Node_Type::Symbol) | |||||
| if (arguments->type != Lisp_Object_Type::Pair || | |||||
| arguments->value.pair->first->type != Lisp_Object_Type::Symbol) | |||||
| { | { | ||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| return; | return; | ||||
| } | } | ||||
| function->rest_argument = arguments->value.pair->first->value.symbol->identifier; | function->rest_argument = arguments->value.pair->first->value.symbol->identifier; | ||||
| if (arguments->value.pair->rest->type != Ast_Node_Type::Nil) { | |||||
| if (arguments->value.pair->rest->type != Lisp_Object_Type::Nil) { | |||||
| create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Lambda_List, arguments->sourceCodeLocation); | ||||
| } | } | ||||
| } else { | } else { | ||||
| @@ -288,20 +288,20 @@ void parse_argument_list(Ast_Node* arguments, Function* function) { | |||||
| } | } | ||||
| int list_length(Ast_Node* node) { | |||||
| if (node->type == Ast_Node_Type::Nil) | |||||
| int list_length(Lisp_Object* node) { | |||||
| if (node->type == Lisp_Object_Type::Nil) | |||||
| return 0; | return 0; | ||||
| if (node->type != Ast_Node_Type::Pair) { | |||||
| if (node->type != Lisp_Object_Type::Pair) { | |||||
| create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation); | create_error(Error_Type::Type_Missmatch, node->sourceCodeLocation); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| int len = 0; | int len = 0; | ||||
| while (node->type == Ast_Node_Type::Pair) { | |||||
| while (node->type == Lisp_Object_Type::Pair) { | |||||
| ++len; | ++len; | ||||
| node = node->value.pair->rest; | node = node->value.pair->rest; | ||||
| if (node->type == Ast_Node_Type::Nil) | |||||
| if (node->type == Lisp_Object_Type::Nil) | |||||
| return len; | return len; | ||||
| } | } | ||||
| @@ -309,9 +309,9 @@ int list_length(Ast_Node* node) { | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| bool is_truthy (Ast_Node* expression, Environment* env); | |||||
| bool is_truthy (Lisp_Object* expression, Environment* env); | |||||
| Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { | |||||
| Lisp_Object* extract_keyword_value(char* keyword, Parsed_Arguments* args) { | |||||
| // NOTE(Felix): This will be a hashmap lookup later | // NOTE(Felix): This will be a hashmap lookup later | ||||
| for (int i = 0; i < args->keyword_keys->next_index; ++i) { | for (int i = 0; i < args->keyword_keys->next_index; ++i) { | ||||
| if (string_equal(args->keyword_keys->data[i]->value.keyword->identifier, keyword)) | if (string_equal(args->keyword_keys->data[i]->value.keyword->identifier, keyword)) | ||||
| @@ -320,26 +320,26 @@ Ast_Node* extract_keyword_value(char* keyword, Parsed_Arguments* args) { | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_arguments_length) { | |||||
| Lisp_Object* eval_arguments(Lisp_Object* arguments, Environment* env, int *out_arguments_length) { | |||||
| int my_out_arguments_length = 0; | int my_out_arguments_length = 0; | ||||
| if (arguments->type == Ast_Node_Type::Nil) { | |||||
| if (arguments->type == Lisp_Object_Type::Nil) { | |||||
| return arguments; | return arguments; | ||||
| } | } | ||||
| Ast_Node* evaluated_arguments = create_ast_node_pair(nullptr, nullptr); | |||||
| Ast_Node* evaluated_arguments_head = evaluated_arguments; | |||||
| Ast_Node* current_head = arguments; | |||||
| while (current_head->type == Ast_Node_Type::Pair) { | |||||
| Lisp_Object* evaluated_arguments = create_lisp_object_pair(nullptr, nullptr); | |||||
| Lisp_Object* evaluated_arguments_head = evaluated_arguments; | |||||
| Lisp_Object* current_head = arguments; | |||||
| while (current_head->type == Lisp_Object_Type::Pair) { | |||||
| try { | try { | ||||
| evaluated_arguments_head->value.pair->first = | evaluated_arguments_head->value.pair->first = | ||||
| eval_expr(current_head->value.pair->first, env); | eval_expr(current_head->value.pair->first, env); | ||||
| } | } | ||||
| current_head = current_head->value.pair->rest; | current_head = current_head->value.pair->rest; | ||||
| if (current_head->type == Ast_Node_Type::Pair) { | |||||
| evaluated_arguments_head->value.pair->rest = create_ast_node_pair(nullptr, nullptr); | |||||
| if (current_head->type == Lisp_Object_Type::Pair) { | |||||
| evaluated_arguments_head->value.pair->rest = 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 == Ast_Node_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; | ||||
| } else { | } else { | ||||
| create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | create_error(Error_Type::Ill_Formed_Arguments, arguments->sourceCodeLocation); | ||||
| @@ -351,7 +351,7 @@ Ast_Node* eval_arguments(Ast_Node* arguments, Environment* env, int *out_argumen | |||||
| return evaluated_arguments; | return evaluated_arguments; | ||||
| } | } | ||||
| Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| Lisp_Object* eval_expr(Lisp_Object* node, Environment* env) { | |||||
| #define report_error(_type) { \ | #define report_error(_type) { \ | ||||
| create_error(_type, node->sourceCodeLocation); \ | create_error(_type, node->sourceCodeLocation); \ | ||||
| return nullptr; \ | return nullptr; \ | ||||
| @@ -360,26 +360,26 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| if (error) | if (error) | ||||
| return nullptr; | return nullptr; | ||||
| Ast_Node* ret = new(Ast_Node); | |||||
| Lisp_Object* ret = new(Lisp_Object); | |||||
| switch (node->type) { | switch (node->type) { | ||||
| case Ast_Node_Type::T: | |||||
| case Ast_Node_Type::Nil: | |||||
| case Lisp_Object_Type::T: | |||||
| case Lisp_Object_Type::Nil: | |||||
| return node; | return node; | ||||
| case Ast_Node_Type::Symbol: { | |||||
| Ast_Node* symbol; | |||||
| case Lisp_Object_Type::Symbol: { | |||||
| Lisp_Object* symbol; | |||||
| try { | try { | ||||
| symbol = lookup_symbol(node, env); | symbol = lookup_symbol(node, env); | ||||
| } | } | ||||
| return symbol; | return symbol; | ||||
| } | } | ||||
| case Ast_Node_Type::Number: | |||||
| case Ast_Node_Type::Keyword: | |||||
| case Ast_Node_Type::String: | |||||
| case Lisp_Object_Type::Number: | |||||
| case Lisp_Object_Type::Keyword: | |||||
| case Lisp_Object_Type::String: | |||||
| return node; | return node; | ||||
| case Ast_Node_Type::Pair: { | |||||
| Ast_Node* lispOperator; | |||||
| if (node->value.pair->first->type != Ast_Node_Type::CFunction && | |||||
| node->value.pair->first->type != Ast_Node_Type::Function) | |||||
| case Lisp_Object_Type::Pair: { | |||||
| Lisp_Object* lispOperator; | |||||
| if (node->value.pair->first->type != Lisp_Object_Type::CFunction && | |||||
| node->value.pair->first->type != Lisp_Object_Type::Function) | |||||
| { | { | ||||
| try { | try { | ||||
| lispOperator = eval_expr(node->value.pair->first, env); | lispOperator = eval_expr(node->value.pair->first, env); | ||||
| @@ -388,17 +388,17 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| lispOperator = node->value.pair->first; | lispOperator = node->value.pair->first; | ||||
| } | } | ||||
| Ast_Node* arguments = node->value.pair->rest; | |||||
| Lisp_Object* arguments = node->value.pair->rest; | |||||
| int arguments_length; | int arguments_length; | ||||
| // check for c function | // check for c function | ||||
| if (lispOperator->type == Ast_Node_Type::CFunction) { | |||||
| Ast_Node* result = lispOperator->value.cfunction->function(arguments, env); | |||||
| if (lispOperator->type == Lisp_Object_Type::CFunction) { | |||||
| Lisp_Object* result = lispOperator->value.cfunction->function(arguments, env); | |||||
| return result; | return result; | ||||
| } | } | ||||
| // check for lisp function | // check for lisp function | ||||
| if (lispOperator->type == Ast_Node_Type::Function) { | |||||
| if (lispOperator->type == Lisp_Object_Type::Function) { | |||||
| // only for lambdas we evaluate the arguments before | // only for lambdas we evaluate the arguments before | ||||
| // apllying | // apllying | ||||
| if (lispOperator->value.function->type == Function_Type::Lambda) { | if (lispOperator->value.function->type == Function_Type::Lambda) { | ||||
| @@ -407,7 +407,7 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| } | } | ||||
| } | } | ||||
| Ast_Node* result; | |||||
| Lisp_Object* result; | |||||
| try { | try { | ||||
| result = apply_arguments_to_function(arguments, lispOperator->value.function); | result = apply_arguments_to_function(arguments, lispOperator->value.function); | ||||
| } | } | ||||
| @@ -421,12 +421,12 @@ Ast_Node* eval_expr(Ast_Node* node, Environment* env) { | |||||
| #undef report_error | #undef report_error | ||||
| } | } | ||||
| bool is_truthy (Ast_Node* expression, Environment* env) { | |||||
| Ast_Node* result; | |||||
| bool is_truthy (Lisp_Object* expression, Environment* env) { | |||||
| Lisp_Object* result; | |||||
| try { | try { | ||||
| result = eval_expr(expression, env); | result = eval_expr(expression, env); | ||||
| } | } | ||||
| if (result->type == Ast_Node_Type::Nil) | |||||
| if (result->type == Lisp_Object_Type::Nil) | |||||
| return false; | return false; | ||||
| return true; | return true; | ||||
| @@ -38,27 +38,27 @@ void panic(char* message) { | |||||
| exit(1); | exit(1); | ||||
| } | } | ||||
| void print(Ast_Node* node) { | |||||
| void print(Lisp_Object* node) { | |||||
| switch (node->type) { | switch (node->type) { | ||||
| case (Ast_Node_Type::Nil): { | |||||
| case (Lisp_Object_Type::Nil): { | |||||
| printf("nil"); | printf("nil"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::T): { | |||||
| case (Lisp_Object_Type::T): { | |||||
| printf("t"); | printf("t"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Number): { | |||||
| case (Lisp_Object_Type::Number): { | |||||
| printf("%f", node->value.number->value); | printf("%f", node->value.number->value); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::String): { | |||||
| case (Lisp_Object_Type::String): { | |||||
| printf("\"%s\"", node->value.string->value); | printf("\"%s\"", node->value.string->value); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Symbol): { | |||||
| case (Lisp_Object_Type::Symbol): { | |||||
| printf("%s", node->value.symbol->identifier); | printf("%s", node->value.symbol->identifier); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Keyword): { | |||||
| case (Lisp_Object_Type::Keyword): { | |||||
| printf(":%s", node->value.keyword->identifier); | printf(":%s", node->value.keyword->identifier); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Function): { | |||||
| case (Lisp_Object_Type::Function): { | |||||
| if (node->value.function->type == Function_Type::Lambda) | if (node->value.function->type == Function_Type::Lambda) | ||||
| printf("[lambda]"); | printf("[lambda]"); | ||||
| else if (node->value.function->type == Function_Type::Special_Lambda) | else if (node->value.function->type == Function_Type::Special_Lambda) | ||||
| @@ -68,11 +68,11 @@ void print(Ast_Node* node) { | |||||
| else | else | ||||
| assert(false); | assert(false); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::CFunction): { | |||||
| case (Lisp_Object_Type::CFunction): { | |||||
| printf("[C-function]"); | printf("[C-function]"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Pair): { | |||||
| Ast_Node* head = node; | |||||
| case (Lisp_Object_Type::Pair): { | |||||
| Lisp_Object* head = node; | |||||
| printf("("); | printf("("); | ||||
| // NOTE(Felix): We cold do a while true here, however in case | // NOTE(Felix): We cold do a while true here, however in case | ||||
| @@ -83,12 +83,12 @@ void print(Ast_Node* node) { | |||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| if (!head) | if (!head) | ||||
| return; | return; | ||||
| if (head->type != Ast_Node_Type::Pair) | |||||
| if (head->type != Lisp_Object_Type::Pair) | |||||
| break; | break; | ||||
| printf(" "); | printf(" "); | ||||
| } | } | ||||
| if (head->type != Ast_Node_Type::Nil) { | |||||
| if (head->type != Lisp_Object_Type::Nil) { | |||||
| printf(" . "); | printf(" . "); | ||||
| print(head); | print(head); | ||||
| } | } | ||||
| @@ -99,27 +99,27 @@ void print(Ast_Node* node) { | |||||
| } | } | ||||
| // XXX(Felix): obv code dublicate | // XXX(Felix): obv code dublicate | ||||
| void fprint(FILE* f, Ast_Node* node) { | |||||
| void fprint(FILE* f, Lisp_Object* node) { | |||||
| switch (node->type) { | switch (node->type) { | ||||
| case (Ast_Node_Type::Nil): { | |||||
| case (Lisp_Object_Type::Nil): { | |||||
| fprintf(f, "nil"); | fprintf(f, "nil"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::T): { | |||||
| case (Lisp_Object_Type::T): { | |||||
| fprintf(f, "t"); | fprintf(f, "t"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Number): { | |||||
| case (Lisp_Object_Type::Number): { | |||||
| fprintf(f, "%f", node->value.number->value); | fprintf(f, "%f", node->value.number->value); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::String): { | |||||
| case (Lisp_Object_Type::String): { | |||||
| fprintf(f, "\"%s\"", node->value.string->value); | fprintf(f, "\"%s\"", node->value.string->value); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Symbol): { | |||||
| case (Lisp_Object_Type::Symbol): { | |||||
| fprintf(f, "%s", node->value.symbol->identifier); | fprintf(f, "%s", node->value.symbol->identifier); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Keyword): { | |||||
| case (Lisp_Object_Type::Keyword): { | |||||
| fprintf(f, ":%s", node->value.keyword->identifier); | fprintf(f, ":%s", node->value.keyword->identifier); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Function): { | |||||
| case (Lisp_Object_Type::Function): { | |||||
| if (node->value.function->type == Function_Type::Lambda) | if (node->value.function->type == Function_Type::Lambda) | ||||
| fprintf(f, "[lambda]"); | fprintf(f, "[lambda]"); | ||||
| else if (node->value.function->type == Function_Type::Special_Lambda) | else if (node->value.function->type == Function_Type::Special_Lambda) | ||||
| @@ -129,11 +129,11 @@ void fprint(FILE* f, Ast_Node* node) { | |||||
| else | else | ||||
| assert(false); | assert(false); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::CFunction): { | |||||
| case (Lisp_Object_Type::CFunction): { | |||||
| fprintf(f, "[C-function]"); | fprintf(f, "[C-function]"); | ||||
| } break; | } break; | ||||
| case (Ast_Node_Type::Pair): { | |||||
| Ast_Node* head = node; | |||||
| case (Lisp_Object_Type::Pair): { | |||||
| Lisp_Object* head = node; | |||||
| fprintf(f, "("); | fprintf(f, "("); | ||||
| // NOTE(Felix): We cold do a while true here, however in case | // NOTE(Felix): We cold do a while true here, however in case | ||||
| @@ -144,12 +144,12 @@ void fprint(FILE* f, Ast_Node* node) { | |||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| if (!head) | if (!head) | ||||
| return; | return; | ||||
| if (head->type != Ast_Node_Type::Pair) | |||||
| if (head->type != Lisp_Object_Type::Pair) | |||||
| break; | break; | ||||
| fprintf(f, " "); | fprintf(f, " "); | ||||
| } | } | ||||
| if (head->type != Ast_Node_Type::Nil) { | |||||
| if (head->type != Lisp_Object_Type::Nil) { | |||||
| fprintf(f, " . "); | fprintf(f, " . "); | ||||
| print(head); | print(head); | ||||
| } | } | ||||
| @@ -1,8 +1,8 @@ | |||||
| struct Ast_Node; | |||||
| struct Lisp_Object; | |||||
| define_array_list(Ast_Node*, Ast_Node); | |||||
| define_array_list(Lisp_Object*, Lisp_Object); | |||||
| enum struct Ast_Node_Type { | |||||
| enum struct Lisp_Object_Type { | |||||
| Nil, | Nil, | ||||
| T, | T, | ||||
| Symbol, | Symbol, | ||||
| @@ -14,17 +14,17 @@ enum struct Ast_Node_Type { | |||||
| CFunction, | CFunction, | ||||
| }; | }; | ||||
| char* Ast_Node_Type_to_string(Ast_Node_Type type) { | |||||
| char* Lisp_Object_Type_to_string(Lisp_Object_Type type) { | |||||
| switch (type) { | switch (type) { | ||||
| case(Ast_Node_Type::Nil): return "nil"; | |||||
| case(Ast_Node_Type::T): return "t"; | |||||
| case(Ast_Node_Type::Number): return "number"; | |||||
| case(Ast_Node_Type::String): return "string"; | |||||
| case(Ast_Node_Type::Symbol): return "symbol"; | |||||
| case(Ast_Node_Type::Keyword): return "keyword"; | |||||
| case(Ast_Node_Type::Function): return "function"; | |||||
| case(Ast_Node_Type::CFunction): return "C-function"; | |||||
| case(Ast_Node_Type::Pair): return "pair"; | |||||
| case(Lisp_Object_Type::Nil): return "nil"; | |||||
| case(Lisp_Object_Type::T): return "t"; | |||||
| case(Lisp_Object_Type::Number): return "number"; | |||||
| case(Lisp_Object_Type::String): return "string"; | |||||
| case(Lisp_Object_Type::Symbol): return "symbol"; | |||||
| case(Lisp_Object_Type::Keyword): return "keyword"; | |||||
| case(Lisp_Object_Type::Function): return "function"; | |||||
| case(Lisp_Object_Type::CFunction): return "C-function"; | |||||
| case(Lisp_Object_Type::Pair): return "pair"; | |||||
| } | } | ||||
| return "unknown"; | return "unknown"; | ||||
| } | } | ||||
| @@ -47,12 +47,12 @@ struct String { | |||||
| }; | }; | ||||
| struct Pair { | struct Pair { | ||||
| Ast_Node* first; | |||||
| Ast_Node* rest; | |||||
| Lisp_Object* first; | |||||
| Lisp_Object* rest; | |||||
| }; | }; | ||||
| struct Positional_Arguments { | struct Positional_Arguments { | ||||
| // TODO(Felix) use Ast_Node_symbols here instead, so we don't have | |||||
| // TODO(Felix) use Lisp_Object_symbols here instead, so we don't have | |||||
| // to convert them to strings and back to symbols | // to convert them to strings and back to symbols | ||||
| char** identifiers; | char** identifiers; | ||||
| int next_index; | int next_index; | ||||
| @@ -63,7 +63,7 @@ struct Keyword_Arguments { | |||||
| char** identifiers; | char** identifiers; | ||||
| // NOTE(Felix): values[i] will be nullptr if no defalut value was | // NOTE(Felix): values[i] will be nullptr if no defalut value was | ||||
| // declared for key identifiers[i] | // declared for key identifiers[i] | ||||
| Ast_Node_Array_List* values; | |||||
| Lisp_Object_Array_List* values; | |||||
| int next_index; | int next_index; | ||||
| int length; | int length; | ||||
| }; | }; | ||||
| @@ -88,7 +88,7 @@ void append_to_positional_argument_list(Positional_Arguments* args, char* identi | |||||
| Keyword_Arguments* create_keyword_argument_list(int initial_capacity) { | Keyword_Arguments* create_keyword_argument_list(int initial_capacity) { | ||||
| Keyword_Arguments* ret = new(Keyword_Arguments); | Keyword_Arguments* ret = new(Keyword_Arguments); | ||||
| ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); | ret->identifiers = (char**)malloc(initial_capacity * sizeof(char*)); | ||||
| ret->values = create_Ast_Node_array_list(initial_capacity); | |||||
| ret->values = create_Lisp_Object_array_list(initial_capacity); | |||||
| ret->next_index = 0; | ret->next_index = 0; | ||||
| ret->length = initial_capacity; | ret->length = initial_capacity; | ||||
| return ret; | return ret; | ||||
| @@ -96,7 +96,7 @@ Keyword_Arguments* create_keyword_argument_list(int initial_capacity) { | |||||
| void append_to_keyword_argument_list(Keyword_Arguments* args, | void append_to_keyword_argument_list(Keyword_Arguments* args, | ||||
| char* identifier, | char* identifier, | ||||
| struct Ast_Node* default_value) | |||||
| struct Lisp_Object* default_value) | |||||
| { | { | ||||
| if (args->next_index == args->length) { | if (args->next_index == args->length) { | ||||
| args->length *= 2; | args->length *= 2; | ||||
| @@ -104,7 +104,7 @@ void append_to_keyword_argument_list(Keyword_Arguments* args, | |||||
| } | } | ||||
| args->identifiers[args->next_index++] = identifier; | args->identifiers[args->next_index++] = identifier; | ||||
| append_to_Ast_Node_array_list(args->values, default_value); | |||||
| append_to_Lisp_Object_array_list(args->values, default_value); | |||||
| } | } | ||||
| struct Environment; | struct Environment; | ||||
| @@ -122,18 +122,18 @@ struct Function { | |||||
| Keyword_Arguments* keyword_arguments; | Keyword_Arguments* keyword_arguments; | ||||
| // rest_argument will be nullptr if no rest argument is declared | // rest_argument will be nullptr if no rest argument is declared | ||||
| char* rest_argument; | char* rest_argument; | ||||
| Ast_Node* body; // implicit prog | |||||
| Lisp_Object* body; // implicit prog | |||||
| Environment* parent_environment; // we are doing closures now!! | Environment* parent_environment; // we are doing closures now!! | ||||
| }; | }; | ||||
| struct CFunction { | struct CFunction { | ||||
| std::function<Ast_Node*(Ast_Node*, Environment*)> function; | |||||
| std::function<Lisp_Object* (Lisp_Object*, Environment*)> function; | |||||
| }; | }; | ||||
| struct Ast_Node { | |||||
| struct Lisp_Object { | |||||
| Source_Code_Location* sourceCodeLocation; | Source_Code_Location* sourceCodeLocation; | ||||
| Ast_Node_Type type; | |||||
| Lisp_Object_Type type; | |||||
| union { | union { | ||||
| Symbol* symbol; | Symbol* symbol; | ||||
| Keyword* keyword; | Keyword* keyword; | ||||
| @@ -146,85 +146,85 @@ struct Ast_Node { | |||||
| }; | }; | ||||
| struct Parsed_Arguments { | struct Parsed_Arguments { | ||||
| Ast_Node_Array_List* positional_arguments; | |||||
| Lisp_Object_Array_List* positional_arguments; | |||||
| // TODO(Felix): Really use hashmap (keyword[sting] -> | // TODO(Felix): Really use hashmap (keyword[sting] -> | ||||
| // value[Ast_Node*]) here | |||||
| Ast_Node_Array_List* keyword_keys; | |||||
| Ast_Node_Array_List* keyword_values; | |||||
| // value[Lisp_Object*]) here | |||||
| Lisp_Object_Array_List* keyword_keys; | |||||
| Lisp_Object_Array_List* keyword_values; | |||||
| }; | }; | ||||
| Ast_Node* create_ast_node() { | |||||
| Ast_Node* node = new(Ast_Node); | |||||
| Lisp_Object* create_lisp_object() { | |||||
| Lisp_Object* node = new(Lisp_Object); | |||||
| node->sourceCodeLocation = nullptr; | node->sourceCodeLocation = nullptr; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_nil() { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::Nil; | |||||
| Lisp_Object* create_lisp_object_nil() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::Nil; | |||||
| node->value.pair = nullptr; | node->value.pair = nullptr; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_t() { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::T; | |||||
| Lisp_Object* create_lisp_object_t() { | |||||
| Lisp_Object* node = create_lisp_object(); | |||||
| node->type = Lisp_Object_Type::T; | |||||
| node->value.pair = nullptr; | node->value.pair = nullptr; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_number(double number) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::Number; | |||||
| 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 = new(Number); | ||||
| node->value.number->value = number; | node->value.number->value = number; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_string(char* str, int length) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::String; | |||||
| 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 = new(String); | ||||
| node->value.string->value = str; | node->value.string->value = str; | ||||
| node->value.string->length = length; | node->value.string->length = length; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_symbol(char* identifier) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::Symbol; | |||||
| 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 = new(Symbol); | ||||
| node->value.symbol->identifier = identifier; | node->value.symbol->identifier = identifier; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_keyword(char* keyword) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::Keyword; | |||||
| 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 = new(Keyword); | ||||
| node->value.keyword->identifier = keyword; | node->value.keyword->identifier = keyword; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_cfunction(std::function<Ast_Node*(Ast_Node*, Environment*)> function) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::CFunction; | |||||
| 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 = new(CFunction); | ||||
| node->value.cfunction->function = function; | node->value.cfunction->function = function; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) { | |||||
| Ast_Node* node = create_ast_node(); | |||||
| node->type = Ast_Node_Type::Pair; | |||||
| 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 = new(Pair); | ||||
| node->value.pair->first = first; | node->value.pair->first = first; | ||||
| node->value.pair->rest = rest; | node->value.pair->rest = rest; | ||||
| return node; | return node; | ||||
| } | } | ||||
| Ast_Node* copy_ast_node(Ast_Node* n) { | |||||
| Ast_Node* target = create_ast_node(); | |||||
| Lisp_Object* copy_lisp_object(Lisp_Object* n) { | |||||
| Lisp_Object* target = create_lisp_object(); | |||||
| *target = *n; | *target = *n; | ||||
| return target; | return target; | ||||
| } | } | ||||
| @@ -9,7 +9,7 @@ | |||||
| #include <functional> | #include <functional> | ||||
| #include "./helpers.cpp" | #include "./helpers.cpp" | ||||
| #include "./ast.cpp" | |||||
| #include "./lisp_object.cpp" | |||||
| #include "./error.cpp" | #include "./error.cpp" | ||||
| #include "./io.cpp" | #include "./io.cpp" | ||||
| #include "./assert.cpp" | #include "./assert.cpp" | ||||
| @@ -19,7 +19,7 @@ | |||||
| #include "./eval.cpp" | #include "./eval.cpp" | ||||
| #include "./testing.cpp" | #include "./testing.cpp" | ||||
| Ast_Node* interprete_file (char* file_name) { | |||||
| Lisp_Object* interprete_file (char* file_name) { | |||||
| 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); | ||||
| @@ -34,12 +34,12 @@ Ast_Node* interprete_file (char* file_name) { | |||||
| built_in_load("pre.slime", env); | built_in_load("pre.slime", env); | ||||
| } | } | ||||
| Ast_Node_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); | ||||
| } | } | ||||
| Ast_Node* result = create_ast_node_nil(); | |||||
| Lisp_Object* result = 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); | ||||
| @@ -64,7 +64,7 @@ int interprete_stdin () { | |||||
| delete_error(); | delete_error(); | ||||
| } | } | ||||
| Ast_Node* parsed, * evaluated; | |||||
| Lisp_Object* parsed, * evaluated; | |||||
| while (true) { | while (true) { | ||||
| printf(">"); | printf(">"); | ||||
| line = read_expression(); | line = read_expression(); | ||||
| @@ -1,8 +1,8 @@ | |||||
| // forward decls -- start | // forward decls -- start | ||||
| void load_built_ins_into_environment(Environment*); | void load_built_ins_into_environment(Environment*); | ||||
| Ast_Node* eval_expr(Ast_Node*, Environment*); | |||||
| void parse_argument_list(Ast_Node*, Function*); | |||||
| int list_length(Ast_Node*); | |||||
| Lisp_Object* eval_expr(Lisp_Object*, Environment*); | |||||
| void parse_argument_list(Lisp_Object*, Function*); | |||||
| int list_length(Lisp_Object*); | |||||
| // forward decls -- end | // forward decls -- end | ||||
| @@ -109,34 +109,34 @@ namespace Parser { | |||||
| return atom; | return atom; | ||||
| } | } | ||||
| Ast_Node* parse_number(char* text, int* index_in_text) { | |||||
| Lisp_Object* parse_number(char* text, int* index_in_text) { | |||||
| double number; | double number; | ||||
| char* str_number = read_atom(text, index_in_text); | char* str_number = read_atom(text, index_in_text); | ||||
| sscanf(str_number, "%lf", &number); | sscanf(str_number, "%lf", &number); | ||||
| Ast_Node* ret = create_ast_node_number(number); | |||||
| Lisp_Object* ret = create_lisp_object_number(number); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| Ast_Node* parse_keyword(char* text, int* index_in_text) { | |||||
| Lisp_Object* parse_keyword(char* text, int* index_in_text) { | |||||
| // we are now on the colon | // we are now on the colon | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| char* str_keyword = read_atom(text, index_in_text); | char* str_keyword = read_atom(text, index_in_text); | ||||
| Ast_Node* ret = create_ast_node_keyword(str_keyword); | |||||
| Lisp_Object* ret = create_lisp_object_keyword(str_keyword); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| Ast_Node* 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); | ||||
| Ast_Node* ret = create_ast_node_symbol(str_symbol); | |||||
| Lisp_Object* ret = create_lisp_object_symbol(str_symbol); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| Ast_Node* parse_string(char* text, int* index_in_text) { | |||||
| Lisp_Object* parse_string(char* text, int* index_in_text) { | |||||
| // the first character is the '"' | // the first character is the '"' | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| @@ -146,7 +146,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'; | ||||
| Ast_Node* ret = create_ast_node_string(str, 0); | |||||
| Lisp_Object* ret = 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,12 +187,12 @@ 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 | ||||
| Ast_Node* ret = create_ast_node_string(string, string_length); | |||||
| Lisp_Object* ret = create_lisp_object_string(string, string_length); | |||||
| inject_scl(ret); | inject_scl(ret); | ||||
| return ret; | return ret; | ||||
| } | } | ||||
| Ast_Node* parse_atom(char* text, int* index_in_text) { | |||||
| Lisp_Object* parse_atom(char* text, int* index_in_text) { | |||||
| // numbers | // numbers | ||||
| if ((text[*index_in_text] <= 57 && // if number | if ((text[*index_in_text] <= 57 && // if number | ||||
| text[*index_in_text] >= 48) | text[*index_in_text] >= 48) | ||||
| @@ -220,7 +220,7 @@ namespace Parser { | |||||
| return parse_symbol(text, index_in_text); | return parse_symbol(text, index_in_text); | ||||
| } | } | ||||
| Ast_Node* parse_expression(char* text, int* index_in_text) { | |||||
| Lisp_Object* parse_expression(char* text, int* index_in_text) { | |||||
| // if it is quoted | // if it is quoted | ||||
| if (text[*index_in_text] == '\'' || | if (text[*index_in_text] == '\'' || | ||||
| @@ -230,7 +230,7 @@ namespace Parser { | |||||
| char quoteType = text[*index_in_text]; | char quoteType = text[*index_in_text]; | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| Ast_Node* result; | |||||
| Lisp_Object* result; | |||||
| 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] == '`' || | ||||
| @@ -246,17 +246,17 @@ namespace Parser { | |||||
| } | } | ||||
| if (quoteType == '\'') | if (quoteType == '\'') | ||||
| return create_ast_node_pair( | |||||
| create_ast_node_symbol("quote"), | |||||
| create_ast_node_pair(result, create_ast_node_nil())); | |||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("quote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| else if (quoteType == '`') | else if (quoteType == '`') | ||||
| return create_ast_node_pair( | |||||
| create_ast_node_symbol("quasiquote"), | |||||
| create_ast_node_pair(result, create_ast_node_nil())); | |||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("quasiquote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| // it has to be an unquote | // it has to be an unquote | ||||
| return create_ast_node_pair( | |||||
| create_ast_node_symbol("unquote"), | |||||
| create_ast_node_pair(result, create_ast_node_nil())); | |||||
| return create_lisp_object_pair( | |||||
| create_lisp_object_symbol("unquote"), | |||||
| create_lisp_object_pair(result, create_lisp_object_nil())); | |||||
| } | } | ||||
| @@ -271,14 +271,14 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| ++parser_col; | ++parser_col; | ||||
| return create_ast_node_nil(); | |||||
| return create_lisp_object_nil(); | |||||
| } | } | ||||
| // okay there is something | // okay there is something | ||||
| Ast_Node* head = new(Ast_Node); | |||||
| head->type = Ast_Node_Type::Pair; | |||||
| Lisp_Object* head = new(Lisp_Object); | |||||
| head->type = Lisp_Object_Type::Pair; | |||||
| head->value.pair = new(Pair); | head->value.pair = new(Pair); | ||||
| Ast_Node* expression = head; | |||||
| Lisp_Object* expression = head; | |||||
| while (true) { | while (true) { | ||||
| if (text[*index_in_text] == '(' || | if (text[*index_in_text] == '(' || | ||||
| @@ -303,7 +303,7 @@ namespace Parser { | |||||
| if (text[(*index_in_text)] == ')') { | if (text[(*index_in_text)] == ')') { | ||||
| head->value.pair->rest = create_ast_node_nil(); | |||||
| head->value.pair->rest = create_lisp_object_nil(); | |||||
| ++parser_col; | ++parser_col; | ||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| break; | break; | ||||
| @@ -325,16 +325,16 @@ namespace Parser { | |||||
| ++(*index_in_text); | ++(*index_in_text); | ||||
| break; | break; | ||||
| } else { | } else { | ||||
| head->value.pair->rest = create_ast_node_pair(nullptr, nullptr); | |||||
| head->value.pair->rest = create_lisp_object_pair(nullptr, nullptr); | |||||
| head = head->value.pair->rest; | head = head->value.pair->rest; | ||||
| } | } | ||||
| } | } | ||||
| // check if we have to create or delete or run macros | // check if we have to create or delete or run macros | ||||
| if (expression->value.pair->first->type == Ast_Node_Type::Symbol) { | |||||
| if (expression->value.pair->first->type == Lisp_Object_Type::Symbol) { | |||||
| if (string_equal("define-syntax", expression->value.pair->first->value.symbol->identifier)) { | if (string_equal("define-syntax", expression->value.pair->first->value.symbol->identifier)) { | ||||
| // create a new macro | // create a new macro | ||||
| Ast_Node* arguments = expression->value.pair->rest; | |||||
| Lisp_Object* arguments = expression->value.pair->rest; | |||||
| int arguments_length; | int arguments_length; | ||||
| // HACK(Felix): almost code duplicate from | // HACK(Felix): almost code duplicate from | ||||
| @@ -349,13 +349,13 @@ namespace Parser { | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| if (arguments->value.pair->first->type != Ast_Node_Type::Symbol) { | |||||
| if (arguments->value.pair->first->type != Lisp_Object_Type::Symbol) { | |||||
| create_error(Error_Type::Type_Missmatch, expression->sourceCodeLocation); | create_error(Error_Type::Type_Missmatch, expression->sourceCodeLocation); | ||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| // extract the name | // extract the name | ||||
| Ast_Node* symbol_for_macro = arguments->value.pair->first; | |||||
| Lisp_Object* symbol_for_macro = arguments->value.pair->first; | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| Function* function = new(Function); | Function* function = new(Function); | ||||
| @@ -363,9 +363,9 @@ namespace Parser { | |||||
| function->type = Function_Type::Macro; | function->type = Function_Type::Macro; | ||||
| // if parameters were specified | // if parameters were specified | ||||
| if (arguments->value.pair->first->type != Ast_Node_Type::Nil) { | |||||
| if (arguments->value.pair->first->type != Lisp_Object_Type::Nil) { | |||||
| try { | try { | ||||
| assert_type(arguments->value.pair->first, Ast_Node_Type::Pair); | |||||
| assert_type(arguments->value.pair->first, Lisp_Object_Type::Pair); | |||||
| } | } | ||||
| try { | try { | ||||
| parse_argument_list(arguments->value.pair->first, function); | parse_argument_list(arguments->value.pair->first, function); | ||||
| @@ -378,7 +378,7 @@ namespace Parser { | |||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| // if there is a docstring, use it | // if there is a docstring, use it | ||||
| if (arguments->value.pair->first->type == Ast_Node_Type::String) { | |||||
| if (arguments->value.pair->first->type == Lisp_Object_Type::String) { | |||||
| function->docstring = arguments->value.pair->first->value.string->value; | function->docstring = arguments->value.pair->first->value.string->value; | ||||
| arguments = arguments->value.pair->rest; | arguments = arguments->value.pair->rest; | ||||
| } else { | } else { | ||||
| @@ -387,17 +387,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_ast_node_pair( | |||||
| create_ast_node_symbol("prog"), | |||||
| function->body = create_lisp_object_pair( | |||||
| create_lisp_object_symbol("prog"), | |||||
| arguments); | arguments); | ||||
| Ast_Node* macro = new(Ast_Node); | |||||
| macro->type = Ast_Node_Type::Function; | |||||
| Lisp_Object* macro = new(Lisp_Object); | |||||
| 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_ast_node_nil(); | |||||
| return 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 --- */ | ||||
| @@ -420,7 +420,7 @@ namespace Parser { | |||||
| for (int i = 0; i < environment_for_macros->next_index; ++i) { | for (int i = 0; i < environment_for_macros->next_index; ++i) { | ||||
| if (string_equal(expression->value.pair->first->value.symbol->identifier, environment_for_macros->keys[i]) && | if (string_equal(expression->value.pair->first->value.symbol->identifier, environment_for_macros->keys[i]) && | ||||
| environment_for_macros->values[i]->type == Ast_Node_Type::Function && | |||||
| environment_for_macros->values[i]->type == Lisp_Object_Type::Function && | |||||
| environment_for_macros->values[i]->value.function->type == Function_Type::Macro) | environment_for_macros->values[i]->value.function->type == Function_Type::Macro) | ||||
| { | { | ||||
| try { | try { | ||||
| @@ -444,16 +444,16 @@ namespace Parser { | |||||
| return expression; | return expression; | ||||
| } | } | ||||
| Ast_Node* parse_single_expression(char* text) { | |||||
| Lisp_Object* parse_single_expression(char* text) { | |||||
| parser_file = "stdin"; | parser_file = "stdin"; | ||||
| parser_line = 1; | parser_line = 1; | ||||
| parser_col = 1; | parser_col = 1; | ||||
| int index_in_text = 0; | int index_in_text = 0; | ||||
| Ast_Node* 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_ast_node_nil(); | |||||
| return 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] == '`' || | ||||
| @@ -474,7 +474,7 @@ namespace Parser { | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| void write_expanded_file(char* file_name, Ast_Node_Array_List* program) { | |||||
| void write_expanded_file(char* file_name, Lisp_Object_Array_List* program) { | |||||
| char* ext = ".expanded"; | char* ext = ".expanded"; | ||||
| char* newName = (char*)calloc(4 + strlen(file_name), sizeof(char)); | char* newName = (char*)calloc(4 + strlen(file_name), sizeof(char)); | ||||
| strcpy(newName, file_name); | strcpy(newName, file_name); | ||||
| @@ -488,7 +488,7 @@ namespace Parser { | |||||
| for (int i = 0; i < program->next_index; ++i) { | for (int i = 0; i < program->next_index; ++i) { | ||||
| // a macro will parse as nil for now, so we skip those | // a macro will parse as nil for now, so we skip those | ||||
| if (program->data[i]->type == Ast_Node_Type::Nil) | |||||
| if (program->data[i]->type == Lisp_Object_Type::Nil) | |||||
| continue; | continue; | ||||
| fprint(f, program->data[i]); | fprint(f, program->data[i]); | ||||
| fprintf(f, "\n\n"); | fprintf(f, "\n\n"); | ||||
| @@ -497,24 +497,24 @@ namespace Parser { | |||||
| fclose(f); | fclose(f); | ||||
| } | } | ||||
| Ast_Node_Array_List* parse_program(char* file_name, char* text) { | |||||
| Lisp_Object_Array_List* parse_program(char* file_name, char* text) { | |||||
| parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1); | parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1); | ||||
| strcpy(parser_file, file_name); | strcpy(parser_file, file_name); | ||||
| parser_line = 1; | parser_line = 1; | ||||
| parser_col = 0; | parser_col = 0; | ||||
| Ast_Node_Array_List* program = create_Ast_Node_array_list(16); | |||||
| Lisp_Object_Array_List* program = create_Lisp_Object_array_list(16); | |||||
| int index_in_text = 0; | int index_in_text = 0; | ||||
| while (text[index_in_text] != '\0') { | while (text[index_in_text] != '\0') { | ||||
| switch (text[index_in_text]) { | switch (text[index_in_text]) { | ||||
| case '(': { | case '(': { | ||||
| Ast_Node* parsed; | |||||
| Lisp_Object* parsed; | |||||
| try { | try { | ||||
| parsed = parse_expression(text, &index_in_text); | parsed = parse_expression(text, &index_in_text); | ||||
| } | } | ||||
| append_to_Ast_Node_array_list(program, parsed); | |||||
| append_to_Lisp_Object_array_list(program, parsed); | |||||
| } break; | } break; | ||||
| case ';': | case ';': | ||||
| case ' ': | case ' ': | ||||
| @@ -57,8 +57,8 @@ | |||||
| #define assert_equal_type(node, _type) \ | #define assert_equal_type(node, _type) \ | ||||
| if (node->type != _type) { \ | if (node->type != _type) { \ | ||||
| print_assert_equal_fail( \ | print_assert_equal_fail( \ | ||||
| Ast_Node_Type_to_string(node->type), \ | |||||
| Ast_Node_Type_to_string(_type), char*, "%s"); \ | |||||
| Lisp_Object_Type_to_string(node->type), \ | |||||
| Lisp_Object_Type_to_string(_type), char*, "%s"); \ | |||||
| return fail; \ | return fail; \ | ||||
| } \ | } \ | ||||
| @@ -87,33 +87,33 @@ | |||||
| testresult test_eval_operands() { | testresult test_eval_operands() { | ||||
| char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; | char operands_string[] = "((eval 1) (+ 1 2) \"okay\" (eval :haha))"; | ||||
| Ast_Node* 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, 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); | ||||
| assert_equal_type(operands, Ast_Node_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Ast_Node_Type::Number); | |||||
| assert_equal_type(operands, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Number); | |||||
| assert_equal_double(operands->value.pair->first->value.number->value, 1); | assert_equal_double(operands->value.pair->first->value.number->value, 1); | ||||
| operands = operands->value.pair->rest; | operands = operands->value.pair->rest; | ||||
| assert_equal_type(operands, Ast_Node_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Ast_Node_Type::Number); | |||||
| assert_equal_type(operands, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Number); | |||||
| assert_equal_double(operands->value.pair->first->value.number->value, 3); | assert_equal_double(operands->value.pair->first->value.number->value, 3); | ||||
| operands = operands->value.pair->rest; | operands = operands->value.pair->rest; | ||||
| assert_equal_type(operands, Ast_Node_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Ast_Node_Type::String); | |||||
| assert_equal_type(operands, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Lisp_Object_Type::String); | |||||
| assert_equal_string(operands->value.pair->first->value.string->value, "okay"); | assert_equal_string(operands->value.pair->first->value.string->value, "okay"); | ||||
| operands = operands->value.pair->rest; | operands = operands->value.pair->rest; | ||||
| assert_equal_type(operands, Ast_Node_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Ast_Node_Type::Keyword); | |||||
| assert_equal_type(operands, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(operands->value.pair->first, Lisp_Object_Type::Keyword); | |||||
| assert_equal_string(operands->value.pair->first->value.keyword->identifier, "haha"); | assert_equal_string(operands->value.pair->first->value.keyword->identifier, "haha"); | ||||
| return pass; | return pass; | ||||
| @@ -128,48 +128,48 @@ testresult test_parse_atom() { | |||||
| "sym +"; // symbols | "sym +"; // symbols | ||||
| // test numbers | // test numbers | ||||
| Ast_Node* result = Parser::parse_atom(string, &index_in_text); | |||||
| Lisp_Object* result = Parser::parse_atom(string, &index_in_text); | |||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 123); | assert_equal_double(result->value.number->value, 123); | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, -1.23e-2); | assert_equal_double(result->value.number->value, -1.23e-2); | ||||
| // test strings | // test strings | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::String); | |||||
| assert_equal_type(result, Lisp_Object_Type::String); | |||||
| assert_equal_string(result->value.string->value, "asd"); | assert_equal_string(result->value.string->value, "asd"); | ||||
| // test keywords | // test keywords | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::Keyword); | |||||
| assert_equal_type(result, Lisp_Object_Type::Keyword); | |||||
| assert_equal_string(result->value.keyword->identifier, "key1"); | assert_equal_string(result->value.keyword->identifier, "key1"); | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::Keyword); | |||||
| assert_equal_type(result, Lisp_Object_Type::Keyword); | |||||
| assert_equal_string(result->value.keyword->identifier, "key:2"); | assert_equal_string(result->value.keyword->identifier, "key:2"); | ||||
| // test symbols | // test symbols | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.symbol->identifier, "sym"); | assert_equal_string(result->value.symbol->identifier, "sym"); | ||||
| ++index_in_text; | ++index_in_text; | ||||
| result = Parser::parse_atom(string, &index_in_text); | result = Parser::parse_atom(string, &index_in_text); | ||||
| assert_equal_type(result, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.symbol->identifier, "+"); | assert_equal_string(result->value.symbol->identifier, "+"); | ||||
| return pass; | return pass; | ||||
| @@ -179,28 +179,28 @@ testresult test_parse_expression() { | |||||
| int index_in_text = 0; | int index_in_text = 0; | ||||
| char string[] = "(fun + 12)"; | char string[] = "(fun + 12)"; | ||||
| Ast_Node* result = Parser::parse_expression(string, &index_in_text); | |||||
| Lisp_Object* result = Parser::parse_expression(string, &index_in_text); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); | assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.pair->first->value.symbol->identifier, "+"); | assert_equal_string(result->value.pair->first->value.symbol->identifier, "+"); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.pair->first->value.number->value, 12); | assert_equal_double(result->value.pair->first->value.number->value, 12); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| assert_equal_type(result, Ast_Node_Type::Nil); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))"; | char string2[] = "(define fun (lambda (x) (+ 5 (* x x ))))"; | ||||
| index_in_text = 0; | index_in_text = 0; | ||||
| @@ -208,21 +208,21 @@ testresult test_parse_expression() { | |||||
| result = Parser::parse_expression(string2, &index_in_text); | result = Parser::parse_expression(string2, &index_in_text); | ||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.pair->first->value.symbol->identifier, "define"); | assert_equal_string(result->value.pair->first->value.symbol->identifier, "define"); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); | assert_equal_string(result->value.pair->first->value.symbol->identifier, "fun"); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| assert_equal_type(result, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Ast_Node_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first->value.pair->first, Ast_Node_Type::Symbol); | |||||
| assert_equal_type(result, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first, Lisp_Object_Type::Pair); | |||||
| assert_equal_type(result->value.pair->first->value.pair->first, Lisp_Object_Type::Symbol); | |||||
| assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda"); | assert_equal_string(result->value.pair->first->value.pair->first->value.symbol->identifier, "lambda"); | ||||
| result = result->value.pair->rest; | result = result->value.pair->rest; | ||||
| @@ -232,12 +232,12 @@ testresult test_parse_expression() { | |||||
| testresult test_built_in_add() { | testresult test_built_in_add() { | ||||
| char exp_string[] = "(+ 10 4)"; | char exp_string[] = "(+ 10 4)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 14); | assert_equal_double(result->value.number->value, 14); | ||||
| return pass; | return pass; | ||||
| @@ -245,12 +245,12 @@ 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)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 6); | assert_equal_double(result->value.number->value, 6); | ||||
| return pass; | return pass; | ||||
| @@ -259,12 +259,12 @@ 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)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 40); | assert_equal_double(result->value.number->value, 40); | ||||
| return pass; | return pass; | ||||
| @@ -273,12 +273,12 @@ 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)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_null(error); | assert_null(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 5); | assert_equal_double(result->value.number->value, 5); | ||||
| return pass; | return pass; | ||||
| @@ -287,12 +287,12 @@ 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)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string1); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 4); | assert_equal_double(result->value.number->value, 4); | ||||
| char exp_string2[] = "(if () 4 5)"; | char exp_string2[] = "(if () 4 5)"; | ||||
| @@ -301,7 +301,7 @@ testresult test_built_in_if() { | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Number); | |||||
| assert_equal_type(result, Lisp_Object_Type::Number); | |||||
| assert_equal_double(result->value.number->value, 5); | assert_equal_double(result->value.number->value, 5); | ||||
| return pass; | return pass; | ||||
| @@ -309,12 +309,12 @@ 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)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string1); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::T); | |||||
| assert_equal_type(result, Lisp_Object_Type::T); | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(and () \"asd\" 4)"; | char exp_string2[] = "(and () \"asd\" 4)"; | ||||
| @@ -323,19 +323,19 @@ testresult test_built_in_and() { | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Nil); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| return pass; | return pass; | ||||
| } | } | ||||
| testresult test_built_in_or() { | testresult test_built_in_or() { | ||||
| char exp_string1[] = "(or \"asd\" nil)"; | char exp_string1[] = "(or \"asd\" nil)"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string1); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::T); | |||||
| assert_equal_type(result, Lisp_Object_Type::T); | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(or () ())"; | char exp_string2[] = "(or () ())"; | ||||
| @@ -344,7 +344,7 @@ testresult test_built_in_or() { | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Nil); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| return pass; | return pass; | ||||
| } | } | ||||
| @@ -352,13 +352,13 @@ testresult test_built_in_or() { | |||||
| testresult test_built_in_not() { | testresult test_built_in_not() { | ||||
| char exp_string1[] = "(not ())"; | char exp_string1[] = "(not ())"; | ||||
| Ast_Node* expression = Parser::parse_single_expression(exp_string1); | |||||
| Ast_Node* result = eval_expr(expression, create_built_ins_environment()); | |||||
| Lisp_Object* expression = Parser::parse_single_expression(exp_string1); | |||||
| Lisp_Object* result = eval_expr(expression, create_built_ins_environment()); | |||||
| // a true case | // a true case | ||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::T); | |||||
| assert_equal_type(result, Lisp_Object_Type::T); | |||||
| // a false case | // a false case | ||||
| char exp_string2[] = "(not \"asd xD\")"; | char exp_string2[] = "(not \"asd xD\")"; | ||||
| @@ -367,7 +367,7 @@ testresult test_built_in_not() { | |||||
| assert_no_error(error); | assert_no_error(error); | ||||
| assert_not_null(result); | assert_not_null(result); | ||||
| assert_equal_type(result, Ast_Node_Type::Nil); | |||||
| assert_equal_type(result, Lisp_Object_Type::Nil); | |||||
| return pass; | return pass; | ||||
| } | } | ||||