Complete splitting code into source files.
This commit is contained in:
parent
dfad4a2cfc
commit
48355b0736
|
@ -6,7 +6,7 @@ pkg_check_modules(MPFR REQUIRED mpfr)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
|
||||||
add_subdirectory(external/libabacus)
|
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_link_libraries(cmdAbacus abacus ${MPFR_LIBRARIES} readline)
|
||||||
target_include_directories(cmdAbacus PUBLIC include ${MPFR_INCLUDE_DIRS})
|
target_include_directories(cmdAbacus PUBLIC include ${MPFR_INCLUDE_DIRS})
|
||||||
target_compile_options(cmdAbacus PUBLIC ${MPFR_CFLAGS_OTHER})
|
target_compile_options(cmdAbacus PUBLIC ${MPFR_CFLAGS_OTHER})
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
#include "types.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "libabacus.h"
|
#include "libabacus.h"
|
||||||
#include "table.h"
|
#include "table.h"
|
||||||
|
@ -11,89 +14,27 @@ extern "C" {
|
||||||
class abacus {
|
class abacus {
|
||||||
private:
|
private:
|
||||||
libab ab;
|
libab ab;
|
||||||
abacus_ref scope;
|
ref scope;
|
||||||
std::map<std::string, abacus_ref> compiled_types;
|
std::map<std::string, ref> compiled_types;
|
||||||
libab_basetype basetype_string = { [](void* s) { delete ((string*) s); }, NULL, 0 };
|
libab_basetype basetype_string = { [](void* s) { delete ((string*) s); }, NULL, 0 };
|
||||||
public:
|
public:
|
||||||
abacus();
|
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_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_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_prefix(const std::string& op, const std::string& func);
|
||||||
void add_operator_postfix(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 <typename ... Ts>
|
template <typename ... Ts>
|
||||||
abacus_ref call(const std::string& bane, Ts...params);
|
ref call(const std::string& bane, Ts...params);
|
||||||
std::string to_string(abacus_ref& value);
|
std::string to_string(ref& value);
|
||||||
~abacus();
|
~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<libab_table>(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<libab_table>(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 <typename ... Ts>
|
template <typename ... Ts>
|
||||||
abacus_ref abacus::call(const std::string& name, Ts...params) {
|
ref abacus::call(const std::string& name, Ts...params) {
|
||||||
abacus_ref value;
|
ref value;
|
||||||
libab_run_function_scoped(&ab, name.c_str(), scope, value, sizeof...(params), (libab_ref*) params...);
|
libab_run_function_scoped(&ab, name.c_str(), scope, value, sizeof...(params), (libab_ref*) params...);
|
||||||
libab_gc_run(&ab.containers);
|
libab_gc_run(&ab.containers);
|
||||||
return value;
|
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<libab_parsetype>(&get<libab_value>(string_value)->type)->data_u.base;
|
|
||||||
if(base != &basetype_string) return "\"to_string\" did not return string.";
|
|
||||||
return get<string>(&get<libab_value>(string_value)->data)->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
abacus::~abacus() {
|
|
||||||
scope = nullptr;
|
|
||||||
libab_free(&ab);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "ref.hpp"
|
||||||
|
#include "util.hpp"
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "libabacus.h"
|
#include "libabacus.h"
|
||||||
}
|
}
|
||||||
|
@ -12,7 +14,7 @@ extern "C" {
|
||||||
mpfr_t output; \
|
mpfr_t output; \
|
||||||
mpfr_init2(output, PRECISION); \
|
mpfr_init2(output, PRECISION); \
|
||||||
mpfr_##func(output, value->value, MPFR_RNDN); \
|
mpfr_##func(output, value->value, MPFR_RNDN); \
|
||||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||||
libab_ref_copy(to_return, into); \
|
libab_ref_copy(to_return, into); \
|
||||||
return LIBAB_SUCCESS; \
|
return LIBAB_SUCCESS; \
|
||||||
}
|
}
|
||||||
|
@ -23,7 +25,7 @@ extern "C" {
|
||||||
mpfr_t output; \
|
mpfr_t output; \
|
||||||
mpfr_init2(output, PRECISION); \
|
mpfr_init2(output, PRECISION); \
|
||||||
mpfr_##func(output, left->value, right->value, MPFR_RNDN); \
|
mpfr_##func(output, left->value, right->value, MPFR_RNDN); \
|
||||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||||
libab_ref_copy(to_return, into); \
|
libab_ref_copy(to_return, into); \
|
||||||
return LIBAB_SUCCESS; \
|
return LIBAB_SUCCESS; \
|
||||||
}
|
}
|
||||||
|
@ -39,23 +41,31 @@ FUNCTION(print_string);
|
||||||
FUNCTION(to_string_num);
|
FUNCTION(to_string_num);
|
||||||
FUNCTION(to_string_bool);
|
FUNCTION(to_string_bool);
|
||||||
FUNCTION(to_string_unit);
|
FUNCTION(to_string_unit);
|
||||||
|
|
||||||
FUNCTION(plus);
|
FUNCTION(plus);
|
||||||
FUNCTION(minus);
|
FUNCTION(minus);
|
||||||
FUNCTION(times);
|
FUNCTION(times);
|
||||||
FUNCTION(divide);
|
FUNCTION(divide);
|
||||||
|
FUNCTION(pow);
|
||||||
|
|
||||||
FUNCTION(lt);
|
FUNCTION(lt);
|
||||||
FUNCTION(lte);
|
FUNCTION(lte);
|
||||||
FUNCTION(equals);
|
FUNCTION(equals);
|
||||||
FUNCTION(gt);
|
FUNCTION(gt);
|
||||||
FUNCTION(gte);
|
FUNCTION(gte);
|
||||||
|
|
||||||
FUNCTION(negate);
|
FUNCTION(negate);
|
||||||
|
|
||||||
FUNCTION(ln);
|
FUNCTION(ln);
|
||||||
FUNCTION(exp);
|
FUNCTION(exp);
|
||||||
|
|
||||||
FUNCTION(sin);
|
FUNCTION(sin);
|
||||||
FUNCTION(cos);
|
FUNCTION(cos);
|
||||||
FUNCTION(tan);
|
FUNCTION(tan);
|
||||||
|
|
||||||
FUNCTION(arcsin);
|
FUNCTION(arcsin);
|
||||||
FUNCTION(arccos);
|
FUNCTION(arccos);
|
||||||
FUNCTION(arctan);
|
FUNCTION(arctan);
|
||||||
|
|
||||||
FUNCTION(quit);
|
FUNCTION(quit);
|
||||||
FUNCTION(request_precision);
|
FUNCTION(request_precision);
|
||||||
|
|
|
@ -1,25 +1,24 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#include "libabacus.h"
|
#include "libabacus.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
class abacus_ref {
|
class ref {
|
||||||
private:
|
private:
|
||||||
libab_ref ref;
|
libab_ref val;
|
||||||
public:
|
public:
|
||||||
abacus_ref();
|
ref();
|
||||||
abacus_ref(void* data, void (*free_func)(void*));
|
ref(void* data, void (*free_func)(void*));
|
||||||
abacus_ref(const abacus_ref& other);
|
ref(const ref& other);
|
||||||
abacus_ref& operator=(const abacus_ref& other);
|
ref& operator=(const ref& other);
|
||||||
abacus_ref& operator=(std::nullptr_t);
|
ref& operator=(std::nullptr_t);
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool operator==(T data);
|
bool operator==(T data);
|
||||||
operator libab_ref*() {
|
operator libab_ref*();
|
||||||
return &ref;
|
~ref();
|
||||||
}
|
|
||||||
~abacus_ref();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
@ -27,39 +26,11 @@ T* get(libab_ref* ref) {
|
||||||
return (T*) libab_ref_get(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 <typename T>
|
template <typename T>
|
||||||
bool abacus_ref::operator==(T data) {
|
bool ref::operator==(T data) {
|
||||||
return libab_ref_get(&ref) == (void*) data;
|
return libab_ref_get(&val) == (void*) data;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
bool abacus_ref::operator==<std::nullptr_t>(std::nullptr_t t) {
|
bool ref::operator==<std::nullptr_t>(std::nullptr_t t);
|
||||||
return libab_ref_get(&ref) == t;
|
|
||||||
}
|
|
||||||
|
|
||||||
abacus_ref::~abacus_ref() {
|
|
||||||
libab_ref_free(&ref);
|
|
||||||
}
|
|
||||||
|
|
|
@ -5,24 +5,15 @@
|
||||||
|
|
||||||
struct string {
|
struct string {
|
||||||
std::string value;
|
std::string value;
|
||||||
string(std::string&& new_value) : value(std::move(new_value)) {}
|
string(std::string&& new_value);
|
||||||
string(const std::string& new_value) : value(new_value) {}
|
string(const std::string& new_value);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct number {
|
struct number {
|
||||||
mpfr_t value;
|
mpfr_t value;
|
||||||
number(const char* new_value) {
|
number(const char* new_value);
|
||||||
mpfr_init2(value, PRECISION);
|
number(mpfr_t&& new_value);
|
||||||
mpfr_set_str(value, new_value, 10, MPFR_RNDN);
|
int to_int();
|
||||||
}
|
~number();
|
||||||
number(mpfr_t&& new_value) {
|
|
||||||
std::swap(value, new_value);
|
|
||||||
}
|
|
||||||
int to_int() {
|
|
||||||
return mpfr_get_si(value, MPFR_RNDN);
|
|
||||||
}
|
|
||||||
~number() {
|
|
||||||
mpfr_clear(value);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
13
include/util.hpp
Normal file
13
include/util.hpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.hpp"
|
||||||
|
#include "ref.hpp"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
ref create_value(libab* ab, T* val);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ref create_value<string>(libab* ab, string* param);
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ref create_value<number>(libab* ab, number* param);
|
63
src/abacus.cpp
Normal file
63
src/abacus.cpp
Normal file
|
@ -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<libab_table>(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<libab_table>(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<libab_parsetype>(&get<libab_value>(string_value)->type)->data_u.base;
|
||||||
|
if(base != &basetype_string) return "\"to_string\" did not return string.";
|
||||||
|
return get<string>(&get<libab_value>(string_value)->data)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
abacus::~abacus() {
|
||||||
|
scope = nullptr;
|
||||||
|
libab_free(&ab);
|
||||||
|
}
|
87
src/main.cpp
87
src/main.cpp
|
@ -14,95 +14,10 @@ extern "C" {
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// == Global State (uh-oh)
|
// == Global State (uh-oh)
|
||||||
bool close_requested = false;
|
bool close_requested = false;
|
||||||
long requested_precision = 3;
|
long requested_precision = 3;
|
||||||
|
|
||||||
//
|
|
||||||
// == BASIC FUNCTIONS
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
abacus_ref create_value(libab* ab, T* val);
|
|
||||||
|
|
||||||
template <>
|
|
||||||
abacus_ref create_value<string>(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<number>(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) {
|
FUNCTION(quit) {
|
||||||
close_requested = true;
|
close_requested = true;
|
||||||
libab_get_unit_value(ab, into);
|
libab_get_unit_value(ab, into);
|
||||||
|
@ -170,7 +85,7 @@ int main() {
|
||||||
add_history(data);
|
add_history(data);
|
||||||
free(data);
|
free(data);
|
||||||
|
|
||||||
abacus_ref value = ab.run(buffer);
|
ref value = ab.run(buffer);
|
||||||
if(value == nullptr) {
|
if(value == nullptr) {
|
||||||
std::cout << "Invalid expression." << std::endl;
|
std::cout << "Invalid expression." << std::endl;
|
||||||
} else {
|
} else {
|
||||||
|
|
15
src/operator_functions.cpp
Normal file
15
src/operator_functions.cpp
Normal file
|
@ -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, >=);
|
5
src/other_functions.cpp
Normal file
5
src/other_functions.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#include "functions.hpp"
|
||||||
|
|
||||||
|
FUNCTION_MPFR(ln, log);
|
||||||
|
FUNCTION_MPFR(exp, exp);
|
||||||
|
|
37
src/ref.cpp
Normal file
37
src/ref.cpp
Normal file
|
@ -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>(std::nullptr_t t) {
|
||||||
|
return libab_ref_get(&val) == t;
|
||||||
|
}
|
40
src/string_functions.cpp
Normal file
40
src/string_functions.cpp
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
#include "functions.hpp"
|
||||||
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
9
src/trig_functions.cpp
Normal file
9
src/trig_functions.cpp
Normal file
|
@ -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);
|
18
src/types.cpp
Normal file
18
src/types.cpp
Normal file
|
@ -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);
|
||||||
|
}
|
19
src/util.cpp
Normal file
19
src/util.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include "util.hpp"
|
||||||
|
|
||||||
|
template <>
|
||||||
|
ref create_value<string>(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<number>(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;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user