#72: refactored source code for [quite] conventional cpp and hpp. Includes in class still exist

This commit is contained in:
Louis Rubet 2017-05-25 18:13:16 +02:00
parent 9a0339079d
commit 9c88a4f679
19 changed files with 191 additions and 1191 deletions

View file

@ -3,20 +3,12 @@ ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS}
bin_PROGRAMS = rpn
rpn_SOURCES = src/rpn.cpp \
src/rpn-branch.h \
src/rpn-cmd.h \
src/rpn-algebra.h \
src/rpn-general-core.h \
src/rpn-general.h \
src/rpn-logs.h \
src/rpn-stack.h \
src/rpn-store.h \
src/rpn-test.h \
src/rpn-trig.h \
src/stack.h
rpn_SOURCES = src/object.cpp \
src/program.cpp \
src/main.cpp
rpn_CFLAGS =
rpn_CFLAGS = -g
rpn_LDFLAGS = -Wl,--no-as-needed -lreadline -lmpfr
dist_noinst_SCRIPTS = autogen.sh

View file

@ -1,3 +1,6 @@
#ifndef CONSTANT_H
#define CONSTANT_H
// default values
//
@ -31,8 +34,26 @@
#define MPFR_RND_STRINGS { "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" }
// return values
// return values, used by all classes
//
typedef enum {
ret_ok,
ret_unknown_err,
ret_missing_operand,
ret_bad_operand_type,
ret_out_of_range,
ret_unknown_variable,
ret_internal,
ret_deadly,
ret_good_bye,
ret_not_impl,
ret_nop,
ret_syntax,
ret_div_by_zero,
ret_runtime_error,
ret_max
} ret_value;
#define RET_VALUE_STRINGS { \
"ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", \
"deadly", "goodbye", "not implemented", "no operation", "syntax error", "division by zero", "runtime error" \
@ -41,3 +62,5 @@
// command types
//
#define CMD_TYPE_STRINGS { "undef", "number", "string", "symbol", "program", "keyword", "keyword" }
#endif

View file

@ -1,3 +1,6 @@
#ifndef DEBUG_H
#define DEBUG_H
static void dump8(unsigned char* to_dump, unsigned long offset,
unsigned long size)
{
@ -43,3 +46,4 @@ static void dump8(unsigned char* to_dump, unsigned long offset,
//
#define TRACE(...) do { (void)printf(__FUNCTION__ ": "); (void)printf(__VA_ARGS__); } while(0)
#endif

View file

@ -1,3 +1,6 @@
#ifndef ESCAPE_H
#define ESCAPE_H
// ANSI escape sequences
// foreground colors
@ -29,4 +32,6 @@
#define ATTR_REVERSE "\33[7m"
#define ATTR_CONCEALED "\33[8m"
#define ATTR_OFF "\33[0m"
#define ATTR_OFF "\33[0m"
#endif

View file

@ -1,25 +1,74 @@
// keywords declaration
struct keyword_t
public:
static ret_value parse(const char* entry, program& prog)
{
cmd_type_t type;
char name[24];
program_fn_t fn;
string comment;
};
static const int g_max_commands = 128;
static keyword_t _keywords[g_max_commands];
vector<string> entries;
ret_value ret = ret_ok;
//1. cut global entry string into shorter strings
if (_cut(entry, entries))
{
//2. make an object from each entry, and add it to the program
for (vector<string>::iterator it = entries.begin(); it != entries.end(); it++)
{
string remaining_entry;
string main_entry = (*it);
while(main_entry.size()>0)
{
// remaining_entry is used only in case of concatenated entry
// ex: entry="1 2+" -> vector<string> = {"1", "2+"} -> first "1", second "2" and remaining_entry="+"
// this remaining entry is treated as an entry
// TODO errors ?
_obj_from_string(main_entry, prog, remaining_entry);
main_entry = remaining_entry;
}
}
}
return ret;
}
// interactive entry and decoding
static ret_value entry(program& prog)
{
char* buf;
ret_value ret;
// declare completion fn (bound to '\t' by default)
rl_completion_entry_function = entry_completion_generator;
// get user entry
buf = readline(prompt);
if (buf != NULL)
{
// parse it
ret = parse(buf, prog);
// keep history
if (buf[0]!=0)
add_history(buf);
}
else
ret = ret_internal;
//TODO
free(buf);
}
private:
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type)
{
for(unsigned int i=0; (i<sizeof(_keywords)/sizeof(_keywords[0])) && (_keywords[i].type != cmd_max); i++)
unsigned int i = 0;
while(s_keywords[i].type != cmd_max)
{
if ((strnlen(_keywords[i].name, sizeof(_keywords[i].name))>0)
&& (strncmp(fn_name, _keywords[i].name, sizeof(_keywords[i].name)) == 0))
if ((strnlen(s_keywords[i].name, sizeof(s_keywords[i].name))>0)
&& (strncmp(fn_name, s_keywords[i].name, sizeof(s_keywords[i].name)) == 0))
{
fn = _keywords[i].fn;
type = _keywords[i].type;
fn = s_keywords[i].fn;
type = s_keywords[i].type;
return ret_ok;
}
i++;
}
return ret_unknown_err;
}
@ -417,16 +466,16 @@ static char* entry_completion_generator(const char* text, int state)
while(too_far == 0)
{
list_index++;
if (_keywords[list_index].fn != NULL)
if (s_keywords[list_index].fn != NULL)
{
// compare list entry with text, return if match
if (strncmp(_keywords[list_index].name, text, len) == 0)
return entry_completion_dupstr(_keywords[list_index].name);
if (strncmp(s_keywords[list_index].name, text, len) == 0)
return entry_completion_dupstr(s_keywords[list_index].name);
}
else
{
// fn=NULL and size=0 = last entry in list -> go out
if (_keywords[list_index].comment.size() == 0)
if (s_keywords[list_index].comment.size() == 0)
too_far = 1;
}
}
@ -443,59 +492,3 @@ static char* entry_completion_dupstr(char* s)
strcpy(r, s);
return r;
}
static ret_value parse(const char* entry, program& prog)
{
vector<string> entries;
ret_value ret = ret_ok;
//1. cut global entry string into shorter strings
if (_cut(entry, entries))
{
//2. make an object from each entry, and add it to the program
for (vector<string>::iterator it = entries.begin(); it != entries.end(); it++)
{
string remaining_entry;
string main_entry = (*it);
while(main_entry.size()>0)
{
// remaining_entry is used only in case of concatenated entry
// ex: entry="1 2+" -> vector<string> = {"1", "2+"} -> first "1", second "2" and remaining_entry="+"
// this remaining entry is treated as an entry
// TODO errors ?
_obj_from_string(main_entry, prog, remaining_entry);
main_entry = remaining_entry;
}
}
}
return ret;
}
// interactive entry and decoding
static ret_value entry(program& prog)
{
char* buf;
ret_value ret;
// declare completion fn (bound to '\t' by default)
rl_completion_entry_function = entry_completion_generator;
// get user entry
buf = readline(prompt);
if (buf != NULL)
{
// parse it
ret = parse(buf, prog);
// keep history
if (buf[0]!=0)
add_history(buf);
}
else
ret = ret_internal;
//TODO
free(buf);
}

