parent
dfad4a2cfc
commit
48355b0736
@ -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); |
@ -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); |
||||
} |
@ -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, >=); |
@ -0,0 +1,5 @@ |
||||
#include "functions.hpp" |
||||
|
||||
FUNCTION_MPFR(ln, log); |
||||
FUNCTION_MPFR(exp, exp); |
||||
|
@ -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; |
||||
} |
@ -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; |
||||
} |
@ -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); |
@ -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); |
||||
} |
@ -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