From 48355b07360659f8300c1589031cfa5fd64d9d10 Mon Sep 17 00:00:00 2001 From: Danila Fedorin Date: Fri, 17 Aug 2018 01:34:58 -0700 Subject: [PATCH] Complete splitting code into source files. --- CMakeLists.txt | 2 +- include/abacus.hpp | 81 +++++------------------------------ include/functions.hpp | 14 +++++- include/ref.hpp | 55 ++++++------------------ include/types.hpp | 21 +++------ include/util.hpp | 13 ++++++ src/abacus.cpp | 63 +++++++++++++++++++++++++++ src/main.cpp | 87 +------------------------------------- src/operator_functions.cpp | 15 +++++++ src/other_functions.cpp | 5 +++ src/ref.cpp | 37 ++++++++++++++++ src/string_functions.cpp | 40 ++++++++++++++++++ src/trig_functions.cpp | 9 ++++ src/types.cpp | 18 ++++++++ src/util.cpp | 19 +++++++++ 15 files changed, 263 insertions(+), 216 deletions(-) create mode 100644 include/util.hpp create mode 100644 src/abacus.cpp create mode 100644 src/operator_functions.cpp create mode 100644 src/other_functions.cpp create mode 100644 src/ref.cpp create mode 100644 src/string_functions.cpp create mode 100644 src/trig_functions.cpp create mode 100644 src/types.cpp create mode 100644 src/util.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eea276..b45a903 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ pkg_check_modules(MPFR REQUIRED mpfr) set(CMAKE_CXX_STANDARD 11) add_subdirectory(external/libabacus) -add_executable(cmdAbacus src/main.cpp) +add_executable(cmdAbacus src/main.cpp src/ref.cpp src/abacus.cpp src/types.cpp src/string_functions.cpp src/util.cpp src/operator_functions.cpp src/trig_functions.cpp src/other_functions.cpp) target_link_libraries(cmdAbacus abacus ${MPFR_LIBRARIES} readline) target_include_directories(cmdAbacus PUBLIC include ${MPFR_INCLUDE_DIRS}) target_compile_options(cmdAbacus PUBLIC ${MPFR_CFLAGS_OTHER}) diff --git a/include/abacus.hpp b/include/abacus.hpp index 25eaa6d..1529b9d 100644 --- a/include/abacus.hpp +++ b/include/abacus.hpp @@ -1,6 +1,9 @@ #pragma once #include "ref.hpp" +#include "types.hpp" +#include +#include extern "C" { #include "libabacus.h" #include "table.h" @@ -11,89 +14,27 @@ extern "C" { class abacus { private: libab ab; - abacus_ref scope; - std::map compiled_types; + ref scope; + std::map compiled_types; libab_basetype basetype_string = { [](void* s) { delete ((string*) s); }, NULL, 0 }; public: abacus(); - void add_variable(const std::string& name, abacus_ref val); + void add_variable(const std::string& name, ref val); void add_function(const std::string& name, libab_function_ptr ptr, const std::string& type); void add_operator_infix(const std::string& op, const std::string& func, int assoc, int prec); void add_operator_prefix(const std::string& op, const std::string& func); void add_operator_postfix(const std::string& op, const std::string& func); - abacus_ref run(const std::string& code); + ref run(const std::string& code); template - abacus_ref call(const std::string& bane, Ts...params); - std::string to_string(abacus_ref& value); + ref call(const std::string& bane, Ts...params); + std::string to_string(ref& value); ~abacus(); }; -abacus::abacus() { - auto parse_function = [](const char* s) { - return (void*) new number(s); - }; - auto free_function = [](void* num) { - delete ((number*) num); - }; - libab_init(&ab, parse_function, free_function); - libab_register_basetype(&ab, "str", &basetype_string); - libab_create_table(&ab, scope, &ab.table); -} - -void abacus::add_variable(const std::string& name, abacus_ref val) { - libab_table_entry* entry = libab_table_search_entry_value(get(scope), name.c_str()); - if(entry) { - libab_ref_free(&entry->data_u.value); - libab_ref_copy(val, &entry->data_u.value); - } else { - libab_put_table_value(get(scope), name.c_str(), std::move(val)); - } -} - -void abacus::add_function(const std::string& name, libab_function_ptr ptr, const std::string& type) { - if(compiled_types.find(type) != compiled_types.end()) { - libab_register_function(&ab, name.c_str(), compiled_types[type], ptr); - } else { - abacus_ref& new_ref = compiled_types[type]; - libab_create_type(&ab, new_ref, type.c_str()); - libab_register_function(&ab, name.c_str(), new_ref, ptr); - } -} - -void abacus::add_operator_infix(const std::string& op, const std::string& func, int assoc, int prec) { - libab_register_operator_infix(&ab, op.c_str(), prec, assoc, func.c_str()); -} -void abacus::add_operator_prefix(const std::string& op, const std::string& func) { - libab_register_operator_prefix(&ab, op.c_str(), func.c_str()); -} -void abacus::add_operator_postfix(const std::string& op, const std::string& func) { - libab_register_operator_postfix(&ab, op.c_str(), func.c_str()); -} - -abacus_ref abacus::run(const std::string& code) { - abacus_ref value; - libab_run_scoped(&ab, code.c_str(), scope, value); - libab_gc_run(&ab.containers); - return value; -} - template -abacus_ref abacus::call(const std::string& name, Ts...params) { - abacus_ref value; +ref abacus::call(const std::string& name, Ts...params) { + ref value; libab_run_function_scoped(&ab, name.c_str(), scope, value, sizeof...(params), (libab_ref*) params...); libab_gc_run(&ab.containers); return value; } - -std::string abacus::to_string(abacus_ref& val) { - abacus_ref string_value = call("to_string", val); - if(string_value == nullptr) return "Unable to convert to string."; - libab_basetype* base = get(&get(string_value)->type)->data_u.base; - if(base != &basetype_string) return "\"to_string\" did not return string."; - return get(&get(string_value)->data)->value; -} - -abacus::~abacus() { - scope = nullptr; - libab_free(&ab); -} diff --git a/include/functions.hpp b/include/functions.hpp index 9654802..d12a276 100644 --- a/include/functions.hpp +++ b/include/functions.hpp @@ -1,5 +1,7 @@ #pragma once +#include "ref.hpp" +#include "util.hpp" extern "C" { #include "libabacus.h" } @@ -12,7 +14,7 @@ extern "C" { mpfr_t output; \ mpfr_init2(output, PRECISION); \ mpfr_##func(output, value->value, MPFR_RNDN); \ - abacus_ref to_return = create_value(ab, new number(std::move(output))); \ + ref to_return = create_value(ab, new number(std::move(output))); \ libab_ref_copy(to_return, into); \ return LIBAB_SUCCESS; \ } @@ -23,7 +25,7 @@ extern "C" { mpfr_t output; \ mpfr_init2(output, PRECISION); \ mpfr_##func(output, left->value, right->value, MPFR_RNDN); \ - abacus_ref to_return = create_value(ab, new number(std::move(output))); \ + ref to_return = create_value(ab, new number(std::move(output))); \ libab_ref_copy(to_return, into); \ return LIBAB_SUCCESS; \ } @@ -39,23 +41,31 @@ FUNCTION(print_string); FUNCTION(to_string_num); FUNCTION(to_string_bool); FUNCTION(to_string_unit); + FUNCTION(plus); FUNCTION(minus); FUNCTION(times); FUNCTION(divide); +FUNCTION(pow); + FUNCTION(lt); FUNCTION(lte); FUNCTION(equals); FUNCTION(gt); FUNCTION(gte); + FUNCTION(negate); + FUNCTION(ln); FUNCTION(exp); + FUNCTION(sin); FUNCTION(cos); FUNCTION(tan); + FUNCTION(arcsin); FUNCTION(arccos); FUNCTION(arctan); + FUNCTION(quit); FUNCTION(request_precision); diff --git a/include/ref.hpp b/include/ref.hpp index 2ef97c3..edd478e 100644 --- a/include/ref.hpp +++ b/include/ref.hpp @@ -1,25 +1,24 @@ #pragma once +#include extern "C" { #include "libabacus.h" #include "util.h" } -class abacus_ref { +class ref { private: - libab_ref ref; + libab_ref val; public: - abacus_ref(); - abacus_ref(void* data, void (*free_func)(void*)); - abacus_ref(const abacus_ref& other); - abacus_ref& operator=(const abacus_ref& other); - abacus_ref& operator=(std::nullptr_t); + ref(); + ref(void* data, void (*free_func)(void*)); + ref(const ref& other); + ref& operator=(const ref& other); + ref& operator=(std::nullptr_t); template bool operator==(T data); - operator libab_ref*() { - return &ref; - } - ~abacus_ref(); + operator libab_ref*(); + ~ref(); }; template @@ -27,39 +26,11 @@ T* get(libab_ref* ref) { return (T*) libab_ref_get(ref); } -abacus_ref::abacus_ref() { - libab_ref_null(&ref); -} - -abacus_ref::abacus_ref(void* data, void (*free_func)(void*)) { - libab_ref_new(&ref, data, free_func); -} - -abacus_ref::abacus_ref(const abacus_ref& other) { - libab_ref_copy(&other.ref, &ref); -} - -abacus_ref& abacus_ref::operator=(const abacus_ref& other) { - libab_ref_copy(&other.ref, &ref); - return *this; -} - -abacus_ref& abacus_ref::operator=(std::nullptr_t t) { - libab_ref_free(&ref); - libab_ref_null(&ref); - return *this; -} template -bool abacus_ref::operator==(T data) { - return libab_ref_get(&ref) == (void*) data; +bool ref::operator==(T data) { + return libab_ref_get(&val) == (void*) data; } template <> -bool abacus_ref::operator==(std::nullptr_t t) { - return libab_ref_get(&ref) == t; -} - -abacus_ref::~abacus_ref() { - libab_ref_free(&ref); -} +bool ref::operator==(std::nullptr_t t); diff --git a/include/types.hpp b/include/types.hpp index ea7392c..262b781 100644 --- a/include/types.hpp +++ b/include/types.hpp @@ -5,24 +5,15 @@ struct string { std::string value; - string(std::string&& new_value) : value(std::move(new_value)) {} - string(const std::string& new_value) : value(new_value) {} + string(std::string&& new_value); + string(const std::string& new_value); }; struct number { mpfr_t value; - number(const char* new_value) { - mpfr_init2(value, PRECISION); - mpfr_set_str(value, new_value, 10, MPFR_RNDN); - } - number(mpfr_t&& new_value) { - std::swap(value, new_value); - } - int to_int() { - return mpfr_get_si(value, MPFR_RNDN); - } - ~number() { - mpfr_clear(value); - } + number(const char* new_value); + number(mpfr_t&& new_value); + int to_int(); + ~number(); }; diff --git a/include/util.hpp b/include/util.hpp new file mode 100644 index 0000000..5722d07 --- /dev/null +++ b/include/util.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "types.hpp" +#include "ref.hpp" + +template +ref create_value(libab* ab, T* val); + +template <> +ref create_value(libab* ab, string* param); + +template <> +ref create_value(libab* ab, number* param); diff --git a/src/abacus.cpp b/src/abacus.cpp new file mode 100644 index 0000000..73f012c --- /dev/null +++ b/src/abacus.cpp @@ -0,0 +1,63 @@ +#include "abacus.hpp" + +abacus::abacus() { + auto parse_function = [](const char* s) { + return (void*) new number(s); + }; + auto free_function = [](void* num) { + delete ((number*) num); + }; + libab_init(&ab, parse_function, free_function); + libab_register_basetype(&ab, "str", &basetype_string); + libab_create_table(&ab, scope, &ab.table); +} + +void abacus::add_variable(const std::string& name, ref val) { + libab_table_entry* entry = libab_table_search_entry_value(get(scope), name.c_str()); + if(entry) { + libab_ref_free(&entry->data_u.value); + libab_ref_copy(val, &entry->data_u.value); + } else { + libab_put_table_value(get(scope), name.c_str(), std::move(val)); + } +} + +void abacus::add_function(const std::string& name, libab_function_ptr ptr, const std::string& type) { + if(compiled_types.find(type) != compiled_types.end()) { + libab_register_function(&ab, name.c_str(), compiled_types[type], ptr); + } else { + ref& new_ref = compiled_types[type]; + libab_create_type(&ab, new_ref, type.c_str()); + libab_register_function(&ab, name.c_str(), new_ref, ptr); + } +} + +void abacus::add_operator_infix(const std::string& op, const std::string& func, int assoc, int prec) { + libab_register_operator_infix(&ab, op.c_str(), prec, assoc, func.c_str()); +} +void abacus::add_operator_prefix(const std::string& op, const std::string& func) { + libab_register_operator_prefix(&ab, op.c_str(), func.c_str()); +} +void abacus::add_operator_postfix(const std::string& op, const std::string& func) { + libab_register_operator_postfix(&ab, op.c_str(), func.c_str()); +} + +ref abacus::run(const std::string& code) { + ref value; + libab_run_scoped(&ab, code.c_str(), scope, value); + libab_gc_run(&ab.containers); + return value; +} + +std::string abacus::to_string(ref& val) { + ref string_value = call("to_string", val); + if(string_value == nullptr) return "Unable to convert to string."; + libab_basetype* base = get(&get(string_value)->type)->data_u.base; + if(base != &basetype_string) return "\"to_string\" did not return string."; + return get(&get(string_value)->data)->value; +} + +abacus::~abacus() { + scope = nullptr; + libab_free(&ab); +} diff --git a/src/main.cpp b/src/main.cpp index dc8feec..6c5e57a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,95 +14,10 @@ extern "C" { #include "util.h" } - // == Global State (uh-oh) bool close_requested = false; long requested_precision = 3; -// -// == BASIC FUNCTIONS - -template -abacus_ref create_value(libab* ab, T* val); - -template <> -abacus_ref create_value(libab* ab, string* param) { - abacus_ref type; - abacus_ref value; - libab_create_type(ab, type, "str"); - libab_create_value_raw(ab, value, (void*) param, type); - return value; -} - -template <> -abacus_ref create_value(libab* ab, number* param) { - abacus_ref type; - abacus_ref value; - libab_get_type_num(ab, type); - libab_create_value_raw(ab, value, (void*) param, type); - return value; -} - -FUNCTION(print_string) { - string* param = (string*) libab_unwrap_param(params, 0); - std::cout << param->value << std::endl; - libab_get_unit_value(ab, into); - return LIBAB_SUCCESS; -} - -FUNCTION(to_string_num) { - number* num = (number*) libab_unwrap_param(params, 0); - mpfr_exp_t exp; - char* str = mpfr_get_str(NULL, &exp, 10, requested_precision, num->value, MPFR_RNDN); - std::string output_string = std::string(str).insert((mpfr_sgn(num->value) < 0) ? 2 : 1, 1, '.'); - if(exp != 1) { - output_string += "e"; - output_string += std::to_string(exp - 1); - } - abacus_ref value = create_value(ab, new string(std::move(output_string))); - libab_ref_copy(value, into); - mpfr_free_str(str); - return LIBAB_SUCCESS; -} - -FUNCTION(to_string_bool) { - int* val = (int*) libab_unwrap_param(params, 0); - abacus_ref value = create_value(ab, new string(*val ? "true" : "false")); - libab_ref_copy(value, into); - return LIBAB_SUCCESS; -} - -FUNCTION(to_string_unit) { - abacus_ref value = create_value(ab, new string("()")); - libab_ref_copy(value, into); - return LIBAB_SUCCESS; -} - -FUNCTION_MPFR2(plus, add) -FUNCTION_MPFR2(minus, sub) -FUNCTION_MPFR2(times, mul) -FUNCTION_MPFR2(divide, div) -FUNCTION_MPFR2(pow, pow); - -FUNCTION_COMPARE(lt, <); -FUNCTION_COMPARE(lte, <=); -FUNCTION_COMPARE(equals, ==); -FUNCTION_COMPARE(gt, >); -FUNCTION_COMPARE(gte, >=); - -FUNCTION_MPFR(negate, neg); - -FUNCTION_MPFR(ln, log); -FUNCTION_MPFR(exp, exp); - -FUNCTION_MPFR(sin, sin); -FUNCTION_MPFR(cos, cos); -FUNCTION_MPFR(tan, tan); - -FUNCTION_MPFR(arcsin, asin); -FUNCTION_MPFR(arccos, acos); -FUNCTION_MPFR(arctan, atan); - FUNCTION(quit) { close_requested = true; libab_get_unit_value(ab, into); @@ -170,7 +85,7 @@ int main() { add_history(data); free(data); - abacus_ref value = ab.run(buffer); + ref value = ab.run(buffer); if(value == nullptr) { std::cout << "Invalid expression." << std::endl; } else { diff --git a/src/operator_functions.cpp b/src/operator_functions.cpp new file mode 100644 index 0000000..d13db0c --- /dev/null +++ b/src/operator_functions.cpp @@ -0,0 +1,15 @@ +#include "functions.hpp" + +FUNCTION_MPFR2(plus, add) +FUNCTION_MPFR2(minus, sub) +FUNCTION_MPFR2(times, mul) +FUNCTION_MPFR2(divide, div) +FUNCTION_MPFR2(pow, pow); + +FUNCTION_MPFR(negate, neg); + +FUNCTION_COMPARE(lt, <); +FUNCTION_COMPARE(lte, <=); +FUNCTION_COMPARE(equals, ==); +FUNCTION_COMPARE(gt, >); +FUNCTION_COMPARE(gte, >=); diff --git a/src/other_functions.cpp b/src/other_functions.cpp new file mode 100644 index 0000000..beeafe8 --- /dev/null +++ b/src/other_functions.cpp @@ -0,0 +1,5 @@ +#include "functions.hpp" + +FUNCTION_MPFR(ln, log); +FUNCTION_MPFR(exp, exp); + diff --git a/src/ref.cpp b/src/ref.cpp new file mode 100644 index 0000000..83c8500 --- /dev/null +++ b/src/ref.cpp @@ -0,0 +1,37 @@ +#include "ref.hpp" + +ref::ref() { + libab_ref_null(&val); +} + +ref::ref(void* data, void (*free_func)(void*)) { + libab_ref_new(&val, data, free_func); +} + +ref::ref(const ref& other) { + libab_ref_copy(&other.val, &val); +} + +ref& ref::operator=(const ref& other) { + libab_ref_copy(&other.val, &val); + return *this; +} + +ref& ref::operator=(std::nullptr_t t) { + libab_ref_free(&val); + libab_ref_null(&val); + return *this; +} + +ref::operator libab_ref*() { + return &val; +} + +ref::~ref() { + libab_ref_free(&val); +} + +template <> +bool ref::operator==(std::nullptr_t t) { + return libab_ref_get(&val) == t; +} diff --git a/src/string_functions.cpp b/src/string_functions.cpp new file mode 100644 index 0000000..fbd3c5e --- /dev/null +++ b/src/string_functions.cpp @@ -0,0 +1,40 @@ +#include "functions.hpp" +#include +#include + +extern int requested_precision; + +FUNCTION(print_string) { + string* param = (string*) libab_unwrap_param(params, 0); + std::cout << param->value << std::endl; + libab_get_unit_value(ab, into); + return LIBAB_SUCCESS; +} + +FUNCTION(to_string_num) { + number* num = (number*) libab_unwrap_param(params, 0); + mpfr_exp_t exp; + char* str = mpfr_get_str(NULL, &exp, 10, requested_precision, num->value, MPFR_RNDN); + std::string output_string = std::string(str).insert((mpfr_sgn(num->value) < 0) ? 2 : 1, 1, '.'); + if(exp != 1) { + output_string += "e"; + output_string += std::to_string(exp - 1); + } + ref value = create_value(ab, new string(std::move(output_string))); + libab_ref_copy(value, into); + mpfr_free_str(str); + return LIBAB_SUCCESS; +} + +FUNCTION(to_string_bool) { + int* val = (int*) libab_unwrap_param(params, 0); + ref value = create_value(ab, new string(*val ? "true" : "false")); + libab_ref_copy(value, into); + return LIBAB_SUCCESS; +} + +FUNCTION(to_string_unit) { + ref value = create_value(ab, new string("()")); + libab_ref_copy(value, into); + return LIBAB_SUCCESS; +} diff --git a/src/trig_functions.cpp b/src/trig_functions.cpp new file mode 100644 index 0000000..b7a7334 --- /dev/null +++ b/src/trig_functions.cpp @@ -0,0 +1,9 @@ +#include "functions.hpp" + +FUNCTION_MPFR(sin, sin); +FUNCTION_MPFR(cos, cos); +FUNCTION_MPFR(tan, tan); + +FUNCTION_MPFR(arcsin, asin); +FUNCTION_MPFR(arccos, acos); +FUNCTION_MPFR(arctan, atan); diff --git a/src/types.cpp b/src/types.cpp new file mode 100644 index 0000000..639e236 --- /dev/null +++ b/src/types.cpp @@ -0,0 +1,18 @@ +#include "types.hpp" + +string::string(std::string&& new_value): value(std::move(new_value)) {} +string::string(const std::string& new_value) : value(new_value) {} + +number::number(const char* new_value) { + mpfr_init2(value, PRECISION); + mpfr_set_str(value, new_value, 10, MPFR_RNDN); +} +number::number(mpfr_t&& new_value) { + std::swap(value, new_value); +} +int number::to_int() { + return mpfr_get_si(value, MPFR_RNDN); +} +number::~number() { + mpfr_clear(value); +} diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..f1c2ca4 --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,19 @@ +#include "util.hpp" + +template <> +ref create_value(libab* ab, string* param) { + ref type; + ref value; + libab_create_type(ab, type, "str"); + libab_create_value_raw(ab, value, (void*) param, type); + return value; +} + +template <> +ref create_value(libab* ab, number* param) { + ref type; + ref value; + libab_get_type_num(ab, type); + libab_create_value_raw(ab, value, (void*) param, type); + return value; +}