View file

@ -1,4 +1,3 @@
//
int rpn_if(branch& myobj)
{

View file

@ -1,135 +0,0 @@
program::keyword_t program::_keywords[] =
{
//GENERAL
{ cmd_undef, "", NULL, "\nGENERAL"},
{ cmd_keyword, "nop", &program::nop, "no operation"},
{ cmd_keyword, "?", &program::help, "" },
{ cmd_keyword, "h", &program::help, "" },
{ cmd_keyword, "help", &program::help, "(or h or ?) this help message" },
{ cmd_keyword, "q", &program::good_bye, "" },
{ cmd_keyword, "quit", &program::good_bye, "(or q or exit) quit software" },
{ cmd_keyword, "exit", &program::good_bye, "" },
{ cmd_keyword, "test", &program::test, "" }, //not seen by user
{ cmd_keyword, "version", &program::rpn_version, "show rpn version" },
{ cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string" },
{ cmd_keyword, "type", &program::type, "show type of stack first entry" },
{ cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default" },
{ cmd_keyword, "prec", &program::precision, "get float precision in bits when first stack is not a number\n\t"
"set float precision in bits when first stack entry is a number. ex: 256 prec\n\t" },
{ cmd_keyword, "round", &program::round, "set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward +inf\", \"toward -inf\", \"away from zero\"] round" },
//REAL
{ cmd_undef, "", NULL, "\nREAL"},
{ cmd_keyword, "+", &program::plus, "addition" },
{ cmd_keyword, "-", &program::minus, "substraction" },
{ cmd_keyword, "neg", &program::neg , "negation" },
{ cmd_keyword, "*", &program::mul, "multiplication" },
{ cmd_keyword, "/", &program::div, "division" },
{ cmd_keyword, "inv", &program::inv, "inverse" },
{ cmd_keyword, "%", &program::purcent, "purcent" },
{ cmd_keyword, "%CH", &program::purcentCH, "inverse purcent" },
{ cmd_keyword, "^", &program::power, "(or pow) power" },
{ cmd_keyword, "pow", &program::power, "" },
{ cmd_keyword, "sqrt", &program::squareroot, "square root" },
{ cmd_keyword, "sq", &program::square, "(or sqr) square" },
{ cmd_keyword, "sqr", &program::square, "" },
{ cmd_keyword, "mod", &program::modulo, "modulo" },
{ cmd_keyword, "abs", &program::rpn_abs, "absolute value" },
//REAL representation
{ cmd_undef, "", NULL, "\nREAL REPRESENTATION"},
{ cmd_keyword, "dec", &program::dec, "decimal representation" },
{ cmd_keyword, "hex", &program::hex, "hexadecimal representation" },
{ cmd_keyword, "bin", &program::bin, "binary representation" },
{ cmd_keyword, "std", &program::std, "standard floating numbers representation. ex: [25] std" },
{ cmd_keyword, "fix", &program::fix, "fixed point representation. ex: 6 fix" },
{ cmd_keyword, "sci", &program::sci, "scientific floating point representation. ex: 20 sci" },
//TEST
{ cmd_undef, "", NULL, "\nTEST"},
{ cmd_keyword, ">", &program::sup, "binary operator >" },
{ cmd_keyword, ">=", &program::sup_eq, "binary operator >=" },
{ cmd_keyword, "<", &program::inf, "binary operator <" },
{ cmd_keyword, "<=", &program::inf_eq, "binary operator <=" },
{ cmd_keyword, "!=", &program::diff, "binary operator != (different)" },
{ cmd_keyword, "==", &program::eq , "binary operator == (equal)" },
{ cmd_keyword, "and", &program::test_and , "boolean operator and" },
{ cmd_keyword, "or", &program::test_or , "boolean operator or" },
{ cmd_keyword, "xor", &program::test_xor , "boolean operator xor" },
{ cmd_keyword, "not", &program::test_not , "boolean operator not" },
{ cmd_keyword, "same", &program::same , "boolean operator same (equal)" },
//STACK
{ cmd_undef, "", NULL, "\nSTACK"},
{ cmd_keyword, "swap", &program::swap, "swap 2 first stack entries" },
{ cmd_keyword, "drop", &program::drop, "drop first stack entry" },
{ cmd_keyword, "drop2", &program::drop2, "drop 2 first stack entries" },
{ cmd_keyword, "erase", &program::erase, "drop all stack entries" },
{ cmd_keyword, "rot", &program::rot, "rotate 3 first stack entries" },
{ cmd_keyword, "dup", &program::dup, "duplicate first stack entry" },
{ cmd_keyword, "dup2", &program::dup2, "duplicate 2 first stack entries" },
{ cmd_keyword, "pick", &program::pick, "push a copy of the given stack level onto the stack" },
{ cmd_keyword, "depth", &program::depth, "give stack depth" },
//STRING
{ cmd_undef, "", NULL, "\nSTRING"},
{ cmd_keyword, "->str", &program::instr, "convert an object into a string" },
{ cmd_keyword, "str->", &program::strout, "convert a string into an object" },
//BRANCH
{ cmd_undef, "", NULL, "\nBRANCH"},
{ cmd_branch, "if", (program_fn_t)&program::rpn_if, "<test-instructions>" },
{ cmd_branch, "then", (program_fn_t)&program::rpn_then, "<true-instructions>" },
{ cmd_branch, "else", (program_fn_t)&program::rpn_else, "<false-instructions>" },
{ cmd_keyword, "end", &program::rpn_end, "(end of if structure)" },
{ cmd_branch, "start", (program_fn_t)&program::rpn_start, "repeat instructions several times" },
{ cmd_branch, "for", (program_fn_t)&program::rpn_for, "repeat instructions several times with variable" },
{ cmd_branch, "next", (program_fn_t)&program::rpn_next, "ex: 1 10 start <instructions> next" },
{ cmd_branch, "step", (program_fn_t)&program::rpn_step, "ex: 1 100 start <instructions> 4 step" },
//STORE
{ cmd_undef, "", NULL, "\nSTORE"},
{ cmd_keyword, "sto", &program::sto, "store a variable. ex: 1 'name' sto" },
{ cmd_keyword, "rcl", &program::rcl, "recall a variable. ex: 'name' rcl" },
{ cmd_keyword, "purge", &program::purge, "delete a variable. ex: 'name' purge" },
{ cmd_keyword, "vars", &program::vars, "list all variables" },
{ cmd_keyword, "edit", &program::edit, "edit a variable content" },
//PROGRAM
{ cmd_undef, "", NULL, "\nPROGRAM"},
{ cmd_keyword, "eval", &program::eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" },
{ cmd_branch, "->", (program_fn_t)&program::inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> >>" },
//TRIG
{ cmd_undef, "", NULL, "\nTRIG"},
{ cmd_keyword, "pi", &program::pi, "PI constant" },
{ cmd_keyword, "sin", &program::rpn_sin, "sinus" },
{ cmd_keyword, "asin", &program::rpn_asin, "arg sinus" },
{ cmd_keyword, "cos", &program::rpn_cos , "cosinus" },
{ cmd_keyword, "acos", &program::rpn_acos, "arg cosinus" },
{ cmd_keyword, "tan", &program::rpn_tan, "tangent" },
{ cmd_keyword, "atan", &program::rpn_atan, "arg tangent" },
{ cmd_keyword, "d->r", &program::d2r, "convert degrees to radians" },
{ cmd_keyword, "r->d", &program::r2d, "convert radians to degrees" },
//LOGS
{ cmd_undef, "", NULL, "\nLOGS"},
{ cmd_keyword, "e", &program::rpn_e, "exp(0) constant" },
{ cmd_keyword, "log", &program::rpn_log, "logarithm base 10" },
{ cmd_keyword, "alog", &program::rpn_alog, "(or exp10) exponential base 10" },
{ cmd_keyword, "exp10", &program::rpn_alog, "" },
{ cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2" },
{ cmd_keyword, "alog2", &program::rpn_alog2, "(or exp2) exponential base 2" },
{ cmd_keyword, "exp2", &program::rpn_alog2, "" },
{ cmd_keyword, "ln", &program::rpn_ln, "logarithm base e" },
{ cmd_keyword, "exp", &program::rpn_exp, "exponential" },
{ cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine" },
{ cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine" },
{ cmd_keyword, "cosh", &program::rpn_sinh, "hyperbolic cosine" },
{ cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine" },
{ cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent" },
{ cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent" },
// end
{ cmd_max, "", NULL, "" },
};

View file

@ -21,18 +21,20 @@ void help()
printf("%s\n", syntax);
// keywords
for(unsigned int i=0; i<sizeof(_keywords)/sizeof(_keywords[0]); i++)
unsigned int i = 0;
while(s_keywords[i].type != cmd_max)
{
if (_keywords[i].comment.size() != 0)
if (s_keywords[i].comment.size() != 0)
{
// titles in bold
if (_keywords[i].type==cmd_undef)
if (s_keywords[i].type==cmd_undef)
printf(ATTR_BOLD);
// show title or keyword + comment
printf("%s\t%s\n", _keywords[i].name, _keywords[i].comment.c_str());
if (_keywords[i].type==cmd_undef)
printf("%s\t%s\n", s_keywords[i].name, s_keywords[i].comment.c_str());
if (s_keywords[i].type==cmd_undef)
printf(ATTR_OFF);
}
i++;
}
printf("\n");
@ -48,8 +50,8 @@ void help()
printf(" with %d digits\n", number::s_current_precision);
// calc precision and rounding mode
printf("Current floating point precision is %d bits\n", (int)s_mpfr_prec);
printf("Current rounding mode is '%s'\n", s_mpfr_rnd_str[s_mpfr_rnd]);
printf("Current floating point precision is %d bits\n", (int)floating_t::s_mpfr_prec);
printf("Current rounding mode is '%s'\n", floating_t::s_mpfr_rnd_str[floating_t::s_mpfr_rnd]);
printf("\n\n");
}
@ -71,7 +73,7 @@ void std()
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD);
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD);
}
void fix()
@ -87,7 +89,7 @@ void fix()
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_FIX);
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_FIX);
}
void sci()
@ -103,7 +105,7 @@ void sci()
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_SCI);
number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_SCI);
}
void rpn_version()
@ -130,10 +132,10 @@ void type()
if (type < 0 || type >= (int)cmd_max)
type = (int)cmd_undef;
unsigned int string_size = strlen(cmd_type_string[type]);
unsigned int string_size = strlen(object::s_cmd_type_string[type]);
unsigned int size = sizeof(symbol)+string_size+1;
symbol* sym = (symbol*)_stack->allocate_back(size, cmd_symbol);
sym->set(cmd_type_string[type], string_size, false);
sym->set(object::s_cmd_type_string[type], string_size, false);
}
void rpn_default()
@ -147,11 +149,11 @@ void precision()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
//set MPFR float precision
long prec = mpfr_get_si(((number*)_stack->pop_back())->_value.mpfr, s_mpfr_rnd);
long prec = mpfr_get_si(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd);
if (prec >= 0)
{
s_mpfr_prec = (mpfr_prec_t)prec;
s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
floating_t::s_mpfr_prec = (mpfr_prec_t)prec;
floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec);
}
else
ERR_CONTEXT(ret_out_of_range);
@ -166,9 +168,9 @@ void round()
bool done = false;
for(int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++)
{
if (string(s_mpfr_rnd_str[rnd]) == str->_value)
if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value)
{
s_mpfr_rnd = (mpfr_rnd_t)rnd;
floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd;
done = true;
}
}

