Add creating tree functions.

This commit is contained in:
Danila Fedorin 2018-06-15 22:56:56 -07:00
parent 695fbed235
commit 28f7cd1b30
2 changed files with 123 additions and 1 deletions

View File

@ -868,6 +868,112 @@ libab_result _interpreter_run_function_node(struct interpreter_state* state,
return result;
}
int _interpreter_compare_function_param(
const void* left, const void* right) {
const libab_tree* data = right;
return data->variant == TREE_FUN_PARAM;
}
int _interpreter_foreach_resolve_function_param(
void* data, va_list args) {
libab_tree* tree = data;
libab_ref* scope = va_arg(args, libab_ref*);
libab_parsetype* type = libab_ref_get(&tree->type);
return libab_resolve_parsetype(type, libab_ref_get(scope));
}
libab_result _interpreter_resolve_function_params(
struct interpreter_state* state, libab_tree* tree,
libab_ref* scope) {
return vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
_interpreter_foreach_resolve_function_param, scope);
}
int _interpreter_foreach_insert_function_param(
void* data, va_list args) {
libab_tree* tree = data;
libab_ref_vec* into = va_arg(args, libab_ref_vec*);
return libab_ref_vec_insert(into, &tree->type);
}
libab_result _interpreter_create_function_type(
struct interpreter_state* state, libab_tree* tree, libab_parsetype** type) {
libab_result result = LIBAB_SUCCESS;
libab_basetype* funciton_type = libab_get_basetype_function(state->ab);
if((*type = malloc(sizeof(**type)))) {
(*type)->variant = LIBABACUS_TYPE_F_PARENT | LIBABACUS_TYPE_F_RESOLVED;
(*type)->data_u.base = funciton_type;
result = libab_ref_vec_init(&(*type)->children);
} else {
result = LIBAB_MALLOC;
}
if(result == LIBAB_SUCCESS) {
result = vec_foreach(&tree->children, NULL, _interpreter_compare_function_param,
_interpreter_foreach_insert_function_param, &(*type)->children);
if(result == LIBAB_SUCCESS) {
result = libab_ref_vec_insert(&(*type)->children, &tree->type);
}
if(result != LIBAB_SUCCESS) {
libab_ref_vec_free(&(*type)->children);
}
}
if(result != LIBAB_SUCCESS) {
free(*type);
*type = NULL;
}
return result;
}
libab_result _interpreter_wrap_function_type(
struct interpreter_state* state, libab_tree* tree, libab_ref* into) {
libab_parsetype* type;
libab_result result = _interpreter_create_function_type(state, tree, &type);
if(result == LIBAB_SUCCESS) {
result = libab_ref_new(into, type, free_parsetype);
}
if(result != LIBAB_SUCCESS) {
libab_ref_null(into);
}
return result;
}
libab_result _interpreter_create_function_value(
struct interpreter_state* state, libab_tree* tree,
libab_ref* scope, libab_ref* into) {
libab_result result = LIBAB_SUCCESS;
libab_ref function, type;
libab_ref_null(&type);
libab_ref_null(into);
result = libab_create_function_tree(&function, free_function, tree, scope);
if(result == LIBAB_SUCCESS) {
libab_ref_free(&type);
result = _interpreter_wrap_function_type(state, tree, &type);
}
if(result == LIBAB_SUCCESS) {
libab_ref_free(into);
result = libab_create_value_ref(into, &function, &type);
}
if(result != LIBAB_SUCCESS) {
libab_ref_free(into);
libab_ref_null(into);
}
libab_ref_free(&function);
libab_ref_free(&type);
return result;
}
libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
libab_ref* into, libab_ref* scope,
int force_scope) {
@ -915,6 +1021,22 @@ libab_result _interpreter_run(struct interpreter_state* state, libab_tree* tree,
libab_ref_get(scope), tree->string_value, OPERATOR_POSTFIX);
result = _interpreter_call_operator(state, to_call, into, scope,
vec_index(&tree->children, 0));
} else if (tree->variant == TREE_FUN) {
libab_ref function;
result =
_interpreter_create_function_value(state, tree, scope, &function);
if(result == LIBAB_SUCCESS) {
result = libab_put_table_value(libab_ref_get(scope),
tree->string_value, &function);
if(result != LIBAB_SUCCESS) {
libab_ref_free(&function);
libab_ref_null(&function);
}
}
libab_ref_copy(&function, into);
libab_ref_free(&function);
} else {
libab_get_unit_value(state->ab, into);
}

View File

@ -20,7 +20,7 @@ int libab_tree_has_string(libab_tree_variant variant) {
int libab_tree_has_scope(libab_tree_variant variant) {
return variant == TREE_BASE || variant == TREE_BLOCK ||
variant == TREE_IF || variant == TREE_WHILE ||
variant == TREE_DOWHILE || variant == TREE_FUN;
variant == TREE_DOWHILE;
}
int libab_tree_has_type(libab_tree_variant variant) {