Resolve function types when they're created.
This commit is contained in:
parent
b9b6a8ec4b
commit
f83b7d169c
|
@ -55,8 +55,18 @@ libab_result libab_copy_string(char** destination, const char* source);
|
||||||
* @param to_resolve the parsetype to resolve.
|
* @param to_resolve the parsetype to resolve.
|
||||||
* @param scope the scope to use for resolving the type info.
|
* @param scope the scope to use for resolving the type info.
|
||||||
*/
|
*/
|
||||||
libab_result libab_resolve_parsetype(libab_parsetype* to_resolve,
|
libab_result libab_resolve_parsetype_inplace(libab_parsetype* to_resolve,
|
||||||
libab_table* scope);
|
libab_table* scope);
|
||||||
|
/**
|
||||||
|
* Resolves the given parsetype, looking through the scope to find
|
||||||
|
* all referenced base types, and creates a copy with these basetypes.
|
||||||
|
* @param to_resolve the parsetype to resolve.
|
||||||
|
* @param scope the scope to use for resolving the type info.
|
||||||
|
* @return the result of the operation.
|
||||||
|
*/
|
||||||
|
libab_result libab_resolve_parsetype_copy(libab_parsetype* to_resolve,
|
||||||
|
libab_table* scope,
|
||||||
|
libab_ref* into);
|
||||||
/**
|
/**
|
||||||
* Creates a new type instance, and stores it into the given reference.
|
* Creates a new type instance, and stores it into the given reference.
|
||||||
* @param to_instantiate the basetype to instantiate.
|
* @param to_instantiate the basetype to instantiate.
|
||||||
|
@ -143,6 +153,13 @@ libab_result libab_create_function_list(libab_ref* into, libab_ref* type);
|
||||||
*/
|
*/
|
||||||
libab_result libab_put_table_value(libab_table* table, const char* key,
|
libab_result libab_put_table_value(libab_table* table, const char* key,
|
||||||
libab_ref* value);
|
libab_ref* value);
|
||||||
|
/**
|
||||||
|
* Gets the basetype of a parsetype.
|
||||||
|
* @param type the parsetype to get the basetype of.
|
||||||
|
* @param scope the scope to use for searches.
|
||||||
|
* @return the basetype.
|
||||||
|
*/
|
||||||
|
libab_basetype* libab_get_basetype(libab_parsetype* type, libab_table* scope);
|
||||||
/**
|
/**
|
||||||
* Returns the data stored in the given reference to a libab_value.
|
* Returns the data stored in the given reference to a libab_value.
|
||||||
* This is not the same as libab_ref_get: libab_ref_get will return directly
|
* This is not the same as libab_ref_get: libab_ref_get will return directly
|
||||||
|
|
|
@ -96,23 +96,6 @@ libab_parsetype* _interpreter_search_type_param_raw(libab_ref_trie* params,
|
||||||
return to_return;
|
return to_return;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_basetype* _interpreter_get_basetype(libab_parsetype* type,
|
|
||||||
libab_table* scope) {
|
|
||||||
libab_ref type_param;
|
|
||||||
libab_basetype* to_return;
|
|
||||||
if(type->variant & LIBABACUS_TYPE_F_RESOLVED) {
|
|
||||||
to_return = type->data_u.base;
|
|
||||||
} else {
|
|
||||||
to_return = libab_table_search_basetype(scope, type->data_u.name);
|
|
||||||
if(to_return == NULL) {
|
|
||||||
libab_table_search_type_param(scope, type->data_u.name, &type_param);
|
|
||||||
to_return = libab_ref_get(&type_param);
|
|
||||||
libab_ref_free(&type_param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.
|
||||||
|
@ -162,14 +145,10 @@ libab_result _interpreter_compare_types(libab_ref* left_type,
|
||||||
|
|
||||||
if (left != NULL && right != NULL) {
|
if (left != NULL && right != NULL) {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
libab_basetype* base_left;
|
|
||||||
libab_basetype* base_right;
|
|
||||||
libab_ref temp_left;
|
libab_ref temp_left;
|
||||||
libab_ref temp_right;
|
libab_ref temp_right;
|
||||||
|
|
||||||
base_left = _interpreter_get_basetype(left, libab_ref_get(scope));
|
result = (left->data_u.base == right->data_u.base)
|
||||||
base_right = _interpreter_get_basetype(right, libab_ref_get(scope));
|
|
||||||
result = (base_left == base_right)
|
|
||||||
? LIBAB_SUCCESS
|
? LIBAB_SUCCESS
|
||||||
: LIBAB_MISMATCHED_TYPE;
|
: LIBAB_MISMATCHED_TYPE;
|
||||||
if (result == LIBAB_SUCCESS &&
|
if (result == LIBAB_SUCCESS &&
|
||||||
|
@ -222,7 +201,7 @@ libab_result _interpreter_copy_resolved_type(libab_ref* type,
|
||||||
} 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;
|
||||||
copy->data_u.base = _interpreter_get_basetype(original, libab_ref_get(scope));
|
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 child_copy;
|
||||||
libab_ref temp_child;
|
libab_ref temp_child;
|
||||||
|
@ -1019,15 +998,30 @@ int _interpreter_compare_function_param(
|
||||||
return data->variant == TREE_FUN_PARAM;
|
return data->variant == TREE_FUN_PARAM;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libab_result _interpreter_resolve_and_insert_param(
|
||||||
|
libab_parsetype* type, libab_table* scope, libab_ref_vec* into) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_ref copy;
|
||||||
|
result = libab_resolve_parsetype_copy(type, scope, ©);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_vec_insert(into, ©);
|
||||||
|
}
|
||||||
|
libab_ref_free(©);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
int _interpreter_foreach_insert_function_param(
|
int _interpreter_foreach_insert_function_param(
|
||||||
void* data, va_list args) {
|
void* data, va_list args) {
|
||||||
libab_tree* tree = data;
|
libab_tree* tree = data;
|
||||||
libab_ref_vec* into = va_arg(args, libab_ref_vec*);
|
libab_ref_vec* into = va_arg(args, libab_ref_vec*);
|
||||||
return libab_ref_vec_insert(into, &tree->type);
|
libab_ref* scope = va_arg(args, libab_ref*);
|
||||||
|
return _interpreter_resolve_and_insert_param(libab_ref_get(&tree->type),
|
||||||
|
libab_ref_get(scope),
|
||||||
|
into);
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_create_function_type(
|
libab_result _interpreter_create_function_type(
|
||||||
struct interpreter_state* state, libab_tree* tree, libab_parsetype** type) {
|
struct interpreter_state* state, libab_tree* tree, libab_ref* scope, libab_parsetype** type) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
libab_basetype* funciton_type = libab_get_basetype_function(state->ab);
|
libab_basetype* funciton_type = libab_get_basetype_function(state->ab);
|
||||||
|
|
||||||
|
@ -1041,9 +1035,10 @@ libab_result _interpreter_create_function_type(
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
|
result = vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
|
||||||
_interpreter_foreach_insert_function_param, &(*type)->children);
|
_interpreter_foreach_insert_function_param, &(*type)->children, scope);
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_vec_insert(&(*type)->children, &tree->type);
|
result = _interpreter_resolve_and_insert_param(libab_ref_get(&tree->type),
|
||||||
|
libab_ref_get(scope), &(*type)->children);
|
||||||
}
|
}
|
||||||
if(result != LIBAB_SUCCESS) {
|
if(result != LIBAB_SUCCESS) {
|
||||||
libab_ref_vec_free(&(*type)->children);
|
libab_ref_vec_free(&(*type)->children);
|
||||||
|
@ -1059,9 +1054,9 @@ libab_result _interpreter_create_function_type(
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result _interpreter_wrap_function_type(
|
libab_result _interpreter_wrap_function_type(
|
||||||
struct interpreter_state* state, libab_tree* tree, libab_ref* into) {
|
struct interpreter_state* state, libab_tree* tree, libab_ref* scope, libab_ref* into) {
|
||||||
libab_parsetype* type;
|
libab_parsetype* type;
|
||||||
libab_result result = _interpreter_create_function_type(state, tree, &type);
|
libab_result result = _interpreter_create_function_type(state, tree, scope, &type);
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_new(into, type, free_parsetype);
|
result = libab_ref_new(into, type, free_parsetype);
|
||||||
|
@ -1085,7 +1080,7 @@ libab_result _interpreter_create_function_value(
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
libab_ref_free(&type);
|
libab_ref_free(&type);
|
||||||
result = _interpreter_wrap_function_type(state, tree, &type);
|
result = _interpreter_wrap_function_type(state, tree, scope, &type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == LIBAB_SUCCESS) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
|
|
@ -340,7 +340,7 @@ libab_result libab_create_type(libab* ab, libab_ref* into, const char* type) {
|
||||||
result = libab_parser_parse_type(&ab->parser, &tokens, type, into);
|
result = libab_parser_parse_type(&ab->parser, &tokens, type, into);
|
||||||
}
|
}
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_resolve_parsetype(libab_ref_get(into),
|
result = libab_resolve_parsetype_inplace(libab_ref_get(into),
|
||||||
libab_ref_get(&ab->table));
|
libab_ref_get(&ab->table));
|
||||||
}
|
}
|
||||||
ll_foreach(&tokens, NULL, compare_always, libab_lexer_foreach_match_free);
|
ll_foreach(&tokens, NULL, compare_always, libab_lexer_foreach_match_free);
|
||||||
|
|
81
src/util.c
81
src/util.c
|
@ -45,7 +45,7 @@ libab_result _libab_check_parsetype(libab_parsetype* to_check) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
libab_result libab_resolve_parsetype(libab_parsetype* to_resolve,
|
libab_result libab_resolve_parsetype_inplace(libab_parsetype* to_resolve,
|
||||||
libab_table* scope) {
|
libab_table* scope) {
|
||||||
libab_result result = LIBAB_SUCCESS;
|
libab_result result = LIBAB_SUCCESS;
|
||||||
int resolve_name, check_parents;
|
int resolve_name, check_parents;
|
||||||
|
@ -61,7 +61,7 @@ libab_result libab_resolve_parsetype(libab_parsetype* to_resolve,
|
||||||
|
|
||||||
if (resolve_name && result == LIBAB_SUCCESS) {
|
if (resolve_name && result == LIBAB_SUCCESS) {
|
||||||
libab_basetype* basetype =
|
libab_basetype* basetype =
|
||||||
libab_table_search_basetype(scope, to_resolve->data_u.name);
|
libab_get_basetype(to_resolve, scope);
|
||||||
if (basetype) {
|
if (basetype) {
|
||||||
free(to_resolve->data_u.name);
|
free(to_resolve->data_u.name);
|
||||||
to_resolve->data_u.base = basetype;
|
to_resolve->data_u.base = basetype;
|
||||||
|
@ -81,7 +81,7 @@ libab_result libab_resolve_parsetype(libab_parsetype* to_resolve,
|
||||||
|
|
||||||
if (to_resolve->variant & LIBABACUS_TYPE_F_PARENT) {
|
if (to_resolve->variant & LIBABACUS_TYPE_F_PARENT) {
|
||||||
while (result == LIBAB_SUCCESS && index < to_resolve->children.size) {
|
while (result == LIBAB_SUCCESS && index < to_resolve->children.size) {
|
||||||
result = libab_resolve_parsetype(
|
result = libab_resolve_parsetype_inplace(
|
||||||
libab_ref_get(&to_resolve->children.data[index]), scope);
|
libab_ref_get(&to_resolve->children.data[index]), scope);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
@ -90,14 +90,61 @@ libab_result libab_resolve_parsetype(libab_parsetype* to_resolve,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _libab_free_parsetype(void* parsetype) {
|
libab_result libab_resolve_parsetype_copy(libab_parsetype* to_resolve,
|
||||||
libab_parsetype_free(parsetype);
|
libab_table* scope,
|
||||||
free(parsetype);
|
libab_ref* into) {
|
||||||
|
libab_result result = LIBAB_SUCCESS;
|
||||||
|
libab_parsetype* parsetype;
|
||||||
|
if((parsetype = malloc(sizeof(*parsetype)))) {
|
||||||
|
parsetype->variant = to_resolve->variant | LIBABACUS_TYPE_F_RESOLVED;
|
||||||
|
} else {
|
||||||
|
result = LIBAB_MALLOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _libab_parsetype_free(void* parsetype) {
|
if(result == LIBAB_SUCCESS) {
|
||||||
libab_parsetype_free(parsetype);
|
libab_basetype* parent_basetype = libab_get_basetype(to_resolve, scope);
|
||||||
|
if(parent_basetype) {
|
||||||
|
parsetype->data_u.base = parent_basetype;
|
||||||
|
} else {
|
||||||
|
result = LIBAB_UNKNOWN_TYPE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS && (to_resolve->variant & LIBABACUS_TYPE_F_PARENT)) {
|
||||||
|
result = libab_ref_vec_init(&parsetype->children);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS && (to_resolve->variant & LIBABACUS_TYPE_F_PARENT)) {
|
||||||
|
size_t i;
|
||||||
|
libab_ref temp;
|
||||||
|
libab_ref new_type;
|
||||||
|
for(i = 0; i < to_resolve->children.size && result == LIBAB_SUCCESS; i++) {
|
||||||
|
libab_ref_vec_index(&to_resolve->children, i, &temp);
|
||||||
|
result = libab_resolve_parsetype_copy(libab_ref_get(&temp), scope, &new_type);
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
libab_ref_vec_insert(&parsetype->children, &new_type);
|
||||||
|
}
|
||||||
|
libab_ref_free(&new_type);
|
||||||
|
libab_ref_free(&temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
|
libab_ref_vec_free(&parsetype->children);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == LIBAB_SUCCESS) {
|
||||||
|
result = libab_ref_new(into, parsetype, free_parsetype);
|
||||||
|
if(result != LIBAB_SUCCESS) libab_parsetype_free(parsetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result != LIBAB_SUCCESS) {
|
||||||
free(parsetype);
|
free(parsetype);
|
||||||
|
libab_ref_null(into);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
|
libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
|
||||||
|
@ -115,7 +162,7 @@ libab_result libab_instantiate_basetype(libab_basetype* to_instantiate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result == LIBAB_SUCCESS) {
|
if (result == LIBAB_SUCCESS) {
|
||||||
result = libab_ref_new(into, parsetype, _libab_parsetype_free);
|
result = libab_ref_new(into, parsetype, free_parsetype);
|
||||||
if (result != LIBAB_SUCCESS) {
|
if (result != LIBAB_SUCCESS) {
|
||||||
libab_parsetype_free(parsetype);
|
libab_parsetype_free(parsetype);
|
||||||
}
|
}
|
||||||
|
@ -332,6 +379,22 @@ libab_result libab_put_table_value(libab_table* table, const char* key,
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
libab_basetype* libab_get_basetype(libab_parsetype* type, libab_table* scope) {
|
||||||
|
libab_ref type_param;
|
||||||
|
libab_basetype* to_return;
|
||||||
|
if(type->variant & LIBABACUS_TYPE_F_RESOLVED) {
|
||||||
|
to_return = type->data_u.base;
|
||||||
|
} else {
|
||||||
|
to_return = libab_table_search_basetype(scope, type->data_u.name);
|
||||||
|
if(to_return == NULL) {
|
||||||
|
libab_table_search_type_param(scope, type->data_u.name, &type_param);
|
||||||
|
to_return = libab_ref_get(&type_param);
|
||||||
|
libab_ref_free(&type_param);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to_return;
|
||||||
|
}
|
||||||
|
|
||||||
void* libab_unwrap_value(libab_ref* ref) {
|
void* libab_unwrap_value(libab_ref* ref) {
|
||||||
libab_value* value = libab_ref_get(ref);
|
libab_value* value = libab_ref_get(ref);
|
||||||
return libab_ref_get(&value->data);
|
return libab_ref_get(&value->data);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user