View file

@ -2,7 +2,7 @@ void rpn_e(void)
{
number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
euler->_value = 1L;
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd));
}
void rpn_log()
@ -11,7 +11,7 @@ void rpn_log()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_log10(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_log10(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_alog()
@ -20,7 +20,7 @@ void rpn_alog()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_exp10(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_exp10(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_log2()
@ -29,7 +29,7 @@ void rpn_log2()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_log2(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_log2(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_alog2()
@ -38,7 +38,7 @@ void rpn_alog2()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_exp2(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_exp2(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_ln()
@ -47,7 +47,7 @@ void rpn_ln()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_log(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_log(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_exp()
@ -56,7 +56,7 @@ void rpn_exp()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_sinh()
@ -65,7 +65,7 @@ void rpn_sinh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_asinh()
@ -74,7 +74,7 @@ void rpn_asinh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_cosh()
@ -83,7 +83,7 @@ void rpn_cosh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_acosh()
@ -92,7 +92,7 @@ void rpn_acosh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_tanh()
@ -101,7 +101,7 @@ void rpn_tanh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_atanh()
@ -110,5 +110,5 @@ void rpn_atanh()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}

View file

@ -6,7 +6,7 @@ void plus()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void minus()
@ -17,7 +17,7 @@ void minus()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void mul()
@ -28,7 +28,7 @@ void mul()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void div()
@ -39,7 +39,7 @@ void div()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void neg()
@ -48,7 +48,7 @@ void neg()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_neg(left->_value.mpfr, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_neg(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void inv()
@ -57,7 +57,7 @@ void inv()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void purcent()
@ -69,8 +69,8 @@ void purcent()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(left->_value.mpfr, left->_value.mpfr, 100L, floating_t::s_mpfr_rnd));
}
void purcentCH()
@ -82,8 +82,8 @@ void purcentCH()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_mul_si(right->_value.mpfr, right->_value.mpfr, 100L, s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_mul_si(right->_value.mpfr, right->_value.mpfr, 100L, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->_value.mpfr, right->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void power()
@ -94,7 +94,7 @@ void power()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void squareroot()
@ -103,7 +103,7 @@ void squareroot()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void square()
@ -112,7 +112,7 @@ void square()
ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_sqr(left->_value.mpfr, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_sqr(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void modulo()
@ -124,7 +124,7 @@ void modulo()
number* right = (number*)_stack->pop_back();
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd));
}
void rpn_abs()
@ -134,7 +134,7 @@ void rpn_abs()
number* left = (number*)_stack->back();
CHECK_MPFR(mpfr_abs(left->_value.mpfr, left->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd));
}
void hex()

View file

@ -105,7 +105,7 @@ void vars(void)
for (int i=0; i<(int)_heap->size(); i++)
{
(void)_heap->get_by_index(i, name, obj, size);
printf("var %d: name '%s', type %s, value ", i+1, name.c_str(), cmd_type_string[obj->_type]);
printf("var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
@ -116,7 +116,7 @@ void vars(void)
for (int i=0; i<(int)parent->_local_heap.size(); i++)
{
(void)parent->_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), cmd_type_string[obj->_type]);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}
@ -127,7 +127,7 @@ void vars(void)
for (int i=0; i<(int)_local_heap.size(); i++)
{
(void)_local_heap.get_by_index(i, name, obj, size);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), cmd_type_string[obj->_type]);
printf("local var %d: name '%s', type %s, value ", i+1, name.c_str(), object::s_cmd_type_string[obj->_type]);
obj->show();
printf("\n");
}

View file

@ -8,9 +8,9 @@ void sup(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void sup_eq(void)
@ -23,9 +23,9 @@ void sup_eq(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void inf(void)
@ -38,9 +38,9 @@ void inf(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void inf_eq(void)
@ -53,9 +53,9 @@ void inf_eq(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void diff(void)
@ -68,9 +68,9 @@ void diff(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void eq(void)
@ -83,9 +83,9 @@ void eq(void)
number* left = (number*)_stack->back();
if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void test_and(void)
@ -99,9 +99,9 @@ void test_and(void)
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
&& (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void test_or(void)
@ -115,9 +115,9 @@ void test_or(void)
if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0)
|| (mpfr_cmp_si(right->_value.mpfr, 0) != 0))
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void test_xor(void)
@ -132,16 +132,16 @@ void test_xor(void)
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
{
if (mpfr_cmp_si(right->_value.mpfr, 0) != 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
else
{
if (mpfr_cmp_si(right->_value.mpfr, 0) == 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
}
@ -152,9 +152,9 @@ void test_not(void)
number* left = (number*)_stack->back();
if (mpfr_cmp_si(left->_value.mpfr, 0) == 0)
mpfr_set_si(left->_value.mpfr, 1, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd);
else
mpfr_set_si(left->_value.mpfr, 0, s_mpfr_rnd);
mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd);
}
void same(void)

View file

@ -2,7 +2,7 @@
void pi(void)
{
number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd));
}
void d2r(void)
@ -12,9 +12,9 @@ void d2r(void)
floating_t pi;
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_const_pi(pi.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(pi.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
}
void r2d(void)
@ -24,9 +24,9 @@ void r2d(void)
floating_t pi;
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_const_pi(pi.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi.mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_const_pi(pi.mpfr, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd));
CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi.mpfr, floating_t::s_mpfr_rnd));
}
void rpn_sin(void)
@ -35,7 +35,7 @@ void rpn_sin(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_asin(void)
@ -44,7 +44,7 @@ void rpn_asin(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_cos(void)
@ -53,7 +53,7 @@ void rpn_cos(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_acos(void)
@ -62,7 +62,7 @@ void rpn_acos(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_tan(void)
@ -71,7 +71,7 @@ void rpn_tan(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}
void rpn_atan(void)
@ -80,5 +80,5 @@ void rpn_atan(void)
ARG_MUST_BE_OF_TYPE(0, cmd_number);
floating_t* left = &((number*)_stack->get_obj(0))->_value;
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, s_mpfr_rnd));
CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd));
}

View file

@ -1,883 +0,0 @@
/*
* rpn.cpp
*
* Copyright 2013 <louis@rubet.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
*
*/
#include <stdlib.h>
#include <stdint.h> //for intmax_t
#include <mpfr.h>
#include <math.h>
#include "constant.h"
#include "debug.h"
extern "C" {
#include <readline/readline.h>
#include <readline/history.h>
}
#include <iostream>
#include <iomanip>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
static string s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT);
static mpfr_prec_t s_mpfr_prec = MPFR_DEFAULT_PREC_BITS;
static unsigned int s_mpfr_prec_bytes = MPFR_DEFAULT_STORING_LENGTH_BYTES;
static mpfr_rnd_t s_mpfr_rnd = MPFR_DEFAULT_RND;
static const char* s_mpfr_rnd_str[5] = MPFR_RND_STRINGS;
//
#include "escape.h"
#include "version.h"
typedef enum {
ret_ok,
ret_unknown_err,
ret_missing_operand,
ret_bad_operand_type,
ret_out_of_range,
ret_unknown_variable,
ret_internal,
ret_deadly,
ret_good_bye,
ret_not_impl,
ret_nop,
ret_syntax,
ret_div_by_zero,
ret_runtime_error,
ret_max
} ret_value;
static const char* ret_value_string[ret_max] = RET_VALUE_STRINGS;
typedef enum {
cmd_undef,
cmd_number,/* floating value to put in stack */
cmd_string,/* string value to put in stack */
cmd_symbol,/* symbol value to put in stack */
cmd_program,/* program */
cmd_keyword,/* langage keyword */
cmd_branch,/* langage branch keyword */
cmd_max
} cmd_type_t;
const char* cmd_type_string[cmd_max] = CMD_TYPE_STRINGS;
// MPFR object
struct floating_t
{
mpfr_t mpfr;
void init(void* significand)
{
mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS);
mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, s_mpfr_prec, significand);
}
void set_significand(void* significand)
{
mpfr->_mpfr_d = (mp_limb_t*)significand;
}
floating_t& operator=(const long int val)
{
mpfr_set_si(mpfr, val, s_mpfr_rnd);
}
floating_t& operator=(const unsigned long val)
{
mpfr_set_ui(mpfr, val, s_mpfr_rnd);
}
operator int()
{
return (int)mpfr_get_si(mpfr, s_mpfr_rnd);
}
bool operator>(const floating_t right)
{
return mpfr_cmp(mpfr, right.mpfr) > 0;
}
bool operator<(const floating_t right)
{
return mpfr_cmp(mpfr, right.mpfr) < 0;
}
};
class program;
class object;
class branch;
typedef void (program::*program_fn_t)(void);
typedef int (program::*branch_fn_t)(branch&);
//
struct object
{
// object type
cmd_type_t _type;
unsigned int _size;
//
unsigned int size() { return _size; }
void show(FILE* stream = stdout);
};
struct number : public object
{
number() { _type = cmd_number; }
floating_t _value;
void init(void* significand)
{
_type = cmd_number;
_representation = dec;
_value.init(significand);
}
void copy(number& op)
{
_value = op._value;
memcpy(_value.mpfr->_mpfr_d, op._value.mpfr->_mpfr_d, s_mpfr_prec_bytes);
}
//
void set(const floating_t& value)
{
_type = cmd_number;
_value.mpfr->_mpfr_d = value.mpfr->_mpfr_d;
}
void set(long value)
{
_type = cmd_number;
_value = value;
}
void set(unsigned long value)
{
_type = cmd_number;
_value = value;
}
static unsigned int calc_size()
{
return (unsigned int)(sizeof(number)+s_mpfr_prec_bytes);
}
//
number operator=(const number& op)
{
number num;
num.set((const floating_t&)op._value);
return num;
}
// representation mode
typedef enum {
std,
fix,
sci
} mode_enum;
static mode_enum s_mode;
enum {
dec,
hex,
bin
} _representation;
// precision
static int s_current_precision;
};
number::mode_enum number::s_mode = DEFAULT_MODE;
int number::s_current_precision = DEFAULT_PRECISION;
struct ostring : public object
{
//
void set(const char* value, unsigned int len)
{
_type = cmd_string;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
len = 0;
}
//
unsigned int _len;
char _value[0];
};
struct oprogram : public object
{
//
void set(const char* value, unsigned int len)
{
_type = cmd_program;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
len = 0;
}
//
unsigned int _len;
char _value[0];
};
struct symbol : public object
{
//
void set(const char* value, unsigned int len, bool auto_eval)
{
_type = cmd_symbol;
_auto_eval = auto_eval;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
len = 0;
}
//
bool _auto_eval;
unsigned int _len;
char _value[0];
};
struct keyword : public object
{
//
void set(program_fn_t fn, const char* value, unsigned int len)
{
_type = cmd_keyword;
_fn = fn;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
len = 0;
}
//
program_fn_t _fn;
unsigned int _len;
char _value[0];
};
struct branch : public object
{
//
void set(branch_fn_t fn, const char* value, unsigned int len)
{
_type = cmd_branch;
_fn = fn;
arg1 = -1;
arg2 = -1;
arg3 = -1;
farg1 = NULL;
farg2 = NULL;
arg_bool = 0;
if (value != NULL)
{
if (len>0)
(void)memcpy(_value, value, len);
_value[len] = 0;
_len = len;
}
else
len = 0;
}
// branch function
branch_fn_t _fn;
// args used by cmd_branch cmds
int arg1, arg2, arg3;
number *farg1, *farg2;
bool arg_bool;
unsigned int _len;
char _value[0];
};
void object::show(FILE* stream)
{
switch(_type)
{
case cmd_number:
switch(((number*)this)->_representation)
{
case number::dec:
mpfr_fprintf(stream, s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr);
break;
case number::hex:
mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((number*)this)->_value.mpfr);
break;
case number::bin:
fprintf(stream, "<binary representation TODO>\n");
}
break;
case cmd_string:
fprintf(stream, "\"%s\"", ((ostring*)this)->_value);
break;
case cmd_program:
fprintf(stream, "<<%s>>", ((oprogram*)this)->_value);
break;
case cmd_symbol:
fprintf(stream, "'%s'", ((symbol*)this)->_value);
break;
case cmd_keyword:
case cmd_branch:
fprintf(stream, "%s", ((keyword*)this)->_value);
break;
default:
fprintf(stream, "< unknown object representation >");
break;
}
}
struct if_layout_t
{
if_layout_t():index_then(-1),index_else(-1),index_end(-1) { }
int index_if;
int index_then;
int index_else;
int index_end;
};
#include "stack.h"
class program : public stack
{
public:
program(program* parent_prog = NULL) { _parent_prog = parent_prog; }
// run this program
ret_value run(stack& stk, heap& hp, heap* parent_local_hp = NULL)
{
bool go_out = false;
ret_value ret = ret_ok;
cmd_type_t type;
// stack comes from outside
_stack = &stk;
// global heap comes from outside
_heap = &hp;
_err = ret_ok;
_err_context = "";
// branches for 'if'
ret = preprocess();
if (ret != ret_ok)
return ret;
// iterate commands
for(int i = 0; (go_out==false) && (i<(int)size());)
{
type = (cmd_type_t)seq_type(i);
// could be an auto-evaluated symbol
if (type == cmd_symbol)
{
auto_rcl((symbol*)seq_obj(i));
i++;
}
// a keyword
else if (type == cmd_keyword)
{
keyword* k = (keyword*)seq_obj(i);
// call matching function
(this->*(k->_fn))();
switch(_err)
{
// no pb -> go on
case ret_ok:
break;
// explicit go out software
case ret_good_bye:
go_out = true;
ret = ret_good_bye;
break;
default:
// error: abort prog
go_out = true;
// error: show it
if (show_error(_err, _err_context) == ret_deadly)
{
// pb showing error -> go out software
ret = ret_good_bye;
}
break;
}
i++;
}
// a branch keyword
else if (type == cmd_branch)
{
// call matching function
branch* b = (branch*)seq_obj(i);
int next_cmd = (this->*(b->_fn))(*b);
switch (next_cmd)
{
case -1:
i++; // meaning 'next command'
break;
case -(int)ret_runtime_error:
// error: show it
(void)show_error(_err, _err_context);
go_out = true;// end of run
break;
default:
i = next_cmd;// new direction
break;
}
}
// not a command, but a stack entry, manage it
else
{
// copy the program stack entry to the running stack
stack::copy_and_push_back(*this, i, stk);
i++;
}
}
return ret;
}
bool compare_keyword(keyword* k, const char* str_to_compare, int len)
{
if (k->_len >= len)
return strncmp(k->_value, str_to_compare, len) == 0;
else
return false;
}
bool compare_branch(branch* b, const char* str_to_compare, int len)
{
if (b->_len >= len)
return strncmp(b->_value, str_to_compare, len) == 0;
else
return false;
}
ret_value preprocess(void)
{
// for if-then-else-end
vector<struct if_layout_t> vlayout;
int layout_index=-1;
// for start-end-step
vector<int> vstartindex;
// analyse if-then-else-end branches
// analyse start-{next, step} branches
for(int i=0; i<(int)size(); i++)
{
int type = seq_type(i);
if (type == cmd_keyword)
{
keyword* k = (keyword*)seq_obj(i);
if (compare_keyword(k, "end", 3))
{
int next = i + 1;
if (next >= (int)size())
next = -1;
if (layout_index<0)
{
// error: show it
show_syntax_error("missing if before end");
return ret_syntax;
}
if (vlayout[layout_index].index_end != -1)
{
// error: show it
show_syntax_error("duplicate end");
return ret_syntax;
}
if (vlayout[layout_index].index_else != -1)
//fill 'end' branch of 'else'
((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i;
else
{
//fill 'end' branch of 'then'
if (vlayout[layout_index].index_then != -1)
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = i;
else
{
// error: show it
show_syntax_error("missing then before end");
return ret_syntax;
}
}
layout_index--;
}
}
else if (type == cmd_branch)
{
branch* k = (branch*)seq_obj(i);
if (compare_branch(k, "if", 2))
{
if_layout_t layout;
layout.index_if = i;
vlayout.push_back(layout);
layout_index++;
}
else if (compare_branch(k, "then", 4))
{
int next = i + 1;
if (next >= (int)size())
next = -1;
// nothing after 'then' -> error
if (next == -1)
{
// error: show it
show_syntax_error("missing end after then");
return ret_syntax;
}
if (layout_index<0)
{
// error: show it
show_syntax_error("missing if before then");
return ret_syntax;
}
if (vlayout[layout_index].index_then != -1)
{
// error: show it
show_syntax_error("duplicate then");
return ret_syntax;
}
vlayout[layout_index].index_then = i;
k->arg1 = next;
k->arg3 = vlayout[layout_index].index_if;
}
else if (compare_branch(k, "else", 4))
{
int next = i + 1;
if (next >= (int)size())
next = -1;
// nothing after 'else' -> error
if (next == -1)
{
// error: show it
show_syntax_error("missing end after else");
return ret_syntax;
}
if (layout_index<0)
{
// error: show it
show_syntax_error("missing if before else");
return ret_syntax;
}
if (vlayout[layout_index].index_then == -1)
{
// error: show it
show_syntax_error("missing then before else");
return ret_syntax;
}
if (vlayout[layout_index].index_else != -1)
{
// error: show it
show_syntax_error("duplicate else");
return ret_syntax;
}
vlayout[layout_index].index_else = i;
k->arg1 = next;// fill branch1 (if was false) of 'else'
k->arg3 = vlayout[layout_index].index_if;
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then'
}
else if (compare_branch(k, "start", 5))
{
vstartindex.push_back(i);
}
else if (compare_branch(k, "for", 3))
{
vstartindex.push_back(i);
k->arg1 = i + 1;// arg1 points on symbol variable
}
else if(compare_branch(k, "next", 4))
{
if (vstartindex.size() == 0)
{
// error: show it
show_syntax_error("missing start or for before next");
return ret_syntax;
}
k->arg1 = vstartindex[vstartindex.size() - 1]; // 'next' arg1 = 'start' index
((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index
vstartindex.pop_back();
}
else if (compare_branch(k, "step", 4))
{
if (vstartindex.size() == 0)
{
// error: show it
show_syntax_error("missing start or for before step");
return ret_syntax;
}
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index
((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index
vstartindex.pop_back();
}
else if (compare_branch(k, "->", 2))
{
k->arg1 = i;// arg1 is '->' command index in program
}
}
}
if (layout_index >= 0)
{
// error: show it
show_syntax_error("missing end");
return ret_syntax;
}
if (vstartindex.size() > 0)
{
// error: show it
show_syntax_error("missing next or step after for or start");
return ret_syntax;
}
return ret_ok;
}
ret_value show_error()
{
ret_value ret;
// show last recorded error
cerr<<ret_value_string[_err]<<"("<<_err<<"): "<<_err_context<<endl;
switch(_err)
{
case ret_internal:
case ret_deadly:
ret = ret_deadly;
default:
ret = ret_ok;
}
return ret;
}
ret_value show_error(ret_value err, string& context)
{
// record error
_err = err;
_err_context = context;
return show_error();
}
ret_value show_error(ret_value err, const char* context)
{
// record error
_err = err;
_err_context = context;
return show_error();
}
void show_syntax_error(const char* context)
{
// record error
_err = ret_syntax;
_err_context = context;
(void)show_error();
}
ret_value get_err(void) { return _err; }
#include "parse.h"
static void show_stack(stack& st, const string& separator = g_show_stack_separator)
{
if (st.size() == 1)
{
((object*)st.back())->show();
printf("\n");
}
else
{
bool show_sep = (! separator.empty());
for (int i = st.size()-1; i>=0; i--)
{
if (show_sep)
printf("%d%s", i+1, separator.c_str());
((object*)st[i])->show();
printf("\n");
}
}
}
static void apply_default()
{
//default float precision, float mode, verbosity
number::s_mode = DEFAULT_MODE;
number::s_current_precision = DEFAULT_PRECISION;
// format for mpfr_printf
stringstream ss;
ss << number::s_current_precision;
s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD);
}
private:
// current error and its context
ret_value _err;
string _err_context;
// global stack holding results for user
stack* _stack;
// global heap (sto, rcl)
heap* _heap;
// local heap for local loop vairables (for..next)
heap _local_heap;
// local stack internally used by branch commands (start, for, next, ..)
stack _branch_stack;
// parent prog for inheriting heaps
program* _parent_prog;
int stack_size()
{
return _stack->size();
}
private:
// carefull : some of these macros modify program flow
#define ERR_CONTEXT(err) do { _err = (err); _err_context = __FUNCTION__; } while(0)
#define MIN_ARGUMENTS(num) do { if (stack_size()<(num)) { ERR_CONTEXT(ret_missing_operand); return; } } while(0)
#define MIN_ARGUMENTS_RET(num, ret) do { if (stack_size()<(num)) { ERR_CONTEXT(ret_missing_operand); return (ret); } } while(0)
#define ARG_MUST_BE_OF_TYPE(num, type) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } } while(0)
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { if (_stack->get_type(num) != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } } while(0)
#define IS_ARG_TYPE(num, type) (_stack->get_type(num) == (type))
#define CHECK_MPFR(op) do { (void)(op); } while(0)
// keywords implementation
#include "rpn-general.h"
#include "rpn-real.h"
#include "rpn-test.h"
#include "rpn-stack.h"
#include "rpn-string.h"
#include "rpn-branch.h"
#include "rpn-store.h"
#include "rpn-program.h"
#include "rpn-trig.h"
#include "rpn-logs.h"
#include "rpn-test-core.h"
};
//keywords declaration
#include "rpn-cmd.h"
//
int main(int argc, char* argv[])
{
heap global_heap;
stack global_stack;
int ret = 0;
// apply default configuration
program::apply_default();
// run with interactive prompt
if (argc == 1)
{
//
for (;;)
{
// make program from interactive entry
program prog;
if (program::entry(prog) == ret_good_bye)
break;
else
{
// run it
if (prog.run(global_stack, global_heap) == ret_good_bye)
break;
else
program::show_stack(global_stack);
}
}
}
// run with cmd line arguments
else
{
program prog;
string entry;
int i;
// make one string from entry
for (i=1; i<argc; i++)
{
entry += argv[i];
entry += ' ';
}
// make program
ret = program::parse(entry.c_str(), prog);
if (ret == ret_ok)
{
string separator = "";
// run it
ret = prog.run(global_stack, global_heap);
program::show_stack(global_stack, separator);
}
}
mpfr_free_cache();
return ret;
}