Begin splitting code into separate files.
This commit is contained in:
parent
05655a2878
commit
dfad4a2cfc
99
include/abacus.hpp
Normal file
99
include/abacus.hpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#pragma once
|
||||
|
||||
#include "ref.hpp"
|
||||
extern "C" {
|
||||
#include "libabacus.h"
|
||||
#include "table.h"
|
||||
#include "value.h"
|
||||
#include "util.h"
|
||||
}
|
||||
|
||||
class abacus {
|
||||
private:
|
||||
libab ab;
|
||||
abacus_ref scope;
|
||||
std::map<std::string, abacus_ref> 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_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);
|
||||
template <typename ... Ts>
|
||||
abacus_ref call(const std::string& bane, Ts...params);
|
||||
std::string to_string(abacus_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<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>
|
||||
abacus_ref abacus::call(const std::string& name, Ts...params) {
|
||||
abacus_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<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);
|
||||
}
|
3
include/config.hpp
Normal file
3
include/config.hpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
#define PRECISION 200
|
61
include/functions.hpp
Normal file
61
include/functions.hpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include "libabacus.h"
|
||||
}
|
||||
|
||||
#define FUNCTION(name) libab_result function_##name( \
|
||||
libab* ab, libab_ref* scope, libab_ref_vec* params, libab_ref* into)
|
||||
|
||||
#define FUNCTION_MPFR(name, func) FUNCTION(name) { \
|
||||
number* value = (number*) libab_unwrap_param(params, 0); \
|
||||
mpfr_t output; \
|
||||
mpfr_init2(output, PRECISION); \
|
||||
mpfr_##func(output, value->value, MPFR_RNDN); \
|
||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||
libab_ref_copy(to_return, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
#define FUNCTION_MPFR2(name, func) FUNCTION(name) { \
|
||||
number* left = (number*) libab_unwrap_param(params, 0); \
|
||||
number* right = (number*) libab_unwrap_param(params, 1); \
|
||||
mpfr_t output; \
|
||||
mpfr_init2(output, PRECISION); \
|
||||
mpfr_##func(output, left->value, right->value, MPFR_RNDN); \
|
||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||
libab_ref_copy(to_return, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
#define FUNCTION_COMPARE(name, op) FUNCTION(name) { \
|
||||
number* left = (number*) libab_unwrap_param(params, 0); \
|
||||
number* right = (number*) libab_unwrap_param(params, 1); \
|
||||
libab_get_bool_value(ab, mpfr_cmp(left->value, right->value) op 0, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
FUNCTION(print_string);
|
||||
FUNCTION(to_string_num);
|
||||
FUNCTION(to_string_bool);
|
||||
FUNCTION(to_string_unit);
|
||||
FUNCTION(plus);
|
||||
FUNCTION(minus);
|
||||
FUNCTION(times);
|
||||
FUNCTION(divide);
|
||||
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);
|
65
include/ref.hpp
Normal file
65
include/ref.hpp
Normal file
|
@ -0,0 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include "libabacus.h"
|
||||
#include "util.h"
|
||||
}
|
||||
|
||||
class abacus_ref {
|
||||
private:
|
||||
libab_ref ref;
|
||||
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);
|
||||
template <typename T>
|
||||
bool operator==(T data);
|
||||
operator libab_ref*() {
|
||||
return &ref;
|
||||
}
|
||||
~abacus_ref();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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 <typename T>
|
||||
bool abacus_ref::operator==(T data) {
|
||||
return libab_ref_get(&ref) == (void*) data;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool abacus_ref::operator==<std::nullptr_t>(std::nullptr_t t) {
|
||||
return libab_ref_get(&ref) == t;
|
||||
}
|
||||
|
||||
abacus_ref::~abacus_ref() {
|
||||
libab_ref_free(&ref);
|
||||
}
|
28
include/types.hpp
Normal file
28
include/types.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
#include <mpfr.h>
|
||||
#include <string>
|
||||
#include "config.hpp"
|
||||
|
||||
struct string {
|
||||
std::string value;
|
||||
string(std::string&& new_value) : value(std::move(new_value)) {}
|
||||
string(const std::string& new_value) : value(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);
|
||||
}
|
||||
};
|
||||
|
218
src/main.cpp
218
src/main.cpp
|
@ -3,6 +3,10 @@
|
|||
#include <mpfr.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include "types.hpp"
|
||||
#include "ref.hpp"
|
||||
#include "functions.hpp"
|
||||
#include "abacus.hpp"
|
||||
extern "C" {
|
||||
#include "libabacus.h"
|
||||
#include "table.h"
|
||||
|
@ -10,99 +14,13 @@ extern "C" {
|
|||
#include "util.h"
|
||||
}
|
||||
|
||||
#define PRECISION 200
|
||||
|
||||
// == Global State (uh-oh)
|
||||
bool close_requested = false;
|
||||
long requested_precision = 3;
|
||||
|
||||
// == STRING Type
|
||||
struct string {
|
||||
std::string value;
|
||||
string(std::string&& new_value) : value(std::move(new_value)) {}
|
||||
string(const std::string& new_value) : value(new_value) {}
|
||||
};
|
||||
|
||||
// MPFR Type
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// == Reference Wrapper
|
||||
class abacus_ref {
|
||||
private:
|
||||
libab_ref ref;
|
||||
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);
|
||||
template <typename T>
|
||||
bool operator==(T data);
|
||||
operator libab_ref*() {
|
||||
return &ref;
|
||||
}
|
||||
~abacus_ref();
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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 <typename T>
|
||||
bool abacus_ref::operator==(T data) {
|
||||
return libab_ref_get(&ref) == (void*) data;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool abacus_ref::operator==<std::nullptr_t>(std::nullptr_t t) {
|
||||
return libab_ref_get(&ref) == t;
|
||||
}
|
||||
|
||||
abacus_ref::~abacus_ref() {
|
||||
libab_ref_free(&ref);
|
||||
}
|
||||
//
|
||||
// == BASIC FUNCTIONS
|
||||
#define FUNCTION(name) libab_result function_##name(libab* ab, libab_ref* scope, libab_ref_vec* params, libab_ref* into)
|
||||
|
||||
template <typename T>
|
||||
abacus_ref create_value(libab* ab, T* val);
|
||||
|
@ -160,42 +78,6 @@ FUNCTION(to_string_unit) {
|
|||
return LIBAB_SUCCESS;
|
||||
}
|
||||
|
||||
#define OPERATOR_FUNCTION(name, op) FUNCTION(name) { \
|
||||
number* left = (number*) libab_unwrap_param(params, 0); \
|
||||
number* right = (number*) libab_unwrap_param(params, 1); \
|
||||
abacus_ref value = create_value(ab, *left op *right); \
|
||||
libab_ref_copy(value, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
#define FUNCTION_MPFR(name, func) FUNCTION(name) { \
|
||||
number* value = (number*) libab_unwrap_param(params, 0); \
|
||||
mpfr_t output; \
|
||||
mpfr_init2(output, PRECISION); \
|
||||
mpfr_##func(output, value->value, MPFR_RNDN); \
|
||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||
libab_ref_copy(to_return, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
#define FUNCTION_MPFR2(name, func) FUNCTION(name) { \
|
||||
number* left = (number*) libab_unwrap_param(params, 0); \
|
||||
number* right = (number*) libab_unwrap_param(params, 1); \
|
||||
mpfr_t output; \
|
||||
mpfr_init2(output, PRECISION); \
|
||||
mpfr_##func(output, left->value, right->value, MPFR_RNDN); \
|
||||
abacus_ref to_return = create_value<number>(ab, new number(std::move(output))); \
|
||||
libab_ref_copy(to_return, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
#define FUNCTION_COMPARE(name, op) FUNCTION(name) { \
|
||||
number* left = (number*) libab_unwrap_param(params, 0); \
|
||||
number* right = (number*) libab_unwrap_param(params, 1); \
|
||||
libab_get_bool_value(ab, mpfr_cmp(left->value, right->value) op 0, into); \
|
||||
return LIBAB_SUCCESS; \
|
||||
}
|
||||
|
||||
FUNCTION_MPFR2(plus, add)
|
||||
FUNCTION_MPFR2(minus, sub)
|
||||
FUNCTION_MPFR2(times, mul)
|
||||
|
@ -221,8 +103,6 @@ FUNCTION_MPFR(arcsin, asin);
|
|||
FUNCTION_MPFR(arccos, acos);
|
||||
FUNCTION_MPFR(arctan, atan);
|
||||
|
||||
FUNCTION(sqrt);
|
||||
|
||||
FUNCTION(quit) {
|
||||
close_requested = true;
|
||||
libab_get_unit_value(ab, into);
|
||||
|
@ -236,96 +116,6 @@ FUNCTION(request_precision) {
|
|||
return LIBAB_SUCCESS;
|
||||
}
|
||||
|
||||
// == Main class
|
||||
class abacus {
|
||||
private:
|
||||
libab ab;
|
||||
abacus_ref scope;
|
||||
std::map<std::string, abacus_ref> 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_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);
|
||||
template <typename ... Ts>
|
||||
abacus_ref call(const std::string& bane, Ts...params);
|
||||
std::string to_string(abacus_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<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>
|
||||
abacus_ref abacus::call(const std::string& name, Ts...params) {
|
||||
abacus_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<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);
|
||||
}
|
||||
int main() {
|
||||
abacus ab;
|
||||
rl_bind_key('\t', rl_insert);
|
||||
|
|
Loading…
Reference in New Issue
Block a user