Search scope as well as type map for type parameters.

This commit is contained in:
Danila Fedorin 2018-06-17 00:12:51 -07:00
parent 065554bcdf
commit 763cfdd7a3

View File

@ -74,6 +74,28 @@ int _interpreter_type_contains_placeholders(libab_ref* type) {
return placeholder; 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 * Compares the two types, filling in any missing type parameters
* in the respective type tries. * 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_result _interpreter_compare_types(libab_ref* left_type,
libab_ref* right_type, libab_ref* right_type,
libab_ref_trie* left_params, libab_ref_trie* left_params,
libab_ref_trie* right_params) { libab_ref_trie* right_params,
libab_ref* scope) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
int left_placeholder; int left_placeholder;
int right_placeholder; int right_placeholder;
libab_parsetype* left = libab_ref_get(left_type); libab_parsetype* left = libab_ref_get(left_type);
libab_parsetype* right = libab_ref_get(right_type); libab_parsetype* right = libab_ref_get(right_type);
libab_ref param_type;
left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE; left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE;
right_placeholder = right->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 { } else {
if (left_placeholder) { if (left_placeholder) {
const char* name = left->data_u.name; const char* name = left->data_u.name;
libab_ref_trie_get(left_params, name, &param_type); left = _interpreter_search_type_param_raw(left_params, scope, name);
left = libab_ref_get(&param_type);
libab_ref_free(&param_type);
if (left == NULL) { if (left == NULL) {
if (!_interpreter_type_contains_placeholders(right_type)) { if (!_interpreter_type_contains_placeholders(right_type)) {
result = libab_ref_trie_put(left_params, name, 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) { } else if (right_placeholder) {
const char* name = right->data_u.name; const char* name = right->data_u.name;
libab_ref_trie_get(right_params, name, &param_type); right = _interpreter_search_type_param_raw(right_params, scope, name);
right = libab_ref_get(&param_type);
libab_ref_free(&param_type);
if (right == NULL) { if (right == NULL) {
if (!_interpreter_type_contains_placeholders(left_type)) { if (!_interpreter_type_contains_placeholders(left_type)) {
result = libab_ref_trie_put(right_params, name, 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(&left->children, index, &temp_left);
libab_ref_vec_index(&right->children, index, &temp_right); libab_ref_vec_index(&right->children, index, &temp_right);
result = _interpreter_compare_types( 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_left);
libab_ref_free(&temp_right); 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_result _interpreter_copy_resolved_type(libab_ref* type,
libab_ref_trie* params, libab_ref_trie* params,
libab_ref* scope,
libab_ref* into) { libab_ref* into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
libab_parsetype* copy; libab_parsetype* copy;
@ -177,7 +196,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
original = libab_ref_get(type); original = libab_ref_get(type);
if (original->variant & LIBABACUS_TYPE_F_PLACE) { 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)))) { } else if ((copy = malloc(sizeof(*copy)))) {
size_t index = 0; size_t index = 0;
copy->variant = original->variant; copy->variant = original->variant;
@ -190,7 +209,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
index++) { index++) {
libab_ref_vec_index(&original->children, index, &temp_child); libab_ref_vec_index(&original->children, index, &temp_child);
result = _interpreter_copy_resolved_type(&temp_child, params, result = _interpreter_copy_resolved_type(&temp_child, params,
&child_copy); scope, &child_copy);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = libab_ref_vec_insert(&copy->children, &child_copy); result = libab_ref_vec_insert(&copy->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_result _interpreter_resolve_type_params(libab_ref* type,
libab_ref_trie* params, libab_ref_trie* params,
libab_ref* scope,
libab_ref* into) { libab_ref* into) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
if (_interpreter_type_contains_placeholders(type)) { if (_interpreter_type_contains_placeholders(type)) {
result = _interpreter_copy_resolved_type(type, params, into); result = _interpreter_copy_resolved_type(type, params, scope, into);
} else { } else {
libab_ref_copy(type, into); 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_result _interpreter_check_types(libab_ref_vec* reference_types,
libab_ref_vec* params, libab_ref_vec* params,
libab_ref_vec* types, libab_ref_vec* types,
libab_ref* scope,
libab_ref_trie* param_map) { libab_ref_trie* param_map) {
libab_result result = LIBAB_SUCCESS; libab_result result = LIBAB_SUCCESS;
libab_ref_trie function_params; libab_ref_trie function_params;
@ -274,11 +295,11 @@ libab_result _interpreter_check_types(libab_ref_vec* reference_types,
right_temp = right_temp =
&((libab_value*)libab_ref_get(&right_value_temp))->type; &((libab_value*)libab_ref_get(&right_value_temp))->type;
result = _interpreter_compare_types( 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) { if (result == LIBAB_SUCCESS) {
result = _interpreter_resolve_type_params( result = _interpreter_resolve_type_params(
right_temp, &child_params, &produced_type); right_temp, &child_params, scope, &produced_type);
if (result != LIBAB_SUCCESS) { if (result != LIBAB_SUCCESS) {
libab_ref_free(&produced_type); 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_trie temp_param_map;
libab_ref_vec temp_new_types; libab_ref_vec temp_new_types;
libab_ref temp_function_value; libab_ref temp_function_value;
libab_value* temp_value;
libab_parsetype* temp_function_type; libab_parsetype* temp_function_type;
libab_function* temp_function;
libab_ref_null(match); libab_ref_null(match);
result = libab_ref_vec_init(&temp_new_types); result = libab_ref_vec_init(&temp_new_types);
for (; index < list_size && result == LIBAB_SUCCESS; index++) { for (; index < list_size && result == LIBAB_SUCCESS; index++) {
libab_function_list_index(function_values, index, &temp_function_value); libab_function_list_index(function_values, index, &temp_function_value);
temp_function_type = libab_ref_get( temp_value = libab_ref_get(&temp_function_value);
&((libab_value*)libab_ref_get(&temp_function_value))->type); 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) && if (((temp_function_type->children.size == params->size + 1) &&
!partial) || !partial) ||
@ -345,7 +369,7 @@ libab_result _interpreter_find_match(libab_function_list* function_values,
partial)) { partial)) {
/* We found a function that has the correct number of parameters. */ /* We found a function that has the correct number of parameters. */
result = _interpreter_check_types( 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) { if (result == LIBAB_MISMATCHED_TYPE) {
/* Mismatch is OK. */ /* Mismatch is OK. */
result = LIBAB_SUCCESS; result = LIBAB_SUCCESS;
@ -766,15 +790,17 @@ libab_result _interpreter_call_function(struct interpreter_state* state,
libab_ref_trie param_map; libab_ref_trie param_map;
libab_value* function_value; libab_value* function_value;
libab_parsetype* function_type; libab_parsetype* function_type;
libab_function* function_instance;
function_value = libab_ref_get(function); function_value = libab_ref_get(function);
function_type = libab_ref_get(&function_value->type); function_type = libab_ref_get(&function_value->type);
function_instance = libab_ref_get(&function_value->data);
libab_ref_null(into); libab_ref_null(into);
result = libab_ref_vec_init(&temp_new_types); result = libab_ref_vec_init(&temp_new_types);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
result = _interpreter_check_types(&function_type->children, result = _interpreter_check_types(&function_type->children,
params, &temp_new_types, &param_map); params, &temp_new_types, &function_instance->scope, &param_map);
if (result == LIBAB_SUCCESS) { if (result == LIBAB_SUCCESS) {
libab_ref_free(into); libab_ref_free(into);