Finish the draft implementation.
This commit is contained in:
parent
070dc179ff
commit
1cd7f3f45a
|
@ -9,7 +9,7 @@
|
||||||
* A function pointer that is called
|
* A function pointer that is called
|
||||||
* to execute a certain type of function.
|
* to execute a certain type of function.
|
||||||
*/
|
*/
|
||||||
typedef void (*libab_function_ptr)();
|
typedef libab_result (*libab_function_ptr)(libab_ref_vec*, libab_ref*);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The variant of the operator that
|
* The variant of the operator that
|
||||||
|
@ -87,6 +87,11 @@ struct libab_function_s {
|
||||||
* The behavior of this function.
|
* The behavior of this function.
|
||||||
*/
|
*/
|
||||||
struct libab_behavior_s behavior;
|
struct libab_behavior_s behavior;
|
||||||
|
/**
|
||||||
|
* The parameters given to this function
|
||||||
|
* if it was created via partial application.
|
||||||
|
*/
|
||||||
|
libab_ref_vec params;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum libab_operator_variant_e libab_operator_variant;
|
typedef enum libab_operator_variant_e libab_operator_variant;
|
||||||
|
|
|
@ -32,7 +32,9 @@ void libab_operator_free(libab_operator* op) {
|
||||||
libab_behavior_free(&op->behavior);
|
libab_behavior_free(&op->behavior);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _function_init(libab_function* function) { return LIBAB_SUCCESS; }
|
libab_result _function_init(libab_function* function) {
|
||||||
|
return libab_ref_vec_init(&function->params);
|
||||||
|
}
|
||||||
libab_result libab_function_init_internal(libab_function* function,
|
libab_result libab_function_init_internal(libab_function* function,
|
||||||
libab_function_ptr fun) {
|
libab_function_ptr fun) {
|
||||||
libab_result result = _function_init(function);
|
libab_result result = _function_init(function);
|
||||||
|
@ -47,4 +49,5 @@ libab_result libab_function_init_tree(libab_function* function,
|
||||||
}
|
}
|
||||||
void libab_function_free(libab_function* fun) {
|
void libab_function_free(libab_function* fun) {
|
||||||
libab_behavior_free(&fun->behavior);
|
libab_behavior_free(&fun->behavior);
|
||||||
|
libab_ref_vec_free(&fun->params);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,20 @@ libab_result _interpreter_create_num_val(struct interpreter_state* state,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _interpreter_type_contains_placeholders(libab_ref* type) {
|
||||||
|
size_t index = 0;
|
||||||
|
int placeholder;
|
||||||
|
libab_ref temp_child;
|
||||||
|
libab_parsetype* parsetype = libab_ref_get(type);
|
||||||
|
placeholder = (parsetype->variant & LIBABACUS_TYPE_F_PLACE) != 0;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return placeholder;
|
||||||
|
}
|
||||||
|
|
||||||
libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_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* left_params, libab_ref_trie* right_params) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
@ -61,15 +75,25 @@ libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_t
|
||||||
libab_ref_trie_get(left_params, name, ¶m_type);
|
libab_ref_trie_get(left_params, name, ¶m_type);
|
||||||
left = libab_ref_get(¶m_type);
|
left = libab_ref_get(¶m_type);
|
||||||
libab_ref_free(¶m_type);
|
libab_ref_free(¶m_type);
|
||||||
if(left == NULL)
|
if(left == NULL) {
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_AMBIGOUS_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, ¶m_type);
|
libab_ref_trie_get(right_params, name, ¶m_type);
|
||||||
right = libab_ref_get(¶m_type);
|
right = libab_ref_get(¶m_type);
|
||||||
libab_ref_free(¶m_type);
|
libab_ref_free(¶m_type);
|
||||||
if(right == NULL)
|
if(right == NULL) {
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
result = LIBAB_AMBIGOUS_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(left != NULL && right != NULL) {
|
if(left != NULL && right != NULL) {
|
||||||
|
@ -97,8 +121,67 @@ libab_result _interpreter_compare_types(libab_ref* left_type, libab_ref* right_t
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _free_parsetype(void* parsetype) {
|
||||||
|
libab_parsetype_free(parsetype);
|
||||||
|
free(parsetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
libab_ref_trie_get(params, original->data_u.name, into);
|
||||||
|
} 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) {
|
||||||
|
libab_ref child_copy;
|
||||||
|
libab_ref temp_child;
|
||||||
|
result = libab_ref_vec_init(©->children);
|
||||||
|
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 = libab_ref_vec_insert(©->children, &child_copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_parsetype_free(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_ref_free(&child_copy);
|
||||||
|
libab_ref_free(&temp_child);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_new(into, copy, _free_parsetype);
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
_free_parsetype(copy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
if(_interpreter_type_contains_placeholders(type)) {
|
||||||
|
result = _interpreter_copy_resolved_type(type, params, into);
|
||||||
|
} else {
|
||||||
|
libab_ref_copy(type, into);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,16 +337,41 @@ libab_result _interpreter_cast_params(libab_ref_vec* params, libab_ref_vec* new_
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_perform_call(libab_function* to_call, 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;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
result = behavior->data_u.internal(params, into);
|
||||||
|
} else {
|
||||||
|
result = _interpreter_call_tree(behavior->data_u.tree, params, into);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
libab_result _interpreter_perform_call(libab_value* to_call, libab_ref_vec* params, libab_ref* into) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_function* function;
|
||||||
|
libab_parsetype* function_type;
|
||||||
|
size_t new_params;
|
||||||
|
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) {
|
||||||
|
_interpreter_call_behavior(&function->behavior, params, into);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
||||||
libab_function_list* list, libab_ref_vec* params) {
|
libab_function_list* list, libab_ref_vec* params, libab_ref* into) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_ref_vec new_types;
|
libab_ref_vec new_types;
|
||||||
libab_ref to_call;
|
libab_ref to_call;
|
||||||
|
libab_ref_null(into);
|
||||||
|
|
||||||
result = _interpreter_find_match(state, list, params, &new_types, &to_call, 0);
|
result = _interpreter_find_match(state, list, params, &new_types, &to_call, 0);
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
@ -280,12 +388,13 @@ libab_result _interpreter_call_function_list(struct interpreter_state* state,
|
||||||
libab_ref_vec new_params;
|
libab_ref_vec new_params;
|
||||||
libab_function* function;
|
libab_function* function;
|
||||||
function = libab_ref_get(&to_call);
|
function = libab_ref_get(&to_call);
|
||||||
/* result = libab_ref_vec_init_copy(&new_params, &function->params); */
|
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);
|
result = _interpreter_cast_params(params, &new_types, &new_params);
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = _interpreter_perform_call(function, &new_params, NULL);
|
libab_ref_free(into);
|
||||||
|
result = _interpreter_perform_call(libab_ref_get(&to_call), &new_params, into);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user