|
|
|
@ -48,8 +48,8 @@ int _interpreter_type_contains_placeholders(libab_ref* type) {
|
|
|
|
|
libab_ref temp_child;
|
|
|
|
|
libab_parsetype* parsetype = libab_ref_get(type);
|
|
|
|
|
placeholder = (parsetype->variant & LIBABACUS_TYPE_F_PLACE) != 0;
|
|
|
|
|
if(parsetype->variant & LIBABACUS_TYPE_F_PARENT) {
|
|
|
|
|
for(; index < parsetype->children.size && !placeholder; index++) {
|
|
|
|
|
if (parsetype->variant & LIBABACUS_TYPE_F_PARENT) {
|
|
|
|
|
for (; index < parsetype->children.size && !placeholder; index++) {
|
|
|
|
|
libab_ref_vec_index(&parsetype->children, index, &temp_child);
|
|
|
|
|
placeholder |= _interpreter_type_contains_placeholders(&temp_child);
|
|
|
|
|
libab_ref_free(&temp_child);
|
|
|
|
@ -58,8 +58,10 @@ int _interpreter_type_contains_placeholders(libab_ref* type) {
|
|
|
|
|
return placeholder;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_type,
|
|
|
|
|
libab_ref_trie* left_params, libab_ref_trie* right_params) {
|
|
|
|
|
libab_result _interpreter_compare_types(libab_ref* left_type,
|
|
|
|
|
libab_ref* right_type,
|
|
|
|
|
libab_ref_trie* left_params,
|
|
|
|
|
libab_ref_trie* right_params) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
int left_placeholder;
|
|
|
|
|
int right_placeholder;
|
|
|
|
@ -69,28 +71,28 @@ libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_t
|
|
|
|
|
|
|
|
|
|
left_placeholder = left->variant & LIBABACUS_TYPE_F_PLACE;
|
|
|
|
|
right_placeholder = right->variant & LIBABACUS_TYPE_F_PLACE;
|
|
|
|
|
if(left_placeholder && right_placeholder) {
|
|
|
|
|
if (left_placeholder && right_placeholder) {
|
|
|
|
|
result = LIBAB_AMBIGOUS_TYPE;
|
|
|
|
|
} else {
|
|
|
|
|
if(left_placeholder) {
|
|
|
|
|
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);
|
|
|
|
|
if(left == NULL) {
|
|
|
|
|
if(!_interpreter_type_contains_placeholders(right_type)) {
|
|
|
|
|
if (left == NULL) {
|
|
|
|
|
if (!_interpreter_type_contains_placeholders(right_type)) {
|
|
|
|
|
result = libab_ref_trie_put(left_params, name, right_type);
|
|
|
|
|
} else {
|
|
|
|
|
result = LIBAB_AMBIGOUS_TYPE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else if(right_placeholder) {
|
|
|
|
|
} 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);
|
|
|
|
|
if(right == NULL) {
|
|
|
|
|
if(!_interpreter_type_contains_placeholders(left_type)) {
|
|
|
|
|
if (right == NULL) {
|
|
|
|
|
if (!_interpreter_type_contains_placeholders(left_type)) {
|
|
|
|
|
result = libab_ref_trie_put(right_params, name, left_type);
|
|
|
|
|
} else {
|
|
|
|
|
result = LIBAB_AMBIGOUS_TYPE;
|
|
|
|
@ -98,21 +100,31 @@ libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_t
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(left != NULL && right != NULL) {
|
|
|
|
|
if (left != NULL && right != NULL) {
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
libab_ref temp_left;
|
|
|
|
|
libab_ref temp_right;
|
|
|
|
|
result = (left->data_u.base == right->data_u.base) ? LIBAB_SUCCESS : LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
if(result == LIBAB_SUCCESS &&
|
|
|
|
|
(left->variant & LIBABACUS_TYPE_F_PARENT || right->variant & LIBABACUS_TYPE_F_PARENT)) {
|
|
|
|
|
result = (left->variant & right->variant & LIBABACUS_TYPE_F_PARENT) ? LIBAB_SUCCESS : LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = (left->children.size == right->children.size) ? LIBAB_SUCCESS : LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
result = (left->data_u.base == right->data_u.base)
|
|
|
|
|
? LIBAB_SUCCESS
|
|
|
|
|
: LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
if (result == LIBAB_SUCCESS &&
|
|
|
|
|
(left->variant & LIBABACUS_TYPE_F_PARENT ||
|
|
|
|
|
right->variant & LIBABACUS_TYPE_F_PARENT)) {
|
|
|
|
|
result =
|
|
|
|
|
(left->variant & right->variant & LIBABACUS_TYPE_F_PARENT)
|
|
|
|
|
? LIBAB_SUCCESS
|
|
|
|
|
: LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = (left->children.size == right->children.size)
|
|
|
|
|
? LIBAB_SUCCESS
|
|
|
|
|
: LIBAB_MISMATCHED_TYPE;
|
|
|
|
|
}
|
|
|
|
|
for(; index < left->children.size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
for (; index < left->children.size && result == LIBAB_SUCCESS;
|
|
|
|
|
index++) {
|
|
|
|
|
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);
|
|
|
|
|
result = _interpreter_compare_types(
|
|
|
|
|
&temp_left, &temp_right, left_params, right_params);
|
|
|
|
|
libab_ref_free(&temp_left);
|
|
|
|
|
libab_ref_free(&temp_right);
|
|
|
|
|
}
|
|
|
|
@ -128,30 +140,34 @@ void _free_parsetype(void* parsetype) {
|
|
|
|
|
free(parsetype);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_copy_resolved_type(libab_ref* type, libab_ref_trie* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
|
|
|
|
libab_ref_trie* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_parsetype* copy;
|
|
|
|
|
libab_parsetype* original;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
} else if((copy = malloc(sizeof(*copy)))) {
|
|
|
|
|
} else if ((copy = malloc(sizeof(*copy)))) {
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
copy->variant = original->variant;
|
|
|
|
|
copy->data_u.base = original->data_u.base;
|
|
|
|
|
if(copy->variant & LIBABACUS_TYPE_F_PARENT) {
|
|
|
|
|
if (copy->variant & LIBABACUS_TYPE_F_PARENT) {
|
|
|
|
|
libab_ref child_copy;
|
|
|
|
|
libab_ref temp_child;
|
|
|
|
|
result = libab_ref_vec_init(©->children);
|
|
|
|
|
for(; index < original->children.size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
for (; index < original->children.size && result == LIBAB_SUCCESS;
|
|
|
|
|
index++) {
|
|
|
|
|
libab_ref_vec_index(&original->children, index, &temp_child);
|
|
|
|
|
result = _interpreter_copy_resolved_type(&temp_child, params, &child_copy);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_copy_resolved_type(&temp_child, params,
|
|
|
|
|
&child_copy);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(©->children, &child_copy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_parsetype_free(copy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -159,9 +175,9 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type, libab_ref_trie* pa
|
|
|
|
|
libab_ref_free(&temp_child);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_new(into, copy, _free_parsetype);
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
_free_parsetype(copy);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -170,16 +186,18 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type, libab_ref_trie* pa
|
|
|
|
|
result = LIBAB_MALLOC;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_resolve_type_params(libab_ref* type, libab_ref_trie* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_resolve_type_params(libab_ref* type,
|
|
|
|
|
libab_ref_trie* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
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);
|
|
|
|
|
} else {
|
|
|
|
|
libab_ref_copy(type, into);
|
|
|
|
@ -188,7 +206,8 @@ libab_result _interpreter_resolve_type_params(libab_ref* type, libab_ref_trie* p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_check_types(struct interpreter_state* state,
|
|
|
|
|
libab_ref_vec* reference_types, libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* reference_types,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* types) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref_trie function_params;
|
|
|
|
@ -204,23 +223,25 @@ libab_result _interpreter_check_types(struct interpreter_state* state,
|
|
|
|
|
libab_ref* right_temp;
|
|
|
|
|
libab_ref produced_type;
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
for(; index < params->size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
for (; index < params->size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
libab_ref_trie_init(&child_params);
|
|
|
|
|
|
|
|
|
|
libab_ref_vec_index(reference_types, index, &left_temp);
|
|
|
|
|
libab_ref_vec_index(params, index, &right_value_temp);
|
|
|
|
|
right_temp = &((libab_value*) libab_ref_get(&right_value_temp))->type;
|
|
|
|
|
result = _interpreter_compare_types(&left_temp,
|
|
|
|
|
right_temp, &function_params, &child_params);
|
|
|
|
|
right_temp =
|
|
|
|
|
&((libab_value*)libab_ref_get(&right_value_temp))->type;
|
|
|
|
|
result = _interpreter_compare_types(
|
|
|
|
|
&left_temp, right_temp, &function_params, &child_params);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_resolve_type_params(right_temp, &child_params, &produced_type);
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_resolve_type_params(
|
|
|
|
|
right_temp, &child_params, &produced_type);
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_free(&produced_type);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(types, &produced_type);
|
|
|
|
|
libab_ref_free(&produced_type);
|
|
|
|
|
}
|
|
|
|
@ -232,7 +253,7 @@ libab_result _interpreter_check_types(struct interpreter_state* state,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_clear(types);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -240,8 +261,10 @@ libab_result _interpreter_check_types(struct interpreter_state* state,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_find_match(struct interpreter_state* state,
|
|
|
|
|
libab_function_list* function_values, libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* new_types, libab_ref* match, int partial) {
|
|
|
|
|
libab_function_list* function_values,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* new_types, libab_ref* match,
|
|
|
|
|
int partial) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
size_t list_size = libab_function_list_size(function_values);
|
|
|
|
@ -253,34 +276,38 @@ libab_result _interpreter_find_match(struct interpreter_state* state,
|
|
|
|
|
libab_ref_null(match);
|
|
|
|
|
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);
|
|
|
|
|
temp_function_type = libab_ref_get(&((libab_value*) libab_ref_get(&temp_function_value))->type);
|
|
|
|
|
temp_function_type = libab_ref_get(
|
|
|
|
|
&((libab_value*)libab_ref_get(&temp_function_value))->type);
|
|
|
|
|
|
|
|
|
|
if(((temp_function_type->children.size == params->size + 1) && !partial) ||
|
|
|
|
|
((temp_function_type->children.size > params->size + 1) && partial)) {
|
|
|
|
|
if (((temp_function_type->children.size == params->size + 1) &&
|
|
|
|
|
!partial) ||
|
|
|
|
|
((temp_function_type->children.size > params->size + 1) &&
|
|
|
|
|
partial)) {
|
|
|
|
|
/* We found a function that has the correct number of parameters. */
|
|
|
|
|
result = _interpreter_check_types(state, &temp_function_type->children, params, &temp_new_types);
|
|
|
|
|
if(result == LIBAB_MISMATCHED_TYPE) {
|
|
|
|
|
result = _interpreter_check_types(
|
|
|
|
|
state, &temp_function_type->children, params, &temp_new_types);
|
|
|
|
|
if (result == LIBAB_MISMATCHED_TYPE) {
|
|
|
|
|
/* Mismatch is OK. */
|
|
|
|
|
result = LIBAB_SUCCESS;
|
|
|
|
|
} else if(result == LIBAB_SUCCESS) {
|
|
|
|
|
} else if (result == LIBAB_SUCCESS) {
|
|
|
|
|
/* Function matched; now, check for other matching calls.
|
|
|
|
|
* More than one matching calls = ambigous call. */
|
|
|
|
|
if(!found_match) {
|
|
|
|
|
/* We haven't found a match previously. Copy data into new_types,
|
|
|
|
|
* and use new memory for temp list. */
|
|
|
|
|
if (!found_match) {
|
|
|
|
|
/* We haven't found a match previously. Copy data into
|
|
|
|
|
* new_types, and use new memory for temp list. */
|
|
|
|
|
found_match = 1;
|
|
|
|
|
*new_types = temp_new_types;
|
|
|
|
|
libab_ref_free(match);
|
|
|
|
|
libab_ref_copy(&temp_function_value, match);
|
|
|
|
|
result = libab_ref_vec_init(&temp_new_types);
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_free(new_types);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* We've found a match previously. So, new_types are initialized,
|
|
|
|
|
* and the call is ambigous. Free all data. */
|
|
|
|
|
/* We've found a match previously. So, new_types are
|
|
|
|
|
* initialized, and the call is ambigous. Free all data. */
|
|
|
|
|
libab_ref_vec_free(new_types);
|
|
|
|
|
libab_ref_vec_free(&temp_new_types);
|
|
|
|
|
result = LIBAB_AMBIGOUS_CALL;
|
|
|
|
@ -288,16 +315,17 @@ libab_result _interpreter_find_match(struct interpreter_state* state,
|
|
|
|
|
} else {
|
|
|
|
|
/* Something bad happened. Free data as best as we can. */
|
|
|
|
|
libab_ref_vec_free(&temp_new_types);
|
|
|
|
|
if(found_match) libab_ref_vec_free(new_types);
|
|
|
|
|
if (found_match)
|
|
|
|
|
libab_ref_vec_free(new_types);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_free(&temp_function_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_free(&temp_new_types);
|
|
|
|
|
if(!found_match)
|
|
|
|
|
if (!found_match)
|
|
|
|
|
libab_ref_null(match);
|
|
|
|
|
} else {
|
|
|
|
|
libab_ref_free(match);
|
|
|
|
@ -307,13 +335,14 @@ libab_result _interpreter_find_match(struct interpreter_state* state,
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_cast_param(libab_ref* param, libab_ref* type, libab_ref_vec* into) {
|
|
|
|
|
libab_result _interpreter_cast_param(libab_ref* param, libab_ref* type,
|
|
|
|
|
libab_ref_vec* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_value* old_value = libab_ref_get(param);
|
|
|
|
|
libab_ref new_value;
|
|
|
|
|
|
|
|
|
|
result = libab_create_value_ref(&new_value, &old_value->data, type);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(into, &new_value);
|
|
|
|
|
}
|
|
|
|
|
libab_ref_free(&new_value);
|
|
|
|
@ -321,13 +350,15 @@ libab_result _interpreter_cast_param(libab_ref* param, libab_ref* type, libab_re
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_cast_params(libab_ref_vec* params, libab_ref_vec* new_types, libab_ref_vec* into) {
|
|
|
|
|
libab_result _interpreter_cast_params(libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* new_types,
|
|
|
|
|
libab_ref_vec* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
libab_ref temp_param;
|
|
|
|
|
libab_ref temp_type;
|
|
|
|
|
|
|
|
|
|
for(; index < params->size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
for (; index < params->size && result == LIBAB_SUCCESS; index++) {
|
|
|
|
|
libab_ref_vec_index(params, index, &temp_param);
|
|
|
|
|
libab_ref_vec_index(new_types, index, &temp_type);
|
|
|
|
|
|
|
|
|
@ -340,14 +371,17 @@ libab_result _interpreter_cast_params(libab_ref_vec* params, libab_ref_vec* new_
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_call_tree(libab_tree* tree, libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_call_tree(libab_tree* tree, libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_call_behavior(libab_behavior* behavior, libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_call_behavior(libab_behavior* behavior,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
if(behavior->variant == BIMPL_INTERNAL) {
|
|
|
|
|
if (behavior->variant == BIMPL_INTERNAL) {
|
|
|
|
|
result = behavior->data_u.internal(params, into);
|
|
|
|
|
} else {
|
|
|
|
|
result = _interpreter_call_tree(behavior->data_u.tree, params, into);
|
|
|
|
@ -355,7 +389,9 @@ libab_result _interpreter_call_behavior(libab_behavior* behavior, libab_ref_vec*
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_perform_function_call(libab_value* to_call, libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_perform_function_call(libab_value* to_call,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_function* function;
|
|
|
|
|
libab_parsetype* function_type;
|
|
|
|
@ -363,16 +399,15 @@ libab_result _interpreter_perform_function_call(libab_value* to_call, libab_ref_
|
|
|
|
|
function = libab_ref_get(&to_call->data);
|
|
|
|
|
function_type = libab_ref_get(&to_call->type);
|
|
|
|
|
new_params = params->size - function->params.size;
|
|
|
|
|
if(function_type->children.size - new_params == 1) {
|
|
|
|
|
if (function_type->children.size - new_params == 1) {
|
|
|
|
|
_interpreter_call_behavior(&function->behavior, params, into);
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_cast_and_perform_function_call(libab_ref* to_call,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* new_types,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_cast_and_perform_function_call(
|
|
|
|
|
libab_ref* to_call, libab_ref_vec* params, libab_ref_vec* new_types,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result;
|
|
|
|
|
libab_ref_vec new_params;
|
|
|
|
|
libab_value* function_value;
|
|
|
|
@ -381,11 +416,12 @@ libab_result _interpreter_cast_and_perform_function_call(libab_ref* to_call,
|
|
|
|
|
function_value = libab_ref_get(to_call);
|
|
|
|
|
function = libab_ref_get(&function_value->data);
|
|
|
|
|
result = libab_ref_vec_init_copy(&new_params, &function->params);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_cast_params(params, new_types, &new_params);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_perform_function_call(function_value, &new_params, into);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_perform_function_call(function_value,
|
|
|
|
|
&new_params, into);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_vec_free(&new_params);
|
|
|
|
@ -394,26 +430,31 @@ libab_result _interpreter_cast_and_perform_function_call(libab_ref* to_call,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
|
|
|
|
libab_function_list* list, libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_function_list* list,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref_vec new_types;
|
|
|
|
|
libab_ref to_call;
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
|
|
|
|
|
result = _interpreter_find_match(state, list, params, &new_types, &to_call, 0);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if(libab_ref_get(&to_call) == NULL) {
|
|
|
|
|
result = _interpreter_find_match(state, list, params, &new_types, &to_call, 1);
|
|
|
|
|
result =
|
|
|
|
|
_interpreter_find_match(state, list, params, &new_types, &to_call, 0);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
if (libab_ref_get(&to_call) == NULL) {
|
|
|
|
|
result = _interpreter_find_match(state, list, params, &new_types,
|
|
|
|
|
&to_call, 1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS && libab_ref_get(&to_call) == NULL) {
|
|
|
|
|
if (result == LIBAB_SUCCESS && libab_ref_get(&to_call) == NULL) {
|
|
|
|
|
result = LIBAB_BAD_CALL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_free(into);
|
|
|
|
|
result = _interpreter_cast_and_perform_function_call(&to_call, params, &new_types, into);
|
|
|
|
|
result = _interpreter_cast_and_perform_function_call(&to_call, params,
|
|
|
|
|
&new_types, into);
|
|
|
|
|
libab_ref_vec_free(&new_types);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -422,7 +463,10 @@ libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_call_function(struct interpreter_state* state, libab_ref* function, libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_call_function(struct interpreter_state* state,
|
|
|
|
|
libab_ref* function,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref_vec temp_new_types;
|
|
|
|
|
libab_value* function_value;
|
|
|
|
@ -433,12 +477,14 @@ libab_result _interpreter_call_function(struct interpreter_state* state, libab_r
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
|
|
|
|
|
result = libab_ref_vec_init(&temp_new_types);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_check_types(state, &function_type->children, params, &temp_new_types);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_check_types(state, &function_type->children,
|
|
|
|
|
params, &temp_new_types);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_free(into);
|
|
|
|
|
result = _interpreter_cast_and_perform_function_call(function, params, &temp_new_types, into);
|
|
|
|
|
result = _interpreter_cast_and_perform_function_call(
|
|
|
|
|
function, params, &temp_new_types, into);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_vec_free(&temp_new_types);
|
|
|
|
@ -447,8 +493,9 @@ libab_result _interpreter_call_function(struct interpreter_state* state, libab_r
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_try_call(struct interpreter_state* state, libab_ref* value,
|
|
|
|
|
libab_ref_vec* params, libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_try_call(struct interpreter_state* state,
|
|
|
|
|
libab_ref* value, libab_ref_vec* params,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_value* callee_value;
|
|
|
|
|
libab_parsetype* callee_type;
|
|
|
|
@ -457,12 +504,11 @@ libab_result _interpreter_try_call(struct interpreter_state* state, libab_ref* v
|
|
|
|
|
callee_type = libab_ref_get(&callee_value->type);
|
|
|
|
|
callee_basetype = callee_type->data_u.base;
|
|
|
|
|
|
|
|
|
|
if(callee_basetype == libab_get_basetype_function_list(state->ab)) {
|
|
|
|
|
result = _interpreter_call_function_list(state,
|
|
|
|
|
libab_ref_get(&callee_value->data), params, into);
|
|
|
|
|
} else if(callee_basetype == libab_get_basetype_function(state->ab)) {
|
|
|
|
|
result = _interpreter_call_function(state,
|
|
|
|
|
value, params, into);
|
|
|
|
|
if (callee_basetype == libab_get_basetype_function_list(state->ab)) {
|
|
|
|
|
result = _interpreter_call_function_list(
|
|
|
|
|
state, libab_ref_get(&callee_value->data), params, into);
|
|
|
|
|
} else if (callee_basetype == libab_get_basetype_function(state->ab)) {
|
|
|
|
|
result = _interpreter_call_function(state, value, params, into);
|
|
|
|
|
} else {
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
result = LIBAB_BAD_CALL;
|
|
|
|
@ -471,21 +517,21 @@ libab_result _interpreter_try_call(struct interpreter_state* state, libab_ref* v
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_cast_and_perform_operator_call(libab_operator* to_call,
|
|
|
|
|
libab_ref_vec* params,
|
|
|
|
|
libab_ref_vec* new_types,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result _interpreter_cast_and_perform_operator_call(
|
|
|
|
|
libab_operator* to_call, libab_ref_vec* params, libab_ref_vec* new_types,
|
|
|
|
|
libab_ref* into) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref_vec new_params;
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
|
|
|
|
|
result = libab_ref_vec_init(&new_params);
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_cast_params(params, new_types, &new_params);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_free(into);
|
|
|
|
|
result = _interpreter_call_behavior(&to_call->behavior, params, into);
|
|
|
|
|
result =
|
|
|
|
|
_interpreter_call_behavior(&to_call->behavior, params, into);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_vec_free(&new_params);
|
|
|
|
@ -499,7 +545,9 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|
|
|
|
int force_scope);
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|
|
|
|
libab_operator* to_call, libab_ref* into, libab_ref* scope, ...) {
|
|
|
|
|
libab_operator* to_call,
|
|
|
|
|
libab_ref* into, libab_ref* scope,
|
|
|
|
|
...) {
|
|
|
|
|
va_list args;
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref_vec params;
|
|
|
|
@ -511,38 +559,42 @@ libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|
|
|
|
operator_type = libab_ref_get(&to_call->type);
|
|
|
|
|
result = libab_ref_vec_init(¶ms);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_init(&new_types);
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_free(¶ms);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_run(state, va_arg(args, libab_tree*), &temp, scope, 0);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result =
|
|
|
|
|
_interpreter_run(state, va_arg(args, libab_tree*), &temp, scope, 0);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(¶ms, &temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_free(&temp);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS && to_call->variant == OPERATOR_INFIX) {
|
|
|
|
|
result = _interpreter_run(state, va_arg(args, libab_tree*), &temp, scope, 0);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS && to_call->variant == OPERATOR_INFIX) {
|
|
|
|
|
result = _interpreter_run(state, va_arg(args, libab_tree*), &temp,
|
|
|
|
|
scope, 0);
|
|
|
|
|
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(¶ms, &temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_free(&temp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_check_types(state, &operator_type->children, ¶ms, &new_types);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_check_types(state, &operator_type->children,
|
|
|
|
|
¶ms, &new_types);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_cast_and_perform_operator_call(to_call, ¶ms, &new_types, into);
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_cast_and_perform_operator_call(
|
|
|
|
|
to_call, ¶ms, &new_types, into);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_ref_vec_free(¶ms);
|
|
|
|
@ -554,8 +606,8 @@ libab_result _interpreter_call_operator(struct interpreter_state* state,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
libab_result _interpreter_run_function_node(struct interpreter_state* state,
|
|
|
|
|
libab_tree* tree,
|
|
|
|
|
libab_ref* into, libab_ref* scope) {
|
|
|
|
|
libab_tree* tree, libab_ref* into,
|
|
|
|
|
libab_ref* scope) {
|
|
|
|
|
libab_result result = LIBAB_SUCCESS;
|
|
|
|
|
libab_ref param;
|
|
|
|
|
libab_ref callee;
|
|
|
|
@ -565,32 +617,32 @@ libab_result _interpreter_run_function_node(struct interpreter_state* state,
|
|
|
|
|
|
|
|
|
|
libab_ref_null(¶m);
|
|
|
|
|
result = libab_ref_vec_init(¶ms);
|
|
|
|
|
for(; count < tree->children.size - 1 && result == LIBAB_SUCCESS; count++) {
|
|
|
|
|
for (; count < tree->children.size - 1 && result == LIBAB_SUCCESS;
|
|
|
|
|
count++) {
|
|
|
|
|
libab_ref_free(¶m);
|
|
|
|
|
child = vec_index(&tree->children, count);
|
|
|
|
|
result = _interpreter_run(state, child, ¶m, scope, 0);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = libab_ref_vec_insert(¶ms, ¶m);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_free(¶ms);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
libab_ref_free(¶m);
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_run(state,
|
|
|
|
|
vec_index(&tree->children,
|
|
|
|
|
tree->children.size - 1),
|
|
|
|
|
&callee, scope, 0);
|
|
|
|
|
if(result != LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_run(
|
|
|
|
|
state, vec_index(&tree->children, tree->children.size - 1), &callee,
|
|
|
|
|
scope, 0);
|
|
|
|
|
if (result != LIBAB_SUCCESS) {
|
|
|
|
|
libab_ref_vec_free(¶ms);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(result == LIBAB_SUCCESS) {
|
|
|
|
|
if (result == LIBAB_SUCCESS) {
|
|
|
|
|
result = _interpreter_try_call(state, &callee, ¶ms, into);
|
|
|
|
|
libab_ref_free(&callee);
|
|
|
|
|
libab_ref_vec_free(¶ms);
|
|
|
|
@ -629,25 +681,29 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
|
|
|
|
|
} else if (tree->variant == TREE_VOID) {
|
|
|
|
|
libab_ref_null(into);
|
|
|
|
|
} else if (tree->variant == TREE_ID) {
|
|
|
|
|
libab_table_search_value(libab_ref_get(scope), tree->string_value, into);
|
|
|
|
|
if(libab_ref_get(into) == NULL) {
|
|
|
|
|
libab_table_search_value(libab_ref_get(scope), tree->string_value,
|
|
|
|
|
into);
|
|
|
|
|
if (libab_ref_get(into) == NULL) {
|
|
|
|
|
result = LIBAB_UNEXPECTED;
|
|
|
|
|
}
|
|
|
|
|
} else if (tree->variant == TREE_CALL) {
|
|
|
|
|
result = _interpreter_run_function_node(state, tree, into, scope);
|
|
|
|
|
} else if (tree->variant == TREE_OP) {
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(libab_ref_get(scope), tree->string_value, OPERATOR_INFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0),
|
|
|
|
|
vec_index(&tree->children, 1));
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(
|
|
|
|
|
libab_ref_get(scope), tree->string_value, OPERATOR_INFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0),
|
|
|
|
|
vec_index(&tree->children, 1));
|
|
|
|
|
} else if (tree->variant == TREE_PREFIX_OP) {
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(libab_ref_get(scope), tree->string_value, OPERATOR_PREFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0));
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(
|
|
|
|
|
libab_ref_get(scope), tree->string_value, OPERATOR_PREFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0));
|
|
|
|
|
} else if (tree->variant == TREE_POSTFIX_OP) {
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(libab_ref_get(scope), tree->string_value, OPERATOR_POSTFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0));
|
|
|
|
|
libab_operator* to_call = libab_table_search_operator(
|
|
|
|
|
libab_ref_get(scope), tree->string_value, OPERATOR_POSTFIX);
|
|
|
|
|
result = _interpreter_call_operator(state, to_call, into, scope,
|
|
|
|
|
vec_index(&tree->children, 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needs_scope) {
|
|
|
|
|