From 763cfdd7a3a1026992aaea8b3628016d588250f6 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Sun, 17 Jun 2018 00:12:51 -0700 Subject: [PATCH] Search scope as well as type map for type parameters. --- src/interpreter.c | 62 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/src/interpreter.c b/src/interpreter.c index 271df85..b215e11 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -74,6 +74,28 @@ int _interpreter_type_contains_placeholders(libab_ref* type) { return placeholder; } +void _interpreter_search_type_param(libab_ref_trie* params, + libab_ref* scope, + const char* name, + libab_ref* into) { + libab_ref_trie_get(params, name, into); + + if(libab_ref_get(into) == NULL) { + libab_table_search_type_param(libab_ref_get(scope), name, into); + } +} + +libab_parsetype* _interpreter_search_type_param_raw(libab_ref_trie* params, + libab_ref* scope, + const char* name) { + libab_ref into; + libab_parsetype* to_return; + _interpreter_search_type_param(params, scope, name, &into); + to_return = libab_ref_get(&into); + libab_ref_free(&into); + return to_return; +} + /** * Compares the two types, filling in any missing type parameters * in the respective type tries. @@ -86,13 +108,13 @@ int _interpreter_type_contains_placeholders(libab_ref* type) { libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_type, libab_ref_trie* left_params, - libab_ref_trie* right_params) { + libab_ref_trie* right_params, + libab_ref* scope) { libab_result result = LIBAB_SUCCESS; int left_placeholder; int right_placeholder; libab_parsetype* left = libab_ref_get(left_type); libab_parsetype* right = libab_ref_get(right_type); - libab_ref param_type; left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE; right_placeholder = right->variant & LIBABACUS_TYPE_F_PLACE; @@ -101,9 +123,7 @@ libab_result _interpreter_compare_types(libab_ref* left_type, } else { if (left_placeholder) { const char* name = left->data_u.name; - libab_ref_trie_get(left_params, name, ¶m_type); - left = libab_ref_get(¶m_type); - libab_ref_free(¶m_type); + left = _interpreter_search_type_param_raw(left_params, scope, name); if (left == NULL) { if (!_interpreter_type_contains_placeholders(right_type)) { result = libab_ref_trie_put(left_params, name, right_type); @@ -113,9 +133,7 @@ libab_result _interpreter_compare_types(libab_ref* left_type, } } else if (right_placeholder) { const char* name = right->data_u.name; - libab_ref_trie_get(right_params, name, ¶m_type); - right = libab_ref_get(¶m_type); - libab_ref_free(¶m_type); + right = _interpreter_search_type_param_raw(right_params, scope, name); if (right == NULL) { if (!_interpreter_type_contains_placeholders(left_type)) { result = libab_ref_trie_put(right_params, name, left_type); @@ -149,7 +167,7 @@ libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref_vec_index(&left->children, index, &temp_left); libab_ref_vec_index(&right->children, index, &temp_right); result = _interpreter_compare_types( - &temp_left, &temp_right, left_params, right_params); + &temp_left, &temp_right, left_params, right_params, scope); libab_ref_free(&temp_left); libab_ref_free(&temp_right); } @@ -170,6 +188,7 @@ libab_result _interpreter_compare_types(libab_ref* left_type, */ libab_result _interpreter_copy_resolved_type(libab_ref* type, libab_ref_trie* params, + libab_ref* scope, libab_ref* into) { libab_result result = LIBAB_SUCCESS; libab_parsetype* copy; @@ -177,7 +196,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type, original = libab_ref_get(type); if (original->variant & LIBABACUS_TYPE_F_PLACE) { - libab_ref_trie_get(params, original->data_u.name, into); + _interpreter_search_type_param(params, scope, original->data_u.name, into); } else if ((copy = malloc(sizeof(*copy)))) { size_t index = 0; copy->variant = original->variant; @@ -190,7 +209,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type, index++) { libab_ref_vec_index(&original->children, index, &temp_child); result = _interpreter_copy_resolved_type(&temp_child, params, - &child_copy); + scope, &child_copy); if (result == LIBAB_SUCCESS) { result = libab_ref_vec_insert(©->children, &child_copy); } @@ -230,10 +249,11 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type, */ libab_result _interpreter_resolve_type_params(libab_ref* type, libab_ref_trie* params, + libab_ref* scope, libab_ref* into) { libab_result result = LIBAB_SUCCESS; if (_interpreter_type_contains_placeholders(type)) { - result = _interpreter_copy_resolved_type(type, params, into); + result = _interpreter_copy_resolved_type(type, params, scope, into); } else { libab_ref_copy(type, into); } @@ -251,6 +271,7 @@ libab_result _interpreter_resolve_type_params(libab_ref* type, libab_result _interpreter_check_types(libab_ref_vec* reference_types, libab_ref_vec* params, libab_ref_vec* types, + libab_ref* scope, libab_ref_trie* param_map) { libab_result result = LIBAB_SUCCESS; libab_ref_trie function_params; @@ -274,11 +295,11 @@ libab_result _interpreter_check_types(libab_ref_vec* reference_types, right_temp = &((libab_value*)libab_ref_get(&right_value_temp))->type; result = _interpreter_compare_types( - &left_temp, right_temp, &function_params, &child_params); + &left_temp, right_temp, &function_params, &child_params, scope); if (result == LIBAB_SUCCESS) { result = _interpreter_resolve_type_params( - right_temp, &child_params, &produced_type); + right_temp, &child_params, scope, &produced_type); if (result != LIBAB_SUCCESS) { libab_ref_free(&produced_type); } @@ -329,15 +350,18 @@ libab_result _interpreter_find_match(libab_function_list* function_values, libab_ref_trie temp_param_map; libab_ref_vec temp_new_types; libab_ref temp_function_value; + libab_value* temp_value; libab_parsetype* temp_function_type; + libab_function* temp_function; libab_ref_null(match); result = libab_ref_vec_init(&temp_new_types); for (; index < list_size && result == LIBAB_SUCCESS; index++) { libab_function_list_index(function_values, index, &temp_function_value); - temp_function_type = libab_ref_get( - &((libab_value*)libab_ref_get(&temp_function_value))->type); + temp_value = libab_ref_get(&temp_function_value); + temp_function_type = libab_ref_get(&temp_value->type); + temp_function = libab_ref_get(&temp_value->data); if (((temp_function_type->children.size == params->size + 1) && !partial) || @@ -345,7 +369,7 @@ libab_result _interpreter_find_match(libab_function_list* function_values, partial)) { /* We found a function that has the correct number of parameters. */ result = _interpreter_check_types( - &temp_function_type->children, params, &temp_new_types, &temp_param_map); + &temp_function_type->children, params, &temp_new_types, &temp_function->scope, &temp_param_map); if (result == LIBAB_MISMATCHED_TYPE) { /* Mismatch is OK. */ result = LIBAB_SUCCESS; @@ -766,15 +790,17 @@ libab_result _interpreter_call_function(struct interpreter_state* state, libab_ref_trie param_map; libab_value* function_value; libab_parsetype* function_type; + libab_function* function_instance; function_value = libab_ref_get(function); function_type = libab_ref_get(&function_value->type); + function_instance = libab_ref_get(&function_value->data); libab_ref_null(into); result = libab_ref_vec_init(&temp_new_types); if (result == LIBAB_SUCCESS) { result = _interpreter_check_types(&function_type->children, - params, &temp_new_types, ¶m_map); + params, &temp_new_types, &function_instance->scope, ¶m_map); if (result == LIBAB_SUCCESS) { libab_ref_free(into);