From 03577269f2c8231ffa5a68cba5762672aa426311 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Thu, 21 Jun 2018 17:06:53 -0700 Subject: [PATCH] Add various ways to call code. --- include/libabacus.h | 40 +++++++++++++++++- src/libabacus.c | 100 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 118 insertions(+), 22 deletions(-) diff --git a/include/libabacus.h b/include/libabacus.h index 3ff8665..3cbd5e0 100644 --- a/include/libabacus.h +++ b/include/libabacus.h @@ -197,17 +197,55 @@ void libab_get_unit_value(libab* ab, libab_ref* into); * @return the result of the computation. */ libab_result libab_run(libab* ab, const char* string, libab_ref* value); +/** + * Runs an already-compiled tree. + * @param ab the libabacus instance to use for executing code. + * @param tree the tree the run. + * @param value the reference into which to store the output. + * @return the result of the computation. + */ +libab_result libab_run_tree(libab* ab, libab_tree* tree, libab_ref* value); /** * Calls a function with the given name and parameters. * @param ab the libabacus instance to use to call the function. * @param function the name of the function to call. - * @param iunto the reference into which to store the result. + * @param into the reference into which to store the result. * @param param_count the number of parameters given to this function. * @return the result of the call. */ libab_result libab_run_function(libab* ab, const char* function, libab_ref* into, size_t param_count, ...); +/** + * Calls a string in a given surrounding scope. + * @param ab the libabacus instance to use to call the function. + * @param strign the string to run. + * @param scope the scope to use for calling the string. + * @param value the reference into which to store the output of the computation. + * @return the result of the computation. + */ +libab_result libab_run_scoped(libab* ab, const char* string, libab_ref* scope, libab_ref* value); +/** + * Calls a tree in a given scope. + * @param ab the libabacus instance to use to call the tree. + * @param tree the tree to call. + * @param scope the scope to use for the call. + * @param value the reference into which to store the output. + * @return the result of the call. + */ +libab_result libab_run_tree_scoped(libab* ab, libab_tree* tree, libab_ref* scope, libab_ref* value); +/** + * Calls a function with the given name and parameters using a given scope. + * @param ab the libabacus instance to use to call the function. + * @param function the name of the function to call. + * @param scope the scope in which to perform the call. + * @param into the reference into which to store the result. + * @param param_count the number of parameters given to this function. + * @return the result of the call. + */ +libab_result libab_run_function_scoped(libab* ab, const char* function, libab_ref* scope, + libab_ref* into, + size_t param_count, ...); /** * Releases all the resources allocated by libabacus. diff --git a/src/libabacus.c b/src/libabacus.c index 32cc414..114339d 100644 --- a/src/libabacus.c +++ b/src/libabacus.c @@ -378,28 +378,49 @@ void libab_get_unit_value(libab* ab, libab_ref* into) { libab_interpreter_unit_value(&ab->intr, into); } -libab_result libab_run(libab* ab, const char* string, libab_ref* value) { +libab_result _create_tree(libab* ab, const char* string, libab_tree** into) { libab_result result = LIBAB_SUCCESS; ll tokens; - libab_tree* root; ll_init(&tokens); - libab_ref_null(value); - + *into = NULL; result = libab_lexer_lex(&ab->lexer, string, &tokens); - if (result == LIBAB_SUCCESS) { - result = libab_parser_parse(&ab->parser, &tokens, string, &root); - } - - if (result == LIBAB_SUCCESS) { - libab_ref_free(value); - result = libab_interpreter_run(&ab->intr, root, &ab->table, SCOPE_NORMAL, value); - libab_tree_free_recursive(root); + if(result == LIBAB_SUCCESS) { + result = libab_parser_parse(&ab->parser, &tokens, string, into); } ll_foreach(&tokens, NULL, compare_always, libab_lexer_foreach_match_free); ll_free(&tokens); + return result; +} + +libab_result _handle_va_params(libab* ab, libab_ref_vec* into, size_t param_count, va_list args) { + libab_result result = libab_ref_vec_init(into); + if(result == LIBAB_SUCCESS) { + while(result == LIBAB_SUCCESS && param_count--) { + result = libab_ref_vec_insert(into, va_arg(args, libab_ref*)); + } + + if(result != LIBAB_SUCCESS) { + libab_ref_vec_free(into); + } + } + return result; +} + +libab_result libab_run(libab* ab, const char* string, libab_ref* value) { + libab_result result; + libab_tree* root; + + libab_ref_null(value); + result = _create_tree(ab, string, &root); + + if (result == LIBAB_SUCCESS) { + libab_ref_free(value); + result = libab_interpreter_run(&ab->intr, root, &ab->table, SCOPE_FORCE, value); + libab_tree_free_recursive(root); + } return result; } @@ -413,16 +434,10 @@ libab_result libab_run_function(libab* ab, const char* function, va_start(args, param_count); libab_ref_null(into); - result = libab_ref_vec_init(¶ms); + result = _handle_va_params(ab, ¶ms, param_count, args); if(result == LIBAB_SUCCESS) { - while(result == LIBAB_SUCCESS && param_count--) { - result = libab_ref_vec_insert(¶ms, va_arg(args, libab_ref*)); - } - - if(result == LIBAB_SUCCESS) { - libab_ref_free(into); - result = libab_interpreter_run_function(&ab->intr, &ab->table, function, ¶ms, into); - } + libab_ref_free(into); + result = libab_interpreter_run_function(&ab->intr, &ab->table, function, ¶ms, into); libab_ref_vec_free(¶ms); } @@ -431,6 +446,49 @@ libab_result libab_run_function(libab* ab, const char* function, return result; } +libab_result libab_run_tree(libab* ab, libab_tree* tree, libab_ref* value) { + return libab_interpreter_run(&ab->intr, tree, &ab->table, SCOPE_FORCE, value); +} + +libab_result libab_run_scoped(libab* ab, const char* string, libab_ref* scope, libab_ref* into) { + libab_result result; + libab_tree* root; + + libab_ref_null(into); + result = _create_tree(ab, string, &root); + if(result == LIBAB_SUCCESS) { + libab_ref_free(into); + result = libab_interpreter_run(&ab->intr, root, scope, SCOPE_NONE, into); + libab_tree_free_recursive(root); + } + + return result; +} + +libab_result libab_run_function_scoped(libab* ab, const char* function, libab_ref* scope, libab_ref* into, + size_t param_count, ...) { + libab_ref_vec params; + libab_result result; + va_list args; + + va_start(args, param_count); + libab_ref_null(into); + result = _handle_va_params(ab, ¶ms, param_count, args); + if(result == LIBAB_SUCCESS) { + libab_ref_free(into); + result = libab_interpreter_run_function(&ab->intr, scope, function, ¶ms, into); + + libab_ref_vec_free(¶ms); + } + va_end(args); + + return result; +} + +libab_result libab_run_tree_scoped(libab* ab, libab_tree* tree, libab_ref* scope, libab_ref* into) { + return libab_interpreter_run(&ab->intr, tree, scope, SCOPE_NONE, into); +} + libab_result libab_free(libab* ab) { libab_table_free(libab_ref_get(&ab->table)); libab_ref_free(&ab->table);