From df7f5e46608cf4f3aa9384ef81a6114c0d5aa9f2 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 5 Feb 2022 14:01:20 +0100 Subject: [PATCH 01/57] #223 add missing return (detected by gcc 11) --- src/object.hpp | 6 +++--- src/program.cpp | 2 +- src/stack.hpp | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/object.hpp b/src/object.hpp index ec0d7d2..4c06fbf 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -44,11 +44,11 @@ struct floating_t { mpfr_custom_move(mpfr, significand); } - floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); } + floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); return *this; } - floating_t& operator=(const long int val) { mpfr_set_si(mpfr, val, s_mpfr_rnd); } + floating_t& operator=(const long int val) { mpfr_set_si(mpfr, val, s_mpfr_rnd); return *this; } - floating_t& operator=(const unsigned long val) { mpfr_set_ui(mpfr, val, s_mpfr_rnd); } + floating_t& operator=(const unsigned long val) { mpfr_set_ui(mpfr, val, s_mpfr_rnd); return *this; } operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); } diff --git a/src/program.cpp b/src/program.cpp index 5bb4729..22af5db 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,4 +1,4 @@ -#include "program.hpp" + #include "program.hpp" //< return type strings const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; diff --git a/src/stack.hpp b/src/stack.hpp index bea54aa..4a81228 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -306,6 +306,8 @@ class heap : public stack { ret = true; } } + + return ret; } /// @brief whether a variable exists in heap or not From 84f54d073bf7c1ee38e9bb3c93d467362f91acd8 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 5 Feb 2022 14:04:08 +0100 Subject: [PATCH 02/57] tool files ignored by git --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 01470ed..426d7bf 100644 --- a/.gitignore +++ b/.gitignore @@ -22,5 +22,9 @@ *.x86_64 *.hex -# editors garbage +# Tools workfiles *~ +.scannerwork/* +*bw-output*/* +.vscode/* +build/* From d3970d403b915cb74910af02e8c2077945b8626b Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 7 Feb 2022 16:36:27 +0100 Subject: [PATCH 03/57] refactoring I (objects) --- .gitmodules | 3 + CMakeLists.txt | 26 +- mpreal | 1 + src/constant.h | 4 +- src/debug.h | 2 - src/main.cpp | 4 +- src/object.cpp | 17 +- src/object.hpp | 315 ++++++++---------- src/parse.cpp | 738 ++++++++++++++---------------------------- src/program.cpp | 391 +++++++++++----------- src/program.hpp | 39 +-- src/rpn-branch.cpp | 44 +-- src/rpn-complex.cpp | 50 +-- src/rpn-general.cpp | 31 +- src/rpn-logs.cpp | 161 ++++----- src/rpn-program.cpp | 26 +- src/rpn-real.cpp | 165 +++++----- src/rpn-stack.cpp | 58 ++-- src/rpn-store.cpp | 116 +++---- src/rpn-string.cpp | 60 ++-- src/rpn-test-core.cpp | 25 +- src/rpn-test.cpp | 165 +++++----- src/rpn-time.cpp | 12 +- src/rpn-trig.cpp | 110 ++++--- src/stack.hpp | 364 +++------------------ 25 files changed, 1149 insertions(+), 1778 deletions(-) create mode 160000 mpreal diff --git a/.gitmodules b/.gitmodules index 335640d..da98e6b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "linenoise-ng"] path = linenoise-ng url = git@github.com:louisrubet/linenoise-ng.git +[submodule "mpreal"] + path = mpreal + url = https://github.com/advanpix/mpreal diff --git a/CMakeLists.txt b/CMakeLists.txt index 8032c07..c1756e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,8 @@ set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md") # compiler options if(CMAKE_COMPILER_IS_GNUCXX) message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}") - set(BASE_COMPILER_OPTIONS "-std=c++0x -Wl,--no-as-needed") + # TODO still up to date? + set(BASE_COMPILER_OPTIONS "-std=c++14 -Wl,--no-as-needed") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -fomit-frame-pointer -s") @@ -37,8 +38,15 @@ if(NOT EXISTS "${PROJECT_SOURCE_DIR}/linenoise-ng/.git") execute_process(COMMAND git checkout v1.1.1-rpn WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/linenoise-ng) endif() +# custom mpreal +if(NOT EXISTS "${PROJECT_SOURCE_DIR}/mpreal/.git") + execute_process(COMMAND git submodule init ${PROJECT_SOURCE_DIR}/mpreal) + execute_process(COMMAND git submodule update ${PROJECT_SOURCE_DIR}/mpreal) + execute_process(COMMAND git checkout mpfrc++-3.6.9 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/mpreal) +endif() + # includes -include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng/include) +include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng/include ${PROJECT_SOURCE_DIR}/mpreal) # build add_executable( @@ -47,19 +55,19 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/object.cpp ${PROJECT_SOURCE_DIR}/src/program.cpp ${PROJECT_SOURCE_DIR}/src/parse.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp ${PROJECT_SOURCE_DIR}/src/rpn-program.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-real.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-real.cpp ${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp ${PROJECT_SOURCE_DIR}/src/rpn-store.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-string.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-string.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test-core.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-time.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-time.cpp + #${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp diff --git a/mpreal b/mpreal new file mode 160000 index 0000000..c45d0d5 --- /dev/null +++ b/mpreal @@ -0,0 +1 @@ +Subproject commit c45d0d522c9bd0dd16d7aac25fa0862dd074ddb0 diff --git a/src/constant.h b/src/constant.h index 9019ffb..a085896 100644 --- a/src/constant.h +++ b/src/constant.h @@ -1,6 +1,7 @@ #ifndef CONSTANT_H #define CONSTANT_H +#define MPFR_USE_NO_MACRO #include // default values @@ -66,6 +67,7 @@ typedef enum { ret_div_by_zero, ret_runtime_error, ret_abort_current_entry, + ret_out_of_memory, ret_max } ret_value; @@ -73,7 +75,7 @@ typedef enum { { \ "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", "aborted current entry" \ + "division by zero", "runtime error", "aborted current entry", "out of memory" \ } // command types diff --git a/src/debug.h b/src/debug.h index b0d4eaa..4f18731 100644 --- a/src/debug.h +++ b/src/debug.h @@ -83,6 +83,4 @@ static void chrono_print(int chrono) { } } -#define max(a, b) (((a) > (b)) ? (a) : (b)) - #endif diff --git a/src/main.cpp b/src/main.cpp index a3f5b58..99953d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,7 +12,7 @@ #include "program.hpp" static heap s_global_heap; -static stack s_global_stack; +static rpnstack s_global_stack; static program* s_prog_to_interrupt = NULL; /// @brief actions to be done at rpn exit @@ -151,7 +151,7 @@ int main(int argc, char* argv[]) { } // make program - ret = program::parse(entry.c_str(), prog); + ret = program::parse(entry, prog); if (ret == ret_ok) { string separator = ""; diff --git a/src/object.cpp b/src/object.cpp index 785e260..57f4bd5 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -3,23 +3,27 @@ using namespace std; #include "constant.h" -#include "mpfr.h" +#define MPFR_USE_NO_MACRO +#include #include "object.hpp" -// floating_t statics -mpfr_prec_t floating_t::s_mpfr_prec = MPFR_DEFAULT_PREC_BITS; -mpfr_rnd_t floating_t::s_mpfr_rnd = MPFR_DEFAULT_RND; -unsigned int floating_t::s_mpfr_prec_bytes = MPFR_DEFAULT_STORING_LENGTH_BYTES; -const char* floating_t::s_mpfr_rnd_str[5] = MPFR_RND_STRINGS; +// TODO remove +// some statics +// mpfr_prec_t floating_t::s_mpfr_prec = MPFR_DEFAULT_PREC_BITS; +// mpfr_rnd_t floating_t::s_mpfr_rnd = MPFR_DEFAULT_RND; // number statics number::mode_enum number::s_mode = DEFAULT_MODE; int number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; +mpfr_prec_t number::s_mpfr_prec = MPFR_DEFAULT_PREC_BITS; +mpfr_rnd_t number::s_mpfr_rnd = MPFR_DEFAULT_RND; string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT); +const char* number::s_mpfr_rnd_str[5] = MPFR_RND_STRINGS; // const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS; +#if 0 /// @brief return if a mpfr is higher to a given precision /// this function is directly copied from mpfr /// @@ -226,3 +230,4 @@ void object::show(FILE* stream) { break; } } +#endif diff --git a/src/object.hpp b/src/object.hpp index 4c06fbf..9444ccf 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,11 +1,15 @@ #ifndef OBJECT_HPP #define OBJECT_HPP -#include -#include +#include +using namespace mpfr; + +#include +#include +using namespace std; // definitions for objects -//// +/// typedef enum { cmd_undef, cmd_number, // floating point number @@ -24,60 +28,20 @@ class branch; typedef void (program::*program_fn_t)(void); typedef int (program::*branch_fn_t)(branch&); -/// @brief MPFR (floating point) object -/// -struct floating_t { - mpfr_prec_t mpfr_prec; // precision in bits - unsigned int mpfr_prec_bytes; // significand storing length in bytes - mpfr_t mpfr; // mpfr object - - void init() { - void* significand = (void*)(this + 1); - mpfr_prec = s_mpfr_prec; - mpfr_prec_bytes = s_mpfr_prec_bytes; - mpfr_custom_init(significand, MPFR_DEFAULT_PREC_BITS); - mpfr_custom_init_set(mpfr, MPFR_ZERO_KIND, 0, mpfr_prec, significand); - } - - void move() { - void* significand = (void*)(this + 1); - mpfr_custom_move(mpfr, significand); - } - - floating_t& operator=(const double val) { mpfr_set_d(mpfr, val, s_mpfr_rnd); return *this; } - - floating_t& operator=(const long int val) { mpfr_set_si(mpfr, val, s_mpfr_rnd); return *this; } - - floating_t& operator=(const unsigned long val) { mpfr_set_ui(mpfr, val, s_mpfr_rnd); return *this; } - - operator double() { return mpfr_get_d(mpfr, s_mpfr_rnd); } - - operator int() { return (int)mpfr_get_si(mpfr, s_mpfr_rnd); } - - operator long() { return 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; } - - // default precision in bits, precision length in bytes, rounding mode - static mpfr_prec_t s_mpfr_prec; - static unsigned int s_mpfr_prec_bytes; - static mpfr_rnd_t s_mpfr_rnd; - static const char* s_mpfr_rnd_str[5]; -}; - /// @brief object - a generic stack object /// struct object { + object(cmd_type_t type = cmd_undef) : _type(type) {} // object type cmd_type_t _type; - unsigned int _size; - // - unsigned int size() { return _size; } - - void show(FILE* stream = stdout); + auto duplicate() { + cout << "typeid(this).name()=" << typeid(this).name() << endl; + return *new decltype(this); + } + virtual string name() { return string("object"); } + virtual void show(ostream& out) { out << "(" << name() << " - unknown representation)"; } + unsigned int size() { return sizeof(*this); } // static const char* s_cmd_type_string[cmd_max]; @@ -85,171 +49,161 @@ struct object { /// @brief stack objects derived from object /// -struct number : public object { - // members - enum { dec, hex, bin, base } _representation; - // base - // carefull: _base is used only if _representation = base - int _base; - // mind that float value is at the end of the object - // because its mantissa is just after the obj in memory - floating_t _value; +struct number : object { + typedef enum { dec, hex, bin, base } repr_enum; + number(repr_enum representation = dec) : object(cmd_number), _representation(representation) { _value = 0L; } + number(mpreal& value, repr_enum representation = dec) : number(representation) { _value = value; } + number(long value, repr_enum representation = dec) : number(representation) { _value = value; } + number(unsigned long value, repr_enum representation = dec) : number(representation) { _value = value; } + number(double value, repr_enum representation = dec) : number(representation) { _value = value; } - // publics - number() { _type = cmd_number; } + repr_enum _representation; + int _base; // carefull: _base is used only if _representation = base - void init() { - _type = cmd_number; - _representation = dec; - _value.init(); + mpreal _value; + + void init() {} + + void set(unsigned long value) { _value = value; } + + virtual string name() { return string("number"); } + virtual void show(ostream& out) { + if (_representation != number::dec) { + object::show(out); + return; + } + switch (number::s_mode) { + case number::std: + out.unsetf(ios::floatfield); + out << setprecision(s_decimal_digits) << _value; + break; + case number::fix: + out << fixed << setprecision(s_decimal_digits) << _value; + break; + case number::sci: + out << scientific << setprecision(s_decimal_digits) << _value; + break; + default: + object::show(out); + break; + } } - void move() { _value.move(); } - - void set(unsigned long value) { - _type = cmd_number; - _value = value; - } - - static unsigned int calc_size() { return (unsigned int)(sizeof(number) + floating_t::s_mpfr_prec_bytes); } - // representation mode typedef enum { std, fix, sci } mode_enum; static mode_enum s_mode; // precision static int s_decimal_digits; + static mpfr_prec_t s_mpfr_prec; + static mpfr_rnd_t s_mpfr_rnd; static string s_mpfr_printf_format; + static const char* s_mpfr_rnd_str[5]; }; /// @brief stack objects derived from object /// -struct complex : public object { - enum { dec, hex } _representation; - // mind that re float value is at the end of the object - // because its mantissa is just after the obj in memory - floating_t _re; +struct ocomplex : object { + number::repr_enum _representation; + ocomplex() : object(cmd_complex) { init(); } - complex() { _type = cmd_complex; } + mpreal _re; + mpreal _im; // re and im float values are at the end of the object - floating_t* re() { return &_re; } - floating_t* im() { return (floating_t*)((char*)&_re + sizeof(floating_t) + _re.mpfr_prec_bytes); } + mpreal* re() { return &_re; } + mpreal* im() { return &_im; } - void init() { - _type = cmd_complex; - _representation = dec; - re()->init(); - im()->init(); - } + void init() {} - void move() { - re()->move(); - im()->move(); - } - - static unsigned int calc_size() { - return (unsigned int)(sizeof(complex) + 2 * (sizeof(floating_t) + floating_t::s_mpfr_prec_bytes)); + virtual string name() { return string("complex"); } + virtual void show(ostream& out) { + if (_representation != number::dec) { + object::show(out); + return; + } + switch (number::s_mode) { + case number::std: + out.unsetf(ios::floatfield); + out << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + case number::fix: + out << fixed << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + break; + case number::sci: + out << scientific << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + break; + default: + object::show(out); + break; + } } }; /// @brief object string -/// -struct ostring : public object { - // ostring may first have been allocated with len+1 bytes - 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 { - _value[_len] = 0; - _len = 0; - } - } +/// +struct ostring : object { + ostring() : object(cmd_string) {} + ostring(const string& value) : object(cmd_string) { set(value); } + ostring(const char* value) : object(cmd_string) { _value = string(value); } + void set(const string& value) { _value = value; } + virtual string name() { return string("complex"); } + virtual void show(ostream& out) { out << "\"" << _value << "\""; } - // length of _value, not including the terminal '\0' - unsigned int _len; - char _value[0]; + string _value; }; /// @brief object program -/// -struct oprogram : public object { - // oprogram may first have been allocated with len+1 bytes - 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 { - _value[0] = 0; - _len = 0; - } - } - - // length of _value, not includiong the terminal '\0' - unsigned int _len; - char _value[0]; +/// +struct oprogram : object { + oprogram() : object(cmd_program) {} + oprogram(const string& value) : object(cmd_program) { set(value); } + void set(const string& value) { _value = value; } + virtual string name() { return string("program"); } + virtual void show(ostream& out) { out << "<< " << _value << " >>"; } + string _value; }; /// @brief object symbol -/// -struct symbol : public object { - // symbol may first have been allocated with len+1 bytes - void set(const char* value, unsigned int len, bool auto_eval) { - _type = cmd_symbol; +/// +struct symbol : object { + symbol(bool auto_eval = true) : object(cmd_symbol), _auto_eval(auto_eval) {} + symbol(const string& value, bool auto_eval = true) : object(cmd_symbol) { set(value, auto_eval); } + void set(string& value, bool auto_eval) { + _value = value; _auto_eval = auto_eval; - - if (value != NULL) { - if (len > 0) (void)memcpy(_value, value, len); - _value[len] = 0; - _len = len; - } else { - _value[0] = 0; - _len = 0; - } } - - // + void set(const string& value, bool auto_eval) { + _value = value; + _auto_eval = auto_eval; + } + virtual string name() { return string("symbol"); } + virtual void show(ostream& out) { out << "'" << _value << "'"; } bool _auto_eval; - // length of _value, not includiong the terminal '\0' - unsigned int _len; - char _value[0]; + string _value; }; /// @brief object keyword -/// -struct keyword : public object { - // keyword may first have been allocated with len+1 bytes - void set(program_fn_t fn, const char* value, unsigned int len) { - _type = cmd_keyword; +/// +struct keyword : object { + keyword() : object(cmd_keyword) {} + keyword(program_fn_t fn, const string& value) : object(cmd_keyword) { set(fn, value); } + void set(program_fn_t fn, const string& value) { _fn = fn; - if (value != NULL) { - if (len > 0) (void)memcpy(_value, value, len); - _value[len] = 0; - _len = len; - } else { - _value[0] = 0; - _len = 0; - } + _value = value; } - - // + virtual string name() { return string("keyword"); } program_fn_t _fn; - // length of _value, not includiong the terminal '\0' - unsigned int _len; - char _value[0]; + string _value; }; /// @brief object branch -/// -struct branch : public object { +/// +struct branch : object { + branch() : object(cmd_branch) {} + branch(branch_fn_t fn, const string& value) : object(cmd_branch) { set(fn, value); } + virtual string name() { return string("branch"); } // - void set(branch_fn_t fn, const char* value, unsigned int len) { - _type = cmd_branch; + void set(branch_fn_t fn, const string& value) { _fn = fn; arg1 = -1; arg2 = -1; @@ -257,26 +211,13 @@ struct branch : public object { farg1 = NULL; farg2 = NULL; arg_bool = 0; - if (value != NULL) { - if (len > 0) (void)memcpy(_value, value, len); - _value[len] = 0; - _len = len; - } else { - _value[0] = 0; - _len = 0; - } + _value = value; } - - // branch function branch_fn_t _fn; - // args used by cmd_branch cmds int arg1, arg2, arg3; number *farg1, *farg2; bool arg_bool; - - // length of _value, not includiong the terminal '\0' - unsigned int _len; - char _value[0]; + string _value; }; #endif diff --git a/src/parse.cpp b/src/parse.cpp index b14c1f6..68371a5 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -2,7 +2,7 @@ /// @brief completion callback as asked by linenoise-ng /// this is called by linenoise-ng whenever the user enters TAB -/// +/// /// @param text the text after wich the user entered TAB /// @param lc the completion object to add strings with linenoiseAddCompletion() /// @@ -11,7 +11,7 @@ void program::entry_completion_generator(const char* text, linenoiseCompletions* int text_len = strnlen(text, 6); // propose all keywords - if (text_len == 0) { + if (text_len == 0) { while (program::s_keywords[i].type != cmd_max) { if (program::s_keywords[i].fn != NULL) // add all keywords @@ -33,7 +33,7 @@ void program::entry_completion_generator(const char* text, linenoiseCompletions* } /// @brief interactive entry and decoding -/// +/// /// @param prog the program to add entered objects /// @return ret_value see this type /// @@ -70,7 +70,7 @@ ret_value program::entry(program& prog) { entry_str += entry; // parse it - ret = parse(entry_str.c_str(), prog); + ret = parse(entry_str, prog); // keep history if (entry[0] != 0) (void)linenoiseHistoryAdd(entry_str.c_str()); @@ -84,543 +84,281 @@ ret_value program::entry(program& prog) { return ret; } -/// @brief return function pointer from function name -/// -/// @param fn_name function name -/// @param fn function pointer -/// @param type the function type (cmd_keyword or cmd_branch) -/// @return ret_value see this type -/// -ret_value program::get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type) { - unsigned int i = 0; - while (s_keywords[i].type != cmd_max) { - if (strncasecmp(fn_name, s_keywords[i].name, sizeof(s_keywords[i].name)) == 0) { - fn = s_keywords[i].fn; - type = s_keywords[i].type; - return ret_ok; - } - i++; - } - return ret_unknown_err; -} - -/// @brief get a keyword object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_keyword(const string& entry, program& prog, string& remaining_entry) { - program_fn_t fn; - unsigned int obj_len; +struct SynElement { cmd_type_t type; - bool ret = false; + string value; + mpreal re; + mpreal im; + program_fn_t fn; + bool operator==(SynElement& other) { + return type == other.type && value == other.value && (re == other.re || (isnan(re) && isnan(other.re))) && + (im == other.im || (isnan(im) && isnan(other.im))); + } +}; - // could be a command - if (program::get_fn(entry.c_str(), fn, type) == ret_ok) { - if (type == cmd_keyword) { - // allocate keyword object - obj_len = sizeof(keyword) + entry.size() + 1; - keyword* new_obj = (keyword*)prog.allocate_back(obj_len, cmd_keyword); - new_obj->set(fn, entry.c_str(), entry.size()); - ret = true; - } else if (type == cmd_branch) { - // allocate branch object - obj_len = sizeof(branch) + entry.size() + 1; - branch* new_obj = (branch*)prog.allocate_back(obj_len, cmd_branch); - new_obj->set((branch_fn_t)fn, entry.c_str(), entry.size()); - ret = true; +struct SynError { + size_t indx; + string err; + bool operator==(SynError& other) { return err == other.err; } +}; + +struct ReservedWord { + cmd_type_t type; + program_fn_t fn; +}; + +static map _keywordsMap; + +static bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry[0] is '"' + for (size_t i = idx + 1; i < entry.size(); i++) { + if (entry[i] == '"') { + if (entry[i] - 1 != '\\') { + elements.push_back({cmd_string, .value = entry.substr(idx + 1, i - idx - 1)}); + nextIdx = i + 1; + return true; + } } } - - return ret; + errors.push_back({entry.size(), "unterminated string"}); + return false; } -/// @brief get a symbol object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_symbol(const string& entry, program& prog, string& remaining_entry) { - bool ret = false; - int entry_len = entry.size(); - unsigned int obj_len; - - if (entry_len >= 1 && entry[0] == '\'') { - if (entry_len == 1) { - // void symbol entry, like ' - // total object length - obj_len = sizeof(symbol) + 1; - - // allocate and set object - // symbol beginning with ' is not autoevaluated - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set("", 0, false); - } else { - // symbol entry, like 'toto' or 'toto - int naked_entry_len; - - // entry length without prefix / postfix - naked_entry_len = entry[entry_len - 1] == '\'' ? (entry_len - 2) : (entry_len - 1); - // total object length - obj_len = sizeof(symbol) + naked_entry_len + 1; - - // allocate and set object - // symbol beginning with ' is not autoevaluated - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len, false); +static bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry[0] is '\'' + for (size_t i = idx + 1; i < entry.size(); i++) { + if (entry[i] == '\'') { + elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, i - idx - 1)}); + nextIdx = i + 1; + return true; } - ret = true; } - - return ret; + errors.push_back({entry.size(), "unterminated symbol"}); + return false; } -/// @brief get an object other from known ones from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_other(const string& entry, program& prog, string& remaining_entry) { - bool ret = false; - int entry_len = entry.size(); - unsigned int obj_len; - - if (entry_len >= 1) { - // entry which is nothing is considered as an auto-evaluated symbol - int naked_entry_len; - - // entry length without prefix / postfix - naked_entry_len = entry[entry_len - 1] == '\'' ? (entry_len - 1) : (entry_len); - // total object length - obj_len = sizeof(symbol) + naked_entry_len + 1; - - // allocate and set object - // symbol not beginning with ' is autoevaluated (ie is evaluated when pushed - // on stack) - symbol* new_obj = (symbol*)prog.allocate_back(obj_len, cmd_symbol); - new_obj->set(entry.c_str(), naked_entry_len, true); - ret = true; - } - - return ret; -} - -/// @brief get a string object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_string(const string& entry, program& prog, string& remaining_entry) { - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len >= 1 && entry[0] == '"') { - if (entry_len == 1) { - // total object length - obj_len = sizeof(ostring) + 1; - - // allocate and set object - ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); - new_obj->set("", 0); - } else { - int naked_entry_len; - - // entry length without prefix / postfix - naked_entry_len = entry[entry_len - 1] == '"' ? (entry_len - 2) : (entry_len - 1); - - // total object length - obj_len = sizeof(ostring) + naked_entry_len + 1; - - // allocate and set object - ostring* new_obj = (ostring*)prog.allocate_back(obj_len, cmd_string); - new_obj->set(entry.substr(1, naked_entry_len).c_str(), naked_entry_len); +static bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry is at least "<<"" + for (size_t i = idx + 2; i < entry.size() - 1; i++) { + if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { + elements.push_back({cmd_program, .value = entry.substr(idx + 2, i - idx - 2)}); + nextIdx = i + 2; + return true; } - ret = true; } - - return ret; + errors.push_back({entry.size(), "unterminated program"}); + return false; } -/// @brief get a program object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_program(string& entry, program& prog, string& remaining_entry) { - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len >= 2 && entry[0] == '<' && entry[1] == '<') { - int naked_entry_len; +static void trim(string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); +} - // entry length without prefix / postfix - if (entry_len >= 4 && entry[entry_len - 1] == '>' && entry[entry_len - 2] == '>') - naked_entry_len = entry_len - 4; +static bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, mpreal& r, char delim = ' ') { + stringstream ss; + string token; + string input; + int base; + + string baseStr = entry.substr(idx, 2); + if (baseStr == "0x" || baseStr == "0X") { + input = entry.substr(idx + 2); + base = 16; + } else if (baseStr == "0b") { + input = entry.substr(idx + 2); + base = 2; + } else { + input = entry.substr(idx); + base = 10; + } + + ss.str(input); + if (getline(ss, token, delim)) { + nextIdx = token.size() + idx + (base != 10 ? 2 : 0); + trim(token); + if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) + return true; else - naked_entry_len = entry_len - 2; - - // total object length - obj_len = sizeof(oprogram) + naked_entry_len + 1; - - // allocate and set object - oprogram* new_obj = (oprogram*)prog.allocate_back(obj_len, cmd_program); - new_obj->set(&entry[2], naked_entry_len); - - ret = true; + return false; } - return ret; + nextIdx = token.size() + idx + (base != 10 ? 2 : 0); + return false; } -/// @brief get a number object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added +static bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + mpreal r; + if (getNumberAt(entry, idx, nextIdx, r)) { + elements.push_back({cmd_number, .re = r}); + return true; + } else { + errors.push_back({entry.size(), "unterminated number"}); + return false; + } +} + +static bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + mpreal re, im; + if (idx + 1 == entry.size()) { + errors.push_back({entry.size(), "unterminated complex"}); + return false; + } + if (!getNumberAt(entry, idx + 1, nextIdx, re, ',')) { + errors.push_back({entry.size(), "unterminated complex"}); + return false; + } + + size_t i = nextIdx; + while (i < entry.size() && entry[i] != ',') i++; + if (i == entry.size()) { + errors.push_back({entry.size(), "unterminated complex"}); + return false; + } + if (!getNumberAt(entry, i + 1, nextIdx, im, ')')) { + errors.push_back({entry.size(), "unterminated complex"}); + return false; + } + if (nextIdx == entry.size() || entry[nextIdx] != ')') { + errors.push_back({entry.size(), "unterminated complex"}); + return false; + } + elements.push_back({cmd_complex, .re = re, .im = im}); + nextIdx++; + return true; +} + +static bool parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, + map& keywords) { + stringstream ss(entry.substr(idx)); + string token; + ss >> token; + + auto resa = keywords.find(token); + if (resa != keywords.end()) { + elements.push_back({resa->second.type, .value = token, .fn = resa->second.fn}); + nextIdx = token.size() + idx; + return true; + } + return false; +} + +static bool parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements) { + stringstream ss(entry.substr(idx)); + string token; + ss >> token; + elements.push_back({cmd_symbol, token}); + nextIdx = token.size() + idx; + return true; +} + +/// @brief lexical analysis of an entry string /// -static bool get_number(string& entry, program& prog, string& remaining_entry) { - char* endptr; - bool ret = false; - - if (entry.size() > 0) { - // pre parse to avoid doing a useless allocation - // detect the begining of a number including nan, inf, @nan@, @inf@ - if (entry.find_first_of("+-0123456789.ni@", 0) == 0) { - // detect an arbitrary base entry like 3bXXX or 27bYYY - int base = 0; - size_t base_detect = entry.find_first_of("b", 0); - if (base_detect == 1 || base_detect == 2) - if (sscanf(entry.c_str(), "%db", &base) == 1 && base >= 2 && base <= 62) - entry = entry.substr(base_detect + 1); - else - base = 0; - - number* num = (number*)prog.allocate_back(number::calc_size(), cmd_number); - - int mpfr_ret = mpfr_strtofr(num->_value.mpfr, entry.c_str(), &endptr, base, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != entry.c_str()) { - // determine representation - if (base != 0) { - num->_representation = number::base; - num->_base = base; - } else { - string beg = entry.substr(0, 2); - if (beg == "0x" || beg == "0X") - num->_representation = number::hex; - else if (beg == "0b" || beg == "0B") - num->_representation = number::bin; - else - num->_representation = number::dec; - } - - ret = true; - - // remaining string if any - remaining_entry = endptr; - } else - (void)prog.pop_back(); - } - } - - return ret; -} - -/// @brief get a complex object from entry and add it to a program -/// -/// @param entry the entry -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added -/// @return false no object was added -/// -static bool get_complex(const string& entry, program& prog, string& remaining_entry) { - char* endptr; - bool ret = false; - - if (entry.size() > 0) { - size_t comma = entry.find(','); - if (comma != string::npos) { - complex* cplx; - - // pre parse RE to avoid doing a useless allocation - // detect the begining of a number, including nan, inf, @nan@, @inf@ - string re_str = entry.substr(1, comma - 1).c_str(); - if (re_str.find_first_of(" +-0123456789.ni@", 0) == 0) { - cplx = (complex*)prog.allocate_back(complex::calc_size(), cmd_complex); - - int mpfr_ret = mpfr_strtofr(cplx->re()->mpfr, re_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != re_str.c_str()) { - // determine representation - string beg = re_str.substr(0, 2); - if (beg == "0x" || beg == "0X") - cplx->_representation = complex::hex; - else - cplx->_representation = complex::dec; - - ret = true; - } else - (void)prog.pop_back(); - } - - // pre parse IM to avoid doing a useless allocation - // detect the begining of a number, including nan, inf, @nan@, @inf@ - string im_str = entry.substr(comma + 1).c_str(); - if (ret == true && im_str.find_first_of(" +-0123456789.ni@", 0) == 0) { - ret = false; - int mpfr_ret = mpfr_strtofr(cplx->im()->mpfr, im_str.c_str(), &endptr, 0, MPFR_DEFAULT_RND); - if (endptr != NULL && endptr != im_str.c_str()) { - // determine representation - string beg = im_str.substr(0, 2); - if (beg == "0x" || beg == "0X") - cplx->_representation = complex::hex; - else - cplx->_representation = complex::dec; - - ret = true; - } else - (void)prog.pop_back(); - } - } - } - - return ret; -} - -/// @brief recognize a comment object from entry -/// -/// @param entry the entry -/// @param remaining_entry the remaining entry after the comment was found -/// @return true a comment was found -/// @return false no comment was found -/// -static bool get_comment(string& entry, string& remaining_entry) { - bool ret = false; - unsigned int obj_len; - int entry_len = entry.size(); - if (entry_len >= 1 && entry[0] == '#') { - // entry (complete line) is ignored - ret = true; - } - return ret; -} - -/// @brief get an object from an entry string and add it to a program -/// /// @param entry the entry string -/// @param prog the program -/// @param remaining_entry the remaining entry after the object was added -/// @return true an object was added to the prog -/// @return false no object was added to the prog +/// @param elements syntax elements vector +/// @param errors errors vector +/// @param keywords reserved keywords +/// @return false=errors, the lexer must stop /// -static bool _obj_from_string(string& entry, program& prog, string& remaining_entry) { - bool ret = false; +static bool lexer(string& entry, vector& elements, vector& errors, + map& keywords) { + size_t jump; + for (size_t i = 0; i < entry.size(); i++) { + if (isspace(entry[i])) continue; + SynElement element; + switch (entry[i]) { + case '"': + if (!parseString(entry, i, jump, errors, elements)) return false; + i = jump - 1; + continue; + case '\'': + if (!parseSymbol(entry, i, jump, errors, elements)) return false; + i = jump - 1; + continue; + case '(': + if (!parseComplex(entry, i, jump, errors, elements)) return false; + i = jump - 1; + continue; + // clang-format off + case '.': case '+': case '-': + // clang-format on + // inf, +inf, -inf and nan are treated as reserved keywords + if (i < entry.size() - 1 && entry[i + 1] < '0' && entry[i + 1] > '9') break; + case '0' ... '9': + if (!parseNumber(entry, i, jump, errors, elements)) return false; + i = jump - 1; + continue; + } + if (i < entry.size() - 1 && (entry.substr(i, 2) == "<<" || entry.substr(i, 2) == "«")) { + if (!parseProgram(entry, i, jump, errors, elements)) return false; + i = jump - 1; + continue; + } else if (parseReserved(entry, i, jump, elements, keywords)) + // found a keywords word, add it with its correct type + i = jump - 1; + else if (parseUnknown(entry, i, jump, elements)) + // last chance, this unknown entry is treated as a symbol + i = jump - 1; + } - remaining_entry.erase(); - - if (get_number(entry, prog, remaining_entry)) - ret = true; - else if (get_symbol(entry, prog, remaining_entry)) - ret = true; - else if (get_string(entry, prog, remaining_entry)) - ret = true; - else if (get_program(entry, prog, remaining_entry)) - ret = true; - else if (get_keyword(entry, prog, remaining_entry)) - ret = true; - else if (get_complex(entry, prog, remaining_entry)) - ret = true; - else if (get_comment(entry, remaining_entry)) - ret = true; - else - // nothing, considered as an auto-evaluated symbol - if (get_other(entry, prog, remaining_entry)) - ret = true; - - return ret; + return true; } -/// @brief cut an entry string into entry chunks with respect of types separators -/// -/// @param entry the entry -/// @param entries the cut entriy vector -/// @return true entries not vempty -/// @return false entries empty -/// -static bool _cut(const char* entry, vector& entries) { - string tmp; - int len = strlen(entry); - - for (int i = 0; i < len; i++) { - switch (entry[i]) { - // symbol - case '\'': - // push prec entry if exists - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - // get symbol - tmp = '\''; - i++; - while ((i < len) && entry[i] != '\'') tmp += entry[i++]; - if ((i < len) && entry[i] != '\'') tmp += '\''; - entries.push_back(tmp); - tmp.clear(); +static bool progFromElements(vector& elements, program& prog) { + for_each(elements.begin(), elements.end(), [&](SynElement& element) { + switch (element.type) { + case cmd_number: + prog.insert(prog.begin(), 1, new number(element.re)); break; - - // string - case '"': - // push prec entry if exists - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - // get expression - tmp = '"'; - i++; - while (i < len && entry[i] != '"') tmp += entry[i++]; - - if ((i < len) && entry[i] != '"') tmp += '"'; - - entries.push_back(tmp); - tmp.clear(); + // case cmd_complex: prog.insert(prog.begin(), 1, new ocomplex(element.re, element.im)); break; + case cmd_string: + prog.insert(prog.begin(), 1, new ostring(element.value)); break; - - // program - case '<': - // push prec entry if exists - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - - if (strncmp(&entry[i], "<<", 2) == 0) { - int up = 1; - - // found a program begin - i += 2; - tmp = "<< "; - - // trim leading spaces - while (i < len && isspace(entry[i])) i++; - - while (i < len) { - if (strncmp(&entry[i], "<<", 2) == 0) { - up++; - i += 2; - tmp += "<< "; - // trim leading spaces - while (i < len && isspace(entry[i])) i++; - } else if (strncmp(&entry[i], ">>", 2) == 0) { - if (isspace(entry[i - 1]) && entry[i - 2] != '>') - tmp += ">>"; - else - tmp += " >>"; - - up--; - i += 2; - - // trim trailing spaces - while (i < len && isspace(entry[i])) i++; - - // found end - if (up == 0) break; - } else { - tmp += entry[i]; - i++; - } - } - while ((up--) > 0) tmp += " >>"; - - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - i--; // i has move 1 too far - } else - // reinject '<'' which is not a prog begin - tmp = "<"; + case cmd_symbol: + prog.insert(prog.begin(), 1, new symbol(element.value)); break; - - // complex - case '(': - // push prec entry if exists - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - // get complex - while ((i < len) && entry[i] != ')') tmp += entry[i++]; - if ((i < len) && entry[i] != ')') tmp += ')'; - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } + // case cmd_program: prog.insert(prog.begin(), 1, new program(element.value)); break; + case cmd_keyword: + prog.insert(prog.begin(), 1, new keyword(element.fn, element.value)); + break; + case cmd_branch: + prog.insert(prog.begin(), 1, new branch((branch_fn_t)element.fn, element.value)); break; - - // other default: - if (!isspace(entry[i])) - tmp += entry[i]; - else { - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - } - break; + return false; } - } - if (tmp.size() > 0) { - entries.push_back(tmp); - tmp.clear(); - } - return entries.size() > 0; + return true; + }); + return true; } /// @brief parse an entry string: cut it into objects chunks and add them to a program -/// +/// /// @param entry the entry string /// @param prog the program /// @return ret_value see this type /// -ret_value program::parse(const char* entry, program& prog) { - vector entries; +ret_value program::parse(string& entry, program& prog) { + vector elements; + vector errors; 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::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 = {"1", "2+"} -> first "1", - // second "2" and remaining_entry="+" this remaining entry is treated as - // an entry + // prepare map for finding reserved keywords + if (_keywordsMap.size() == 0) + for (int i = 0; s_keywords[i].type != cmd_max; i++) + _keywordsMap[s_keywords[i].name] = {s_keywords[i].type, s_keywords[i].fn}; - // TODO errors ? - _obj_from_string(main_entry, prog, remaining_entry); - main_entry = remaining_entry; - } - } + // separate the entry string + if (lexer(entry, elements, errors, _keywordsMap)) { + // make objects from parsed elements + if (!progFromElements(elements, prog)) prog.show_error(ret_unknown_err, "error creating program from entry"); + } else { + for(SynError& err: errors) + prog.show_syntax_error(err.err.c_str()); } return ret; diff --git a/src/program.cpp b/src/program.cpp index 22af5db..94ce863 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,4 +1,4 @@ - #include "program.hpp" +#include "program.hpp" //< return type strings const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; @@ -20,51 +20,55 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "history", &program::rpn_history, "see commands history"}, // USUAL OPERATIONS ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, - {cmd_keyword, "+", &program::rpn_plus, "addition"}, - {cmd_keyword, "-", &program::rpn_minus, "substraction"}, - {cmd_keyword, "chs", &program::rpn_neg, "negation"}, - {cmd_keyword, "neg", &program::rpn_neg, ""}, - {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, - {cmd_keyword, "/", &program::rpn_div, "division"}, - {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, - {cmd_keyword, "^", &program::rpn_power, "power"}, - {cmd_keyword, "pow", &program::rpn_power, ""}, - {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, - {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, - {cmd_keyword, "sqr", &program::rpn_square, ""}, - {cmd_keyword, "abs", &program::rpn_abs, "absolute value"}, - {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"}, - {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"}, - {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, - {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"}, - {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, + // {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, + // {cmd_keyword, "+", &program::rpn_plus, "addition"}, + // {cmd_keyword, "-", &program::rpn_minus, "substraction"}, + // {cmd_keyword, "chs", &program::rpn_neg, "negation"}, + // {cmd_keyword, "neg", &program::rpn_neg, ""}, + // {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, + // {cmd_keyword, "/", &program::rpn_div, "division"}, + // {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, + // {cmd_keyword, "^", &program::rpn_power, "power"}, + // {cmd_keyword, "pow", &program::rpn_power, ""}, + // {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, + // {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, + // {cmd_keyword, "sqr", &program::rpn_square, ""}, + // {cmd_keyword, "abs", &program::rpn_abs, "absolute value"}, + // {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"}, + // {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"}, + // {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, + // {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"}, + // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, + // {cmd_keyword, "inf", &program::rpn_inf, "positive infinite"}, + // {cmd_keyword, "+inf", &program::rpn_inf, "positive infinite"}, + // {cmd_keyword, "-inf", &program::rpn_minf, "negative infinite"}, + // {cmd_keyword, "nan", &program::rpn_nan, "not a number"}, // OPERATIONS ON REALS - {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, - {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, - {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, - {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, - {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, - {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, - {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, - {cmd_keyword, "floor", &program::rpn_floor, "largest number <="}, - {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="}, - {cmd_keyword, "ip", &program::rpn_ip, "integer part"}, - {cmd_keyword, "fp", &program::rpn_fp, "fractional part"}, - {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"}, - {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, + // {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, + // {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, + // {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, + // {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, + // {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, + // {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, + // {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, + // {cmd_keyword, "floor", &program::rpn_floor, "largest number <="}, + // {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="}, + // {cmd_keyword, "ip", &program::rpn_ip, "integer part"}, + // {cmd_keyword, "fp", &program::rpn_fp, "fractional part"}, + // {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"}, + // {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, - // nOPERATIONS ON COMPLEXES - {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, - {cmd_keyword, "re", &program::rpn_re, "complex real part"}, - {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, - {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, - {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"}, - {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, - {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, - {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, - {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, + // OPERATIONS ON COMPLEXES + // {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, + // {cmd_keyword, "re", &program::rpn_re, "complex real part"}, + // {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, + // {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, + // {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"}, + // {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, + // {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, + // {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, + // {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, // MODE {cmd_undef, "", NULL, "\nMODE"}, @@ -111,41 +115,42 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, // STRING - {cmd_undef, "", NULL, "\nSTRING"}, - {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, - {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, - {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, - {cmd_keyword, "num", &program::rpn_num, - "return ASCII code of the first character of the string in stack level 1 " - "as a real number"}, - {cmd_keyword, "size", &program::rpn_strsize, "return the length of the string"}, - {cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, - {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, + // {cmd_undef, "", NULL, "\nSTRING"}, + // {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, + // {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, + // {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, + // {cmd_keyword, "num", &program::rpn_num, + // "return ASCII code of the first character of the string in stack level 1 " + // "as a real number"}, + // {cmd_keyword, "size", &program::rpn_strsize, "return the length of the string"}, + // {cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, + // {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, // BRANCH - {cmd_undef, "", NULL, "\nBRANCH"}, - {cmd_branch, "if", (program_fn_t)&program::rpn_if, - "if then else " - "end"}, - {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"}, - {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"}, - {cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, - {cmd_branch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, - {cmd_branch, "for", (program_fn_t)&program::rpn_for, - " for next| step"}, - {cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, - {cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, - {cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, - {cmd_keyword, "ifte", &program::rpn_ifte, - "similar to if-then-else-end, " - " ifte"}, - {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, - {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, - {cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""}, - {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, - {cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""}, - {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, - {cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""}, + // {cmd_undef, "", NULL, "\nBRANCH"}, + // {cmd_branch, "if", (program_fn_t)&program::rpn_if, + // "if then else " + // "end"}, + // {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"}, + // {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"}, + // {cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, + // {cmd_branch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, + // {cmd_branch, "for", (program_fn_t)&program::rpn_for, + // " for next| step"}, + // {cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, + // {cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, + // {cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, + // {cmd_keyword, "ifte", &program::rpn_ifte, + // "similar to if-then-else-end, " + // " ifte"}, + // {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, + // {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, + // {cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""}, + // {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat + // end"}, + // {cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""}, + // {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, + // {cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""}, // STORE {cmd_undef, "", NULL, "\nSTORE"}, @@ -155,13 +160,12 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "vars", &program::rpn_vars, "list all variables"}, {cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"}, {cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"}, - {cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, - {cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, - {cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, - {cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, - {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, - {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, - + // {cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, + // {cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, + // {cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, + // {cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, + // {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, + // {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, // PROGRAM {cmd_undef, "", NULL, "\nPROGRAM"}, {cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, @@ -170,43 +174,43 @@ program::keyword_t program::s_keywords[] = { ">>"}, // TRIG ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, - {cmd_keyword, "pi", &program::rpn_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::rpn_d2r, "convert degrees to radians"}, - {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, + // {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, + // {cmd_keyword, "pi", &program::rpn_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::rpn_d2r, "convert degrees to radians"}, + // {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, - {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, - {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, - {cmd_keyword, "log", &program::rpn_ln, ""}, - {cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, - {cmd_keyword, "exp", &program::rpn_exp, "exponential"}, - {cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, - {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"}, - {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"}, - {cmd_keyword, "exp10", &program::rpn_alog10, ""}, - {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"}, - {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"}, - {cmd_keyword, "exp2", &program::rpn_alog2, ""}, - {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"}, + // {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, + // {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, + // {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, + // {cmd_keyword, "log", &program::rpn_ln, ""}, + // {cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, + // {cmd_keyword, "exp", &program::rpn_exp, "exponential"}, + // {cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, + // {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"}, + // {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"}, + // {cmd_keyword, "exp10", &program::rpn_alog10, ""}, + // {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"}, + // {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"}, + // {cmd_keyword, "exp2", &program::rpn_alog2, ""}, + // {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"}, // TIME AND DATE - {cmd_undef, "", NULL, "\nTIME AND DATE"}, - {cmd_keyword, "time", &program::rpn_time, "time in local format"}, - {cmd_keyword, "date", &program::rpn_date, "date in local format"}, - {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, + // {cmd_undef, "", NULL, "\nTIME AND DATE"}, + // {cmd_keyword, "time", &program::rpn_time, "time in local format"}, + // {cmd_keyword, "date", &program::rpn_date, "date in local format"}, + // {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, // end {cmd_max, "", NULL, ""}, @@ -218,7 +222,7 @@ program::keyword_t program::s_keywords[] = { /// @param hp the heap, storing variables /// @return ret_value see this type /// -ret_value program::run(stack& stk, heap& hp) { +ret_value program::run(rpnstack& stk, heap& hp) { bool go_out = false; ret_value ret = ret_ok; cmd_type_t type; @@ -238,67 +242,69 @@ ret_value program::run(stack& stk, heap& hp) { // iterate commands for (int i = 0; (go_out == false) && (interrupt_now == false) && (i < (int)size());) { - type = (cmd_type_t)seq_type(i); + switch((cmd_type_t)(*this)[i]->_type) { + // could be an auto-evaluated symbol + case cmd_symbol: + auto_rcl((symbol*)(*this)[i]); + i++; + break; - // 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 + // a keyword + case cmd_keyword: { + keyword* k = (keyword*)(*this)[i]; + // call the 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; - } - i++; - } + break; + default: + // error: abort prog + go_out = true; - // 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; + // error: show it + if (show_error(_err, _err_context) == ret_deadly) { + // pb showing error -> go out software + ret = ret_good_bye; + } + break; + } + i++; + 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++; + // a branch keyword + case cmd_branch: { + // call matching function + branch* b = (branch*)(*this)[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; + } + break; + } + + default: + // not a command, but a stack entry, manage it + // copy the program stack entry to the running stack + stk.push_back((*this)[i]); + i++; + break; } } @@ -324,8 +330,8 @@ void program::stop() { interrupt_now = true; } /// @return false the branch name is NOT str_to_compare /// bool program::compare_branch(branch* b, const char* str_to_compare, int len) { - if (b->_len >= len) - return strncasecmp(b->_value, str_to_compare, len) == 0; + if (str_to_compare != nullptr) + return b->_value == str_to_compare; else return false; } @@ -347,9 +353,8 @@ ret_value program::preprocess(void) { // 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_branch) { - branch* k = (branch*)seq_obj(i); + if ((*this)[i]->_type == cmd_branch) { + branch* k = (branch*)(*this)[i]; if (compare_branch(k, "if", 2)) { if_layout_t layout; layout.index_if_or_do_or_while = i; @@ -406,7 +411,7 @@ ret_value program::preprocess(void) { vlayout[layout_index].index_else = i; k->arg1 = next; // fill branch1 (if was false) of 'else' k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = + ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg2 = next; // fill branch2 (if was false) of 'then' } else if (compare_branch(k, "start", 5)) vstartindex.push_back(i); @@ -420,7 +425,7 @@ ret_value program::preprocess(void) { return ret_syntax; } k->arg1 = vstartindex[vstartindex.size() - 1]; // 'next' arg1 = 'start' index - ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = + ((branch*)(*this)[vstartindex[vstartindex.size() - 1]])->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); } else if (compare_branch(k, "step", 4)) { @@ -430,7 +435,7 @@ ret_value program::preprocess(void) { return ret_syntax; } k->arg1 = vstartindex[vstartindex.size() - 1]; // fill 'step' branch1 = 'start' index - ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = + ((branch*)(*this)[vstartindex[vstartindex.size() - 1]])->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); } else if (compare_branch(k, "->", 2)) { @@ -522,7 +527,7 @@ ret_value program::preprocess(void) { } // fill 'repeat' arg1 with 'end+1' - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg1 = i + 1; + ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg1 = i + 1; layout_index--; } else { // this end closes an if..then..(else) @@ -533,11 +538,11 @@ ret_value program::preprocess(void) { } if (vlayout[layout_index].index_else != -1) // fill 'end' branch of 'else' - ((branch*)seq_obj(vlayout[layout_index].index_else))->arg2 = i; + ((branch*)(*this)[vlayout[layout_index].index_else])->arg2 = i; else { // fill 'end' branch of 'then' if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - ((branch*)seq_obj(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = i; + ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg2 = i; else { // error: show it show_syntax_error("missing then"); @@ -634,15 +639,15 @@ ret_value program::get_err(void) { return _err; } /// @param st the stack to show /// @param show_separator whether to show a stack level prefix or not /// -void program::show_stack(stack& st, bool show_separator) { +void program::show_stack(rpnstack& st, bool show_separator) { if (st.size() == 1) { - ((object*)st.back())->show(); - printf("\n"); + st.front()->show(cout); + cout << endl; } else { - for (int i = st.size() - 1; i >= 0; i--) { - if (show_separator) printf("%d%s", i + 1, SHOW_STACK_SEPARATOR); - ((object*)st[i])->show(); - printf("\n"); + for (int i = 0; i < st.size(); i++) { + if (show_separator) cout << st.size() - i << SHOW_STACK_SEPARATOR; + st[i]->show(cout); + cout << endl; } } } @@ -658,8 +663,4 @@ void program::apply_default() { stringstream ss; ss << number::s_decimal_digits; number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD); - - // default calc precision for MPFR - floating_t::s_mpfr_prec = (mpfr_prec_t)MPFR_DEFAULT_PREC_BITS; - floating_t::s_mpfr_prec_bytes = MPFR_DEFAULT_STORING_LENGTH_BYTES; } diff --git a/src/program.hpp b/src/program.hpp index b36b9a7..0377dcc 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -11,12 +11,15 @@ #include #include #include +#include #include #include using namespace std; // external libs +#define MPFR_USE_NO_MACRO #include + #include "linenoise.h" // internal includes @@ -40,7 +43,7 @@ struct if_layout_t { }; //< program class: the class containing a string parser, all the programs keywords, a stack for running the program -class program : public stack { +class program : public vector { public: program(program* parent_prog = NULL) { _parent_prog = parent_prog; @@ -48,15 +51,15 @@ class program : public stack { } // parser - static ret_value parse(const char* entry, program& prog); + static ret_value parse(string& entry, program& prog); static ret_value entry(program& prog); static void entry_completion_generator(const char* text, linenoiseCompletions* lc); static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type); // running - ret_value run(stack& stk, heap& hp); + ret_value run(rpnstack& stk, heap& hp); void stop(); - bool compare_keyword(keyword* k, const char* str_to_compare, int len); + // bool compare_keyword(keyword* k, const char* str_to_compare, int len); bool compare_branch(branch* b, const char* str_to_compare, int len); ret_value preprocess(void); @@ -66,7 +69,7 @@ class program : public stack { void show_syntax_error(const char* context); ret_value get_err(void); - static void show_stack(stack& st, bool show_separator = true); + static void show_stack(rpnstack& st, bool show_separator = true); static void apply_default(); @@ -78,7 +81,7 @@ class program : public stack { string _err_context; // global stack holding results for user - stack* _stack; + rpnstack* _stack; // global heap (sto, rcl) heap* _heap; @@ -87,7 +90,7 @@ class program : public stack { heap _local_heap; // calc stack internally used by branch and calc commands - stack _calc_stack; + rpnstack _calc_stack; // parent prog for inheriting heaps program* _parent_prog; @@ -168,7 +171,7 @@ class program : public stack { void rpn_atanh(); // program - bool find_variable(string& variable, object*& obj, unsigned int& size); + bool find_variable(string& variable, object*& obj); void rpn_eval(void); int rpn_inprog(branch& myobj); @@ -243,14 +246,14 @@ class program : public stack { void rpn_strsub(); // test-core - void test_get_stack(string& stack_is, stack& stk); + void test_get_stack(string& stack_is, rpnstack& stk); void test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed); void rpn_test(); void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed); // test - int cmp_strings_on_stack_top(); + long cmp_strings_on_stack_top(); void rpn_sup(void); void rpn_sup_eq(void); void rpn_inf(void); @@ -304,23 +307,23 @@ class program : public stack { } \ } while (0) -#define ARG_MUST_BE_OF_TYPE(num, type) \ - do { \ - if (_stack->get_type(num) != (type)) { \ - ERR_CONTEXT(ret_bad_operand_type); \ - return; \ - } \ +#define ARG_MUST_BE_OF_TYPE(num, type) \ + do { \ + if (_stack->at(num)->_type != (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)) { \ + if (_stack->at(num)->_type != (type)) { \ ERR_CONTEXT(ret_bad_operand_type); \ return (ret); \ } \ } while (0) -#define IS_ARG_TYPE(num, type) (_stack->get_type(num) == (type)) +#define IS_ARG_TYPE(num, type) (_stack->at(num)->_type == (type)) #define CHECK_MPFR(op) \ do { \ diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index d52a700..cdf305a 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -11,7 +11,7 @@ int program::rpn_if(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0) + if (mpfr_cmp_si(((number*)_stack->at(0))->_value.mpfr, 0UL) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; @@ -30,7 +30,7 @@ int program::rpn_then(branch& myobj) { // myobj.arg3 = index of if // if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1) - branch* if_cmd = (branch*)seq_obj(myobj.arg3); + branch* if_cmd = (branch*)(*this)[myobj.arg3]; if (if_cmd->arg1 == 1) return myobj.arg1; else @@ -49,7 +49,7 @@ int program::rpn_else(branch& myobj) { // myobj.arg3 = index of if // if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1) - branch* if_cmd = (branch*)seq_obj(myobj.arg3); + branch* if_cmd = (branch*)(*this)[myobj.arg3]; if (if_cmd->arg1 == 1) return myobj.arg2; else @@ -116,13 +116,13 @@ void program::rpn_ift(void) { // check ift arg // arg is true if number != 0 or if is nan or +/-inf - number* testee = ((number*)_stack->get_obj(1)); + number* testee = ((number*)_stack->at(1)); if (!mpfr_zero_p(testee->_value.mpfr)) { - CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); + CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); (void)_stack->pop_back(2); - CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); + CHECK_MPFR(rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); (void)_calc_stack.pop_back(); } else (void)_stack->pop_back(2); @@ -140,16 +140,16 @@ void program::rpn_ifte(void) { // check ifte arg // arg is true if number != 0 or if is nan or +/-inf - number* testee = ((number*)_stack->get_obj(2)); + number* testee = ((number*)_stack->at(2)); if (!mpfr_zero_p(testee->_value.mpfr)) - CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack)); + CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack)); else - CHECK_MPFR(stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); + CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); (void)_stack->pop_back(3); - CHECK_MPFR(stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); + CHECK_MPFR(rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); (void)_calc_stack.pop_back(); } @@ -198,12 +198,12 @@ int program::rpn_start(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); // farg2 = last value of start command - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); myobj.farg2 = (number*)_calc_stack.back(); _stack->pop_back(); // farg1 = first value of start command - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); myobj.farg1 = (number*)_calc_stack.back(); _stack->pop_back(); @@ -230,16 +230,16 @@ int program::rpn_for(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); - symbol* sym = ((symbol*)seq_obj(myobj.arg1)); + symbol* sym = (symbol*)(*this)[myobj.arg1]; // farg2 = last value of for command // arg1 = index of symbol to increase - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); myobj.farg2 = (number*)_calc_stack.back(); _stack->pop_back(); // farg1 = first value of for command - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); myobj.farg1 = (number*)_calc_stack.back(); _stack->pop_back(); @@ -251,7 +251,7 @@ int program::rpn_for(branch& myobj) { ret = myobj.arg2 + 1; else { // store symbol with first value - _local_heap.add(sym->_value, (object*)myobj.farg1, myobj.farg1->size()); + _local_heap[sym->_value] = myobj.farg1; ret = myobj.arg1 + 1; } @@ -267,7 +267,7 @@ int program::rpn_for(branch& myobj) { int program::rpn_next(branch& myobj) { // arg1 = index of start or for command in program // farg1 = current count - branch* start_or_for = (branch*)seq_obj(myobj.arg1); + branch* start_or_for = (branch*)(*this)[myobj.arg1]; if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.farg1 = start_or_for->farg1; @@ -281,10 +281,10 @@ int program::rpn_next(branch& myobj) { if (start_or_for->arg1 != -1) { object* obj; unsigned int size; - symbol* var = (symbol*)seq_obj(start_or_for->arg1); + symbol* var = (symbol*)(*this)[start_or_for->arg1]; // increase symbol variable - _local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); + _local_heap[var->_value] = myobj.farg1; } // test value @@ -321,7 +321,7 @@ int program::rpn_step(branch& myobj) { else { // arg1 = index of start or for command in program // farg1 = current count - branch* start_or_for = (branch*)seq_obj(myobj.arg1); + branch* start_or_for = (branch*)(*this)[myobj.arg1]; if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.farg1 = start_or_for->farg1; @@ -335,10 +335,10 @@ int program::rpn_step(branch& myobj) { if (start_or_for->arg1 != -1) { object* obj; unsigned int size; - symbol* var = (symbol*)seq_obj(start_or_for->arg1); + symbol* var = (symbol*)(*this)[start_or_for->arg1]; // increase symbol variable - _local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); + _local_heap[var->_value] = myobj.farg1; } // test loop value is out of range diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index 27e031e..8072ab4 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -7,11 +7,12 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); - number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->re()->mpfr, floating_t::s_mpfr_rnd)); + number* re = new number(); + _stack->push_back(re); + CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.at(0))->re()->mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(); } @@ -22,11 +23,12 @@ void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); - number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.get_obj(0))->im()->mpfr, floating_t::s_mpfr_rnd)); + number* im = new number(); + _stack->push_back(im); + CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.at(0))->im()->mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(); } @@ -39,11 +41,12 @@ void program::rpn_arg() { // calc atan2(x/y) complex* cplx = (complex*)_stack->pop_back(); - number* num = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* num = new number(); + _calc_stack.push_back(num); CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); _calc_stack.pop_back(); } @@ -66,14 +69,15 @@ void program::rpn_r2c() { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); _stack->pop_back(); - complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex); - CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.get_obj(1))->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd)); + complex* cplx = new complex(); + _stack->push_back(cplx); + CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.at(1))->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(2); } @@ -84,11 +88,13 @@ void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); - number* re = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - number* im = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* re = new number(); + _stack->push_back(re); + number* im = new number(); + _stack->push_back(im); CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, floating_t::s_mpfr_rnd)); @@ -106,13 +112,13 @@ void program::rpn_r2p() { rpn_dup(); rpn_arg(); - complex* cplx = (complex*)_stack->get_obj(1); + complex* cplx = (complex*)_stack->at(1); CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); _stack->pop_back(); rpn_swap(); rpn_abs(); - cplx = (complex*)_stack->get_obj(1); + cplx = (complex*)_stack->at(1); CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); _stack->pop_back(); } @@ -124,12 +130,12 @@ void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _calc_stack.allocate_back(number::calc_size(), cmd_number); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + _calc_stack.push_back(new number()); // assert complex is polar - complex* rhotheta = (complex*)_calc_stack.get_obj(1); - number* tmp = (number*)_calc_stack.get_obj(0); + complex* rhotheta = (complex*)_calc_stack.at(1); + number* tmp = (number*)_calc_stack.at(0); complex* result = (complex*)_stack->back(); // calc cos(theta) diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index e038a9b..1e7c152 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -56,8 +56,8 @@ void program::rpn_help() { printf(" with %d digits after the decimal point\n", number::s_decimal_digits); // bits precision, decimal digits and rounding mode - 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("Current floating point precision is %d bits\n", (int)number::s_mpfr_prec); + printf("Current rounding mode is \"%s\"\n", number::s_mpfr_rnd_str[number::s_mpfr_rnd]); printf("\n\n"); } @@ -158,19 +158,13 @@ void program::rpn_sci() { /// @brief version keyword implementation /// void program::rpn_version() { - // allocate and set object - unsigned int naked_entry_len = strlen(version); - ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring) + naked_entry_len + 1, cmd_string); - str->set(version, naked_entry_len); + _stack->push_back(new ostring(version)); } /// @brief uname keyword implementation /// void program::rpn_uname() { - // allocate and set object - unsigned int naked_entry_len = strlen(uname); - ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring) + naked_entry_len + 1, cmd_string); - str->set(uname, naked_entry_len); + _stack->push_back(new ostring(uname)); } /// @brief history keyword implementation @@ -193,11 +187,7 @@ void program::rpn_type() { int type = _stack->pop_back()->_type; if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef; - - unsigned int string_size = strlen(object::s_cmd_type_string[type]); - unsigned int size = sizeof(symbol) + string_size + 1; - ostring* typ = (ostring*)_stack->allocate_back(size, cmd_string); - typ->set(object::s_cmd_type_string[type], string_size); + _stack->push_back(new ostring(object::s_cmd_type_string[type])); } /// @brief default keyword implementation @@ -211,15 +201,14 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - unsigned long prec = mpfr_get_ui(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); + unsigned long prec = static_cast(_stack->pop_back())->_value.toULong(); if (prec >= (unsigned long)MPFR_PREC_MIN && prec <= (unsigned long)MPFR_PREC_MAX) { - floating_t::s_mpfr_prec = (mpfr_prec_t)prec; - floating_t::s_mpfr_prec_bytes = mpfr_custom_get_size(prec); + number::s_mpfr_prec = (mpfr_prec_t)prec; // modify digits seen by user if std mode if (number::s_mode == number::std) { // calc max nb of digits user can see with the current bit precision - number::s_decimal_digits = base_digits_from_bit_precision(10, floating_t::s_mpfr_prec); + number::s_decimal_digits = base_digits_from_bit_precision(10, number::s_mpfr_prec); number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD); } } else @@ -235,8 +224,8 @@ void program::rpn_round() { ostring* str = (ostring*)_stack->pop_back(); bool done = false; for (int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++) { - if (string(floating_t::s_mpfr_rnd_str[rnd]) == str->_value) { - floating_t::s_mpfr_rnd = (mpfr_rnd_t)rnd; + if (string(number::s_mpfr_rnd_str[rnd]) == str->_value) { + number::s_mpfr_rnd = (mpfr_rnd_t)rnd; done = true; } } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 78b2819..d6489df 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -3,7 +3,8 @@ /// @brief e keyword implementation /// void program::rpn_e(void) { - number* euler = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* euler = new number(); + _stack->push_back(euler); euler->_value = 1L; CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd)); } @@ -13,11 +14,12 @@ void program::rpn_e(void) { void program::rpn_log10() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { // log10(z)=ln(z)/ln(10) rpn_ln(); - number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* ten = new number(); + _stack->push_back(ten); CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); rpn_ln(); rpn_div(); @@ -30,9 +32,10 @@ void program::rpn_log10() { void program::rpn_alog10() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; - number* ten = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { + floating_t* left = &((number*)_stack->at(0))->_value; + number* ten = new number(); + _stack->push_back(ten); CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); rpn_ln(); rpn_mul(); @@ -45,11 +48,12 @@ void program::rpn_alog10() { void program::rpn_log2() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { // log2(z)=ln(z)/ln(2) rpn_ln(); - number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* two = new number(); + _stack->push_back(two); CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_ln(); rpn_div(); @@ -62,9 +66,10 @@ void program::rpn_log2() { void program::rpn_alog2() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; - number* two = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { + floating_t* left = &((number*)_stack->at(0))->_value; + number* two = new number(); + _stack->push_back(two); CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_ln(); rpn_mul(); @@ -77,31 +82,32 @@ void program::rpn_alog2() { void program::rpn_ln() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); // x<0 -> ln(x) = ln(-x)+i*pi if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) { - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); left = (number*)_calc_stack.back(); - complex* cplx = (complex*)_stack->allocate_back(complex::calc_size(), cmd_complex); + complex* cplx = new complex(); + _stack->push_back(cplx); CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(); } else CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* x = ((complex*)_calc_stack.get_obj(0))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(0))->im(); + floating_t* x = ((complex*)_calc_stack.at(0))->re(); + floating_t* y = ((complex*)_calc_stack.at(0))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); // 1. atan(x/y) CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); @@ -123,18 +129,18 @@ void program::rpn_ln() { void program::rpn_exp() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // exp(x)*(cos(y)+i sin(y)) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* x = ((complex*)_calc_stack.get_obj(0))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(0))->im(); + floating_t* x = ((complex*)_calc_stack.at(0))->re(); + floating_t* y = ((complex*)_calc_stack.at(0))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -152,11 +158,12 @@ void program::rpn_exp() { void program::rpn_expm() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { // exp(x)-1 rpn_exp(); - number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* one = new number(); + _stack->push_back(one); CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_minus(); } else @@ -168,9 +175,10 @@ void program::rpn_expm() { void program::rpn_lnp1() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number || _stack->get_type(0) == cmd_complex) { + if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { // ln(x+1) - number* one = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* one = new number(); + _stack->push_back(one); CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_plus(); @@ -184,19 +192,21 @@ void program::rpn_lnp1() { void program::rpn_sinh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; - floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); + number* num = new number(); + _stack->push_back(num); + floating_t* tmp = &num->_value; + floating_t* x = ((complex*)_calc_stack.at(1))->re(); + floating_t* y = ((complex*)_calc_stack.at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -216,14 +226,15 @@ void program::rpn_sinh() { void program::rpn_asinh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // asinh(z)=ln(z+sqrt(1+z*z)) rpn_dup(); rpn_square(); - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* num = new number(); + _stack->push_back(num); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_plus(); rpn_squareroot(); @@ -238,19 +249,21 @@ void program::rpn_asinh() { void program::rpn_cosh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; - floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); + number* num = new number(); + _stack->push_back(num); + floating_t* tmp = &num->_value; + floating_t* x = ((complex*)_calc_stack.at(1))->re(); + floating_t* y = ((complex*)_calc_stack.at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -270,17 +283,19 @@ void program::rpn_cosh() { void program::rpn_acosh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // acosh(z)=ln(z+sqrt(z+1)sqrt(z-1)) rpn_dup(); - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* num = new number(); + _stack->push_back(num); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_plus(); rpn_dup(); - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + num = (number*)new number(); + _stack->push_back(num); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_minus(); rpn_mul(); @@ -296,18 +311,18 @@ void program::rpn_acosh() { void program::rpn_tanh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y)) rpn_dup(); - floating_t* x = ((complex*)_stack->get_obj(1))->re(); - floating_t* y = ((complex*)_stack->get_obj(1))->im(); + floating_t* x = ((complex*)_stack->at(1))->re(); + floating_t* y = ((complex*)_stack->at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(1))->re(); - floating_t* im = ((complex*)_stack->get_obj(1))->im(); + floating_t* re = ((complex*)_stack->at(1))->re(); + floating_t* im = ((complex*)_stack->at(1))->im(); CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -326,23 +341,25 @@ void program::rpn_tanh() { void program::rpn_atanh() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // atanh(z)=0.5*ln((1+z)/(1-z)) rpn_dup(); - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + + number* num; + _stack->push_back(num = new number); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_plus(); rpn_swap(); - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(num = new number); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_minus(); rpn_neg(); rpn_div(); rpn_ln(); - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(num = new number); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); rpn_mul(); } else diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 0a970e3..e349a94 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -4,26 +4,25 @@ /// /// @param variable the variable name to find /// @param obj the variable object found -/// @param size its size /// @return true variable was found /// @return false variable was not found /// -bool program::find_variable(string& variable, object*& obj, unsigned int& size) { +bool program::find_variable(string& variable, object*& obj) { bool found = false; program* parent = _parent_prog; - if (_local_heap.get(variable, obj, size)) + if (_local_heap.get(variable, obj)) found = true; else { while (parent != NULL) { - if (parent->_local_heap.get(variable, obj, size)) { + if (parent->_local_heap.get(variable, obj)) { found = true; break; } parent = parent->_parent_prog; } if (!found) { - if (_heap->get(variable, obj, size)) found = true; + if (_heap->get(variable, obj)) found = true; } } @@ -40,11 +39,10 @@ void program::rpn_eval(void) { if (IS_ARG_TYPE(0, cmd_symbol)) { // recall a variable object* obj; - unsigned int size; string variable(((symbol*)_stack->back())->_value); // if variable holds a program, run this program - if (find_variable(variable, obj, size)) { + if (find_variable(variable, obj)) { if (obj->_type == cmd_program) { prog_text = ((oprogram*)obj)->_value; (void)_stack->pop_back(); @@ -52,7 +50,7 @@ void program::rpn_eval(void) { } else { // else recall this variable (i.e. stack its content) (void)_stack->pop_back(); - stack::copy_and_push_back(obj, *_stack, size); + _stack->push_back(obj); } } else ERR_CONTEXT(ret_unknown_variable); @@ -68,7 +66,7 @@ void program::rpn_eval(void) { program prog(this); // make program from entry - if (program::parse(prog_text.c_str(), prog) == ret_ok) { + if (program::parse(prog_text, prog) == ret_ok) { // run it prog.run(*_stack, *_heap); } @@ -93,9 +91,9 @@ int program::rpn_inprog(branch& myobj) { // find next oprogram object for (unsigned int i = myobj.arg1 + 1; i < size(); i++) { // count symbol - if (seq_type(i) == cmd_symbol) count_symbols++; + if ((*this)[i]->_type == cmd_symbol) count_symbols++; // stop if prog - else if (seq_type(i) == cmd_program) { + else if ((*this)[i]->_type == cmd_program) { prog_found = true; break; } @@ -130,16 +128,16 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0)); + _local_heap[string(((symbol*)(*this)[i])->_value)] = _stack->at(0); (void)_stack->pop_back(); } // run the program - string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value); + string entry(((oprogram*)(*this)[myobj.arg1 + count_symbols + 1])->_value); program prog(this); // make the program from entry - if (program::parse(entry.c_str(), prog) == ret_ok) { + if (program::parse(entry, prog) == ret_ok) { // run it prog.run(*_stack, *_heap); } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 35dcc39..75043af 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -6,45 +6,33 @@ void program::rpn_plus() { MIN_ARGUMENTS(2); // adding strings - if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - unsigned int left_str_size = ((ostring*)_stack->get_obj(1))->_len; - unsigned int right_str_size = ((ostring*)_stack->get_obj(0))->_len; - - stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - (void)_stack->pop_back(); - (void)_stack->pop_back(); - - ostring* str = - (ostring*)_stack->allocate_back(left_str_size + right_str_size + 1 + sizeof(ostring), cmd_string); - str->_len = left_str_size + right_str_size; - - strncpy(str->_value, ((ostring*)_calc_stack.get_obj(1))->_value, left_str_size); - strncat(str->_value, ((ostring*)_calc_stack.get_obj(0))->_value, right_str_size); - _calc_stack.pop_back(); - _calc_stack.pop_back(); + if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) { + string str = + static_cast(_stack->at(1))->_value + static_cast(_stack->at(0))->_value; + _stack->pop_back(2); + _stack->push_back(new ostring(str)); } // adding numbers - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // adding complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { complex* right = (complex*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); } // adding complex+number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // adding number+complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); @@ -59,26 +47,26 @@ void program::rpn_minus() { MIN_ARGUMENTS(2); // substracting numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // substracting complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { complex* right = (complex*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); } // substracting complex-number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // substracting number-complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); @@ -93,17 +81,17 @@ void program::rpn_mul() { MIN_ARGUMENTS(2); // multiplying numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // multiplying complexes (a+ib)*(x+iy)=(ax-by)+i(ay+bx)=a(x+iy)+b(-y+ix) - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { complex* right = (complex*)_stack->pop_back(); // x+iy complex* left = (complex*)_stack->back(); // a+ib - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); complex* left_sav = (complex*)_calc_stack.back(); // a+ib // left: (a+ib)->(ax+iay) @@ -122,14 +110,14 @@ void program::rpn_mul() { _calc_stack.pop_back(); } // multiplying complex*number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // multiplying number*complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); @@ -144,23 +132,25 @@ void program::rpn_mul() { /// void program::do_divide_complexes() { //(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2) - complex* right = (complex*)_stack->get_obj(0); // x+iy - complex* left = (complex*)_stack->get_obj(1); // a+ib + complex* right = (complex*)_stack->at(0); // x+iy + complex* left = (complex*)_stack->at(1); // a+ib // 1. calc (x^2-y^2) in _calc_stack - number* ex = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* ex; + _calc_stack.push_back(ex = new number); CHECK_MPFR(mpfr_mul(ex->_value.mpfr, right->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); // x2 - number* wy = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* wy; + _calc_stack.push_back(wy = new number); CHECK_MPFR(mpfr_mul(wy->_value.mpfr, right->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); // y2 CHECK_MPFR(mpfr_add(ex->_value.mpfr, ex->_value.mpfr, wy->_value.mpfr, floating_t::s_mpfr_rnd)); // ex=x2+y2 - stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); // x+iy - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - complex* left_sav = (complex*)_calc_stack.get_obj(1); // a+ib - complex* right_sav = (complex*)_calc_stack.get_obj(0); // x+iy + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); // x+iy + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + complex* left_sav = (complex*)_calc_stack.at(1); // a+ib + complex* right_sav = (complex*)_calc_stack.at(0); // x+iy // 2. left.re=ax+by CHECK_MPFR(mpfr_mul(left->re()->mpfr, left_sav->re()->mpfr, right_sav->re()->mpfr, @@ -192,40 +182,40 @@ void program::rpn_div() { MIN_ARGUMENTS(2); // dividing numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // dividing complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) do_divide_complexes(); // dividing complex/number - else if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { number* right = (number*)_stack->pop_back(); complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); } // dividing number/complex - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_number) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { // 1. copy out - stack::copy_and_push_back(*_stack, _stack->size() - 1, - _calc_stack); // complex - stack::copy_and_push_back(*_stack, _stack->size() - 2, - _calc_stack); // number + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, + _calc_stack); // complex + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, + _calc_stack); // number _stack->pop_back(2); // 2. copy back (2 complexes on stack) - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, - *_stack); // complex back to stack - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, - *_stack); // complex back to stack + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, + *_stack); // complex back to stack + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, + *_stack); // complex back to stack // 3. set complex level 2 to (number,0) - complex* new_cplx = (complex*)_stack->get_obj(1); + complex* new_cplx = (complex*)_stack->at(1); CHECK_MPFR( - mpfr_set(new_cplx->re()->mpfr, ((number*)_calc_stack.get_obj(0))->_value.mpfr, floating_t::s_mpfr_rnd)); + mpfr_set(new_cplx->re()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_ui(new_cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); _calc_stack.pop_back(2); @@ -240,10 +230,10 @@ void program::rpn_div() { void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_neg(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { complex* left = (complex*)_stack->back(); CHECK_MPFR(mpfr_neg(left->re()->mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_neg(left->im()->mpfr, left->im()->mpfr, floating_t::s_mpfr_rnd)); @@ -256,14 +246,14 @@ void program::rpn_neg() { void program::rpn_inv() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // 1. duplicate rpn_dup(); // 2. set complex level 2 to (1,0) - complex* cplx = (complex*)_stack->get_obj(1); + complex* cplx = (complex*)_stack->at(1); CHECK_MPFR(mpfr_set_ui(cplx->re()->mpfr, 1UL, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_ui(cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); // 3. divide @@ -306,10 +296,10 @@ void program::rpn_power() { MIN_ARGUMENTS(2); bool done_on_real = false; - if (_stack->get_type(1) == cmd_number) { + if (_stack->at(1)->_type == cmd_number) { ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* right = (number*)_stack->get_obj(0); - number* left = (number*)_stack->get_obj(1); + number* right = (number*)_stack->at(0); + number* left = (number*)_stack->at(1); if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) { CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); @@ -317,27 +307,27 @@ void program::rpn_power() { done_on_real = true; } else { // copy power out - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); // negative number -> complex number - _stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(new number); CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); rpn_r2c(); // copy power back - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); _calc_stack.pop_back(); } } // carrefull, no 'else' here if (!done_on_real) { - if (_stack->get_type(1) == cmd_complex) { + if (_stack->at(1)->_type == cmd_complex) { ARG_MUST_BE_OF_TYPE(0, cmd_number); // power on tmp stack - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); // switch complex to polar @@ -362,23 +352,23 @@ void program::rpn_power() { /// @brief sqrt keyword implementation /// void program::rpn_squareroot() { - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); else { // negative number -> complex square root - _stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(new number); CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); rpn_r2c(); - _stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(new number); CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); rpn_power(); } - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // calc cplx^0.5 - _stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(new number); CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); rpn_power(); } else @@ -390,10 +380,10 @@ void program::rpn_squareroot() { void program::rpn_square() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_sqr(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { rpn_dup(); rpn_mul(); } else @@ -418,12 +408,12 @@ void program::rpn_modulo() { void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // 1. copy out -> calc x2+iy2 - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); // 2. calc x2+iy2 @@ -432,7 +422,7 @@ void program::rpn_abs() { CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); // 3. new real on stack - _stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(new number); number* module = (number*)_stack->back(); // 4. set it to |x2+y2| then take sqrt @@ -479,8 +469,8 @@ void program::rpn_base() { if (mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MIN) >= 0 && mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MAX) <= 0) { int base = (int)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); - ((number*)_stack->get_obj(0))->_base = base; - ((number*)_stack->get_obj(0))->_representation = number::base; + ((number*)_stack->at(0))->_base = base; + ((number*)_stack->at(0))->_representation = number::base; } else ERR_CONTEXT(ret_out_of_range); } @@ -493,7 +483,8 @@ void program::rpn_fact() { // fact(n) = gamma(n+1) number* left = (number*)_stack->back(); - number* right = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* right; + _stack->push_back(right = new number); right->_value = 1L; rpn_plus(); @@ -505,12 +496,12 @@ void program::rpn_fact() { void program::rpn_sign() { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { + if (_stack->at(0)->_type == cmd_number) { // fact(n) = gamma(n+1) number* left = (number*)_stack->back(); int result = mpfr_sgn(left->_value.mpfr); left->_value = (long)result; - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // calc x/sqrt(x*x+y*y) +iy/sqrt(x*x+y*y) rpn_dup(); rpn_abs(); @@ -533,8 +524,10 @@ void program::rpn_mant() { else { mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); - number* one = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - number* ten = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* one; + _stack->push_back(one = new number); + number* ten; + _stack->push_back(ten = new number); ten->_value = 10L; one->_value = 1L; @@ -566,8 +559,10 @@ void program::rpn_xpon() { double exponant = 0.0; mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); - number* one = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); - number* ten = (number*)_calc_stack.allocate_back(number::calc_size(), cmd_number); + number* one; + _stack->push_back(one = new number); + number* ten; + _stack->push_back(ten = new number); ten->_value = 10L; one->_value = 1L; diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index e55febc..9611466 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -4,11 +4,11 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); (void)_stack->pop_back(2); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); _calc_stack.pop_back(2); } @@ -32,7 +32,7 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd); + int args = (int)((number*)_stack->back())->_value.toLong(); MIN_ARGUMENTS(args + 1); (void)_stack->pop_back(args + 1); @@ -46,15 +46,15 @@ void program::rpn_erase(void) { (void)_stack->pop_back(_stack->size()); } /// void program::rpn_dup(void) { MIN_ARGUMENTS(1); - stack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack); } /// @brief dup2 keyword implementation /// void program::rpn_dup2(void) { MIN_ARGUMENTS(2); - stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); } /// @brief dupn keyword implementation @@ -63,11 +63,11 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd); + int args = (int)((number*)_stack->back())->_value.toLong(); MIN_ARGUMENTS(args + 1); _stack->pop_back(); - for (int i = 0; i < args; i++) stack::copy_and_push_back(*_stack, _stack->size() - args, *_stack); + for (int i = 0; i < args; i++) rpnstack::copy_and_push_back(*_stack, _stack->size() - args, *_stack); } /// @brief pick keyword implementation @@ -84,7 +84,7 @@ void program::rpn_pick(void) { return; } - stack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack); } /// @brief rot keyword implementation @@ -92,23 +92,19 @@ void program::rpn_pick(void) { void program::rpn_rot(void) { MIN_ARGUMENTS(3); - stack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); (void)_stack->pop_back(3); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack); _calc_stack.pop_back(3); } /// @brief depth keyword implementation /// -void program::rpn_depth(void) { - unsigned long depth = (unsigned long)_stack->size(); - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - num->set(depth); -} +void program::rpn_depth(void) { _stack->push_back(new number(_stack->size())); } /// @brief roll keyword implementation /// @@ -116,17 +112,17 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd); + int args = (int)((number*)_stack->back())->_value.toLong(); MIN_ARGUMENTS(args + 1); _stack->pop_back(); for (int i = 0; i < args; i++) { - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); (void)_stack->pop_back(); } - for (int i = 1; i < args; i++) stack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack); - stack::copy_and_push_back(_calc_stack, args - 1, *_stack); + for (int i = 1; i < args; i++) rpnstack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack); + rpnstack::copy_and_push_back(_calc_stack, args - 1, *_stack); _calc_stack.pop_back(args); } @@ -137,18 +133,18 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)mpfr_get_si(((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd); + int args = (int)((number*)_stack->back())->_value.toLong(); MIN_ARGUMENTS(args + 1); _stack->pop_back(); for (int i = 0; i < args; i++) { - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); (void)_stack->pop_back(); } - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack); - for (int i = 1; i < args; i++) stack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack); + for (int i = 1; i < args; i++) rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack); _calc_stack.pop_back(args); } @@ -158,5 +154,5 @@ void program::rpn_rolld(void) { void program::rpn_over(void) { MIN_ARGUMENTS(2); - stack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 244ec4e..0e634d9 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -7,36 +7,37 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); string name(((symbol*)_stack->pop_back())->_value); - _heap->add(name, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[name] = _stack->at(0); (void)_stack->pop_back(); } /// @brief sto+ keyword implementation /// +#if 0 void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); - if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_plus(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } - } else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number) { + } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_plus(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else @@ -48,27 +49,27 @@ void program::rpn_stoadd(void) { void program::rpn_stosub(void) { MIN_ARGUMENTS(2); - if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_minus(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } - } else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number) { + } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_minus(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else @@ -80,27 +81,27 @@ void program::rpn_stosub(void) { void program::rpn_stomul(void) { MIN_ARGUMENTS(2); - if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_mul(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } - } else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number) { + } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_mul(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else @@ -112,27 +113,27 @@ void program::rpn_stomul(void) { void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); - if (_stack->get_type(0) == cmd_symbol && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_div(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } - } else if (_stack->get_type(1) == cmd_symbol && _stack->get_type(0) == cmd_number) { + } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); _stack->pop_back(); string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_div(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else @@ -144,13 +145,13 @@ void program::rpn_stodiv(void) { void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_symbol) { + if (_stack->at(0)->_type == cmd_symbol) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_neg(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else @@ -162,18 +163,19 @@ void program::rpn_stoneg(void) { void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_symbol) { + if (_stack->at(0)->_type == cmd_symbol) { // get variable value on stack level 1, make op then modify variable string variable(((symbol*)_stack->back())->_value); rpn_rcl(); if (_err == ret_ok) { rpn_inv(); - _heap->add(variable, _stack->get_obj(0), _stack->get_len(0)); + (*_heap)[variable] = _stack->at(0); _stack->pop_back(); } } else ERR_CONTEXT(ret_bad_operand_type); } +#endif /// @brief rcl keyword implementation /// @@ -183,13 +185,12 @@ void program::rpn_rcl(void) { // recall a variable object* obj; - unsigned int size; string variable(((symbol*)_stack->back())->_value); // mind the order of heaps - if (find_variable(variable, obj, size)) { + if (find_variable(variable, obj)) { (void)_stack->pop_back(); - stack::copy_and_push_back(obj, *_stack, size); + _stack->push_back(obj); } else ERR_CONTEXT(ret_unknown_variable); } @@ -199,27 +200,12 @@ void program::rpn_rcl(void) { void program::rpn_edit(void) { MIN_ARGUMENTS(1); - FILE* tmp = tmpfile(); - if (tmp != NULL) { - // re-write stack objet in a stream - ((object*)_stack->pop_back())->show(tmp); + ostringstream st; + // re-write stack objet in a stream + ((object*)_stack->pop_back())->show(st); - // edit: stuff chars using linenoise facility - int len = (int)ftell(tmp); - rewind(tmp); - - // get stream data - void* file_data = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fileno(tmp), 0); - if (file_data != MAP_FAILED) { - // set it as the linenoise line entry - linenoisePreloadBuffer((const char*)file_data); - munmap(file_data, len); - } else - ERR_CONTEXT(ret_runtime_error); - - fclose(tmp); - } else - ERR_CONTEXT(ret_runtime_error); + // set it as the linenoise line entry + linenoisePreloadBuffer((const char*)st.str().c_str()); } /// @brief recall then eval a symbol variable if it is auto-evaluable @@ -229,17 +215,16 @@ void program::rpn_edit(void) { void program::auto_rcl(symbol* symb) { if (symb->_auto_eval) { object* obj; - unsigned int size; string variable(symb->_value); // mind the order of heaps - if (find_variable(variable, obj, size)) { - stack::copy_and_push_back(obj, *_stack, size); + if (find_variable(variable, obj)) { + _stack->push_back(obj); if (obj->_type == cmd_program) rpn_eval(); } else - stack::copy_and_push_back(symb, *_stack, symb->size()); + _stack->push_back(symb); } else - stack::copy_and_push_back(symb, *_stack, symb->size()); + _stack->push_back(symb); } /// @brief purge keyword implementation @@ -256,25 +241,24 @@ void program::rpn_purge(void) { /// void program::rpn_vars(void) { object* obj; - unsigned int size; program* parent = _parent_prog; string name; // heap variables - for (int i = 0; i < (int)_heap->count_vars(); i++) { - (void)_heap->get_by_index(i, name, obj, size); + for (int i = 0; i < (int)_heap->size(); i++) { + (void)_heap->get_by_index(i, name, obj); printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(), object::s_cmd_type_string[obj->_type]); - obj->show(); + obj->show(cout); printf("\n"); } // parents local variables while (parent != NULL) { for (int i = 0; i < (int)parent->_local_heap.size(); i++) { - (void)parent->_local_heap.get_by_index(i, name, obj, size); + (void)parent->_local_heap.get_by_index(i, name, obj); printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), object::s_cmd_type_string[obj->_type]); - obj->show(); + obj->show(cout); printf("\n"); } parent = parent->_parent_prog; @@ -282,13 +266,13 @@ void program::rpn_vars(void) { // local variables for (int i = 0; i < (int)_local_heap.size(); i++) { - (void)_local_heap.get_by_index(i, name, obj, size); + (void)_local_heap.get_by_index(i, name, obj); printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), object::s_cmd_type_string[obj->_type]); - obj->show(); + obj->show(cout); printf("\n"); } } /// @brief clusr keyword implementation /// -void program::rpn_clusr(void) { _heap->erase_all(); } +void program::rpn_clusr(void) { _heap->clear(); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 8b36654..312aeee 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -1,3 +1,5 @@ +#include + #include "program.hpp" /// @brief ->str keyword implementation @@ -6,7 +8,8 @@ void program::rpn_instr() { MIN_ARGUMENTS(1); // stringify only if not already a string - if (_stack->get_type(0) != cmd_string) { + if (_stack->at(0)->_type != cmd_string) { + // TODO really ugly, to change // write the object in stack(0) in a string and remove this obj FILE* tmp = tmpfile(); if (tmp != NULL) { @@ -14,14 +17,21 @@ void program::rpn_instr() { // reserve the correct size on stack unsigned int str_size = (unsigned int)ftell(tmp); - ostring* str = (ostring*)_stack->allocate_back(str_size + 1 + sizeof(ostring), cmd_string); - str->_len = str_size; + char* buf = (char*)malloc(str_size); + if (buf == nullptr) { + ERR_CONTEXT(ret_out_of_memory); + goto destroy_file; + } // fill the obj rewind(tmp); - if (fread(str->_value, str_size, 1, tmp) != 1) ERR_CONTEXT(ret_runtime_error); - str->_value[str_size] = 0; + if (fread(buf, str_size, 1, tmp) != 1) ERR_CONTEXT(ret_runtime_error); + _stack->push_back(new ostring(buf)); + + destroy_file: + char filePath[PATH_MAX]; fclose(tmp); + if (fcntl(fileno(tmp), 12 /*F_GETPATH*/, filePath) != -1) remove(filePath); } else ERR_CONTEXT(ret_runtime_error); } @@ -38,7 +48,7 @@ void program::rpn_strout() { program prog; // make program from string in stack level 1 - if (program::parse(entry.c_str(), prog) == ret_ok) + if (program::parse(entry, prog) == ret_ok) // run it prog.run(*_stack, *_heap); } @@ -52,13 +62,7 @@ void program::rpn_chr() { // get arg as number % 256 char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); if (the_chr < 32 || the_chr > 126) the_chr = '.'; - - // reserve the correct size on stack (1 char) - unsigned int str_size = 1; - ostring* str = (ostring*)_stack->allocate_back(str_size + 1 + sizeof(ostring), cmd_string); - str->_len = str_size; - str->_value[0] = the_chr; - str->_value[1] = 0; + _stack->push_back(new ostring(string(1, the_chr))); } /// @brief num keyword implementation @@ -68,8 +72,7 @@ void program::rpn_num() { ARG_MUST_BE_OF_TYPE(0, cmd_string); double the_chr = (double)((ostring*)_stack->pop_back())->_value[0]; - number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - numb->_value = the_chr; + _stack->push_back(new number(the_chr)); } /// @brief size keyword implementation @@ -78,9 +81,8 @@ void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - double len = ((ostring*)_stack->pop_back())->_len; - number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - numb->_value = len; + double len = ((ostring*)_stack->pop_back())->_value.size(); + _stack->push_back(new number(len)); } /// @brief pos keyword implementation @@ -90,28 +92,23 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(1, cmd_string); - long pos = 0; - char* src = ((ostring*)_stack->get_obj(1))->_value; - char* found = strstr(src, ((ostring*)_stack->get_obj(0))->_value); - if (found != NULL) pos = (long)(found - src) + 1L; - + size_t pos = static_cast(_stack->at(1))->_value.find(((ostring*)_stack->at(0))->_value); _stack->pop_back(2); - - number* numb = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - numb->_value = pos; + _stack->push_back(new number(pos)); } /// @brief sub keyword implementation /// void program::rpn_strsub() { +#if 0 MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_string); - long first = long(((number*)_stack->get_obj(1))->_value) - 1; - long last = long(((number*)_stack->get_obj(0))->_value) - 1; - long len = ((ostring*)_stack->get_obj(2))->_len; + long first = long(((number*)_stack->at(1))->_value) - 1; + long last = long(((number*)_stack->at(0))->_value) - 1; + long len = ((ostring*)_stack->at(2))->_len; bool result_is_void = false; _stack->pop_back(2); @@ -131,11 +128,11 @@ void program::rpn_strsub() { ostring* str = (ostring*)_calc_stack.allocate_back(str_size + 1 + sizeof(ostring), cmd_string); str->_len = str_size; - memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->get_obj(0))->_value + first, str_size); + memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->at(0))->_value + first, str_size); ((ostring*)_calc_stack.back())->_value[str_size] = 0; _stack->pop_back(); - stack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); _calc_stack.pop_back(); } else { _stack->pop_back(); @@ -143,4 +140,5 @@ void program::rpn_strsub() { str->_len = 0; str->_value[0] = 0; } +#endif } diff --git a/src/rpn-test-core.cpp b/src/rpn-test-core.cpp index fae6ea1..f8f9e08 100644 --- a/src/rpn-test-core.cpp +++ b/src/rpn-test-core.cpp @@ -5,26 +5,13 @@ /// @param stack_is the output string /// @param stk the stack /// -void program::test_get_stack(string& stack_is, stack& stk) { +void program::test_get_stack(string& stack_is, rpnstack& stk) { for (int i = 0; i < (int)stk.size(); i++) { - FILE* tmp_file = tmpfile(); - char* line = NULL; - size_t len; - if (i > 0) stack_is += ", "; - if (tmp_file != NULL) { - ((object*)stk.seq_obj(i))->show(tmp_file); - - // write stack in a tmp file - (void)rewind(tmp_file); - if (getline(&line, &len, tmp_file) >= 0) { - stack_is += line; - free(line); - } - (void)fclose(tmp_file); - } else - ERR_CONTEXT(ret_runtime_error); + ostringstream st; + stk[stk.size() - i - 1]->show(st); + stack_is += st.str(); } } @@ -91,7 +78,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail string test_title; string entry; ret_value ret; - stack stk; + rpnstack stk; heap hp; bool failed = false; bool is_first_step; @@ -209,7 +196,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail } else if (entry.size() > 0) { // parse entry and run line program prog; - ret = program::parse(entry.c_str(), prog); + ret = program::parse(entry, prog); if (ret == ret_ok) { // run it (void)prog.run(stk, hp); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 8294a65..799a818 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -5,12 +5,13 @@ /// @return 0 strings are equal /// @return !0 strings are not equal (see strcmp output) /// -int program::cmp_strings_on_stack_top() { +long program::cmp_strings_on_stack_top() { // _stack sould have 2 strings at level 1 and 2 // this function removes these 2 entries - ostring* right = (ostring*)_stack->pop_back(); - ostring* left = (ostring*)_stack->pop_back(); - return strncmp(left->_value, right->_value, min(left->_len, right->_len)); + long res = (long)static_cast(_stack->at(0))->_value.compare(static_cast(_stack->at(1))->_value); + (void)_stack->pop_back(); + (void)_stack->pop_back(); + return res; } /// @brief > keyword implementation @@ -19,21 +20,19 @@ void program::rpn_sup(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) > 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) > 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp > 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -43,21 +42,19 @@ void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) >= 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) >= 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp >= 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -67,21 +64,19 @@ void program::rpn_inf(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) < 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) < 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp < 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -91,21 +86,19 @@ void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) <= 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) <= 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp <= 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -115,36 +108,30 @@ void program::rpn_diff(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) != 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) != 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { bool diff = false; - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->pop_back(); + ocomplex* right = (ocomplex*)_stack->pop_back(); + ocomplex* left = (ocomplex*)_stack->pop_back(); - if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0) + if (mpfr_cmp(left->re()->mpfr_ptr(), right->re()->mpfr_ptr()) != 0 || mpfr_cmp(left->im()->mpfr_ptr(), right->im()->mpfr_ptr()) != 0) diff = true; - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - if (diff) - mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd); - else - mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd); + _stack->push_back(new number(diff?1L:0L)); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp != 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -154,36 +141,30 @@ void program::rpn_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->get_type(0) == cmd_number && _stack->get_type(1) == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr, right->_value.mpfr) == 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) == 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } // complexes - else if (_stack->get_type(0) == cmd_complex && _stack->get_type(1) == cmd_complex) { + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { bool diff = false; - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->pop_back(); + ocomplex* right = (ocomplex*)_stack->pop_back(); + ocomplex* left = (ocomplex*)_stack->pop_back(); - if (mpfr_cmp(left->re()->mpfr, right->re()->mpfr) != 0 || mpfr_cmp(left->im()->mpfr, right->im()->mpfr) != 0) + if (mpfr_cmp(left->re()->mpfr_ptr(), right->re()->mpfr_ptr()) != 0 || mpfr_cmp(left->im()->mpfr_ptr(), right->im()->mpfr_ptr()) != 0) diff = true; - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - if (diff) - mpfr_set_si(num->_value.mpfr, 0, floating_t::s_mpfr_rnd); - else - mpfr_set_si(num->_value.mpfr, 1, floating_t::s_mpfr_rnd); + _stack->push_back(new number(diff?0L:1L)); } // strings - else if (_stack->get_type(0) == cmd_string && _stack->get_type(1) == cmd_string) { - int res_cmp = cmp_strings_on_stack_top(); - number* res = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - res->_value = (res_cmp == 0) ? 1L : 0L; - } else + else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + _stack->push_back(new number(cmp_strings_on_stack_top())); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -197,10 +178,10 @@ void program::rpn_test_and(void) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) && (mpfr_cmp_si(right->_value.mpfr, 0) != 0)) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if ((mpfr_cmp_si(left->_value.mpfr_ptr(), 0) != 0) && (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0)) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } /// @brief or keyword implementation @@ -213,10 +194,10 @@ void program::rpn_test_or(void) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - if ((mpfr_cmp_si(left->_value.mpfr, 0) != 0) || (mpfr_cmp_si(right->_value.mpfr, 0) != 0)) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if ((mpfr_cmp_si(left->_value.mpfr_ptr(), 0) != 0) || (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0)) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } /// @brief xor keyword implementation @@ -229,16 +210,16 @@ void program::rpn_test_xor(void) { number* right = (number*)_stack->pop_back(); number* left = (number*)_stack->back(); - 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, floating_t::s_mpfr_rnd); + if (mpfr_cmp_si(left->_value.mpfr_ptr(), 0) == 0) { + if (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } else { - if (mpfr_cmp_si(right->_value.mpfr, 0) == 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) == 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } } @@ -249,10 +230,10 @@ void program::rpn_test_not(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); number* left = (number*)_stack->back(); - if (mpfr_cmp_si(left->_value.mpfr, 0) == 0) - mpfr_set_si(left->_value.mpfr, 1, floating_t::s_mpfr_rnd); + if (mpfr_cmp_si(left->_value.mpfr_ptr(), 0) == 0) + mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); else - mpfr_set_si(left->_value.mpfr, 0, floating_t::s_mpfr_rnd); + mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); } /// @brief test same implementation diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index fd03c5e..65dcc4a 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -1,4 +1,5 @@ #include + #include "program.hpp" /// @brief time keyword implementation @@ -18,8 +19,8 @@ void program::rpn_time() { ((double)tm->tm_sec) * 1000000.0 + (double)(ts.tv_nsec / 1000); // push it - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd)); + number* num; + _stack->push_back(num = static_cast(new number(date))); // division is done here because of real precision) CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 10000000000.0, floating_t::s_mpfr_rnd)); } else @@ -42,8 +43,8 @@ void program::rpn_date() { date = (double)(tm->tm_mon + 1) * 1000000.0 + (double)(tm->tm_mday) * 10000.0 + (double)(tm->tm_year + 1900); // push it - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd)); + number* num; + _stack->push_back(num = static_cast(new number(date))); // division is done here because of real precision) CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 1000000.0, floating_t::s_mpfr_rnd)); } else @@ -66,8 +67,7 @@ void program::rpn_ticks() { date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); // push it - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, date, floating_t::s_mpfr_rnd)); + _stack->push_back(static_cast(new number(date))); } else ERR_CONTEXT(ret_internal); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 32e32be..9bf7acb 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -3,7 +3,8 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - number* pi = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* pi; + _stack->push_back(pi = static_cast(new number)); CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd)); } @@ -17,7 +18,7 @@ void program::rpn_d2r(void) { rpn_pi(); floating_t* pi = &((number*)_stack->pop_back())->_value; - floating_t* left = &((number*)_stack->get_obj(0))->_value; + floating_t* left = &((number*)_stack->at(0))->_value; 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)); @@ -33,7 +34,7 @@ void program::rpn_r2d(void) { rpn_pi(); floating_t* pi = &((number*)_stack->pop_back())->_value; - floating_t* left = &((number*)_stack->get_obj(0))->_value; + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, floating_t::s_mpfr_rnd)); @@ -44,19 +45,21 @@ void program::rpn_r2d(void) { void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; - floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); + number* num = static_cast(new number); + _stack->push_back(num); + floating_t* tmp = &num->_value; + floating_t* x = ((complex*)_calc_stack.at(1))->re(); + floating_t* y = ((complex*)_calc_stack.at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -76,33 +79,33 @@ void program::rpn_sin(void) { void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { number* num; complex* i; // asin(z)=-iln(iz+sqrt(1-z*z)) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - i = (complex*)_calc_stack.get_obj(0); + i = (complex*)_calc_stack.at(0); CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_dup(); rpn_square(); - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(num = static_cast(new number)); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_minus(); rpn_neg(); rpn_squareroot(); rpn_swap(); - stack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); rpn_mul(); rpn_plus(); rpn_ln(); - stack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); rpn_mul(); rpn_neg(); _calc_stack.pop_back(); @@ -115,19 +118,21 @@ void program::rpn_asin(void) { void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; - floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); + number* num = static_cast(new number); + _stack->push_back(num); + floating_t* tmp = &num->_value; + floating_t* x = ((complex*)_calc_stack.at(1))->re(); + floating_t* y = ((complex*)_calc_stack.at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); @@ -148,14 +153,15 @@ void program::rpn_cos(void) { void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // acos(z)=pi/2-asin(z) rpn_asin(); rpn_pi(); - number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + number* num; + _stack->push_back(num = static_cast(new number)); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_div(); rpn_minus(); @@ -169,19 +175,21 @@ void program::rpn_acos(void) { void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { // tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - floating_t* tmp = &((number*)_calc_stack.allocate_back(number::calc_size(), cmd_number))->_value; - floating_t* x = ((complex*)_calc_stack.get_obj(1))->re(); - floating_t* y = ((complex*)_calc_stack.get_obj(1))->im(); + number* num = static_cast(new number); + _stack->push_back(num); + floating_t* tmp = &num->_value; + floating_t* x = ((complex*)_calc_stack.at(1))->re(); + floating_t* y = ((complex*)_calc_stack.at(1))->im(); - floating_t* re = ((complex*)_stack->get_obj(0))->re(); - floating_t* im = ((complex*)_stack->get_obj(0))->im(); + floating_t* re = ((complex*)_stack->at(0))->re(); + floating_t* im = ((complex*)_stack->at(0))->im(); // x->2x CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd)); @@ -211,36 +219,36 @@ void program::rpn_tan(void) { void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack->get_type(0) == cmd_number) { - floating_t* left = &((number*)_stack->get_obj(0))->_value; + if (_stack->at(0)->_type == cmd_number) { + floating_t* left = &((number*)_stack->at(0))->_value; CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); - } else if (_stack->get_type(0) == cmd_complex) { + } else if (_stack->at(0)->_type == cmd_complex) { number* num; complex* i; // atan(z)=0.5i(ln((1-iz)/(1+iz)) - stack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - i = (complex*)_calc_stack.get_obj(0); + i = (complex*)_calc_stack.at(0); CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd)); CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd)); - stack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); rpn_mul(); - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(num = static_cast(new number)); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); rpn_minus(); // iz-1 rpn_neg(); // 1-iz rpn_dup(); rpn_neg(); // iz-1 - num = (number*)_stack->allocate_back(number::calc_size(), cmd_number); + _stack->push_back(num = static_cast(new number)); CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); rpn_plus(); // iz+1 rpn_div(); rpn_ln(); CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd)); - stack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); rpn_mul(); _calc_stack.pop_back(); diff --git a/src/stack.hpp b/src/stack.hpp index 4a81228..8d0d065 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -2,35 +2,20 @@ #define __stack_h__ #include -#include -using namespace std; -// allocation base size -#define ALLOC_STACK_CHUNK (64 * 1024) +#include +#include +#include + +#include "object.hpp" +using namespace std; /// @brief stack object, parens of program, storing execution stack values or programs /// -class stack { +class rpnstack : public deque { public: - stack() { - _base = NULL; - _base_pointer = NULL; - _total_size = 0; - _total_count_pointer = 0; - erase(); - } - - virtual ~stack() { - if (_base != NULL) free(_base); - if (_base_pointer != NULL) free(_base_pointer); - } - - /// @brief remove all the stack elements - /// - void erase() { - _current = _base; - _count = 0; - } + rpnstack() {} + virtual ~rpnstack() {} /// @brief copy a whole stack entry and push it back to another stack /// @@ -38,349 +23,76 @@ class stack { /// @param index_from index t ocopy from /// @param to copy to /// - static void copy_and_push_back(stack& from, unsigned int index_from, stack& to) { - object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from)); - memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from)); - - if (allocated->_type == cmd_number) - ((number*)allocated)->move(); - else if (allocated->_type == cmd_complex) - ((complex*)allocated)->move(); + static void copy_and_push_back(rpnstack& from, unsigned int index_from, rpnstack& to) { + to.push_back(from[index_from]); } - /// @brief copy a whole stack entry and push it back to another stack - /// - /// @param from copy from - /// @param index_from index t ocopy from - /// @param to copy to - /// - static void copy_and_push_back(object* from, stack& to, unsigned int size) { - object* allocated = to.allocate_back(size, from->_type); - memcpy(allocated, from, size); - - if (allocated->_type == cmd_number) - ((number*)allocated)->move(); - else if (allocated->_type == cmd_complex) - ((complex*)allocated)->move(); + static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { + to.push_front(from[index_from]); } - /// @brief allocate one object back on an already populated (or not) stack - /// the object function move is called on every reallocated object on the stack - /// the object function init is called on the new allocated object if its type is cmd_number or cmd_complex + /// @brief pop back several entries /// - /// @param size the object size in bytes - /// @param type the object type - /// @return object* the allocated object + /// @param levels nb of entries /// - object* allocate_back(unsigned int size, cmd_type_t type) { - object* allocated; - bool data_is_reallocated = false; - char* old_base; - - // manage data memory allocation (add as much as memory it is needed) - if (((_current - _base) + size) > _total_size) { - // calc nb of needed pages - unsigned long page_number = 1 + ((_current - _base) + size - _total_size) / ALLOC_STACK_CHUNK; - _total_size += page_number * ALLOC_STACK_CHUNK; - - old_base = _base; - _base = (char*)realloc(_base, _total_size); - - _current = _base + (_current - old_base); - data_is_reallocated = true; - } - - // manage pointers memory allocation (add one page if needed) - if ((_count + 1) > _total_count_pointer) { - _base_pointer = - (object**)realloc(_base_pointer, (_total_count_pointer * sizeof(object*)) + ALLOC_STACK_CHUNK); - _total_count_pointer += (ALLOC_STACK_CHUNK / sizeof(object)); - } - - // recalc object pointers in case of base reallocation - if (data_is_reallocated) { - for (int i = 0; i < _count; i++) { - _base_pointer[i] = (object*)(_base + ((char*)_base_pointer[i] - old_base)); - if (_base_pointer[i]->_type == cmd_number) - ((number*)_base_pointer[i])->move(); - else if (_base_pointer[i]->_type == cmd_complex) - ((complex*)_base_pointer[i])->move(); - } - } - - // manage stack itself - _base_pointer[_count++] = (object*)_current; - allocated = (object*)_current; - _current += size; - - // init object - allocated->_type = type; - allocated->_size = size; - if (type == cmd_number) - ((number*)allocated)->init(); - else if (type == cmd_complex) - ((complex*)allocated)->init(); - - return allocated; + void pop_back(int levels) { + for (int i = 0; i < levels; i++) deque::pop_back(); } - object* pop_back(int pop_count = 1) { - object* back = NULL; - - // pop several entries, return the last - while (pop_count-- > 0) { - if (_count > 0) { - _current = (char*)_base_pointer[--_count]; - back = (object*)_current; - } - } - - return back; + /// @brief pop back 1 entry + /// + /// @return retrieved object + /// + object* pop_back() { + object* o = back(); + pop_back(1); + return o; } - - /// @brief the number of objects on stack - /// - /// @return unsigned int - /// - unsigned int size() { return _count; } - - /// @brief stack access (stack_level=0=first out) - /// - /// @param stack_level the object stack level - /// @return object* pointer on object at this stack level - /// - object* get_obj(unsigned int stack_level) { return seq_obj(_count - stack_level - 1); } - - /// @brief same as get_obj - /// - /// @param stack_level the object stack level - /// @return object* pointer on object at this stack level - /// - object* operator[](unsigned int stack_level) { return seq_obj(_count - stack_level - 1); } - - /// @brief returns the last object on stack - /// - /// @return object* the object - /// - object* back() { - object* obj = NULL; - if (_count > 0) obj = _base_pointer[_count - 1]; - return obj; - } - - /// @brief get an object len - /// - /// @param index the object stack level - /// @return unsigned int the length in bytes - /// - unsigned int get_len(unsigned int index) { return seq_len(_count - index - 1); } - - /// @brief get an object type - /// - /// @param index the object stack level - /// @return cmd_type_t the object type - /// - cmd_type_t get_type(unsigned int index) { return seq_type(_count - index - 1); } - - /// @brief sequential object access (index is counted from front) - /// - /// @param index object index from front - /// @return object* the object pointer - /// - object* seq_obj(unsigned int index) { - object* obj = NULL; - if (index < _count) obj = _base_pointer[index]; - return obj; - } - - /// @brief get an object len - /// - /// @param index the object stack level from front - /// @return unsigned int the length in bytes - /// - unsigned int seq_len(unsigned int index) { - unsigned int len = 0; - if (index < _count) len = _base_pointer[index]->_size; - return len; - } - - /// @brief get an object len - /// - /// @param index the object stack level from front - /// @return cmd_type_t the object type - /// - cmd_type_t seq_type(unsigned int index) { - cmd_type_t type = cmd_undef; - if (index < _count) type = _base_pointer[index]->_type; - return type; - } - - private: - char* _base; - char* _current; - object** _base_pointer; - - unsigned int _count; //< stack count - unsigned int _total_count_pointer; //< total number of possible pointers - unsigned int _total_size; //< total allocated data size in bytes }; /// @brief heap object, storing variables (=named object) /// -class heap : public stack { +class heap : public map { public: heap() {} virtual ~heap() {} - /// @brief add a variable on the heap - /// - /// @param name the variable name - /// @param obj the variable content - /// @param size the variable size in bytes - /// @return object* - /// - object* add(const string name, object* obj, unsigned int size) { - map::iterator i = _map.find(name); - object* local = NULL; - - // variable does not exist in heap or already exists but its size is too - // short -> allocate - if (i != _map.end()) local = seq_obj(i->second); - - if (local == NULL || (local != NULL && size > local->_size)) { - copy_and_push_back(obj, *this, size); - _map[name] = ((stack*)this)->size() - 1; - } else { - // variable already exists in heap but previous was larger -> don't - // reallocate copy a whole stack entry and push it back to another stack - memcpy(local, obj, size); - if (local->_type == cmd_number) - ((number*)local)->move(); - else if (local->_type == cmd_complex) - ((complex*)local)->move(); - } - - return local; - } - /// @brief get a variable - /// + /// /// @param name the variable name /// @param obj the variable content - /// @param size the variable size in bytes /// @return true the variable was found /// @return false the variable was not found /// - bool get(const string name, object*& obj, unsigned int& size) { + bool get(const string name, object*& obj) { bool ret = false; - map::iterator i = _map.find(name); - - if (i != _map.end()) { - obj = seq_obj(i->second); - size = obj->_size; + auto i = find(name); + if (i != end()) { + obj = i->second; ret = true; } return ret; } - /// @brief replace a variable value by another - /// - /// @param name the variable name - /// @param obj the new value - /// @param size the variable size in bytes - /// @return true the variable was found - /// @return false the variable was not found - /// - bool replace_value(const string name, object* obj, unsigned int size) { - bool ret = false; - map::iterator i = _map.find(name); - - if (i != _map.end()) { - object* obj_dst = seq_obj(i->second); - if (size <= obj_dst->_size) { - (void)memcpy(obj_dst, obj, size); - if (obj_dst->_type == cmd_number) - ((number*)obj_dst)->move(); - else if (obj_dst->_type == cmd_complex) - ((complex*)obj_dst)->move(); - ret = true; - } - } - - return ret; - } - - /// @brief whether a variable exists in heap or not - /// - /// @param name the variable name - /// @return true the variable exists - /// @return false variable does not exist - /// - bool exist(const string name) { return (_map.find(name) != _map.end()); } - /// @brief get a variable by its index in heap - /// + /// /// @param num the variable index /// @param name the variable name /// @param obj the variable content - /// @param size the variable size in bytes /// @return true the variable was found /// @return false the variable was not found /// - bool get_by_index(int num, string& name, object*& obj, unsigned int& size) { - if (num >= 0 && num < (int)_map.size()) { + bool get_by_index(int num, string& name, object*& obj) { + if (num >= 0 && num < (int)size()) { object* local; - map::iterator i = _map.begin(); - - for (int j = 0; j < num; j++) i++; - - local = (object*)seq_obj(i->second); - name = i->first; - obj = local; - size = local->_size; + auto i = begin(); + for (; num > 0; num--, i++) + ; + obj = i->second; return true; } else return false; } - - /// @brief erase a variable - /// - /// @param name the variable name - /// @return true the variable was found - /// @return false the variable was not found - /// - bool erase(const string& name) { - map::iterator i = _map.find(name); - bool ret = false; - - if (i != _map.end()) { - // remove variable from map - _map.erase(i->first); - ret = true; - - // TODO: remove unused stack entries - } - return ret; - } - - /// @brief erase all variables - /// - void erase_all(void) { - // map - _map.erase(_map.begin(), _map.end()); - - // and stack - ((stack*)this)->erase(); - } - - /// @brief get the variables nb - /// - /// @return unsigned int the variables nb - /// - unsigned int count_vars() { return _map.size(); } - - private: - map _map; }; #endif // __stack_h__ From 9825a1640917563ce474a9fd73b7538b46dfdf77 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 11 Feb 2022 14:00:15 +0100 Subject: [PATCH 04/57] refactoring II --- CMakeLists.txt | 4 +- src/constant.h | 23 +- src/object.cpp | 11 +- src/object.hpp | 125 +++--- src/parse.cpp | 125 +++--- src/program.cpp | 99 ++-- src/program.hpp | 2 +- src/rpn-branch.cpp | 106 ++--- src/rpn-complex.cpp | 82 ++-- src/rpn-general.cpp | 112 ++--- src/rpn-logs.cpp | 160 +++---- src/rpn-program.cpp | 18 +- src/rpn-real.cpp | 425 ++++++------------ src/rpn-stack.cpp | 94 ++-- src/rpn-store.cpp | 88 ++-- src/rpn-string.cpp | 32 +- src/rpn-test-core.cpp | 21 +- src/rpn-test.cpp | 126 +++--- src/rpn-time.cpp | 10 +- src/rpn-trig.cpp | 132 +++--- src/stack.hpp | 28 +- src/version.h | 33 +- test/02-general.txt | 49 -- test/05-test.txt | 30 ++ test/{01-mode.txt => 10-mode.txt} | 0 test/{10-complex.txt => 100-complex.txt} | 0 test/{12-time.txt => 120-time.txt} | 0 test/20-general.txt | 24 + test/21-parse-string.txt | 62 +++ test/22-parse-symbol.txt | 67 +++ test/23-parse-number.txt | 47 ++ test/24-parse-complex.txt | 40 ++ test/25-parse-other.txt | 19 + test/26-parse-program.txt | 53 +++ test/{11-base-entry.txt => 27-base-entry.txt} | 0 test/{03-branch.txt => 30-branch.txt} | 0 test/{04-stack.txt => 40-stack.txt} | 89 ++-- test/{05-real.txt => 50-real.txt} | 0 test/{06-string.txt => 60-string.txt} | 0 test/{07-test.txt => 70-test.txt} | 0 test/{08-store.txt => 80-store.txt} | 0 test/{09-program.txt => 90-program.txt} | 0 ...-manual-tests.txt => 999-manual-tests.txt} | 0 test/all.txt | 33 +- 44 files changed, 1244 insertions(+), 1125 deletions(-) delete mode 100644 test/02-general.txt create mode 100644 test/05-test.txt rename test/{01-mode.txt => 10-mode.txt} (100%) rename test/{10-complex.txt => 100-complex.txt} (100%) rename test/{12-time.txt => 120-time.txt} (100%) create mode 100644 test/20-general.txt create mode 100644 test/21-parse-string.txt create mode 100644 test/22-parse-symbol.txt create mode 100644 test/23-parse-number.txt create mode 100644 test/24-parse-complex.txt create mode 100644 test/25-parse-other.txt create mode 100644 test/26-parse-program.txt rename test/{11-base-entry.txt => 27-base-entry.txt} (100%) rename test/{03-branch.txt => 30-branch.txt} (100%) rename test/{04-stack.txt => 40-stack.txt} (69%) rename test/{05-real.txt => 50-real.txt} (100%) rename test/{06-string.txt => 60-string.txt} (100%) rename test/{07-test.txt => 70-test.txt} (100%) rename test/{08-store.txt => 80-store.txt} (100%) rename test/{09-program.txt => 90-program.txt} (100%) rename test/{99-manual-tests.txt => 999-manual-tests.txt} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1756e4..6ae1df4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,12 +55,12 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/object.cpp ${PROJECT_SOURCE_DIR}/src/program.cpp ${PROJECT_SOURCE_DIR}/src/parse.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp #${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp #${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp ${PROJECT_SOURCE_DIR}/src/rpn-program.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-real.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-real.cpp ${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp ${PROJECT_SOURCE_DIR}/src/rpn-store.cpp #${PROJECT_SOURCE_DIR}/src/rpn-string.cpp diff --git a/src/constant.h b/src/constant.h index a085896..6388a9d 100644 --- a/src/constant.h +++ b/src/constant.h @@ -21,14 +21,15 @@ // rounding method #define MPFR_DEFAULT_RND MPFR_RNDN +#define MPFR_ROUND_STRINGS \ + {"nearest (even)", MPFR_RNDN}, {"toward zero", MPFR_RNDZ}, {"toward +inf", MPFR_RNDU}, {"toward -inf", MPFR_RNDD}, \ + {"away from zero", MPFR_RNDA}, {"faithful rounding", MPFR_RNDF}, { \ + "nearest (away from zero)", MPFR_RNDNA \ + } // 128 bits significand precision #define MPFR_DEFAULT_PREC_BITS 128 -// 128 bits significand storing length in bytes, result of -// mpfr_custom_get_size(128) -#define MPFR_DEFAULT_STORING_LENGTH_BYTES 16 - // constants // @@ -46,9 +47,6 @@ #define MPFR_FORMAT_SCI "Re" #define MPFR_FORMAT_HEX "%Ra" -#define MPFR_RND_STRINGS \ - { "nearest", "toward zero", "toward +inf", "toward -inf", "away from zero" } - // return values, used by all classes // typedef enum { @@ -57,6 +55,7 @@ typedef enum { ret_missing_operand, ret_bad_operand_type, ret_out_of_range, + ret_bad_value, ret_unknown_variable, ret_internal, ret_deadly, @@ -71,11 +70,11 @@ typedef enum { 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", "aborted current entry", "out of memory" \ +#define RET_VALUE_STRINGS \ + { \ + "ok", "unknown command", "missing operand", "bad operand type", "out of range", "bad value", \ + "unknown variable", "internal error, aborting", "deadly", "goodbye", "not implemented", "no operation", \ + "syntax error", "division by zero", "runtime error", "aborted current entry", "out of memory" \ } // command types diff --git a/src/object.cpp b/src/object.cpp index 57f4bd5..fd9192a 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -8,17 +8,10 @@ using namespace std; #include "object.hpp" // TODO remove -// some statics -// mpfr_prec_t floating_t::s_mpfr_prec = MPFR_DEFAULT_PREC_BITS; -// mpfr_rnd_t floating_t::s_mpfr_rnd = MPFR_DEFAULT_RND; // number statics number::mode_enum number::s_mode = DEFAULT_MODE; int number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; -mpfr_prec_t number::s_mpfr_prec = MPFR_DEFAULT_PREC_BITS; -mpfr_rnd_t number::s_mpfr_rnd = MPFR_DEFAULT_RND; -string number::s_mpfr_printf_format = string(MPFR_DEFAULT_FORMAT); -const char* number::s_mpfr_rnd_str[5] = MPFR_RND_STRINGS; // const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS; @@ -36,7 +29,7 @@ static bool is_min(mpfr_t p, mpfr_prec_t prec) { // see mpfr_vasprintf code bool ret; int round_away; - switch (floating_t::s_mpfr_rnd) { + switch (mpreal::get_default_rnd()) { case MPFR_RNDA: round_away = 1; break; @@ -120,7 +113,7 @@ static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_aft fputc('0', stream); } } else { - char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, floating_t::s_mpfr_rnd); + char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, mpreal::get_default_rnd()); char* print_from; if (str != NULL) { int len = strlen(str); diff --git a/src/object.hpp b/src/object.hpp index 9444ccf..a2349da 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -4,8 +4,9 @@ #include using namespace mpfr; -#include +#include #include +#include using namespace std; // definitions for objects @@ -35,10 +36,7 @@ struct object { // object type cmd_type_t _type; // - auto duplicate() { - cout << "typeid(this).name()=" << typeid(this).name() << endl; - return *new decltype(this); - } + auto duplicate() { return *new decltype(this); } virtual string name() { return string("object"); } virtual void show(ostream& out) { out << "(" << name() << " - unknown representation)"; } unsigned int size() { return sizeof(*this); } @@ -51,20 +49,18 @@ struct object { /// struct number : object { typedef enum { dec, hex, bin, base } repr_enum; - number(repr_enum representation = dec) : object(cmd_number), _representation(representation) { _value = 0L; } - number(mpreal& value, repr_enum representation = dec) : number(representation) { _value = value; } - number(long value, repr_enum representation = dec) : number(representation) { _value = value; } - number(unsigned long value, repr_enum representation = dec) : number(representation) { _value = value; } - number(double value, repr_enum representation = dec) : number(representation) { _value = value; } + number(repr_enum representation = dec) : object(cmd_number), _representation(representation) { value = 0L; } + number(mpreal& value_, repr_enum representation = dec) : number(representation) { value = value_; } + number(long value_, repr_enum representation = dec) : number(representation) { value = value_; } + number(unsigned long value_, repr_enum representation = dec) : number(representation) { value = value_; } + number(double value_, repr_enum representation = dec) : number(representation) { value = value_; } repr_enum _representation; int _base; // carefull: _base is used only if _representation = base - mpreal _value; + mpreal value; - void init() {} - - void set(unsigned long value) { _value = value; } + void set(unsigned long value_) { value = value_; } virtual string name() { return string("number"); } virtual void show(ostream& out) { @@ -75,13 +71,13 @@ struct number : object { switch (number::s_mode) { case number::std: out.unsetf(ios::floatfield); - out << setprecision(s_decimal_digits) << _value; + out << setprecision(s_decimal_digits) << value; break; case number::fix: - out << fixed << setprecision(s_decimal_digits) << _value; + out << fixed << setprecision(s_decimal_digits) << value; break; case number::sci: - out << scientific << setprecision(s_decimal_digits) << _value; + out << scientific << setprecision(s_decimal_digits) << value; break; default: object::show(out); @@ -95,27 +91,18 @@ struct number : object { // precision static int s_decimal_digits; - static mpfr_prec_t s_mpfr_prec; - static mpfr_rnd_t s_mpfr_rnd; - static string s_mpfr_printf_format; - static const char* s_mpfr_rnd_str[5]; }; /// @brief stack objects derived from object /// struct ocomplex : object { number::repr_enum _representation; - ocomplex() : object(cmd_complex) { init(); } - - mpreal _re; - mpreal _im; - - // re and im float values are at the end of the object - mpreal* re() { return &_re; } - mpreal* im() { return &_im; } - - void init() {} - + ocomplex() : object(cmd_complex) {} + ocomplex(mpreal& re_, mpreal& im_) : object(cmd_complex) { + value.real(re_); + value.imag(im_); + } + complex value; virtual string name() { return string("complex"); } virtual void show(ostream& out) { if (_representation != number::dec) { @@ -125,12 +112,15 @@ struct ocomplex : object { switch (number::s_mode) { case number::std: out.unsetf(ios::floatfield); - out << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + out << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; + break; case number::fix: - out << fixed << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + out << fixed << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() + << ")"; break; case number::sci: - out << scientific << setprecision(number::s_decimal_digits) << "(" << _re << ", " << _im << ")"; + out << scientific << setprecision(number::s_decimal_digits) << "(" << value.real() << "," + << value.imag() << ")"; break; default: object::show(out); @@ -143,81 +133,80 @@ struct ocomplex : object { /// struct ostring : object { ostring() : object(cmd_string) {} - ostring(const string& value) : object(cmd_string) { set(value); } - ostring(const char* value) : object(cmd_string) { _value = string(value); } - void set(const string& value) { _value = value; } + ostring(const string& value_) : object(cmd_string) { set(value_); } + ostring(const char* value_) : object(cmd_string) { value = string(value_); } + void set(const string& value_) { value = value_; } virtual string name() { return string("complex"); } - virtual void show(ostream& out) { out << "\"" << _value << "\""; } - - string _value; + virtual void show(ostream& out) { out << "\"" << value << "\""; } + string value; }; /// @brief object program /// struct oprogram : object { oprogram() : object(cmd_program) {} - oprogram(const string& value) : object(cmd_program) { set(value); } - void set(const string& value) { _value = value; } + oprogram(const string& value_) : object(cmd_program) { set(value_); } + void set(const string& value_) { value = value_; } virtual string name() { return string("program"); } - virtual void show(ostream& out) { out << "<< " << _value << " >>"; } - string _value; + virtual void show(ostream& out) { out << "«" << value << "»"; } + string value; }; /// @brief object symbol /// struct symbol : object { - symbol(bool auto_eval = true) : object(cmd_symbol), _auto_eval(auto_eval) {} - symbol(const string& value, bool auto_eval = true) : object(cmd_symbol) { set(value, auto_eval); } - void set(string& value, bool auto_eval) { - _value = value; - _auto_eval = auto_eval; + symbol(bool auto_eval_ = true) : object(cmd_symbol), auto_eval(auto_eval_) {} + symbol(const string& value_, bool auto_eval_ = true) : object(cmd_symbol) { set(value_, auto_eval_); } + void set(string& value_, bool auto_eval_) { + value = value_; + auto_eval = auto_eval_; } - void set(const string& value, bool auto_eval) { - _value = value; - _auto_eval = auto_eval; + void set(const string& value_, bool auto_eval_) { + value = value_; + auto_eval = auto_eval_; } virtual string name() { return string("symbol"); } - virtual void show(ostream& out) { out << "'" << _value << "'"; } - bool _auto_eval; - string _value; + virtual void show(ostream& out) { out << "'" << value << "'"; } + bool auto_eval; + string value; }; /// @brief object keyword /// struct keyword : object { keyword() : object(cmd_keyword) {} - keyword(program_fn_t fn, const string& value) : object(cmd_keyword) { set(fn, value); } - void set(program_fn_t fn, const string& value) { - _fn = fn; - _value = value; + keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword) { set(fn_, value_); } + void set(program_fn_t fn_, const string& value_) { + fn = fn_; + value = value_; } virtual string name() { return string("keyword"); } - program_fn_t _fn; - string _value; + program_fn_t fn; + string value; }; /// @brief object branch /// struct branch : object { branch() : object(cmd_branch) {} - branch(branch_fn_t fn, const string& value) : object(cmd_branch) { set(fn, value); } + branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { set(fn_, value_); } virtual string name() { return string("branch"); } // - void set(branch_fn_t fn, const string& value) { - _fn = fn; + void set(branch_fn_t fn_, const string& value_) { + fn = fn_; arg1 = -1; arg2 = -1; arg3 = -1; farg1 = NULL; farg2 = NULL; arg_bool = 0; - _value = value; + value = value_; } - branch_fn_t _fn; + branch_fn_t fn; int arg1, arg2, arg3; number *farg1, *farg2; bool arg_bool; - string _value; + string value; }; #endif diff --git a/src/parse.cpp b/src/parse.cpp index 68371a5..974fa0b 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -109,9 +109,14 @@ struct ReservedWord { static map _keywordsMap; +static void trim(string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); +} + static bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - // here we are sure that entry[0] is '"' + // here we are sure that entry[0] is at least '"' for (size_t i = idx + 1; i < entry.size(); i++) { if (entry[i] == '"') { if (entry[i] - 1 != '\\') { @@ -121,13 +126,14 @@ static bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - // here we are sure that entry[0] is '\'' + // here we are sure that entry[0] is at least '\'' for (size_t i = idx + 1; i < entry.size(); i++) { if (entry[i] == '\'') { elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, i - idx - 1)}); @@ -135,27 +141,35 @@ static bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - // here we are sure that entry is at least "<<"" + // here we are sure that entry is at least "<<" + // find last ">>" or "»" + int countNested = 0; for (size_t i = idx + 2; i < entry.size() - 1; i++) { - if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { - elements.push_back({cmd_program, .value = entry.substr(idx + 2, i - idx - 2)}); - nextIdx = i + 2; - return true; + if ((entry[i] == '<' && entry[i + 1] == '<') || (entry.substr(i, 2) == "«")) + countNested++; + else if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { + if (countNested == 0) { + string prg = entry.substr(idx + 2, i - idx - 2); + trim(prg); + elements.push_back({cmd_program, .value = prg}); + nextIdx = i + 2; + return true; + } else + countNested--; } } - errors.push_back({entry.size(), "unterminated program"}); - return false; -} - -static void trim(string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); - s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); + string prg = entry.substr(idx + 2, entry.size() - idx - 2); + trim(prg); + elements.push_back({cmd_program, .value = prg}); + nextIdx = entry.size(); + return true; } static bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, mpreal& r, char delim = ' ') { @@ -205,27 +219,28 @@ static bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& elements) { mpreal re, im; if (idx + 1 == entry.size()) { - errors.push_back({entry.size(), "unterminated complex"}); - return false; + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol } if (!getNumberAt(entry, idx + 1, nextIdx, re, ',')) { - errors.push_back({entry.size(), "unterminated complex"}); - return false; + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol } size_t i = nextIdx; while (i < entry.size() && entry[i] != ',') i++; if (i == entry.size()) { - errors.push_back({entry.size(), "unterminated complex"}); - return false; + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol } + if (!getNumberAt(entry, i + 1, nextIdx, im, ')')) { - errors.push_back({entry.size(), "unterminated complex"}); - return false; - } - if (nextIdx == entry.size() || entry[nextIdx] != ')') { - errors.push_back({entry.size(), "unterminated complex"}); - return false; + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol } elements.push_back({cmd_complex, .re = re, .im = im}); nextIdx++; @@ -283,24 +298,20 @@ static bool lexer(string& entry, vector& elements, vector& if (!parseComplex(entry, i, jump, errors, elements)) return false; i = jump - 1; continue; - // clang-format off - case '.': case '+': case '-': - // clang-format on - // inf, +inf, -inf and nan are treated as reserved keywords - if (i < entry.size() - 1 && entry[i + 1] < '0' && entry[i + 1] > '9') break; - case '0' ... '9': - if (!parseNumber(entry, i, jump, errors, elements)) return false; - i = jump - 1; - continue; } if (i < entry.size() - 1 && (entry.substr(i, 2) == "<<" || entry.substr(i, 2) == "«")) { if (!parseProgram(entry, i, jump, errors, elements)) return false; i = jump - 1; continue; - } else if (parseReserved(entry, i, jump, elements, keywords)) + } else if (parseReserved(entry, i, jump, elements, keywords)) { // found a keywords word, add it with its correct type i = jump - 1; - else if (parseUnknown(entry, i, jump, elements)) + continue; + } else if (parseNumber(entry, i, jump, errors, elements)) { + i = jump - 1; + continue; + } + if (parseUnknown(entry, i, jump, elements)) // last chance, this unknown entry is treated as a symbol i = jump - 1; } @@ -309,37 +320,41 @@ static bool lexer(string& entry, vector& elements, vector& } static bool progFromElements(vector& elements, program& prog) { - for_each(elements.begin(), elements.end(), [&](SynElement& element) { + // TODO control elements creation + for (SynElement& element : elements) { switch (element.type) { case cmd_number: - prog.insert(prog.begin(), 1, new number(element.re)); + prog.push_back(new number(element.re)); + break; + case cmd_complex: + prog.push_back(new ocomplex(element.re, element.im)); break; - // case cmd_complex: prog.insert(prog.begin(), 1, new ocomplex(element.re, element.im)); break; case cmd_string: - prog.insert(prog.begin(), 1, new ostring(element.value)); + prog.push_back(new ostring(element.value)); break; case cmd_symbol: - prog.insert(prog.begin(), 1, new symbol(element.value)); + prog.push_back(new symbol(element.value)); + break; + case cmd_program: + prog.push_back(new oprogram(element.value)); break; - // case cmd_program: prog.insert(prog.begin(), 1, new program(element.value)); break; case cmd_keyword: - prog.insert(prog.begin(), 1, new keyword(element.fn, element.value)); + prog.push_back(new keyword(element.fn, element.value)); break; case cmd_branch: - prog.insert(prog.begin(), 1, new branch((branch_fn_t)element.fn, element.value)); + prog.push_back(new branch((branch_fn_t)element.fn, element.value)); break; default: return false; } - return true; - }); + } return true; } /// @brief parse an entry string: cut it into objects chunks and add them to a program /// /// @param entry the entry string -/// @param prog the program +/// @param prog the program to be filled /// @return ret_value see this type /// ret_value program::parse(string& entry, program& prog) { @@ -356,10 +371,8 @@ ret_value program::parse(string& entry, program& prog) { if (lexer(entry, elements, errors, _keywordsMap)) { // make objects from parsed elements if (!progFromElements(elements, prog)) prog.show_error(ret_unknown_err, "error creating program from entry"); - } else { - for(SynError& err: errors) - prog.show_syntax_error(err.err.c_str()); - } + } else + for (SynError& err : errors) prog.show_syntax_error(err.err.c_str()); return ret; } diff --git a/src/program.cpp b/src/program.cpp index 94ce863..de2f8cd 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -3,7 +3,7 @@ //< return type strings const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; -//< kanguage reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef) +//< language reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef) program::keyword_t program::s_keywords[] = { // GENERAL {cmd_undef, "", NULL, "\nGENERAL"}, @@ -20,16 +20,16 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "history", &program::rpn_history, "see commands history"}, // USUAL OPERATIONS ON REALS AND COMPLEXES - // {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, - // {cmd_keyword, "+", &program::rpn_plus, "addition"}, - // {cmd_keyword, "-", &program::rpn_minus, "substraction"}, - // {cmd_keyword, "chs", &program::rpn_neg, "negation"}, - // {cmd_keyword, "neg", &program::rpn_neg, ""}, - // {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, - // {cmd_keyword, "/", &program::rpn_div, "division"}, - // {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, - // {cmd_keyword, "^", &program::rpn_power, "power"}, - // {cmd_keyword, "pow", &program::rpn_power, ""}, + {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, + {cmd_keyword, "+", &program::rpn_plus, "addition"}, + {cmd_keyword, "-", &program::rpn_minus, "substraction"}, + {cmd_keyword, "chs", &program::rpn_neg, "negation"}, + {cmd_keyword, "neg", &program::rpn_neg, ""}, + {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, + {cmd_keyword, "/", &program::rpn_div, "division"}, + {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, + {cmd_keyword, "^", &program::rpn_power, "power"}, + {cmd_keyword, "pow", &program::rpn_power, ""}, // {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, // {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, // {cmd_keyword, "sqr", &program::rpn_square, ""}, @@ -39,15 +39,11 @@ program::keyword_t program::s_keywords[] = { // {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, // {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"}, // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, - // {cmd_keyword, "inf", &program::rpn_inf, "positive infinite"}, - // {cmd_keyword, "+inf", &program::rpn_inf, "positive infinite"}, - // {cmd_keyword, "-inf", &program::rpn_minf, "negative infinite"}, - // {cmd_keyword, "nan", &program::rpn_nan, "not a number"}, // OPERATIONS ON REALS - // {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, - // {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, - // {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, + {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, + {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, + {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, // {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, // {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, // {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, @@ -127,30 +123,29 @@ program::keyword_t program::s_keywords[] = { // {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, // BRANCH - // {cmd_undef, "", NULL, "\nBRANCH"}, - // {cmd_branch, "if", (program_fn_t)&program::rpn_if, - // "if then else " - // "end"}, - // {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"}, - // {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"}, - // {cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, - // {cmd_branch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, - // {cmd_branch, "for", (program_fn_t)&program::rpn_for, - // " for next| step"}, - // {cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, - // {cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, - // {cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, - // {cmd_keyword, "ifte", &program::rpn_ifte, - // "similar to if-then-else-end, " - // " ifte"}, - // {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, - // {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, - // {cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""}, - // {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat - // end"}, - // {cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""}, - // {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, - // {cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""}, + {cmd_undef, "", NULL, "\nBRANCH"}, + {cmd_branch, "if", (program_fn_t)&program::rpn_if, + "if then else " + "end"}, + {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"}, + {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"}, + {cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, + {cmd_branch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, + {cmd_branch, "for", (program_fn_t)&program::rpn_for, + " for next| step"}, + {cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, + {cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, + {cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, + {cmd_keyword, "ifte", &program::rpn_ifte, + "similar to if-then-else-end, " + " ifte"}, + {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, + {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, + {cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""}, + {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, + {cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""}, + {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, + {cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""}, // STORE {cmd_undef, "", NULL, "\nSTORE"}, @@ -242,7 +237,7 @@ ret_value program::run(rpnstack& stk, heap& hp) { // iterate commands for (int i = 0; (go_out == false) && (interrupt_now == false) && (i < (int)size());) { - switch((cmd_type_t)(*this)[i]->_type) { + switch ((cmd_type_t)(*this)[i]->_type) { // could be an auto-evaluated symbol case cmd_symbol: auto_rcl((symbol*)(*this)[i]); @@ -253,7 +248,7 @@ ret_value program::run(rpnstack& stk, heap& hp) { case cmd_keyword: { keyword* k = (keyword*)(*this)[i]; // call the matching function - (this->*(k->_fn))(); + (this->*(k->fn))(); switch (_err) { // no pb -> go on case ret_ok: @@ -282,7 +277,7 @@ ret_value program::run(rpnstack& stk, heap& hp) { case cmd_branch: { // call matching function branch* b = (branch*)(*this)[i]; - int next_cmd = (this->*(b->_fn))(*b); + int next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { case -1: i++; // meaning 'next command' @@ -302,7 +297,7 @@ ret_value program::run(rpnstack& stk, heap& hp) { default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - stk.push_back((*this)[i]); + stk.push_front((*this)[i]); i++; break; } @@ -331,7 +326,7 @@ void program::stop() { interrupt_now = true; } /// bool program::compare_branch(branch* b, const char* str_to_compare, int len) { if (str_to_compare != nullptr) - return b->_value == str_to_compare; + return b->value == str_to_compare; else return false; } @@ -644,8 +639,8 @@ void program::show_stack(rpnstack& st, bool show_separator) { st.front()->show(cout); cout << endl; } else { - for (int i = 0; i < st.size(); i++) { - if (show_separator) cout << st.size() - i << SHOW_STACK_SEPARATOR; + for (int i = st.size() - 1; i >= 0; i--) { + if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; st[i]->show(cout); cout << endl; } @@ -658,9 +653,5 @@ void program::apply_default() { // default float precision, float mode number::s_mode = DEFAULT_MODE; number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; - - // format for mpfr_printf - stringstream ss; - ss << number::s_decimal_digits; - number::s_mpfr_printf_format = string(MPFR_FORMAT_BEG) + ss.str() + string(MPFR_FORMAT_STD); + mpreal::set_default_prec(MPFR_DEFAULT_PREC_BITS); } diff --git a/src/program.hpp b/src/program.hpp index 0377dcc..c1dc795 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -43,7 +43,7 @@ struct if_layout_t { }; //< program class: the class containing a string parser, all the programs keywords, a stack for running the program -class program : public vector { +class program : public deque { public: program(program* parent_prog = NULL) { _parent_prog = parent_prog; diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index cdf305a..1f537c1 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -1,7 +1,7 @@ #include "program.hpp" /// @brief if keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -11,16 +11,16 @@ int program::rpn_if(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - if (mpfr_cmp_si(((number*)_stack->at(0))->_value.mpfr, 0UL) != 0) + if (((number*)_stack->at(0))->value != 0) myobj.arg1 = 1; else myobj.arg1 = 0; - (void)_stack->pop_back(); + (void)_stack->pop_front(); return -1; } /// @brief then keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @@ -38,7 +38,7 @@ int program::rpn_then(branch& myobj) { } /// @brief else keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -57,7 +57,7 @@ int program::rpn_else(branch& myobj) { } /// @brief end keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -72,8 +72,8 @@ int program::rpn_end(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); // check arg - number* arg = (number*)_stack->pop_back(); - if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1; + number* arg = (number*)_stack->pop_front(); + if (arg->value == 0) ret = myobj.arg1; } // arg2 = index of while+1 in case of while..repeat..end else if (myobj.arg2 != -1) @@ -83,7 +83,7 @@ int program::rpn_end(branch& myobj) { } /// @brief do keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -94,7 +94,7 @@ int program::rpn_do(branch& myobj) { } /// @brief until keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -105,7 +105,7 @@ int program::rpn_until(branch& myobj) { } /// @brief ift keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -118,18 +118,18 @@ void program::rpn_ift(void) { // arg is true if number != 0 or if is nan or +/-inf number* testee = ((number*)_stack->at(1)); - if (!mpfr_zero_p(testee->_value.mpfr)) { - CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); - (void)_stack->pop_back(2); + if (testee->value != 0) { + CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack)); + (void)_stack->pop_front(2); - CHECK_MPFR(rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); - (void)_calc_stack.pop_back(); + CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); + (void)_calc_stack.pop_front(); } else - (void)_stack->pop_back(2); + (void)_stack->pop_front(2); } /// @brief ifte keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -142,19 +142,19 @@ void program::rpn_ifte(void) { // arg is true if number != 0 or if is nan or +/-inf number* testee = ((number*)_stack->at(2)); - if (!mpfr_zero_p(testee->_value.mpfr)) - CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack)); + if (testee->value != 0) + CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 2, _calc_stack)); else - CHECK_MPFR(rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack)); + CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack)); - (void)_stack->pop_back(3); + (void)_stack->pop_front(3); - CHECK_MPFR(rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack)); - (void)_calc_stack.pop_back(); + CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); + (void)_calc_stack.pop_front(); } /// @brief while keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -165,7 +165,7 @@ int program::rpn_while(branch& myobj) { } /// @brief repeat keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -178,14 +178,14 @@ int program::rpn_repeat(branch& myobj) { // check arg // myobj.arg1 is end+1 - number* arg = (number*)_stack->pop_back(); - if (mpfr_cmp_si(arg->_value.mpfr, 0UL) == 0) ret = myobj.arg1; + number* arg = (number*)_stack->pop_front(); + if (arg->value == 0) ret = myobj.arg1; return ret; } /// @brief start keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -198,17 +198,17 @@ int program::rpn_start(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); // farg2 = last value of start command - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); myobj.farg2 = (number*)_calc_stack.back(); - _stack->pop_back(); + _stack->pop_front(); // farg1 = first value of start command - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); myobj.farg1 = (number*)_calc_stack.back(); - _stack->pop_back(); + _stack->pop_front(); // test value - if (myobj.farg1->_value > myobj.farg2->_value) + if (myobj.farg1->value > myobj.farg2->value) // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' @@ -218,7 +218,7 @@ int program::rpn_start(branch& myobj) { } /// @brief for keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -234,24 +234,24 @@ int program::rpn_for(branch& myobj) { // farg2 = last value of for command // arg1 = index of symbol to increase - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); myobj.farg2 = (number*)_calc_stack.back(); - _stack->pop_back(); + _stack->pop_front(); // farg1 = first value of for command - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); myobj.farg1 = (number*)_calc_stack.back(); - _stack->pop_back(); + _stack->pop_front(); // test value - if (myobj.farg1->_value > myobj.farg2->_value) + if (myobj.farg1->value > myobj.farg2->value) // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' ret = myobj.arg2 + 1; else { // store symbol with first value - _local_heap[sym->_value] = myobj.farg1; + _local_heap[sym->value] = myobj.farg1; ret = myobj.arg1 + 1; } @@ -259,7 +259,7 @@ int program::rpn_for(branch& myobj) { } /// @brief next keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -275,7 +275,7 @@ int program::rpn_next(branch& myobj) { // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - mpfr_add_si(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, 1UL, MPFR_RNDD); + myobj.farg1->value++; // for command: increment symbol too if (start_or_for->arg1 != -1) { @@ -284,14 +284,14 @@ int program::rpn_next(branch& myobj) { symbol* var = (symbol*)(*this)[start_or_for->arg1]; // increase symbol variable - _local_heap[var->_value] = myobj.farg1; + _local_heap[var->value] = myobj.farg1; } // test value - if (myobj.farg1->_value > start_or_for->farg2->_value) { + if (myobj.farg1->value > start_or_for->farg2->value) { // end of loop myobj.arg_bool = false; // init again next time - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); return -1; } else { // for command: next instruction will be after symbol variable @@ -303,7 +303,7 @@ int program::rpn_next(branch& myobj) { } /// @brief step keyword (branch) implementation -/// +/// /// @param myobj the current branch object /// @return int index of the next object to run in the current program /// @return -1 the next object index to run in the current program is the current+1 @@ -313,10 +313,10 @@ int program::rpn_step(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - number* step = (number*)_stack->pop_back(); + number* step = (number*)_stack->pop_front(); // end of loop if step is negative or zero - if (mpfr_cmp_d(step->_value.mpfr, 0.0) <= 0) + if (step->value <= 0) ret = -1; else { // arg1 = index of start or for command in program @@ -329,7 +329,7 @@ int program::rpn_step(branch& myobj) { // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_RNDD); + mpfr_add(myobj.farg1->value.mpfr_ptr(), myobj.farg1->value.mpfr_ptr(), step->value.mpfr_ptr(), MPFR_RNDD); // for command: increment symbol too if (start_or_for->arg1 != -1) { @@ -338,14 +338,14 @@ int program::rpn_step(branch& myobj) { symbol* var = (symbol*)(*this)[start_or_for->arg1]; // increase symbol variable - _local_heap[var->_value] = myobj.farg1; + _local_heap[var->value] = myobj.farg1; } // test loop value is out of range - if (myobj.farg1->_value > start_or_for->farg2->_value) { + if (myobj.farg1->value > start_or_for->farg2->value) { // end of loop myobj.arg_bool = false; // init again next time - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); ret = -1; } else { // for command: next instruction will be after symbol variable diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index 8072ab4..f8e7c36 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -7,13 +7,13 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); number* re = new number(); - _stack->push_back(re); - CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.at(0))->re()->mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(); + _stack->push_front(re); + CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.at(0))->re()->mpfr, mpreal::get_default_rnd())); + _calc_stack.pop_front(); } /// @brief im keyword implementation @@ -23,13 +23,13 @@ void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); number* im = new number(); - _stack->push_back(im); - CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.at(0))->im()->mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(); + _stack->push_front(im); + CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.at(0))->im()->mpfr, mpreal::get_default_rnd())); + _calc_stack.pop_front(); } /// @brief arg keyword implementation @@ -40,14 +40,14 @@ void program::rpn_arg() { ARG_MUST_BE_OF_TYPE(0, cmd_complex); // calc atan2(x/y) - complex* cplx = (complex*)_stack->pop_back(); + complex* cplx = (complex*)_stack->pop_front(); number* num = new number(); _calc_stack.push_back(num); - CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, mpreal::get_default_rnd())); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_back(); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); + _calc_stack.pop_front(); } /// @brief conj keyword implementation @@ -58,7 +58,7 @@ void program::rpn_conj() { ARG_MUST_BE_OF_TYPE(0, cmd_complex); complex* cplx = (complex*)_stack->back(); - CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, mpreal::get_default_rnd())); } /// @brief r2c keyword implementation @@ -69,16 +69,16 @@ void program::rpn_r2c() { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 2, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); + _stack->pop_front(); complex* cplx = new complex(); - _stack->push_back(cplx); - CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.at(1))->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(2); + _stack->push_front(cplx); + CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.at(1))->_value.mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, mpreal::get_default_rnd())); + _calc_stack.pop_front(2); } /// @brief c2r keyword implementation @@ -88,17 +88,17 @@ void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); number* re = new number(); - _stack->push_back(re); + _stack->push_front(re); number* im = new number(); - _stack->push_back(im); + _stack->push_front(im); - CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(); + CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, mpreal::get_default_rnd())); + _calc_stack.pop_front(); } /// @brief r2p keyword implementation @@ -113,14 +113,14 @@ void program::rpn_r2p() { rpn_arg(); complex* cplx = (complex*)_stack->at(1); - CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); - _stack->pop_back(); + CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, mpreal::get_default_rnd())); + _stack->pop_front(); rpn_swap(); rpn_abs(); cplx = (complex*)_stack->at(1); - CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, floating_t::s_mpfr_rnd)); - _stack->pop_back(); + CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, mpreal::get_default_rnd())); + _stack->pop_front(); } /// @brief p2r keyword implementation @@ -130,7 +130,7 @@ void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); _calc_stack.push_back(new number()); // assert complex is polar @@ -139,16 +139,16 @@ void program::rpn_p2r() { complex* result = (complex*)_stack->back(); // calc cos(theta) - CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); // calc rcos(theta) - CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); // calc sin(theta) - CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); // calc rsin(theta) - CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); } diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 1e7c152..5d601f4 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -15,78 +15,63 @@ void program::rpn_good_bye() { ERR_CONTEXT(ret_good_bye); } /// void program::rpn_help() { // software name - printf("\n" ATTR_BOLD "%s" ATTR_OFF "\n", uname); + cout << endl << ATTR_BOLD << uname << ATTR_OFF << endl; // description - printf("%s\n\n", description); + cout << description << endl << endl; // syntax - printf("%s\n", syntax); + cout << syntax << endl; // keywords unsigned int i = 0; while (s_keywords[i].type != cmd_max) { if (s_keywords[i].comment.size() != 0) { // titles in bold - if (s_keywords[i].type == cmd_undef) printf(ATTR_BOLD); + if (s_keywords[i].type == cmd_undef) cout << ATTR_BOLD; // show title or keyword + comment - 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); + cout << s_keywords[i].name << '\t' << s_keywords[i].comment << endl; + if (s_keywords[i].type == cmd_undef) cout << ATTR_OFF; } i++; } - printf("\n"); + cout << endl; // show mode - printf("Current float mode is "); + cout << "Current float mode is "; switch (number::s_mode) { case number::std: - printf("'std'"); + cout << "'std'"; break; case number::fix: - printf("'fix'"); + cout << "'fix'"; break; case number::sci: - printf("'sci'"); + cout << "'sci'"; break; default: - printf("unknown"); + cout << "unknown"; break; } - printf(" with %d digits after the decimal point\n", number::s_decimal_digits); // bits precision, decimal digits and rounding mode - printf("Current floating point precision is %d bits\n", (int)number::s_mpfr_prec); - printf("Current rounding mode is \"%s\"\n", number::s_mpfr_rnd_str[number::s_mpfr_rnd]); - printf("\n\n"); -} - -/// @brief calculate a number of digits for a given base from a precision in bits -/// -/// @param base the base -/// @param bit_precision the precision in bits -/// @return int the number of digits -/// -static int base_digits_from_bit_precision(int base, int bit_precision) { - return (int)ceil(bit_precision * log(2.0) / log((double)base)) - 1; -} - -/// @brief print a decimal digit in a given MPFR format -/// -/// @param decimal_digits the number -/// @param printf_format the format -/// @return string the result string -/// -static string make_digit_format(int decimal_digits, const char* printf_format) { - stringstream ss; - ss << MPFR_FORMAT_BEG; - ss << number::s_decimal_digits; - ss << printf_format; - return ss.str(); + cout << " with " << number::s_decimal_digits << " digits after the decimal point" << endl; + cout << "Current floating point precision is " << (int)mpreal::get_default_prec() << " bits" << endl; + struct RndStrings { + string name; + mp_rnd_t rnd; + }; + vector rndStrings{MPFR_ROUND_STRINGS}; + for (RndStrings r : rndStrings) + if (r.rnd == mpreal::get_default_rnd()) { + cout << "Current rounding mode is " << r.name << endl; + break; + } + cout << endl << endl; } /// @brief whether a precision is in the precision min/max -/// +/// /// @param precision the precision in bits /// @return true the precision is good /// @return false the precision is not good @@ -110,13 +95,12 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_back())->_value); + double digits = double(((number*)_stack->pop_front())->value); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::std; number::s_decimal_digits = (int)digits; - number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD); } else ERR_CONTEXT(ret_out_of_range); } @@ -127,13 +111,12 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_back())->_value); + double digits = double(((number*)_stack->pop_front())->value); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::fix; number::s_decimal_digits = (int)digits; - number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_FIX); } else ERR_CONTEXT(ret_out_of_range); } @@ -144,28 +127,23 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_back())->_value); + double digits = double(((number*)_stack->pop_front())->value); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::sci; number::s_decimal_digits = (int)digits; - number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_SCI); } else ERR_CONTEXT(ret_out_of_range); } /// @brief version keyword implementation /// -void program::rpn_version() { - _stack->push_back(new ostring(version)); -} +void program::rpn_version() { _stack->push_front(new ostring(version)); } /// @brief uname keyword implementation /// -void program::rpn_uname() { - _stack->push_back(new ostring(uname)); -} +void program::rpn_uname() { _stack->push_front(new ostring(uname)); } /// @brief history keyword implementation /// @@ -185,9 +163,9 @@ void program::rpn_history() { void program::rpn_type() { MIN_ARGUMENTS(1); - int type = _stack->pop_back()->_type; + int type = _stack->pop_front()->_type; if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef; - _stack->push_back(new ostring(object::s_cmd_type_string[type])); + _stack->push_front(new ostring(object::s_cmd_type_string[type])); } /// @brief default keyword implementation @@ -201,15 +179,14 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - unsigned long prec = static_cast(_stack->pop_back())->_value.toULong(); + unsigned long prec = static_cast(_stack->pop_front())->value.toULong(); if (prec >= (unsigned long)MPFR_PREC_MIN && prec <= (unsigned long)MPFR_PREC_MAX) { - number::s_mpfr_prec = (mpfr_prec_t)prec; + mpreal::set_default_prec(prec); // modify digits seen by user if std mode if (number::s_mode == number::std) { // calc max nb of digits user can see with the current bit precision - number::s_decimal_digits = base_digits_from_bit_precision(10, number::s_mpfr_prec); - number::s_mpfr_printf_format = make_digit_format(number::s_decimal_digits, MPFR_FORMAT_STD); + number::s_decimal_digits = bits2digits(mpreal::get_default_prec()); } } else ERR_CONTEXT(ret_out_of_range); @@ -221,13 +198,12 @@ void program::rpn_round() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - ostring* str = (ostring*)_stack->pop_back(); - bool done = false; - for (int rnd = (int)MPFR_DEFAULT_RND; rnd <= (int)MPFR_RNDA; rnd++) { - if (string(number::s_mpfr_rnd_str[rnd]) == str->_value) { - number::s_mpfr_rnd = (mpfr_rnd_t)rnd; - done = true; - } - } - if (!done) ERR_CONTEXT(ret_out_of_range); + map matchRound{MPFR_ROUND_STRINGS}; + + auto found = matchRound.find(((ostring*)_stack->back())->value); + if (found != matchRound.end()) + mpreal::set_default_rnd(found->second); + else + ERR_CONTEXT(ret_out_of_range); + _stack->pop_front(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index d6489df..d280128 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -4,9 +4,9 @@ /// void program::rpn_e(void) { number* euler = new number(); - _stack->push_back(euler); + _stack->push_front(euler); euler->_value = 1L; - CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, mpreal::get_default_rnd())); } /// @brief log10 keyword implementation @@ -19,8 +19,8 @@ void program::rpn_log10() { rpn_ln(); number* ten = new number(); - _stack->push_back(ten); - CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); + _stack->push_front(ten); + CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, mpreal::get_default_rnd())); rpn_ln(); rpn_div(); } else @@ -35,8 +35,8 @@ void program::rpn_alog10() { if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { floating_t* left = &((number*)_stack->at(0))->_value; number* ten = new number(); - _stack->push_back(ten); - CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, floating_t::s_mpfr_rnd)); + _stack->push_front(ten); + CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, mpreal::get_default_rnd())); rpn_ln(); rpn_mul(); rpn_exp(); @@ -53,8 +53,8 @@ void program::rpn_log2() { rpn_ln(); number* two = new number(); - _stack->push_back(two); - CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); + _stack->push_front(two); + CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, mpreal::get_default_rnd())); rpn_ln(); rpn_div(); } else @@ -69,8 +69,8 @@ void program::rpn_alog2() { if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { floating_t* left = &((number*)_stack->at(0))->_value; number* two = new number(); - _stack->push_back(two); - CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); + _stack->push_front(two); + CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, mpreal::get_default_rnd())); rpn_ln(); rpn_mul(); rpn_exp(); @@ -87,21 +87,21 @@ void program::rpn_ln() { // x<0 -> ln(x) = ln(-x)+i*pi if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) { - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); left = (number*)_calc_stack.back(); complex* cplx = new complex(); - _stack->push_back(cplx); - CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(); + _stack->push_front(cplx); + CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, mpreal::get_default_rnd())); + _calc_stack.pop_front(); } else - CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); floating_t* x = ((complex*)_calc_stack.at(0))->re(); floating_t* y = ((complex*)_calc_stack.at(0))->im(); @@ -110,16 +110,16 @@ void program::rpn_ln() { floating_t* im = ((complex*)_stack->at(0))->im(); // 1. atan(x/y) - CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, mpreal::get_default_rnd())); // 2. 0.5*ln(x*x+y*y) - CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, mpreal::get_default_rnd())); - _calc_stack.pop_back(); + _calc_stack.pop_front(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -131,10 +131,10 @@ void program::rpn_exp() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // exp(x)*(cos(y)+i sin(y)) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); floating_t* x = ((complex*)_calc_stack.at(0))->re(); floating_t* y = ((complex*)_calc_stack.at(0))->im(); @@ -142,13 +142,13 @@ void program::rpn_exp() { floating_t* re = ((complex*)_stack->at(0))->re(); floating_t* im = ((complex*)_stack->at(0))->im(); - CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(); + _calc_stack.pop_front(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -163,8 +163,8 @@ void program::rpn_expm() { rpn_exp(); number* one = new number(); - _stack->push_back(one); - CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(one); + CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_minus(); } else ERR_CONTEXT(ret_bad_operand_type); @@ -178,8 +178,8 @@ void program::rpn_lnp1() { if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { // ln(x+1) number* one = new number(); - _stack->push_back(one); - CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(one); + CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_plus(); rpn_ln(); @@ -194,13 +194,13 @@ void program::rpn_sinh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); number* num = new number(); - _stack->push_back(num); + _stack->push_front(num); floating_t* tmp = &num->_value; floating_t* x = ((complex*)_calc_stack.at(1))->re(); floating_t* y = ((complex*)_calc_stack.at(1))->im(); @@ -208,15 +208,15 @@ void program::rpn_sinh() { floating_t* re = ((complex*)_stack->at(0))->re(); floating_t* im = ((complex*)_stack->at(0))->im(); - CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -228,14 +228,14 @@ void program::rpn_asinh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // asinh(z)=ln(z+sqrt(1+z*z)) rpn_dup(); rpn_square(); number* num = new number(); - _stack->push_back(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_plus(); rpn_squareroot(); rpn_plus(); @@ -251,13 +251,13 @@ void program::rpn_cosh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); number* num = new number(); - _stack->push_back(num); + _stack->push_front(num); floating_t* tmp = &num->_value; floating_t* x = ((complex*)_calc_stack.at(1))->re(); floating_t* y = ((complex*)_calc_stack.at(1))->im(); @@ -265,15 +265,15 @@ void program::rpn_cosh() { floating_t* re = ((complex*)_stack->at(0))->re(); floating_t* im = ((complex*)_stack->at(0))->im(); - CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -285,18 +285,18 @@ void program::rpn_acosh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // acosh(z)=ln(z+sqrt(z+1)sqrt(z-1)) rpn_dup(); number* num = new number(); - _stack->push_back(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_plus(); rpn_dup(); num = (number*)new number(); - _stack->push_back(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); rpn_minus(); rpn_mul(); rpn_squareroot(); @@ -313,7 +313,7 @@ void program::rpn_tanh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y)) rpn_dup(); @@ -324,13 +324,13 @@ void program::rpn_tanh() { floating_t* re = ((complex*)_stack->at(1))->re(); floating_t* im = ((complex*)_stack->at(1))->im(); - CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, mpreal::get_default_rnd())); rpn_div(); } else ERR_CONTEXT(ret_bad_operand_type); @@ -343,24 +343,24 @@ void program::rpn_atanh() { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // atanh(z)=0.5*ln((1+z)/(1-z)) rpn_dup(); number* num; - _stack->push_back(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = new number); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_plus(); rpn_swap(); - _stack->push_back(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = new number); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_minus(); rpn_neg(); rpn_div(); rpn_ln(); - _stack->push_back(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); + _stack->push_front(num = new number); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, mpreal::get_default_rnd())); rpn_mul(); } else ERR_CONTEXT(ret_bad_operand_type); diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index e349a94..fdb9d22 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -39,24 +39,24 @@ void program::rpn_eval(void) { if (IS_ARG_TYPE(0, cmd_symbol)) { // recall a variable object* obj; - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); // if variable holds a program, run this program if (find_variable(variable, obj)) { if (obj->_type == cmd_program) { - prog_text = ((oprogram*)obj)->_value; - (void)_stack->pop_back(); + prog_text = ((oprogram*)obj)->value; + (void)_stack->pop_front(); run_prog = true; } else { // else recall this variable (i.e. stack its content) - (void)_stack->pop_back(); - _stack->push_back(obj); + (void)_stack->pop_front(); + _stack->push_front(obj); } } else ERR_CONTEXT(ret_unknown_variable); } else if (IS_ARG_TYPE(0, cmd_program)) { // eval a program - prog_text = ((oprogram*)_stack->pop_back())->_value; + prog_text = ((oprogram*)_stack->pop_front())->value; run_prog = true; } else ERR_CONTEXT(ret_bad_operand_type); @@ -128,12 +128,12 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[string(((symbol*)(*this)[i])->_value)] = _stack->at(0); - (void)_stack->pop_back(); + _local_heap[string(((symbol*)(*this)[i])->value)] = _stack->at(0); + (void)_stack->pop_front(); } // run the program - string entry(((oprogram*)(*this)[myobj.arg1 + count_symbols + 1])->_value); + string entry(((oprogram*)(*this)[myobj.arg1 + count_symbols + 1])->value); program prog(this); // make the program from entry diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 75043af..a05692b 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -7,36 +7,34 @@ void program::rpn_plus() { // adding strings if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) { - string str = - static_cast(_stack->at(1))->_value + static_cast(_stack->at(0))->_value; - _stack->pop_back(2); - _stack->push_back(new ostring(str)); + ostring* right = (ostring*)_stack->pop_front(); + ostring* left = (ostring*)_stack->front(); + left->value += right->value; } // adding numbers else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_add(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + number* left = (number*)_stack->front(); + left->value += right->value; } // adding complexes else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); + ocomplex* right = (ocomplex*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->front(); + left->value += right->value; } // adding complex+number else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value += right->value; } // adding number+complex else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value += right->value; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -48,29 +46,28 @@ void program::rpn_minus() { // substracting numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + left->value -= right->value; } // substracting complexes else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - complex* right = (complex*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); + ocomplex* right = (ocomplex*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value -= right->value; } // substracting complex-number else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value -= right->value; } // substracting number-complex else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_sub(left->re()->mpfr, right->_value.mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value -= right->value; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -82,100 +79,32 @@ void program::rpn_mul() { // multiplying numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_mul(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + left->value *= right->value; } - // multiplying complexes (a+ib)*(x+iy)=(ax-by)+i(ay+bx)=a(x+iy)+b(-y+ix) + // multiplying complexes else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - complex* right = (complex*)_stack->pop_back(); // x+iy - complex* left = (complex*)_stack->back(); // a+ib - - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - complex* left_sav = (complex*)_calc_stack.back(); // a+ib - - // left: (a+ib)->(ax+iay) - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->re()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - - // right: (x+iy)-> (bx-iby) - CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_neg(right->im()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - - // left=left+transpose(right) - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(left->im()->mpfr, left->im()->mpfr, right->re()->mpfr, floating_t::s_mpfr_rnd)); - - _calc_stack.pop_back(); + ocomplex* right = (ocomplex*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value *= right->value; } // multiplying complex*number else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value *= right->value; } // multiplying number*complex else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value *= right->value; } else ERR_CONTEXT(ret_bad_operand_type); } -/// @brief divide the 2 complexes on stack -/// result on the prog stack -/// -void program::do_divide_complexes() { - //(a+ib)/(x+iy)=(a+ib)(x-iy)/(x^2+y^2)=(ax+by+i(bx-ay))/(x^2+y^2) - complex* right = (complex*)_stack->at(0); // x+iy - complex* left = (complex*)_stack->at(1); // a+ib - - // 1. calc (x^2-y^2) in _calc_stack - number* ex; - _calc_stack.push_back(ex = new number); - CHECK_MPFR(mpfr_mul(ex->_value.mpfr, right->re()->mpfr, right->re()->mpfr, - floating_t::s_mpfr_rnd)); // x2 - number* wy; - _calc_stack.push_back(wy = new number); - CHECK_MPFR(mpfr_mul(wy->_value.mpfr, right->im()->mpfr, right->im()->mpfr, - floating_t::s_mpfr_rnd)); // y2 - CHECK_MPFR(mpfr_add(ex->_value.mpfr, ex->_value.mpfr, wy->_value.mpfr, - floating_t::s_mpfr_rnd)); // ex=x2+y2 - - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); // x+iy - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - complex* left_sav = (complex*)_calc_stack.at(1); // a+ib - complex* right_sav = (complex*)_calc_stack.at(0); // x+iy - - // 2. left.re=ax+by - CHECK_MPFR(mpfr_mul(left->re()->mpfr, left_sav->re()->mpfr, right_sav->re()->mpfr, - floating_t::s_mpfr_rnd)); // left.re=ax - CHECK_MPFR(mpfr_mul(right->re()->mpfr, left_sav->im()->mpfr, right_sav->im()->mpfr, - floating_t::s_mpfr_rnd)); // right.re=by - CHECK_MPFR(mpfr_add(left->re()->mpfr, left->re()->mpfr, right->re()->mpfr, - floating_t::s_mpfr_rnd)); // left.re=ax+by - - // 3. left.im=bx-ay - CHECK_MPFR(mpfr_mul(left->im()->mpfr, left_sav->im()->mpfr, right_sav->re()->mpfr, - floating_t::s_mpfr_rnd)); // left.im=bx - CHECK_MPFR(mpfr_mul(right->im()->mpfr, left_sav->re()->mpfr, right_sav->im()->mpfr, - floating_t::s_mpfr_rnd)); // right.im=ay - CHECK_MPFR(mpfr_sub(left->im()->mpfr, left->im()->mpfr, right->im()->mpfr, - floating_t::s_mpfr_rnd)); // left.im=bx-ay - - // 4. left.re/=(x^2-y^2), left.im/=(x^2+y^2) - CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, ex->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, ex->_value.mpfr, floating_t::s_mpfr_rnd)); - - _stack->pop_back(); - _calc_stack.pop_back(4); -} - /// @brief / keyword implementation /// void program::rpn_div() { @@ -183,44 +112,28 @@ void program::rpn_div() { // dividing numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_div(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + left->value /= right->value; } // dividing complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) - do_divide_complexes(); + else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { + number* right = (number*)_stack->pop_front(); + number* left = (number*)_stack->back(); + left->value /= right->value; + } // dividing complex/number else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_back(); - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_div(left->re()->mpfr, left->re()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(left->im()->mpfr, left->im()->mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value /= right->value; } // dividing number/complex else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { - // 1. copy out - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, - _calc_stack); // complex - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, - _calc_stack); // number - _stack->pop_back(2); - - // 2. copy back (2 complexes on stack) - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, - *_stack); // complex back to stack - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, - *_stack); // complex back to stack - - // 3. set complex level 2 to (number,0) - complex* new_cplx = (complex*)_stack->at(1); - CHECK_MPFR( - mpfr_set(new_cplx->re()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_ui(new_cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); - _calc_stack.pop_back(2); - - // 4. divide - do_divide_complexes(); + rpn_swap(); + number* right = (number*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value /= right->value; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -232,11 +145,10 @@ void program::rpn_neg() { if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_neg(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + left->value = -left->value; } else if (_stack->at(0)->_type == cmd_complex) { - complex* left = (complex*)_stack->back(); - CHECK_MPFR(mpfr_neg(left->re()->mpfr, left->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_neg(left->im()->mpfr, left->im()->mpfr, floating_t::s_mpfr_rnd)); + ocomplex* left = (ocomplex*)_stack->back(); + left->value = -left->value; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -248,16 +160,10 @@ void program::rpn_inv() { if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_si_div(left->_value.mpfr, 1L, left->_value.mpfr, floating_t::s_mpfr_rnd)); + left->value = 1 / left->value; } else if (_stack->at(0)->_type == cmd_complex) { - // 1. duplicate - rpn_dup(); - // 2. set complex level 2 to (1,0) - complex* cplx = (complex*)_stack->at(1); - CHECK_MPFR(mpfr_set_ui(cplx->re()->mpfr, 1UL, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_ui(cplx->im()->mpfr, 0UL, floating_t::s_mpfr_rnd)); - // 3. divide - do_divide_complexes(); + ocomplex* left = (ocomplex*)_stack->back(); + left->value = mpreal{1} / left->value; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -268,12 +174,10 @@ void program::rpn_purcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - - 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)); + left->value *= right->value; + left->value /= 100; } /// @brief %CH keyword implementation @@ -282,12 +186,10 @@ void program::rpn_purcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - - 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)); + right->value *= 100; + left->value /= right->value; } /// @brief power keyword implementation @@ -296,80 +198,40 @@ void program::rpn_power() { MIN_ARGUMENTS(2); bool done_on_real = false; - if (_stack->at(1)->_type == cmd_number) { + if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* right = (number*)_stack->at(0); - number* left = (number*)_stack->at(1); - - if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) { - CHECK_MPFR(mpfr_pow(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); - _stack->pop_back(); - done_on_real = true; - } else { - // copy power out - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); - - // negative number -> complex number - _stack->push_back(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); - rpn_r2c(); - - // copy power back - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_back(); - } - } - - // carrefull, no 'else' here - if (!done_on_real) { - if (_stack->at(1)->_type == cmd_complex) { - ARG_MUST_BE_OF_TYPE(0, cmd_number); - - // power on tmp stack - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); - - // switch complex to polar - complex* cplx = (complex*)_stack->back(); - rpn_r2p(); - - // new abs=abs^exponent - number* exponent = (number*)_calc_stack.back(); - CHECK_MPFR(mpfr_pow(cplx->re()->mpfr, cplx->re()->mpfr, exponent->_value.mpfr, floating_t::s_mpfr_rnd)); - - // new arg=arg*exponent - CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, exponent->_value.mpfr, floating_t::s_mpfr_rnd)); - - // back to cartesian - rpn_p2r(); - _calc_stack.pop_back(); - } else - ERR_CONTEXT(ret_bad_operand_type); - } + number* right = (number*)_stack->pop_front(); + number* left = (number*)_stack->back(); + // TODO pow seems not to be a friend of mpreal + //left->value.mpfr_ptr = pow(right->value); + mpfr_pow(left->value.mpfr_ptr(), left->value.mpfr_ptr(), right->value.mpfr_ptr(), mpreal::get_default_rnd()); + } else + ERR_CONTEXT(ret_bad_operand_type); + // TODO manage complex case } +#if 0 /// @brief sqrt keyword implementation /// void program::rpn_squareroot() { if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - if (mpfr_cmp_d(left->_value.mpfr, 0.0) >= 0) - CHECK_MPFR(mpfr_sqrt(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + if (left->value >= 0) + left->value = rec_sqrt(left->value); else { // negative number -> complex square root - _stack->push_back(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.0, floating_t::s_mpfr_rnd)); + _stack->push_front(new number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.0, mpreal::get_default_rnd())); rpn_r2c(); - _stack->push_back(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); + _stack->push_front(new number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.5, mpreal::get_default_rnd())); rpn_power(); } } else if (_stack->at(0)->_type == cmd_complex) { // calc cplx^0.5 - _stack->push_back(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->_value.mpfr, 0.5, floating_t::s_mpfr_rnd)); + _stack->push_front(new number); + CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.5, mpreal::get_default_rnd())); rpn_power(); } else ERR_CONTEXT(ret_bad_operand_type); @@ -382,7 +244,7 @@ void program::rpn_square() { if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_sqr(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sqr(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { rpn_dup(); rpn_mul(); @@ -397,12 +259,14 @@ void program::rpn_modulo() { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_fmod(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_fmod(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); } +#endif +#if 0 /// @brief abs keyword implementation /// void program::rpn_abs() { @@ -410,27 +274,27 @@ void program::rpn_abs() { if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // 1. copy out -> calc x2+iy2 - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); // 2. calc x2+iy2 - complex* cplx = (complex*)_calc_stack.back(); - CHECK_MPFR(mpfr_mul(cplx->re()->mpfr, cplx->re()->mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(cplx->im()->mpfr, cplx->im()->mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); + ocomplex* cplx = (ocomplex*)_calc_stack.back(); + CHECK_MPFR(mpfr_mul(cplx->re.mpfr, cplx->re.mpfr, cplx->re.mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(cplx->im.mpfr, cplx->im.mpfr, cplx->im.mpfr, mpreal::get_default_rnd())); // 3. new real on stack - _stack->push_back(new number); + _stack->push_front(new number); number* module = (number*)_stack->back(); // 4. set it to |x2+y2| then take sqrt - CHECK_MPFR(mpfr_set(module->_value.mpfr, cplx->re()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(module->_value.mpfr, module->_value.mpfr, cplx->im()->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sqrt(module->_value.mpfr, module->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set(module->value.mpfr, cplx->re.mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_add(module->value.mpfr, module->value.mpfr, cplx->im.mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sqrt(module->value.mpfr, module->value.mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(); + _calc_stack.pop_front(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -466,9 +330,9 @@ void program::rpn_base() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MIN) >= 0 && - mpfr_cmp_d(((number*)_stack->back())->_value.mpfr, (double)BASE_MAX) <= 0) { - int base = (int)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); + if (mpfr_cmp_d(((number*)_stack->back())->value.mpfr, (double)BASE_MIN) >= 0 && + mpfr_cmp_d(((number*)_stack->back())->value.mpfr, (double)BASE_MAX) <= 0) { + int base = (int)mpfr_get_d(((number*)_stack->pop_front())->value.mpfr, mpreal::get_default_rnd()); ((number*)_stack->at(0))->_base = base; ((number*)_stack->at(0))->_representation = number::base; } else @@ -484,11 +348,11 @@ void program::rpn_fact() { // fact(n) = gamma(n+1) number* left = (number*)_stack->back(); number* right; - _stack->push_back(right = new number); - right->_value = 1L; + _stack->push_front(right = new number); + right->value = 1L; rpn_plus(); - CHECK_MPFR(mpfr_gamma(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_gamma(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } /// @brief sign keyword implementation @@ -499,8 +363,8 @@ void program::rpn_sign() { if (_stack->at(0)->_type == cmd_number) { // fact(n) = gamma(n+1) number* left = (number*)_stack->back(); - int result = mpfr_sgn(left->_value.mpfr); - left->_value = (long)result; + int result = mpfr_sgn(left->value.mpfr); + left->value = (long)result; } else if (_stack->at(0)->_type == cmd_complex) { // calc x/sqrt(x*x+y*y) +iy/sqrt(x*x+y*y) rpn_dup(); @@ -518,27 +382,27 @@ void program::rpn_mant() { number* left = (number*)_stack->back(); - if (mpfr_number_p(left->_value.mpfr)) { - if (mpfr_zero_p(left->_value.mpfr)) - left->_value = 0.0; + if (mpfr_number_p(left->value.mpfr)) { + if (mpfr_zero_p(left->value.mpfr)) + left->value = 0.0; else { - mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); + mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd()); number* one; - _stack->push_back(one = new number); + _stack->push_front(one = new number); number* ten; - _stack->push_back(ten = new number); - ten->_value = 10L; + _stack->push_front(ten = new number); + ten->value = 10L; - one->_value = 1L; - while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) - mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); + one->value = 1L; + while (mpfr_greaterequal_p(left->value.mpfr, one->value.mpfr)) + mpfr_div(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - one->_value = 0.1; - while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) - mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); + one->value = 0.1; + while (mpfr_less_p(left->value.mpfr, one->value.mpfr)) + mpfr_mul(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } } else ERR_CONTEXT(ret_out_of_range); @@ -552,35 +416,35 @@ void program::rpn_xpon() { number* left = (number*)_stack->back(); - if (mpfr_number_p(left->_value.mpfr)) { - if (mpfr_zero_p(left->_value.mpfr)) - left->_value = 0.0; + if (mpfr_number_p(left->value.mpfr)) { + if (mpfr_zero_p(left->value.mpfr)) + left->value = 0.0; else { double exponant = 0.0; - mpfr_abs(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd); + mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd()); number* one; - _stack->push_back(one = new number); + _stack->push_front(one = new number); number* ten; - _stack->push_back(ten = new number); - ten->_value = 10L; + _stack->push_front(ten = new number); + ten->value = 10L; - one->_value = 1L; - while (mpfr_greaterequal_p(left->_value.mpfr, one->_value.mpfr)) { - mpfr_div(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); + one->value = 1L; + while (mpfr_greaterequal_p(left->value.mpfr, one->value.mpfr)) { + mpfr_div(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); exponant += 1.0; } - one->_value = 0.1; - while (mpfr_less_p(left->_value.mpfr, one->_value.mpfr)) { - mpfr_mul(left->_value.mpfr, left->_value.mpfr, ten->_value.mpfr, floating_t::s_mpfr_rnd); + one->value = 0.1; + while (mpfr_less_p(left->value.mpfr, one->value.mpfr)) { + mpfr_mul(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); exponant -= 1.0; } - left->_value = exponant; + left->value = exponant; - _calc_stack.pop_back(); - _calc_stack.pop_back(); + _calc_stack.pop_front(); + _calc_stack.pop_front(); } } else ERR_CONTEXT(ret_out_of_range); @@ -594,7 +458,7 @@ void program::rpn_floor() { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_floor(left->_value.mpfr, left->_value.mpfr)); + CHECK_MPFR(mpfr_floor(left->value.mpfr, left->value.mpfr)); } /// @brief ceil keyword implementation @@ -605,7 +469,7 @@ void program::rpn_ceil() { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_ceil(left->_value.mpfr, left->_value.mpfr)); + CHECK_MPFR(mpfr_ceil(left->value.mpfr, left->value.mpfr)); } /// @brief fp keyword implementation @@ -616,7 +480,7 @@ void program::rpn_fp() { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_frac(left->_value.mpfr, left->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_frac(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } /// @brief ip keyword implementation @@ -627,7 +491,7 @@ void program::rpn_ip() { number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_trunc(left->_value.mpfr, left->_value.mpfr)); + CHECK_MPFR(mpfr_trunc(left->value.mpfr, left->value.mpfr)); } /// @brief min keyword implementation @@ -637,10 +501,10 @@ void program::rpn_min() { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_min(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_min(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); } /// @brief max keyword implementation @@ -650,8 +514,9 @@ void program::rpn_max() { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_max(left->_value.mpfr, left->_value.mpfr, right->_value.mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_max(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); } +#endif diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 9611466..2767283 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -4,26 +4,22 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - (void)_stack->pop_back(2); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_back(2); + rpnstack::copy_and_push_front(*_stack, 1, *_stack); + (void)_stack->del(2); } /// @brief drop keyword implementation /// void program::rpn_drop(void) { MIN_ARGUMENTS(1); - (void)_stack->pop_back(); + (void)_stack->pop_front(); } /// @brief drop2 keyword implementation /// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); - (void)_stack->pop_back(2); + (void)_stack->pop_front(2); } /// @brief dropn keyword implementation @@ -32,29 +28,21 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->_value.toLong(); + int args = (int)((number*)_stack->front())->value.toLong(); MIN_ARGUMENTS(args + 1); - (void)_stack->pop_back(args + 1); + _stack->del(0, args); } /// @brief erase / del keyword implementation /// -void program::rpn_erase(void) { (void)_stack->pop_back(_stack->size()); } +void program::rpn_erase(void) { (void)_stack->del(0, _stack->size() - 1); } /// @brief dup keyword implementation /// void program::rpn_dup(void) { MIN_ARGUMENTS(1); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, *_stack); -} - -/// @brief dup2 keyword implementation -/// -void program::rpn_dup2(void) { - MIN_ARGUMENTS(2); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); + rpnstack::copy_and_push_front(*_stack, 0, *_stack); } /// @brief dupn keyword implementation @@ -63,11 +51,19 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->_value.toLong(); + int args = (int)((number*)_stack->back())->value.toLong(); MIN_ARGUMENTS(args + 1); - _stack->pop_back(); + _stack->pop_front(); - for (int i = 0; i < args; i++) rpnstack::copy_and_push_back(*_stack, _stack->size() - args, *_stack); + for (int i = 0; i < args; i++) rpnstack::copy_and_push_front(*_stack, args - 1, *_stack); +} + +/// @brief dup2 keyword implementation +/// +void program::rpn_dup2(void) { + MIN_ARGUMENTS(2); + rpnstack::copy_and_push_front(*_stack, 1, *_stack); + rpnstack::copy_and_push_front(*_stack, 1, *_stack); } /// @brief pick keyword implementation @@ -76,7 +72,7 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_back())->_value); + unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_front())->value); // treat stack depth errors if ((to_pick == 0) || (to_pick > _stack->size())) { @@ -84,7 +80,7 @@ void program::rpn_pick(void) { return; } - rpnstack::copy_and_push_back(*_stack, _stack->size() - to_pick, *_stack); + rpnstack::copy_and_push_front(*_stack, to_pick - 1, *_stack); } /// @brief rot keyword implementation @@ -92,19 +88,19 @@ void program::rpn_pick(void) { void program::rpn_rot(void) { MIN_ARGUMENTS(3); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 3, _calc_stack); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, _calc_stack); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - (void)_stack->pop_back(3); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 2, *_stack); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 3, *_stack); - _calc_stack.pop_back(3); + rpnstack::copy_and_push_front(*_stack, 2, _calc_stack); + rpnstack::copy_and_push_front(*_stack, 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); + (void)_stack->pop_front(3); + rpnstack::copy_and_push_front(_calc_stack, 1, *_stack); + rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_front(_calc_stack, 2, *_stack); + _calc_stack.pop_front(3); } /// @brief depth keyword implementation /// -void program::rpn_depth(void) { _stack->push_back(new number(_stack->size())); } +void program::rpn_depth(void) { _stack->push_front(new number(_stack->size())); } /// @brief roll keyword implementation /// @@ -112,19 +108,19 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->_value.toLong(); + int args = (int)((number*)_stack->back())->value.toLong(); MIN_ARGUMENTS(args + 1); - _stack->pop_back(); + _stack->pop_front(); for (int i = 0; i < args; i++) { - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - (void)_stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); + (void)_stack->pop_front(); } - for (int i = 1; i < args; i++) rpnstack::copy_and_push_back(_calc_stack, args - 1 - i, *_stack); - rpnstack::copy_and_push_back(_calc_stack, args - 1, *_stack); + for (int i = 1; i < args; i++) rpnstack::copy_and_push_front(_calc_stack, args - 1 - i, *_stack); + rpnstack::copy_and_push_front(_calc_stack, args - 1, *_stack); - _calc_stack.pop_back(args); + _calc_stack.pop_front(args); } /// @brief rolld keyword implementation @@ -133,20 +129,20 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->_value.toLong(); + int args = (int)((number*)_stack->back())->value.toLong(); MIN_ARGUMENTS(args + 1); - _stack->pop_back(); + _stack->pop_front(); for (int i = 0; i < args; i++) { - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - (void)_stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); + (void)_stack->pop_front(); } - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - args, *_stack); + rpnstack::copy_and_push_front(_calc_stack, args - 1, *_stack); - for (int i = 1; i < args; i++) rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - i, *_stack); + for (int i = 1; i < args; i++) rpnstack::copy_and_push_front(_calc_stack, i - 1, *_stack); - _calc_stack.pop_back(args); + _calc_stack.pop_front(args); } /// @brief over keyword implementation @@ -154,5 +150,5 @@ void program::rpn_rolld(void) { void program::rpn_over(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_back(*_stack, _stack->size() - 2, *_stack); + rpnstack::copy_and_push_front(*_stack, 1, *_stack); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 0e634d9..6a32c41 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -6,9 +6,9 @@ void program::rpn_sto(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - string name(((symbol*)_stack->pop_back())->_value); + string name(((symbol*)_stack->pop_front())->value); (*_heap)[name] = _stack->at(0); - (void)_stack->pop_back(); + (void)_stack->pop_front(); } /// @brief sto+ keyword implementation @@ -19,26 +19,26 @@ void program::rpn_stoadd(void) { if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_plus(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_plus(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -51,26 +51,26 @@ void program::rpn_stosub(void) { if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_minus(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_minus(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -83,26 +83,26 @@ void program::rpn_stomul(void) { if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_mul(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_mul(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -115,26 +115,26 @@ void program::rpn_stodiv(void) { if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_div(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { // copy value, get variable value on stack level 1, // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_back(); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); + _stack->pop_front(); - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); rpn_div(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -147,12 +147,12 @@ void program::rpn_stoneg(void) { if (_stack->at(0)->_type == cmd_symbol) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_neg(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -165,12 +165,12 @@ void program::rpn_stoinv(void) { if (_stack->at(0)->_type == cmd_symbol) { // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); rpn_rcl(); if (_err == ret_ok) { rpn_inv(); (*_heap)[variable] = _stack->at(0); - _stack->pop_back(); + _stack->pop_front(); } } else ERR_CONTEXT(ret_bad_operand_type); @@ -185,12 +185,12 @@ void program::rpn_rcl(void) { // recall a variable object* obj; - string variable(((symbol*)_stack->back())->_value); + string variable(((symbol*)_stack->back())->value); // mind the order of heaps if (find_variable(variable, obj)) { - (void)_stack->pop_back(); - _stack->push_back(obj); + (void)_stack->pop_front(); + _stack->push_front(obj); } else ERR_CONTEXT(ret_unknown_variable); } @@ -202,7 +202,7 @@ void program::rpn_edit(void) { ostringstream st; // re-write stack objet in a stream - ((object*)_stack->pop_back())->show(st); + ((object*)_stack->pop_front())->show(st); // set it as the linenoise line entry linenoisePreloadBuffer((const char*)st.str().c_str()); @@ -213,18 +213,18 @@ void program::rpn_edit(void) { /// @param symb the smlbol to recall and autoeval /// void program::auto_rcl(symbol* symb) { - if (symb->_auto_eval) { + if (symb->auto_eval) { object* obj; - string variable(symb->_value); + string variable(symb->value); // mind the order of heaps if (find_variable(variable, obj)) { - _stack->push_back(obj); + _stack->push_front(obj); if (obj->_type == cmd_program) rpn_eval(); } else - _stack->push_back(symb); + _stack->push_front(symb); } else - _stack->push_back(symb); + _stack->push_front(symb); } /// @brief purge keyword implementation @@ -233,7 +233,7 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - string name(((symbol*)_stack->pop_back())->_value); + string name(((symbol*)_stack->pop_front())->value); if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 312aeee..d5799c6 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -13,7 +13,7 @@ void program::rpn_instr() { // write the object in stack(0) in a string and remove this obj FILE* tmp = tmpfile(); if (tmp != NULL) { - ((object*)_stack->pop_back())->show(tmp); + ((object*)_stack->pop_front())->show(tmp); // reserve the correct size on stack unsigned int str_size = (unsigned int)ftell(tmp); @@ -26,7 +26,7 @@ void program::rpn_instr() { // fill the obj rewind(tmp); if (fread(buf, str_size, 1, tmp) != 1) ERR_CONTEXT(ret_runtime_error); - _stack->push_back(new ostring(buf)); + _stack->push_front(new ostring(buf)); destroy_file: char filePath[PATH_MAX]; @@ -43,7 +43,7 @@ void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - string entry(((ostring*)_stack->pop_back())->_value); + string entry(((ostring*)_stack->pop_front())->_value); program prog; @@ -60,9 +60,9 @@ void program::rpn_chr() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // get arg as number % 256 - char the_chr = (char)mpfr_get_d(((number*)_stack->pop_back())->_value.mpfr, floating_t::s_mpfr_rnd); + char the_chr = (char)mpfr_get_d(((number*)_stack->pop_front())->_value.mpfr, mpreal::get_default_rnd()); if (the_chr < 32 || the_chr > 126) the_chr = '.'; - _stack->push_back(new ostring(string(1, the_chr))); + _stack->push_front(new ostring(string(1, the_chr))); } /// @brief num keyword implementation @@ -71,8 +71,8 @@ void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - double the_chr = (double)((ostring*)_stack->pop_back())->_value[0]; - _stack->push_back(new number(the_chr)); + double the_chr = (double)((ostring*)_stack->pop_front())->_value[0]; + _stack->push_front(new number(the_chr)); } /// @brief size keyword implementation @@ -81,8 +81,8 @@ void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - double len = ((ostring*)_stack->pop_back())->_value.size(); - _stack->push_back(new number(len)); + double len = ((ostring*)_stack->pop_front())->_value.size(); + _stack->push_front(new number(len)); } /// @brief pos keyword implementation @@ -93,8 +93,8 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(1, cmd_string); size_t pos = static_cast(_stack->at(1))->_value.find(((ostring*)_stack->at(0))->_value); - _stack->pop_back(2); - _stack->push_back(new number(pos)); + _stack->pop_front(2); + _stack->push_front(new number(pos)); } /// @brief sub keyword implementation @@ -111,7 +111,7 @@ void program::rpn_strsub() { long len = ((ostring*)_stack->at(2))->_len; bool result_is_void = false; - _stack->pop_back(2); + _stack->pop_front(2); if (first < 0) first = 0; if (last < 0) last = 0; @@ -131,11 +131,11 @@ void program::rpn_strsub() { memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->at(0))->_value + first, str_size); ((ostring*)_calc_stack.back())->_value[str_size] = 0; - _stack->pop_back(); - rpnstack::copy_and_push_back(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_back(); + _stack->pop_front(); + rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); + _calc_stack.pop_front(); } else { - _stack->pop_back(); + _stack->pop_front(); ostring* str = (ostring*)_stack->allocate_back(1 + sizeof(ostring), cmd_string); str->_len = 0; str->_value[0] = 0; diff --git a/src/rpn-test-core.cpp b/src/rpn-test-core.cpp index f8f9e08..dfb7d08 100644 --- a/src/rpn-test-core.cpp +++ b/src/rpn-test-core.cpp @@ -1,22 +1,23 @@ #include "program.hpp" /// @brief write stack in a string, each entry separated between commas -/// +/// /// @param stack_is the output string /// @param stk the stack /// void program::test_get_stack(string& stack_is, rpnstack& stk) { - for (int i = 0; i < (int)stk.size(); i++) { - if (i > 0) stack_is += ", "; - + ostringstream st; + stk[stk.size() - 1]->show(st); + stack_is += st.str(); + for (int i = (int)stk.size() - 2; i >= 0; i--) { ostringstream st; - stk[stk.size() - i - 1]->show(st); - stack_is += st.str(); + stk[i]->show(st); + stack_is += ", " + st.str(); } } /// @brief show the tests results -/// +/// /// @param title test title /// @param tests tests nb /// @param tests_failed failed tests nb @@ -47,14 +48,14 @@ void program::rpn_test() { int total_steps = 0; int total_steps_failed = 0; - string test_filename = ((ostring*)_stack->pop_back())->_value; - printf("\nrpn version is %s\n", version); + string test_filename = ((ostring*)_stack->pop_front())->value; + printf("\nrpn version is %s\n", version.c_str()); test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); } /// @brief load a test file and run its tests -/// +/// /// @param test_filename the test file filename /// @param total_tests the total tests nb /// @param total_tests_failed the total failed tests nb diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 799a818..392e358 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -8,9 +8,9 @@ long program::cmp_strings_on_stack_top() { // _stack sould have 2 strings at level 1 and 2 // this function removes these 2 entries - long res = (long)static_cast(_stack->at(0))->_value.compare(static_cast(_stack->at(1))->_value); - (void)_stack->pop_back(); - (void)_stack->pop_back(); + long res = (long)static_cast(_stack->at(0))->value.compare(static_cast(_stack->at(1))->value); + (void)_stack->pop_front(); + (void)_stack->pop_front(); return res; } @@ -21,17 +21,17 @@ void program::rpn_sup(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) > 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) > 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -43,17 +43,17 @@ void program::rpn_sup_eq(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) >= 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) >= 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -65,17 +65,17 @@ void program::rpn_inf(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) < 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) < 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -87,17 +87,17 @@ void program::rpn_inf_eq(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) <= 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) <= 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -109,28 +109,23 @@ void program::rpn_diff(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) != 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) != 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // complexes else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - bool diff = false; - ocomplex* right = (ocomplex*)_stack->pop_back(); - ocomplex* left = (ocomplex*)_stack->pop_back(); - - if (mpfr_cmp(left->re()->mpfr_ptr(), right->re()->mpfr_ptr()) != 0 || mpfr_cmp(left->im()->mpfr_ptr(), right->im()->mpfr_ptr()) != 0) - diff = true; - - _stack->push_back(new number(diff?1L:0L)); + ocomplex* right = (ocomplex*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->pop_front(); + _stack->push_front(new number(left->value != right->value?1L:0L)); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -142,28 +137,23 @@ void program::rpn_eq(void) { // numbers if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp(left->_value.mpfr_ptr(), right->_value.mpfr_ptr()) == 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) == 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } // complexes else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - bool diff = false; - ocomplex* right = (ocomplex*)_stack->pop_back(); - ocomplex* left = (ocomplex*)_stack->pop_back(); - - if (mpfr_cmp(left->re()->mpfr_ptr(), right->re()->mpfr_ptr()) != 0 || mpfr_cmp(left->im()->mpfr_ptr(), right->im()->mpfr_ptr()) != 0) - diff = true; - - _stack->push_back(new number(diff?0L:1L)); + ocomplex* right = (ocomplex*)_stack->pop_front(); + ocomplex* left = (ocomplex*)_stack->pop_front(); + _stack->push_front(new number(left->value == right->value?1L:0L)); } // strings else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) - _stack->push_back(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top())); else ERR_CONTEXT(ret_bad_operand_type); } @@ -175,13 +165,13 @@ void program::rpn_test_and(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if ((mpfr_cmp_si(left->_value.mpfr_ptr(), 0) != 0) && (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0)) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if ((mpfr_cmp_si(left->value.mpfr_ptr(), 0) != 0) && (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0)) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } /// @brief or keyword implementation @@ -191,13 +181,13 @@ void program::rpn_test_or(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if ((mpfr_cmp_si(left->_value.mpfr_ptr(), 0) != 0) || (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0)) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if ((mpfr_cmp_si(left->value.mpfr_ptr(), 0) != 0) || (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0)) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } /// @brief xor keyword implementation @@ -207,19 +197,19 @@ void program::rpn_test_xor(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_back(); + number* right = (number*)_stack->pop_front(); number* left = (number*)_stack->back(); - if (mpfr_cmp_si(left->_value.mpfr_ptr(), 0) == 0) { - if (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) != 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp_si(left->value.mpfr_ptr(), 0) == 0) { + if (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } else { - if (mpfr_cmp_si(right->_value.mpfr_ptr(), 0) == 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp_si(right->value.mpfr_ptr(), 0) == 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } } @@ -230,10 +220,10 @@ void program::rpn_test_not(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); number* left = (number*)_stack->back(); - if (mpfr_cmp_si(left->_value.mpfr_ptr(), 0) == 0) - mpfr_set_si(left->_value.mpfr_ptr(), 1, number::s_mpfr_rnd); + if (mpfr_cmp_si(left->value.mpfr_ptr(), 0) == 0) + mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); else - mpfr_set_si(left->_value.mpfr_ptr(), 0, number::s_mpfr_rnd); + mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); } /// @brief test same implementation diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index 65dcc4a..b30f503 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -20,9 +20,9 @@ void program::rpn_time() { // push it number* num; - _stack->push_back(num = static_cast(new number(date))); + _stack->push_front(num = static_cast(new number(date))); // division is done here because of real precision) - CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 10000000000.0, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 10000000000.0, mpreal::get_default_rnd())); } else ERR_CONTEXT(ret_internal); } @@ -44,9 +44,9 @@ void program::rpn_date() { // push it number* num; - _stack->push_back(num = static_cast(new number(date))); + _stack->push_front(num = static_cast(new number(date))); // division is done here because of real precision) - CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 1000000.0, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 1000000.0, mpreal::get_default_rnd())); } else ERR_CONTEXT(ret_internal); } @@ -67,7 +67,7 @@ void program::rpn_ticks() { date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); // push it - _stack->push_back(static_cast(new number(date))); + _stack->push_front(static_cast(new number(date))); } else ERR_CONTEXT(ret_internal); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 9bf7acb..1088797 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -4,8 +4,8 @@ /// void program::rpn_pi(void) { number* pi; - _stack->push_back(pi = static_cast(new number)); - CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, floating_t::s_mpfr_rnd)); + _stack->push_front(pi = static_cast(new number)); + CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, mpreal::get_default_rnd())); } /// @brief d->r keyword implementation @@ -17,11 +17,11 @@ void program::rpn_d2r(void) { // add pi on stack rpn_pi(); - floating_t* pi = &((number*)_stack->pop_back())->_value; + floating_t* pi = &((number*)_stack->pop_front())->_value; floating_t* left = &((number*)_stack->at(0))->_value; - 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)); + CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, mpreal::get_default_rnd())); } /// @brief r->d keyword implementation @@ -33,11 +33,11 @@ void program::rpn_r2d(void) { // add pi on stack rpn_pi(); - floating_t* pi = &((number*)_stack->pop_back())->_value; + floating_t* pi = &((number*)_stack->pop_front())->_value; floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, 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, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, mpreal::get_default_rnd())); } /// @brief sin keyword implementation @@ -47,13 +47,13 @@ void program::rpn_sin(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); number* num = static_cast(new number); - _stack->push_back(num); + _stack->push_front(num); floating_t* tmp = &num->_value; floating_t* x = ((complex*)_calc_stack.at(1))->re(); floating_t* y = ((complex*)_calc_stack.at(1))->im(); @@ -61,15 +61,15 @@ void program::rpn_sin(void) { floating_t* re = ((complex*)_stack->at(0))->re(); floating_t* im = ((complex*)_stack->at(0))->im(); - CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -81,34 +81,34 @@ void program::rpn_asin(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { number* num; complex* i; // asin(z)=-iln(iz+sqrt(1-z*z)) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); i = (complex*)_calc_stack.at(0); - CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, mpreal::get_default_rnd())); rpn_dup(); rpn_square(); - _stack->push_back(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = static_cast(new number)); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_minus(); rpn_neg(); rpn_squareroot(); rpn_swap(); - rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); rpn_mul(); rpn_plus(); rpn_ln(); - rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); rpn_mul(); rpn_neg(); - _calc_stack.pop_back(); + _calc_stack.pop_front(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -120,13 +120,13 @@ void program::rpn_cos(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); number* num = static_cast(new number); - _stack->push_back(num); + _stack->push_front(num); floating_t* tmp = &num->_value; floating_t* x = ((complex*)_calc_stack.at(1))->re(); floating_t* y = ((complex*)_calc_stack.at(1))->im(); @@ -134,16 +134,16 @@ void program::rpn_cos(void) { floating_t* re = ((complex*)_stack->at(0))->re(); floating_t* im = ((complex*)_stack->at(0))->im(); - CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -155,14 +155,14 @@ void program::rpn_acos(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // acos(z)=pi/2-asin(z) rpn_asin(); rpn_pi(); number* num; - _stack->push_back(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = static_cast(new number)); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); rpn_div(); rpn_minus(); rpn_neg(); @@ -177,13 +177,13 @@ void program::rpn_tan(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { // tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); number* num = static_cast(new number); - _stack->push_back(num); + _stack->push_front(num); floating_t* tmp = &num->_value; floating_t* x = ((complex*)_calc_stack.at(1))->re(); floating_t* y = ((complex*)_calc_stack.at(1))->im(); @@ -192,24 +192,24 @@ void program::rpn_tan(void) { floating_t* im = ((complex*)_stack->at(0))->im(); // x->2x - CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, mpreal::get_default_rnd())); // y->2y - CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, mpreal::get_default_rnd())); // sin(2x)+sinh(2y) - CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, mpreal::get_default_rnd())); // cosh(2y)+cos(2x) - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, mpreal::get_default_rnd())); // sin(2x)+sinh(2y) / (cosh(2y)+cos(2x)) - CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_back(2); + _calc_stack.pop_front(2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -221,37 +221,37 @@ void program::rpn_atan(void) { if (_stack->at(0)->_type == cmd_number) { floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { number* num; complex* i; // atan(z)=0.5i(ln((1-iz)/(1+iz)) - rpnstack::copy_and_push_back(*_stack, _stack->size() - 1, _calc_stack); + rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); i = (complex*)_calc_stack.at(0); - CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, floating_t::s_mpfr_rnd)); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, floating_t::s_mpfr_rnd)); + CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, mpreal::get_default_rnd())); + CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, mpreal::get_default_rnd())); - rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); + rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); rpn_mul(); - _stack->push_back(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = static_cast(new number)); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); rpn_minus(); // iz-1 rpn_neg(); // 1-iz rpn_dup(); rpn_neg(); // iz-1 - _stack->push_back(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, floating_t::s_mpfr_rnd)); + _stack->push_front(num = static_cast(new number)); + CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); rpn_plus(); // iz+1 rpn_div(); rpn_ln(); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, floating_t::s_mpfr_rnd)); - rpnstack::copy_and_push_back(_calc_stack, 0, *_stack); + CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, mpreal::get_default_rnd())); + rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); rpn_mul(); - _calc_stack.pop_back(); + _calc_stack.pop_front(); } else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/src/stack.hpp b/src/stack.hpp index 8d0d065..831a809 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -23,29 +23,39 @@ class rpnstack : public deque { /// @param index_from index t ocopy from /// @param to copy to /// - static void copy_and_push_back(rpnstack& from, unsigned int index_from, rpnstack& to) { - to.push_back(from[index_from]); - } - static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { to.push_front(from[index_from]); } + /// @brief erase a stack entry from it index + /// + /// @param first index to start + /// @param last index to stop + /// + void del(int first = 0, int last = -1) { + if (size() >0) { + if (last == -1) + erase(begin() + first); + else if (last >= first) + erase(begin() + first, begin() + last + 1); // carefull, deque::erase doesn't include the last element + } + } + /// @brief pop back several entries /// /// @param levels nb of entries /// - void pop_back(int levels) { - for (int i = 0; i < levels; i++) deque::pop_back(); + void pop_front(int levels) { + for (int i = 0; i < levels; i++) deque::pop_front(); } /// @brief pop back 1 entry /// /// @return retrieved object /// - object* pop_back() { - object* o = back(); - pop_back(1); + object* pop_front() { + object* o = front(); + pop_front(1); return o; } }; diff --git a/src/version.h b/src/version.h index 83f9054..f84606b 100644 --- a/src/version.h +++ b/src/version.h @@ -1,22 +1,23 @@ // version and soft name -#define RPN_VERSION "2.3.2" -static const char version[] = RPN_VERSION; -static const char uname[] = "rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3\n"; +#define RPN_VERSION "2.4" +static const string version{RPN_VERSION}; +static const string uname{"rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3"}; -#define STRINGIFY(a) STRINGIFY_ONE(a) -#define STRINGIFY_ONE(a) #a +#define XSTR(a) STR(a) +#define STR(a) #a // description -static const char description[] = ATTR_BOLD - "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF - "otation language\n\n" - "using " ATTR_BOLD "GMP" ATTR_OFF - " v" STRINGIFY(__GNU_MP_VERSION) "." STRINGIFY(__GNU_MP_VERSION_MINOR) "." STRINGIFY( - __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING - " under GNU LGPL\n" - "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION " under BSD\n"; +static const string description{ + ATTR_BOLD "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF + "otation language\n\n" + "using " ATTR_BOLD "GMP" ATTR_OFF + " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( + __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING + " under GNU LGPL\n" + "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION + " under BSD\n"}; // syntax -static const char syntax[] = ATTR_BOLD "Syntax" ATTR_OFF - ": rpn [command]\n" - "with optional command = list of commands"; +static const string syntax{ATTR_BOLD "Syntax" ATTR_OFF + ": rpn [command]\n" + "with optional command = list of commands"}; diff --git a/test/02-general.txt b/test/02-general.txt deleted file mode 100644 index efa0822..0000000 --- a/test/02-general.txt +++ /dev/null @@ -1,49 +0,0 @@ -## GENERAL -default del - -# version -version --> stack size should be 1 -del - -uname --> stack size should be 1 -del - -# type (1) -1 type --> stack should be "number" -del - -# type (2) -"hey" type --> stack should be "string" -del - -# type (3) -<< -> n << n >> >> type --> stack should be "program" -del - -# type (4) -(1,2) type --> stack should be "complex" -del - -# type (5) -type --> error should be 2 -del - -# default -2 sci 1 --> stack should be 1.00e+00 -default --> stack should be 1 -del - -# nop -nop --> stack size should be 0 --> error should be 0 -del diff --git a/test/05-test.txt b/test/05-test.txt new file mode 100644 index 0000000..9ff416e --- /dev/null +++ b/test/05-test.txt @@ -0,0 +1,30 @@ +## TEST the test framwork +default del + +# testing the stack size 1 +-> stack size should be 0 + +# testing the stack size 2 +1 +-> stack size should be 1 +del +-> stack size should be 0 + +# testing the stack size 3 +1 2 3 4 5 +-> stack size should be 5 +del + +# testing stack +1 2 3 +-> stack should be 1, 2, 3 +del +-> stack should be + +# testing error 1 +del +-> error should be 0 + +# testing error 2 +drop +-> error should be 2 diff --git a/test/01-mode.txt b/test/10-mode.txt similarity index 100% rename from test/01-mode.txt rename to test/10-mode.txt diff --git a/test/10-complex.txt b/test/100-complex.txt similarity index 100% rename from test/10-complex.txt rename to test/100-complex.txt diff --git a/test/12-time.txt b/test/120-time.txt similarity index 100% rename from test/12-time.txt rename to test/120-time.txt diff --git a/test/20-general.txt b/test/20-general.txt new file mode 100644 index 0000000..7807b33 --- /dev/null +++ b/test/20-general.txt @@ -0,0 +1,24 @@ +## GENERAL +default del + +# version +version +-> stack size should be 1 +del + +uname +-> stack size should be 1 +del + +# default +2 sci 1 +-> stack should be 1.00e+00 +default +-> stack should be 1 +del + +# nop +nop +-> stack size should be 0 +-> error should be 0 +del diff --git a/test/21-parse-string.txt b/test/21-parse-string.txt new file mode 100644 index 0000000..0249e41 --- /dev/null +++ b/test/21-parse-string.txt @@ -0,0 +1,62 @@ +## PARSE STRING +default del + +# type +"hey" type +-> stack should be "string" +del + +# void 1 +"" +-> stack should be "" +del + +# void 2 +" +-> stack should be "" +del + +# string +"abcd" +-> stack should be "abcd" +del + +# unterminated +"abcd +-> stack should be "abcd" +del + +# unterminated 2 +"abcd" "abc +-> stack should be "abcd", "abc" +del + +# spaces +"abc d" +-> stack should be "abc d" +del + +# spaces 2 +" abcd " +-> stack should be " abcd " +del + +# spaces 3 +" abcd " "def" "gh ij" +-> stack should be " abcd ", "def", "gh ij" +del + +# spaces 4 +" . abcd . ;; " +-> stack should be " . abcd . ;; " +del + +# spaces 5 +" . abcd . ;; " "ab c +-> stack should be " . abcd . ;; ", "ab c" +del + +# nested types +"1.0 swap drop +-> stack should be "1.0 swap drop" +del diff --git a/test/22-parse-symbol.txt b/test/22-parse-symbol.txt new file mode 100644 index 0000000..01a6ee9 --- /dev/null +++ b/test/22-parse-symbol.txt @@ -0,0 +1,67 @@ +## PARSE SYMBOL +default del + +# type +'hey' type +-> stack should be "symbol" +del + +# void 1 +'' +-> stack should be '' +del + +# void 2 +' +-> stack should be '' +del + +# symbol +'abcd' +-> stack should be 'abcd' +del + +# unterminated +'abcd +-> stack should be 'abcd' +del + +# unterminated 2 +'abcd' 'abc +-> stack should be 'abcd', 'abc' +del + +# spaces +'abc d' +-> stack should be 'abc d' +del + +# spaces 2 +' abcd ' +-> stack should be ' abcd ' +del + +# spaces 3 +' abcd ' 'def' 'gh ij' +-> stack should be ' abcd ', 'def', 'gh ij' +del + +# spaces 4 +' . abcd . ;; ' +-> stack should be ' . abcd . ;; ' +del + +# spaces 5 +' . abcd . ;; ' 'ab c +-> stack should be ' . abcd . ;; ', 'ab c' +del + +# nested types 1 +'1' +-> stack should be '1' +del + +# nested types 2 +'1.0 swap drop +-> stack should be '1.0 swap drop' +del diff --git a/test/23-parse-number.txt b/test/23-parse-number.txt new file mode 100644 index 0000000..fde5c19 --- /dev/null +++ b/test/23-parse-number.txt @@ -0,0 +1,47 @@ +## PARSE NUMBER +default del + +# type +1.0 type +-> stack should be "number" +del + +# numb 1 +3.14 +3.14 -3.14 +-> stack should be 3.14, 3.14, -3.14 +del + +# spaces + -3.14 -3 .14 +-> stack should be -3.14, -3, 0.14 +del + +# exp entry ++3.14e2 +-> stack should be 314 +del + +# inf nan ++inf inf -inf nan +-> stack should be inf, inf, -inf, nan +del + +# hex +0x10 0X10 +-> stack should be 16, 16 +del + +# hex err +0x 0X +-> stack should be '0x', '0X' +del + +# bin +0b1101 0b0 +-> stack should be 13, 0 +del + +# bin err +0b +-> stack should be '0b' +del diff --git a/test/24-parse-complex.txt b/test/24-parse-complex.txt new file mode 100644 index 0000000..cd0551a --- /dev/null +++ b/test/24-parse-complex.txt @@ -0,0 +1,40 @@ +## PARSE COMPLEX +default del + +# type +(1,2) type +-> stack should be "complex" +del + +# cplx +(1,2) (1, 2) ( 1 , 2 ) +-> stack should be (1,2), (1,2), (1,2) +del + +# cplx inf nan +(inf,3) +(-inf,nan) (inf,-inf) +-> stack should be (inf,3), (-inf,nan), (inf,-inf) +del + +# unterminated +( 3.14e2 , -2 +-> stack should be (314,-2) +del + +# unterminated 2 +(-inf, nan +-> stack should be (-inf,nan) +del + +# unterminated err +( +(a +(123 +(, +(,) +(12, +(,13) +(,3.14 +-> stack should be '(', '(a', '(123', '(,', '(,)', '(12,', '(,13)', '(,3.14' +del diff --git a/test/25-parse-other.txt b/test/25-parse-other.txt new file mode 100644 index 0000000..b532ee5 --- /dev/null +++ b/test/25-parse-other.txt @@ -0,0 +1,19 @@ +## PARSE COMPLEX +default del + +# some command ++ +-> error should be 2 +del + +# some command 2 + + +-> error should be 2 +del + +# some command 3 + + - +-> error should be 2 +del + +# TODO test all keywords with errors diff --git a/test/26-parse-program.txt b/test/26-parse-program.txt new file mode 100644 index 0000000..4469536 --- /dev/null +++ b/test/26-parse-program.txt @@ -0,0 +1,53 @@ +## PARSE SYMBOL +default del + +# type +<< I >> type +-> stack should be "program" +del + +# prog 1 +<< I am a program >> +-> stack should be «I am a program» +del + +# prog 2 +<> +-> stack should be «I am a program» +del + +# prog 3 +<< I am a program >> +-> stack should be «I am a program» +del + +# prog 4 +«I am a program» +-> stack should be «I am a program» +del + +# prog 5 +« I am a program » +-> stack should be «I am a program» +del + +# unterminated 1 +<< prog +-> stack should be «prog» +del + +# unterminated 2 +« prog +-> stack should be «prog» +del + +# unterminated 3 +<< prog> +-> stack should be «prog>» +del + +# unterminated 4 +<< +« +-> stack should be «», «» +del diff --git a/test/11-base-entry.txt b/test/27-base-entry.txt similarity index 100% rename from test/11-base-entry.txt rename to test/27-base-entry.txt diff --git a/test/03-branch.txt b/test/30-branch.txt similarity index 100% rename from test/03-branch.txt rename to test/30-branch.txt diff --git a/test/04-stack.txt b/test/40-stack.txt similarity index 69% rename from test/04-stack.txt rename to test/40-stack.txt index 282ce25..a19d1d0 100644 --- a/test/04-stack.txt +++ b/test/40-stack.txt @@ -74,13 +74,8 @@ del -> stack should be 2, 3, 1 del -# test rot with start -5 6 7 1 2 start rot next --> stack should be 7, 5, 6 -del - -# test rot with next -5 6 7 1 2 for i rot next +# test rot 2 +5 6 7 rot rot -> stack should be 7, 5, 6 del @@ -109,7 +104,7 @@ erase # test erase -> stack size should be 0 -del +erase # test del 1 2 3 4 5 @@ -120,13 +115,13 @@ del 1 2 2 dropn -> stack size should be 0 del - + # test dropn error 1 2 3 dropn -> stack size should be 3 -> error should be 2 del - + # test dupn 1 2 3 4 3 dupn -> stack should be 1, 2, 3, 4, 2, 3, 4 @@ -143,40 +138,40 @@ del -> stack should be 1, 3, 4, 5, 2 del -# test roll with filled stack -10 11 1 2 3 4 5 4 roll --> stack should be 10, 11, 1, 3, 4, 5, 2 -del - -# test roll error -1 2 3 4 5 6 roll --> stack size should be 6 --> error should be 2 -del - -# test rolld -10 20 30 40 50 3 rolld --> stack should be 10, 20, 50, 30, 40 -del - -# test rolld with filled stack -80 90 10 20 30 40 50 3 rolld --> stack should be 80, 90, 10, 20, 50, 30, 40 -del - -# test rolld error -1 2 3 4 5 6 rolld --> stack size should be 6 --> error should be 2 -del - -# test over -3.14 15.16 over --> stack should be 3.14, 15.16, 3.14 -del - -# test over error -2 over --> stack size should be 1 --> error should be 2 -del +# # test roll with filled stack +# 10 11 1 2 3 4 5 4 roll +# -> stack should be 10, 11, 1, 3, 4, 5, 2 +# del +# +# # test roll error +# 1 2 3 4 5 6 roll +# -> stack size should be 6 +# -> error should be 2 +# del +# +# # test rolld +# 10 20 30 40 50 3 rolld +# -> stack should be 10, 20, 50, 30, 40 +# del +# +# # test rolld with filled stack +# 80 90 10 20 30 40 50 3 rolld +# -> stack should be 80, 90, 10, 20, 50, 30, 40 +# del +# +# # test rolld error +# 1 2 3 4 5 6 rolld +# -> stack size should be 6 +# -> error should be 2 +# del +# +# # test over +# 3.14 15.16 over +# -> stack should be 3.14, 15.16, 3.14 +# del +# +# # test over error +# 2 over +# -> stack size should be 1 +# -> error should be 2 +# del diff --git a/test/05-real.txt b/test/50-real.txt similarity index 100% rename from test/05-real.txt rename to test/50-real.txt diff --git a/test/06-string.txt b/test/60-string.txt similarity index 100% rename from test/06-string.txt rename to test/60-string.txt diff --git a/test/07-test.txt b/test/70-test.txt similarity index 100% rename from test/07-test.txt rename to test/70-test.txt diff --git a/test/08-store.txt b/test/80-store.txt similarity index 100% rename from test/08-store.txt rename to test/80-store.txt diff --git a/test/09-program.txt b/test/90-program.txt similarity index 100% rename from test/09-program.txt rename to test/90-program.txt diff --git a/test/99-manual-tests.txt b/test/999-manual-tests.txt similarity index 100% rename from test/99-manual-tests.txt rename to test/999-manual-tests.txt diff --git a/test/all.txt b/test/all.txt index 7d9e2d8..94ace3f 100644 --- a/test/all.txt +++ b/test/all.txt @@ -1,13 +1,20 @@ -#include 01-mode.txt -#include 02-general.txt -#include 03-branch.txt -#include 04-stack.txt -#include 05-real.txt -#include 06-string.txt -#include 07-test.txt -#include 08-store.txt -#include 09-program.txt -#include 10-complex.txt -#include 11-base-entry.txt -#include 12-time.txt -#include 99-manual-tests.txt +#include 10-mode.txt +#include 20-general.txt +#include 21-parse-string.txt +#include 22-parse-symbol.txt +#include 23-parse-number.txt +#include 24-parse-complex.txt +#include 25-parse-other.txt +#include 26-parse-program.txt +#include 27-base-entry.txt +#include 30-branch.txt +#include 40-stack.txt +#include 50-real.txt +#include 60-string.txt +#include 70-test.txt +#include 80-store.txt +#include 90-program.txt +#include 100-complex.txt +#include 110-base-entry.txt +#include 120-time.txt +#include 999-manual-tests.txt From dc758483e5324d32d25a4b1724c8fd28db05ceaa Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 12 Feb 2022 19:11:22 +0100 Subject: [PATCH 05/57] refactoring tests --- src/.clang-format | 12 +- src/constant.h | 2 - src/main.cpp | 11 +- src/object.cpp | 7 +- src/object.hpp | 122 +- src/program.cpp | 29 +- src/program.hpp | 49 +- src/rpn-general.cpp | 22 +- src/rpn-real.cpp | 306 ++--- src/rpn-store.cpp | 9 +- src/rpn-test-core.cpp | 102 +- src/stack.hpp | 48 +- test/005-test-framework.md | 47 + test/010-mode.md | 75 + test/{20-general.txt => 020-general.md} | 47 +- test/021-parse-string.md | 101 ++ test/022-parse-symbol.md | 107 ++ test/023-parse-number.md | 75 + ...parse-complex.txt => 024-parse-complex.md} | 59 +- test/025-parse-other.md | 27 + test/026-parse-program.md | 86 ++ test/{27-base-entry.txt => 027-base-entry.md} | 345 +++-- test/030-branch.md | 637 +++++++++ test/040-stack.md | 289 ++++ test/05-test.txt | 30 - test/050-real.md | 753 ++++++++++ test/060-string.md | 307 +++++ test/{70-test.txt => 070-test.md} | 652 ++++++--- test/080-store.md | 377 +++++ test/090-program.md | 93 ++ test/10-mode.txt | 47 - test/100-complex.md | 1208 +++++++++++++++++ test/100-complex.txt | 758 ----------- test/{120-time.txt => 110-time.md} | 50 +- test/21-parse-string.txt | 62 - test/22-parse-symbol.txt | 67 - test/23-parse-number.txt | 47 - test/25-parse-other.txt | 19 - test/26-parse-program.txt | 53 - test/30-branch.txt | 397 ------ test/40-stack.txt | 177 --- test/50-real.txt | 470 ------- test/60-string.txt | 213 --- test/80-store.txt | 226 --- test/90-program.txt | 56 - test/999-manual-tests.md | 61 + test/999-manual-tests.txt | 41 - test/all.md | 22 + test/all.txt | 20 - 49 files changed, 5418 insertions(+), 3402 deletions(-) create mode 100644 test/005-test-framework.md create mode 100644 test/010-mode.md rename test/{20-general.txt => 020-general.md} (50%) create mode 100644 test/021-parse-string.md create mode 100644 test/022-parse-symbol.md create mode 100644 test/023-parse-number.md rename test/{24-parse-complex.txt => 024-parse-complex.md} (56%) create mode 100644 test/025-parse-other.md create mode 100644 test/026-parse-program.md rename test/{27-base-entry.txt => 027-base-entry.md} (60%) create mode 100644 test/030-branch.md create mode 100644 test/040-stack.md delete mode 100644 test/05-test.txt create mode 100644 test/050-real.md create mode 100644 test/060-string.md rename test/{70-test.txt => 070-test.md} (50%) create mode 100644 test/080-store.md create mode 100644 test/090-program.md delete mode 100644 test/10-mode.txt create mode 100644 test/100-complex.md delete mode 100644 test/100-complex.txt rename test/{120-time.txt => 110-time.md} (50%) delete mode 100644 test/21-parse-string.txt delete mode 100644 test/22-parse-symbol.txt delete mode 100644 test/23-parse-number.txt delete mode 100644 test/25-parse-other.txt delete mode 100644 test/26-parse-program.txt delete mode 100644 test/30-branch.txt delete mode 100644 test/40-stack.txt delete mode 100644 test/50-real.txt delete mode 100644 test/60-string.txt delete mode 100644 test/80-store.txt delete mode 100644 test/90-program.txt create mode 100644 test/999-manual-tests.md delete mode 100644 test/999-manual-tests.txt create mode 100644 test/all.md delete mode 100644 test/all.txt diff --git a/src/.clang-format b/src/.clang-format index 486aeb0..26fd6a7 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -1,3 +1,9 @@ -BasedOnStyle: Google -IndentWidth: '4' -ColumnLimit: 120 \ No newline at end of file +--- +BasedOnStyle: LLVM +IndentWidth: 4 +--- +Language: Cpp +# Force pointers to the type for C++. +DerivePointerAlignment: false +PointerAlignment: Left +ColumnLimit: 120 diff --git a/src/constant.h b/src/constant.h index 6388a9d..b150109 100644 --- a/src/constant.h +++ b/src/constant.h @@ -79,8 +79,6 @@ typedef enum { // command types // -#define CMD_TYPE_STRINGS \ - { "undef", "number", "complex", "string", "symbol", "program", "keyword", "keyword" } // history #define HISTORY_FILE ".rpn_history" diff --git a/src/main.cpp b/src/main.cpp index 99953d1..e577899 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -30,6 +30,7 @@ void exit_interactive_rpn() { // save it if (linenoiseHistorySave(history_path) != 0) fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno)); + linenoiseHistoryFree(); } } @@ -48,7 +49,7 @@ void init_interactive_rpn() { } /// @brief handle CtrlC signal (sigaction handler): exit rpn -/// +/// /// @param sig signal, see POSIX sigaction /// @param siginfo signal info, see POSIX sigaction /// @param context see POSIX sigaction @@ -63,7 +64,7 @@ static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { } /// @brief handle SIGSEGV signal (sigaction handler): stop and exit rpn -/// +/// /// @param sig signal, see POSIX sigaction /// @param siginfo signal info, see POSIX sigaction /// @param context see POSIX sigaction @@ -75,11 +76,11 @@ static void segv_handler(int sig, siginfo_t* siginfo, void* context) { } /// @brief setup signals handlers to stop with honours -/// +/// /// @param prog the prog to catch the signals to, must be checked not NULL by user /// static void catch_signals(program* prog) { - struct sigaction act; + struct sigaction act = {0}; s_prog_to_interrupt = prog; @@ -95,7 +96,7 @@ static void catch_signals(program* prog) { } /// @brief rpn entry point -/// +/// /// @param argc command line args nb /// @param argv command line args nb /// @return int 0=ok diff --git a/src/object.cpp b/src/object.cpp index fd9192a..25126ee 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -13,9 +13,6 @@ using namespace std; number::mode_enum number::s_mode = DEFAULT_MODE; int number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; -// -const char* object::s_cmd_type_string[cmd_max] = CMD_TYPE_STRINGS; - #if 0 /// @brief return if a mpfr is higher to a given precision /// this function is directly copied from mpfr @@ -166,7 +163,7 @@ void object::show(FILE* stream) { switch (_type) { case cmd_number: - switch (((number*)this)->_representation) { + switch (((number*)this)->repr) { case number::dec: mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr); break; @@ -186,7 +183,7 @@ void object::show(FILE* stream) { } break; case cmd_complex: - switch (((complex*)this)->_representation) { + switch (((complex*)this)->repr) { case number::dec: fprintf(stream, "("); mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr); diff --git a/src/object.hpp b/src/object.hpp index a2349da..c9401e3 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -4,6 +4,7 @@ #include using namespace mpfr; +#include #include #include #include @@ -13,13 +14,13 @@ using namespace std; /// typedef enum { cmd_undef, - cmd_number, // floating point number - cmd_complex, // complex, couple of floating point numbers - cmd_string, // string like "string" - cmd_symbol, // symbol like 'symbol' - cmd_program, // program like << instructions >> - cmd_keyword, // langage keyword - cmd_branch, // langage branch keyword + cmd_number, // floating point number + cmd_complex, // complex, couple of floating point numbers + cmd_string, // string like "string" + cmd_symbol, // symbol like 'symbol' + cmd_program, // program like << instructions >> + cmd_keyword, // langage keyword + cmd_branch, // langage branch keyword cmd_max } cmd_type_t; @@ -33,55 +34,50 @@ typedef int (program::*branch_fn_t)(branch&); /// struct object { object(cmd_type_t type = cmd_undef) : _type(type) {} - // object type + virtual ~object() {} cmd_type_t _type; - // - auto duplicate() { return *new decltype(this); } + virtual object* clone() { + object* o = new object(); + if (o != nullptr) + *o = *this; + return o; + } + virtual string name() { return string("object"); } virtual void show(ostream& out) { out << "(" << name() << " - unknown representation)"; } unsigned int size() { return sizeof(*this); } - - // - static const char* s_cmd_type_string[cmd_max]; }; /// @brief stack objects derived from object /// struct number : object { typedef enum { dec, hex, bin, base } repr_enum; - number(repr_enum representation = dec) : object(cmd_number), _representation(representation) { value = 0L; } - number(mpreal& value_, repr_enum representation = dec) : number(representation) { value = value_; } - number(long value_, repr_enum representation = dec) : number(representation) { value = value_; } - number(unsigned long value_, repr_enum representation = dec) : number(representation) { value = value_; } - number(double value_, repr_enum representation = dec) : number(representation) { value = value_; } - - repr_enum _representation; - int _base; // carefull: _base is used only if _representation = base + number(repr_enum repr_ = dec, int base_ = 10) : object(cmd_number), repr(repr_), _base(base_) {} + number(mpreal& value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } + number(long value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } + number(unsigned long value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } + number(double value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } + repr_enum repr; + int _base; // carefull: _base is used only if repr = base mpreal value; - void set(unsigned long value_) { value = value_; } - + virtual object* clone() { return new number(this->value, repr, _base); } virtual string name() { return string("number"); } virtual void show(ostream& out) { - if (_representation != number::dec) { - object::show(out); - return; - } switch (number::s_mode) { - case number::std: - out.unsetf(ios::floatfield); - out << setprecision(s_decimal_digits) << value; - break; - case number::fix: - out << fixed << setprecision(s_decimal_digits) << value; - break; - case number::sci: - out << scientific << setprecision(s_decimal_digits) << value; - break; - default: - object::show(out); - break; + case number::std: // std + precision + base + out << value; + break; + case number::fix: // fixed + precision + base + out << fixed << setprecision(s_decimal_digits) << value; + break; + case number::sci: // sci + precision + out << scientific << setprecision(s_decimal_digits) << value; + break; + default: + object::show(out); + break; } } @@ -96,35 +92,41 @@ struct number : object { /// @brief stack objects derived from object /// struct ocomplex : object { - number::repr_enum _representation; - ocomplex() : object(cmd_complex) {} - ocomplex(mpreal& re_, mpreal& im_) : object(cmd_complex) { + ocomplex(number::repr_enum repr_ = number::dec, int base_ = 10) : object(cmd_complex), repr(repr_), _base(base_) {} + ocomplex(complex& value_, number::repr_enum repr_ = number::dec, int base_ = 10) : ocomplex(repr_, base_) { + value = value_; + } + ocomplex(mpreal& re_, mpreal& im_, number::repr_enum repr_ = number::dec, int base_ = 10) : ocomplex(repr_, base_) { value.real(re_); value.imag(im_); } + + number::repr_enum repr; + int _base; complex value; + + virtual object* clone() { return new ocomplex(this->value, repr, _base); } virtual string name() { return string("complex"); } virtual void show(ostream& out) { - if (_representation != number::dec) { + if (repr != number::dec) { object::show(out); return; } switch (number::s_mode) { - case number::std: - out.unsetf(ios::floatfield); - out << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; - break; - case number::fix: - out << fixed << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() - << ")"; - break; - case number::sci: - out << scientific << setprecision(number::s_decimal_digits) << "(" << value.real() << "," - << value.imag() << ")"; - break; - default: - object::show(out); - break; + case number::std: + out.unsetf(ios::floatfield); + out << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; + break; + case number::fix: + out << fixed << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; + break; + case number::sci: + out << scientific << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() + << ")"; + break; + default: + object::show(out); + break; } } }; @@ -136,7 +138,7 @@ struct ostring : object { ostring(const string& value_) : object(cmd_string) { set(value_); } ostring(const char* value_) : object(cmd_string) { value = string(value_); } void set(const string& value_) { value = value_; } - virtual string name() { return string("complex"); } + virtual string name() { return string("string"); } virtual void show(ostream& out) { out << "\"" << value << "\""; } string value; }; diff --git a/src/program.cpp b/src/program.cpp index de2f8cd..6f15a4e 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -23,27 +23,24 @@ program::keyword_t program::s_keywords[] = { {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, {cmd_keyword, "+", &program::rpn_plus, "addition"}, {cmd_keyword, "-", &program::rpn_minus, "substraction"}, - {cmd_keyword, "chs", &program::rpn_neg, "negation"}, - {cmd_keyword, "neg", &program::rpn_neg, ""}, {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, {cmd_keyword, "/", &program::rpn_div, "division"}, {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, + {cmd_keyword, "chs", &program::rpn_neg, "negation"}, + {cmd_keyword, "neg", &program::rpn_neg, ""}, {cmd_keyword, "^", &program::rpn_power, "power"}, {cmd_keyword, "pow", &program::rpn_power, ""}, - // {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, + {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, // {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, // {cmd_keyword, "sqr", &program::rpn_square, ""}, // {cmd_keyword, "abs", &program::rpn_abs, "absolute value"}, - // {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"}, - // {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"}, - // {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, // {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"}, // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, // OPERATIONS ON REALS {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, - {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, - {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, + //{cmd_keyword, "%", &program::rpn_purcent, "purcent"}, + //{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, // {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, // {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, // {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, @@ -77,6 +74,9 @@ program::keyword_t program::s_keywords[] = { "+inf\", \"toward -inf\", \"away from zero\"] round"}, {cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default"}, {cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"}, + {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"}, + // {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"}, + // {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, // TESTS {cmd_undef, "", NULL, "\nTEST"}, @@ -237,16 +237,17 @@ ret_value program::run(rpnstack& stk, heap& hp) { // iterate commands for (int i = 0; (go_out == false) && (interrupt_now == false) && (i < (int)size());) { - switch ((cmd_type_t)(*this)[i]->_type) { + object* o = (*this)[i]; + switch (o->_type) { // could be an auto-evaluated symbol case cmd_symbol: - auto_rcl((symbol*)(*this)[i]); + auto_rcl((symbol*)o); i++; break; // a keyword case cmd_keyword: { - keyword* k = (keyword*)(*this)[i]; + keyword* k = (keyword*)o; // call the matching function (this->*(k->fn))(); switch (_err) { @@ -270,13 +271,14 @@ ret_value program::run(rpnstack& stk, heap& hp) { break; } i++; + delete o; break; } // a branch keyword case cmd_branch: { // call matching function - branch* b = (branch*)(*this)[i]; + branch* b = (branch*)o; int next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { case -1: @@ -291,13 +293,14 @@ ret_value program::run(rpnstack& stk, heap& hp) { i = next_cmd; // new direction break; } + delete o; break; } default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - stk.push_front((*this)[i]); + stk.push_front(o); i++; break; } diff --git a/src/program.hpp b/src/program.hpp index c1dc795..17cf5e9 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -283,51 +283,30 @@ class program : public deque { void rpn_ticks(); }; -// convinience macros for rpn_xx function +// clang-format off + +// convenience macros for rpn_xx function // carefull : some of these macros modify program flow -#define ERR_CONTEXT(err) \ - do { \ - _err = (err); \ - _err_context = __FUNCTION__; \ +#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(num) \ - do { \ - if (stack_size() < (num)) { \ - ERR_CONTEXT(ret_missing_operand); \ - return; \ - } \ +#define MIN_ARGUMENTS_RET(num, ret) do { \ + if (stack_size() < (num)) { ERR_CONTEXT(ret_missing_operand); return (ret); } \ } while (0) -#define MIN_ARGUMENTS_RET(num, ret) \ - do { \ - if (stack_size() < (num)) { \ - ERR_CONTEXT(ret_missing_operand); \ - return (ret); \ - } \ +#define ARG_MUST_BE_OF_TYPE(num, type) do { \ + if (_stack->at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } \ } while (0) -#define ARG_MUST_BE_OF_TYPE(num, type) \ - do { \ - if (_stack->at(num)->_type != (type)) { \ - ERR_CONTEXT(ret_bad_operand_type); \ - return; \ - } \ - } while (0) - -#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ - do { \ - if (_stack->at(num)->_type != (type)) { \ - ERR_CONTEXT(ret_bad_operand_type); \ - return (ret); \ - } \ +#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { \ + if (_stack->at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } \ } while (0) #define IS_ARG_TYPE(num, type) (_stack->at(num)->_type == (type)) -#define CHECK_MPFR(op) \ - do { \ - (void)(op); \ - } while (0) +#define CHECK_MPFR(op) do { (void)(op); } while (0) #endif diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 5d601f4..8d9a624 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -95,12 +95,13 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_front())->value); + double digits = double(_stack->value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::std; number::s_decimal_digits = (int)digits; + _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -111,12 +112,13 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_front())->value); + double digits = double(_stack->value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::fix; number::s_decimal_digits = (int)digits; + _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -127,12 +129,13 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(((number*)_stack->pop_front())->value); + double digits = double(_stack->value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::sci; number::s_decimal_digits = (int)digits; + _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -162,10 +165,8 @@ void program::rpn_history() { /// void program::rpn_type() { MIN_ARGUMENTS(1); - - int type = _stack->pop_front()->_type; - if (type < 0 || type >= (int)cmd_max) type = (int)cmd_undef; - _stack->push_front(new ostring(object::s_cmd_type_string[type])); + _stack->push(new ostring(_stack->at(0)->name())); + _stack->del(1); } /// @brief default keyword implementation @@ -179,7 +180,7 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - unsigned long prec = static_cast(_stack->pop_front())->value.toULong(); + unsigned long prec = _stack->value(0).toULong(); if (prec >= (unsigned long)MPFR_PREC_MIN && prec <= (unsigned long)MPFR_PREC_MAX) { mpreal::set_default_prec(prec); @@ -188,6 +189,7 @@ void program::rpn_precision() { // calc max nb of digits user can see with the current bit precision number::s_decimal_digits = bits2digits(mpreal::get_default_prec()); } + _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -200,10 +202,10 @@ void program::rpn_round() { map matchRound{MPFR_ROUND_STRINGS}; - auto found = matchRound.find(((ostring*)_stack->back())->value); + auto found = matchRound.find(_stack->value(0)); if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else ERR_CONTEXT(ret_out_of_range); - _stack->pop_front(); + _stack->pop(); } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index a05692b..92a3096 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -5,36 +5,31 @@ void program::rpn_plus() { MIN_ARGUMENTS(2); - // adding strings - if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) { - ostring* right = (ostring*)_stack->pop_front(); - ostring* left = (ostring*)_stack->front(); - left->value += right->value; + // strings + if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { + _stack->value(1) += _stack->value(0); + _stack->pop(); } - // adding numbers - else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->front(); - left->value += right->value; + // numbers + else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->value(1) += _stack->value(0); + _stack->pop(); } - // adding complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - ocomplex* right = (ocomplex*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->front(); - left->value += right->value; + // complexes + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->value(1) += _stack->value(0); + _stack->pop(); } - // adding complex+number - else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value += right->value; + // complex+number + else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { + _stack->value(1) += _stack->value(0); + _stack->pop(); } - // adding number+complex - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { + // number+complex + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value += right->value; + _stack->value(1) += _stack->value(0); + _stack->pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -44,30 +39,26 @@ void program::rpn_plus() { void program::rpn_minus() { MIN_ARGUMENTS(2); - // substracting numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - left->value -= right->value; + // numbers + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->value(1) -= _stack->value(0); + _stack->pop(); } - // substracting complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - ocomplex* right = (ocomplex*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value -= right->value; + // complexes + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->value(1) -= _stack->value(0); + _stack->pop(); } - // substracting complex-number - else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value -= right->value; + // subbing complex-number + else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { + _stack->value(1) -= _stack->value(0); + _stack->pop(); } - // substracting number-complex - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { + // number-complex + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value -= right->value; + _stack->value(1) = _stack->value(0) - _stack->value(1); + _stack->pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -77,30 +68,26 @@ void program::rpn_minus() { void program::rpn_mul() { MIN_ARGUMENTS(2); - // multiplying numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - left->value *= right->value; + // mutiplying numbers + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->value(1) *= _stack->value(0); + _stack->pop(); } - // multiplying complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - ocomplex* right = (ocomplex*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value *= right->value; + // mutiplying complexes + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->value(1) *= _stack->value(0); + _stack->pop(); } - // multiplying complex*number - else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value *= right->value; + // mutiplying complex*number + else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { + _stack->value(1) *= _stack->value(0); + _stack->pop(); } - // multiplying number*complex - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { + // mutiplying number*complex + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value *= right->value; + _stack->value(1) *= _stack->value(0); + _stack->pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -111,29 +98,25 @@ void program::rpn_div() { MIN_ARGUMENTS(2); // dividing numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - left->value /= right->value; + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->value(1) /= _stack->value(0); + _stack->pop(); } // dividing complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - left->value /= right->value; + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->value(1) /= _stack->value(0); + _stack->pop(); } // dividing complex/number - else if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_complex) { - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value /= right->value; + else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { + _stack->value(1) /= _stack->value(0); + _stack->pop(); } // dividing number/complex - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_number) { + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { rpn_swap(); - number* right = (number*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->back(); - left->value /= right->value; + _stack->value(1) = _stack->value(0) / _stack->value(1); + _stack->pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -143,13 +126,11 @@ void program::rpn_div() { void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - number* left = (number*)_stack->back(); - left->value = -left->value; - } else if (_stack->at(0)->_type == cmd_complex) { - ocomplex* left = (ocomplex*)_stack->back(); - left->value = -left->value; - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = -_stack->value(0); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = -_stack->value(0); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -158,12 +139,80 @@ void program::rpn_neg() { void program::rpn_inv() { MIN_ARGUMENTS(1); + if (_stack->type(0) == cmd_number) + _stack->value(0) = 1 / _stack->value(0); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = mpreal{1} / _stack->value(0); + else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief power keyword implementation +/// +void program::rpn_power() { + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->value(1) = pow(_stack->value(1), _stack->value(0)); + _stack->pop(); + } else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->value(1) = pow(_stack->value(1), _stack->value(0)); + _stack->pop(); + } else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { + _stack->value(1) = pow(_stack->value(1), _stack->value(0)); + _stack->pop(); + } else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + rpn_swap(); + _stack->value(1) = pow(_stack->value(0), _stack->value(1)); + _stack->pop(); + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief sqrt keyword implementation +/// +void program::rpn_squareroot() { + if (_stack->type(0) == cmd_number) { + if (_stack->value(0) >= 0) { + _stack->value(0) = rec_sqrt(_stack->value(0)); + } else { + // negative number -> square root is compl ex + _stack->push(new ocomplex);// TODO manage new errors + _stack->value(0) = sqrt(_stack->value(1)); + _stack->pop_front(1); + } + } else if (_stack->type(0) == cmd_complex) + _stack->value(0) = sqrt(_stack->value(0)); + else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief hex keyword implementation +/// +void program::rpn_hex() { + MIN_ARGUMENTS(1); + if (_stack->type(0) == cmd_number) + _stack->obj(0)->repr = number::hex; + else if (_stack->type(0) == cmd_complex) + _stack->obj(0)->repr = number::hex; + else { + ERR_CONTEXT(ret_bad_operand_type); + return; + } + number::s_decimal_digits = 0; +} + +#if 0 + +/// @brief sq keyword implementation +/// +void program::rpn_square() { + MIN_ARGUMENTS(1); + if (_stack->at(0)->_type == cmd_number) { number* left = (number*)_stack->back(); - left->value = 1 / left->value; + CHECK_MPFR(mpfr_sqr(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { - ocomplex* left = (ocomplex*)_stack->back(); - left->value = mpreal{1} / left->value; + rpn_dup(); + rpn_mul(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -192,66 +241,6 @@ void program::rpn_purcentCH() { left->value /= right->value; } -/// @brief power keyword implementation -/// -void program::rpn_power() { - MIN_ARGUMENTS(2); - bool done_on_real = false; - - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - // TODO pow seems not to be a friend of mpreal - //left->value.mpfr_ptr = pow(right->value); - mpfr_pow(left->value.mpfr_ptr(), left->value.mpfr_ptr(), right->value.mpfr_ptr(), mpreal::get_default_rnd()); - } else - ERR_CONTEXT(ret_bad_operand_type); - // TODO manage complex case -} - -#if 0 -/// @brief sqrt keyword implementation -/// -void program::rpn_squareroot() { - if (_stack->at(0)->_type == cmd_number) { - number* left = (number*)_stack->back(); - - if (left->value >= 0) - left->value = rec_sqrt(left->value); - else { - // negative number -> complex square root - _stack->push_front(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.0, mpreal::get_default_rnd())); - rpn_r2c(); - _stack->push_front(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.5, mpreal::get_default_rnd())); - rpn_power(); - } - } else if (_stack->at(0)->_type == cmd_complex) { - // calc cplx^0.5 - _stack->push_front(new number); - CHECK_MPFR(mpfr_set_d(((number*)_stack->back())->value.mpfr, 0.5, mpreal::get_default_rnd())); - rpn_power(); - } else - ERR_CONTEXT(ret_bad_operand_type); -} - -/// @brief sq keyword implementation -/// -void program::rpn_square() { - MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_sqr(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - rpn_dup(); - rpn_mul(); - } else - ERR_CONTEXT(ret_bad_operand_type); -} - /// @brief mod keyword implementation /// void program::rpn_modulo() { @@ -299,21 +288,12 @@ void program::rpn_abs() { ERR_CONTEXT(ret_bad_operand_type); } -/// @brief hex keyword implementation -/// -void program::rpn_hex() { - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::hex; - number::s_decimal_digits = 0; -} - /// @brief bin keyword implementation /// void program::rpn_bin() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::bin; + ((number*)_stack->back())->repr = number::bin; } /// @brief dec keyword implementation @@ -321,7 +301,7 @@ void program::rpn_bin() { void program::rpn_dec() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->_representation = number::dec; + ((number*)_stack->back())->repr = number::dec; } /// @brief base keyword implementation @@ -334,7 +314,7 @@ void program::rpn_base() { mpfr_cmp_d(((number*)_stack->back())->value.mpfr, (double)BASE_MAX) <= 0) { int base = (int)mpfr_get_d(((number*)_stack->pop_front())->value.mpfr, mpreal::get_default_rnd()); ((number*)_stack->at(0))->_base = base; - ((number*)_stack->at(0))->_representation = number::base; + ((number*)_stack->at(0))->repr = number::base; } else ERR_CONTEXT(ret_out_of_range); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 6a32c41..c2a0618 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -209,7 +209,7 @@ void program::rpn_edit(void) { } /// @brief recall then eval a symbol variable if it is auto-evaluable -/// +/// /// @param symb the smlbol to recall and autoeval /// void program::auto_rcl(symbol* symb) { @@ -247,7 +247,7 @@ void program::rpn_vars(void) { // heap variables for (int i = 0; i < (int)_heap->size(); i++) { (void)_heap->get_by_index(i, name, obj); - printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(), object::s_cmd_type_string[obj->_type]); + printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); obj->show(cout); printf("\n"); } @@ -256,8 +256,7 @@ void program::rpn_vars(void) { while (parent != NULL) { for (int i = 0; i < (int)parent->_local_heap.size(); i++) { (void)parent->_local_heap.get_by_index(i, name, obj); - printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), - object::s_cmd_type_string[obj->_type]); + printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); obj->show(cout); printf("\n"); } @@ -267,7 +266,7 @@ void program::rpn_vars(void) { // local variables for (int i = 0; i < (int)_local_heap.size(); i++) { (void)_local_heap.get_by_index(i, name, obj); - printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), object::s_cmd_type_string[obj->_type]); + printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); obj->show(cout); printf("\n"); } diff --git a/src/rpn-test-core.cpp b/src/rpn-test-core.cpp index dfb7d08..1ad6c54 100644 --- a/src/rpn-test-core.cpp +++ b/src/rpn-test-core.cpp @@ -1,3 +1,5 @@ +#include + #include "program.hpp" /// @brief write stack in a string, each entry separated between commas @@ -7,6 +9,10 @@ /// void program::test_get_stack(string& stack_is, rpnstack& stk) { ostringstream st; + if (stk.empty()) { + stack_is.clear(); + return; + } stk[stk.size() - 1]->show(st); stack_is += st.str(); for (int i = (int)stk.size() - 2; i >= 0; i--) { @@ -25,31 +31,33 @@ void program::test_get_stack(string& stack_is, rpnstack& stk) { /// @param steps_failed failed steps nb /// void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) { - printf("%s: run %d tests: %d passed, ", title.c_str(), tests, tests - tests_failed); - if (tests_failed > 0) printf(FG_RED); - printf("%d failed", tests_failed); - if (tests_failed > 0) printf(COLOR_OFF); + cout << title << ": run " << tests << " tests: " << tests - tests_failed << " passed, "; + if (tests_failed > 0) cout << FG_RED; + cout << tests_failed << " failed"; + if (tests_failed > 0) cout << COLOR_OFF; - printf(" (%d steps: %d passed, ", steps, steps - steps_failed); - if (steps_failed > 0) printf(FG_RED); - printf("%d failed", steps_failed); - if (steps_failed > 0) printf(COLOR_OFF); - printf(")\n"); + cout << " (" << steps << " steps: " << steps - steps_failed << " passed, "; + if (steps_failed > 0) cout << FG_RED; + cout << steps_failed << " failed"; + if (steps_failed > 0) cout << COLOR_OFF; + cout << ")" << endl; } /// @brief test keyword implementation /// void program::rpn_test() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + //TODO go back to string + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); int total_tests = 0; int total_tests_failed = 0; int total_steps = 0; int total_steps_failed = 0; - string test_filename = ((ostring*)_stack->pop_front())->value; - printf("\nrpn version is %s\n", version.c_str()); + string test_filename = _stack->value(0); + _stack->pop(); + cout << endl << "rpn version is " << version << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); } @@ -93,21 +101,22 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail while (!test_file.eof()) { getline(test_file, entry); + if (entry.empty()) continue; - if (entry.substr(0, 8) == "#include") + if (entry.substr(0, 8) == "@include") test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed); - else if (entry.substr(0, 2) == "##") - printf("\n%s: %s\n", test_filename.c_str(), entry.substr(3).c_str()); - else if (entry.substr(0, 2) == "# ") { + else if (entry.substr(0, 2) == "# ") + cout << endl << test_filename << ": " << entry.substr(2) << endl; + else if (entry.substr(0, 3) == "## ") { // indicates the status of previous test - if (failed == false && tests > 0) printf(FG_GREEN " PASSED" COLOR_OFF "\n"); + if (failed == false && tests > 0) cout << FG_GREEN << " PASSED" << COLOR_OFF << endl; failed = false; // read a test title test_title = entry; is_first_step = true; is_test_error_shown = false; - printf("%s", test_title.c_str()); + cout << test_title; } // treat "-> stack size should be " else if (entry.find(stack_size, 0) == 0) { @@ -124,15 +133,15 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (size != (int)stk.size()) { // count fail test and step if (!is_test_error_shown) { - printf(FG_RED " FAIL" COLOR_OFF "\n"); + cout << FG_RED << " FAIL" << COLOR_OFF << endl; tests_failed++; is_test_error_shown = true; } steps_failed++; // show failure - printf("\t%s\n", entry.c_str()); - printf("\tbut real stack size is " FG_RED "%d" COLOR_OFF "\n", stk.size()); + cout << '\t' << entry << endl; + cout << "\t but real stack size is " << FG_RED << stk.size() << COLOR_OFF << endl; failed = true; } is_first_step = false; @@ -152,15 +161,15 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (stack_is != stack_should_be) { // count fail test and step if (!is_test_error_shown) { - printf(FG_RED " FAIL" COLOR_OFF "\n"); + cout << FG_RED << " FAIL" << COLOR_OFF << endl; tests_failed++; is_test_error_shown = true; } steps_failed++; // show failure - printf("\t%s\n", entry.c_str()); - printf("\tbut real stack is " FG_RED "%s" COLOR_OFF "\n", stack_is.c_str()); + cout << '\t' << entry << endl; + cout << "\t but real stack is " << FG_RED << stack_is << COLOR_OFF << endl; failed = true; } is_first_step = false; @@ -179,36 +188,57 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (err_should_be != last_err) { // count fail test and step if (!is_test_error_shown) { - printf(FG_RED " FAIL" COLOR_OFF "\n"); + cout << FG_RED << " FAIL" << COLOR_OFF << endl; tests_failed++; is_test_error_shown = true; } steps_failed++; // show failure - printf("\t%s\n", entry.c_str()); - printf("\tbut last error is " FG_RED "%d" COLOR_OFF "\n", last_err); + cout << '\t' << entry << endl; + cout << "\t but last error is " << FG_RED << last_err << COLOR_OFF << endl; failed = true; } is_first_step = false; } else if (entry.find(cmd_exit, 0) == 0) { // forced test end break; - } else if (entry.size() > 0) { + } + // treat unknown "->" + else if (entry.find("->", 0) == 0) { + // count test + if (is_first_step) tests++; + steps++; + + // count fail test and step + if (!is_test_error_shown) { + cout << FG_RED << " FAIL" << COLOR_OFF << endl; + tests_failed++; + is_test_error_shown = true; + } + steps_failed++; + + // show failure + cout << FG_RED << "\tthis test '" << entry << "' is unknown" << COLOR_OFF << endl; + failed = true; + } else { // parse entry and run line - program prog; - ret = program::parse(entry, prog); - if (ret == ret_ok) { - // run it - (void)prog.run(stk, hp); - last_err = (int)prog.get_err(); + entry = regex_replace(entry, regex("`"), ""); + if (!entry.empty()) { + program prog; + ret = program::parse(entry, prog); + if (ret == ret_ok) { + // run it + (void)prog.run(stk, hp); + last_err = (int)prog.get_err(); + } } } } // last test // indicates the status of previous test - if (failed == false && tests > 0) printf(FG_GREEN " PASSED" COLOR_OFF "\n"); + if (failed == false && tests > 0) cout << FG_GREEN << " PASSED" << COLOR_OFF << endl; // cerr back cerr.rdbuf(cerr_old_buffer); @@ -223,5 +253,5 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail total_steps_failed += steps_failed; } } else - fprintf(stderr, "test file '%s' not found\n", test_filename.c_str()); + cerr << "test file '" << test_filename << "' not found" << endl; } diff --git a/src/stack.hpp b/src/stack.hpp index 831a809..5eb63e6 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -15,7 +15,10 @@ using namespace std; class rpnstack : public deque { public: rpnstack() {} - virtual ~rpnstack() {} + virtual ~rpnstack() { + for_each(begin(), end(), [](object* o) { delete o; }); + erase(begin(), end()); + } /// @brief copy a whole stack entry and push it back to another stack /// @@ -24,7 +27,10 @@ class rpnstack : public deque { /// @param to copy to /// static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { - to.push_front(from[index_from]); + // carefull: caller must ensure that index_from is correct + auto newObj = from[index_from]->clone(); + if (newObj != nullptr) + to.push_front(newObj); } /// @brief erase a stack entry from it index @@ -33,7 +39,7 @@ class rpnstack : public deque { /// @param last index to stop /// void del(int first = 0, int last = -1) { - if (size() >0) { + if (size() > 0) { if (last == -1) erase(begin() + first); else if (last >= first) @@ -41,15 +47,19 @@ class rpnstack : public deque { } } - /// @brief pop back several entries + /// @brief pop front several entries /// /// @param levels nb of entries /// - void pop_front(int levels) { - for (int i = 0; i < levels; i++) deque::pop_front(); + void pop_front(int levels, bool del = true) { + for (int i = 0; i < levels; i++) { + if (del) + delete deque::front(); + deque::pop_front(); + } } - /// @brief pop back 1 entry + /// @brief pop front 1 entry /// /// @return retrieved object /// @@ -58,6 +68,30 @@ class rpnstack : public deque { pop_front(1); return o; } + + // access helpers + cmd_type_t type(int level) { + // carefull: caller must ensure that level is correct + return at(level)->_type; + } + + template auto obj(int level) { + // carefull: caller must ensure that level is correct + return static_cast(at(level)); + } + + template auto& value(int level) { + // carefull: caller must ensure that level is correct + return static_cast(at(level))->value; + } + + void pop() { + (void)rpnstack::pop_front(1); + } + + void push(object* o) { + deque::push_front(o); + } }; /// @brief heap object, storing variables (=named object) diff --git a/test/005-test-framework.md b/test/005-test-framework.md new file mode 100644 index 0000000..1847485 --- /dev/null +++ b/test/005-test-framework.md @@ -0,0 +1,47 @@ +# TEST the test framwork + +`default del` + +## testing the stack size 1 + +-> stack size should be 0 + +## testing the stack size 2 + +`1` + +-> stack size should be 1 + +`del` + +-> stack size should be 0 + +## testing the stack size 3 + +`1 2 3 4 5` + +-> stack size should be 5 + +`del` + +## testing stack + +`1 2 3` + +-> stack should be 1, 2, 3 + +`del` + +-> stack should be + +## testing error 1 + +`del` + +-> error should be 0 + +## testing error 2 + +`drop` + +-> error should be 2 diff --git a/test/010-mode.md b/test/010-mode.md new file mode 100644 index 0000000..8be5de3 --- /dev/null +++ b/test/010-mode.md @@ -0,0 +1,75 @@ +# MODE +`default del` + +## std (1) + +``` +del +38 std +``` + +-> stack size should be 0 + +-> error should be 0 + +`del` + +## std (2) + +`1 3 /` + +-> stack should be 0.33333333333333333333333333333333333333 + +`del` + +## fix (1) + +`10 fix 1` + +-> stack should be 1.0000000000 + +`del` + +## fix (2) + +`1 4 fix` + +-> stack should be 1.0000 + +`del` + +## fix (3) + +`-1 fix` + +-> error should be 4 + +`del` + +## sci (1) + +`1 12 sci` + +-> stack should be 1.000000000000e+00 + +`del` + +## sci (2) + +`1 2 sci` + +-> stack should be 1.00e+00 + +## default + +`default` + +-> stack should be 1 + +## sci (3) + +`-1 sci` + +-> error should be 4 + +`del` diff --git a/test/20-general.txt b/test/020-general.md similarity index 50% rename from test/20-general.txt rename to test/020-general.md index 7807b33..eef03f8 100644 --- a/test/20-general.txt +++ b/test/020-general.md @@ -1,24 +1,41 @@ -## GENERAL -default del +# GENERAL + +`default del ` + +## version + +`version` -# version -version -> stack size should be 1 -del -uname +`del` + +## uname + +`uname` + -> stack size should be 1 -del -# default -2 sci 1 +`del` + +## default + +`2 sci 1` + -> stack should be 1.00e+00 -default --> stack should be 1 -del -# nop -nop +`default` + +-> stack should be 1 + +`del` + +## nop + +`nop` + -> stack size should be 0 + -> error should be 0 -del + +`del` diff --git a/test/021-parse-string.md b/test/021-parse-string.md new file mode 100644 index 0000000..dc3e417 --- /dev/null +++ b/test/021-parse-string.md @@ -0,0 +1,101 @@ +# PARSE STRING + +`default del` + +## type + +`"hey" type` + +-> stack should be "string" + +`del` + +## void 1 + +`""` + +-> stack should be "" + +`del` + +## void 2 + +`"` + +-> stack should be "" + +`del` + +## string + +`"abcd"` + +-> stack should be "abcd" + +`del` + +## unterminated + +`"abcd` + +-> stack should be "abcd" + +`del` + +## unterminated 2 + +`"abcd" "abc` + +-> stack should be "abcd", "abc" + +`del` + +## spaces + +`"abc d"` + +-> stack should be "abc d" + +`del` + +## spaces 2 + +`" abcd "` + +-> stack should be " abcd " + +`del` + +## spaces 3 + +`" abcd " "def" "gh ij"` + +-> stack should be " abcd ", "def", "gh ij" + +`del` + +## spaces 4 + +`" . abcd . ;; "` + +-> stack should be " . abcd . ;; " + +`del` + +## spaces 5 + +``` +" . abcd . ;; " "ab c +``` + +-> stack should be " . abcd . ;; ", "ab c " + +`del` + +## nested types + +`"1.0 swap drop` + +-> stack should be "1.0 swap drop" + +`del` diff --git a/test/022-parse-symbol.md b/test/022-parse-symbol.md new file mode 100644 index 0000000..1f0d30d --- /dev/null +++ b/test/022-parse-symbol.md @@ -0,0 +1,107 @@ +# PARSE SYMBOL + +`default del ` + +## type + +`'hey' type` + +-> stack should be "symbol" + +`del` + +## void 1 + +`''` + +-> stack should be '' + +`del` + +## void 2 + +`'` + +-> stack should be '' + +`del` + +## symbol + +`'abcd'` + +-> stack should be 'abcd' + +`del` + +## unterminated + +`'abcd` + +-> stack should be 'abcd' + +`del` + +## unterminated 2 + +`'abcd' 'abc` + +-> stack should be 'abcd', 'abc' + +`del` + +## spaces + +`'abc d'` + +-> stack should be 'abc d' + +`del` + +## spaces 2 + +`' abcd '` + +-> stack should be ' abcd ' + +`del` + +## spaces 3 + +`' abcd ' 'def' 'gh ij'` + +-> stack should be ' abcd ', 'def', 'gh ij' + +`del` + +## spaces 4 + +`' . abcd . ;; '` + +-> stack should be ' . abcd . ;; ' + +`del` + +## spaces 5 + +`' . abcd . ;; ' 'ab c` + +-> stack should be ' . abcd . ;; ', 'ab c' + +`del` + +## nested types 1 + +`'1'` + +-> stack should be '1' + +`del` + +## nested types 2 + +`'1.0 swap drop` + +-> stack should be '1.0 swap drop' + +`del` diff --git a/test/023-parse-number.md b/test/023-parse-number.md new file mode 100644 index 0000000..b4a22b2 --- /dev/null +++ b/test/023-parse-number.md @@ -0,0 +1,75 @@ +# PARSE NUMBER + +`default del` + +## type + +`1.0 type` + +-> stack should be "number" + +`del` + +## numb 1 + +`3.14 +3.14 -3.14` + +-> stack should be 3.14, 3.14, -3.14 + +`del` + +## spaces + +` -3.14 -3 .14` + +-> stack should be -3.14, -3, 0.14 + +`del` + +## exp entry + +`+3.14e2` + +-> stack should be 314 + +`del` + +## inf nan + +`+inf inf -inf nan` + +-> stack should be inf, inf, -inf, nan + +`del` + +## hex + +`0x10 0X10` + +-> stack should be 16, 16 + +`del` + +## hex err + +`0x 0X` + +-> stack should be '0x', '0X' + +`del` + +## bin + +`0b1101 0b0` + +-> stack should be 13, 0 + +`del` + +## bin err + +`0b` + +-> stack should be '0b' + +`del` diff --git a/test/24-parse-complex.txt b/test/024-parse-complex.md similarity index 56% rename from test/24-parse-complex.txt rename to test/024-parse-complex.md index cd0551a..1135568 100644 --- a/test/24-parse-complex.txt +++ b/test/024-parse-complex.md @@ -1,33 +1,53 @@ -## PARSE COMPLEX -default del +# PARSE COMPLEX + +`default del` + +## type + +`(1,2) type` -# type -(1,2) type -> stack should be "complex" -del -# cplx -(1,2) (1, 2) ( 1 , 2 ) +`del` + +## cplx + +`(1,2) (1, 2) ( 1 , 2 )` + -> stack should be (1,2), (1,2), (1,2) -del -# cplx inf nan +`del` + +## cplx inf nan + +``` (inf,3) (-inf,nan) (inf,-inf) +``` + -> stack should be (inf,3), (-inf,nan), (inf,-inf) -del -# unterminated -( 3.14e2 , -2 +`del` + +## unterminated + +`( 3.14e2 , -2` + -> stack should be (314,-2) -del -# unterminated 2 -(-inf, nan +`del` + +## unterminated 2 + +`(-inf, nan` + -> stack should be (-inf,nan) -del -# unterminated err +`del` + +## unterminated err + +``` ( (a (123 @@ -36,5 +56,8 @@ del (12, (,13) (,3.14 +``` + -> stack should be '(', '(a', '(123', '(,', '(,)', '(12,', '(,13)', '(,3.14' -del + +`del` diff --git a/test/025-parse-other.md b/test/025-parse-other.md new file mode 100644 index 0000000..aa4389c --- /dev/null +++ b/test/025-parse-other.md @@ -0,0 +1,27 @@ +# PARSE COMPLEX + +`default del` + +## some command + +`+` + +-> error should be 2 + +`del` + +## some command 2 + +` +` + +-> error should be 2 + +`del` + +## some command 3 + +` + -` + +-> error should be 2 + +`del` diff --git a/test/026-parse-program.md b/test/026-parse-program.md new file mode 100644 index 0000000..c44903b --- /dev/null +++ b/test/026-parse-program.md @@ -0,0 +1,86 @@ +# PARSE SYMBOL + +`default del ` + +## type + +`<< I >> type` + +-> stack should be "program" + +`del` + +## prog 1 + +`<< I am a program >>` + +-> stack should be «I am a program» + +`del` + +## prog 2 + +`<>` + +-> stack should be «I am a program» + +`del` + +## prog 3 + +`<< I am a program >>` + +-> stack should be «I am a program» + +`del` + +## prog 4 + +`«I am a program»` + +-> stack should be «I am a program» + +`del` + +## prog 5 + +`« I am a program »` + +-> stack should be «I am a program» + +`del` + +## unterminated 1 + +`<< prog` + +-> stack should be «prog» + +`del` + +## unterminated 2 + +`« prog` + +-> stack should be «prog» + +`del` + +## unterminated 3 + +`<< prog>` + +-> stack should be «prog>» + +`del` + +## unterminated 4 + +``` +<< +« +``` + +-> stack should be «», «» + +`del` diff --git a/test/27-base-entry.txt b/test/027-base-entry.md similarity index 60% rename from test/27-base-entry.txt rename to test/027-base-entry.md index 618bb68..8c591b6 100644 --- a/test/27-base-entry.txt +++ b/test/027-base-entry.md @@ -1,196 +1,325 @@ -## fix entry -default del +# fix entry -# table for fixed entry, 4 fix output >= 0 +`default del` + +## table for fixed entry, 4 fix output >= 0 + +``` 4 fix 1 0.01 0.0001 0.00006 0.00004 0 0.012 0.001256 100 100.001 100.00006 100.00004 12345678910111213.12355 --> stack should be 1.0000, 0.0100, 0.0001, 0.0001, 0.0000, 0.0000, 0.0120, 0.0013, 100.0000, 100.0010, 100.0001, 100.0000, 12345678910111213.1236 -del default +``` -# table for fixed entry, 4 fix output <= 0 +-> stack should be 1.0000, 0.0100, 0.0001, 0.0001, 0.0000, 0.0000, 0.0120, 0.0013, 100.0000, 100.0010, 100.0001, 100.0000, 12345678910111213.1236 + +`del default` + +## table for fixed entry, 4 fix output <= 0 + +``` 4 fix -1 -0.01 -0.0001 -0.00006 -0.00004 -0 -0.012 -0.001256 -100 -100.001 -100.00006 -100.00004 -12345678910111213.12355 --> stack should be -1.0000, -0.0100, -0.0001, -0.0001, -0.0000, -0.0000, -0.0120, -0.0013, -100.0000, -100.0010, -100.0001, -100.0000, -12345678910111213.1236 -del default +``` -# table for sci entry, 4 fix output >= 0 +-> stack should be -1.0000, -0.0100, -0.0001, -0.0001, -0.0000, -0.0000, -0.0120, -0.0013, -100.0000, -100.0010, -100.0001, -100.0000, -12345678910111213.1236 + +`del default` + +## table for sci entry, 4 fix output >= 0 + +``` 4 fix 0e100 1e0 1.e0 1.001e0 1.e-3 1.e-4 6.e-5 4.e-5 1.00001e2 1.0000006e2 1.0000004e2 1234.5678917e2 --> stack should be 0.0000, 1.0000, 1.0000, 1.0010, 0.0010, 0.0001, 0.0001, 0.0000, 100.0010, 100.0001, 100.0000, 123456.7892 -del default +``` -# table for sci entry, 4 fix output <= 0 +-> stack should be 0.0000, 1.0000, 1.0000, 1.0010, 0.0010, 0.0001, 0.0001, 0.0000, 100.0010, 100.0001, 100.0000, 123456.7892 + +`del default` + +## table for sci entry, 4 fix output <= 0 + +``` 4 fix -0e100 -1e0 -1.e0 -1.001e0 -1.e-3 -1.e-4 -6.e-5 -4.e-5 -1.00001e2 -1.0000006e2 -1.0000004e2 -1234.5678917e2 --> stack should be -0.0000, -1.0000, -1.0000, -1.0010, -0.0010, -0.0001, -0.0001, -0.0000, -100.0010, -100.0001, -100.0000, -123456.7892 -del default +``` -# table for singularity +-> stack should be -0.0000, -1.0000, -1.0000, -1.0010, -0.0010, -0.0001, -0.0001, -0.0000, -100.0010, -100.0001, -100.0000, -123456.7892 + +`del default` + +## table for singularity + +``` 4 fix nan @nan@ -nan inf -inf @inf@ -@inf@ --> stack should be nan, nan, nan, inf, -inf, inf, -inf -del default +``` -# some strange behaviour (1) +-> stack should be nan, nan, nan, inf, -inf, inf, -inf + +`del default` + +## some strange behaviour (1) + +``` 0 fix 1 2 / dup + --> stack should be 1 -del default +``` -# some strange behaviour (2) +-> stack should be 1 + +`del default` + +## some strange behaviour (2) + +``` 1 fix 0.6 --> stack should be 0.6 -del default +``` -# some strange behaviour (3) +-> stack should be 0.6 + +`del default` + +## some strange behaviour (3) + +``` 0 fix 110.6 0.6 +``` + -> stack should be 111, 1 -del default -# hex (1) -0x4000000000000 +`del default` + +## hex (1) + +`0x4000000000000` + -> stack should be 0x4000000000000 -del default -# hex (2) -2 50 ^ hex +`del default` + +## hex (2) + +`2 50 ^ hex` + -> stack should be 0x4000000000000 -del default -# hex (3) -12.34 hex +`del default` + +## hex (3) + +`12.34 hex` + -> stack should be 0xc -del default -# dec (1) -2 50 ^ +`del default` + +## dec (1) + +`2 50 ^` + -> stack should be 1125899906842624 -del default -# dec (2) -0x4000000000000 dec +`del default` + +## dec (2) + +`0x4000000000000 dec` + -> stack should be 1125899906842624 -del default -# dec (3) -12.34 dec +`del default` + +## dec (3) + +`12.34 dec` + -> stack should be 12.34 -del default -# bin (1) -0b100000000000000000000000000000000000000000000000000 bin +`del default` + +## bin (1) + +`0b100000000000000000000000000000000000000000000000000 bin` + -> stack should be 0b100000000000000000000000000000000000000000000000000 -del default -# bin (2) -2 50 ^ bin +`del default` + +## bin (2) + +`2 50 ^ bin` + -> stack should be 0b100000000000000000000000000000000000000000000000000 -del default -# bin (3) -0x4000000000000 bin +`del default` + +## bin (3) + +`0x4000000000000 bin` + -> stack should be 0b100000000000000000000000000000000000000000000000000 -del default -# bin (4) -12.34 bin +`del default` + +## bin (4) + +`12.34 bin` + -> stack should be 0b1100 -del default -# base entry (1) -3b111 dup dec +`del default` + +## base entry (1) + +`3b111 dup dec` + -> stack should be 3b111, 13 -del default -# base entry (2) -3b114 +`del default` + +## base entry (2) + +`3b114` + -> stack should be 3b11, 4 -del default -# base entry (3) -1b0 +`del default` + +## base entry (3) + +`1b0` + -> stack should be 1, 'b0' -del default -# base entry (4) -62b20 dup dec +`del default` + +## base entry (4) + +`62b20 dup dec` + -> stack should be 62b20, 124 -del default -# base entry (5) -63b20 +`del default` + +## base entry (5) + +`63b20` + -> stack should be 63, 'b20' -del default -# base entry (6) -2b11001100 0b11001100 == +`del default` + +## base entry (6) + +`2b11001100 0b11001100 ==` + -> stack should be 2b1 -del default -# base entry (7) -10b1234 1234 == +`del default` + +## base entry (7) + +`10b1234 1234 ==` + -> stack should be 10b1 -del default -# base entry (8) -16b1234 0x1234 == +`del default` + +## base entry (8) + +`16b1234 0x1234 ==` + -> stack should be 16b1 -del default -# base display (1) -2 62 for i 62 i base next +`del default` + +## base display (1) + +`2 62 for i 62 i base next` + -> stack should be 2b111110, 3b2022, 4b332, 5b222, 6b142, 7b116, 8b76, 9b68, 10b62, 11b57, 12b52, 13b4a, 14b46, 15b42, 16b3e, 17b3b, 18b38, 19b35, 20b32, 21b2k, 22b2i, 23b2g, 24b2e, 25b2c, 26b2a, 27b28, 28b26, 29b24, 30b22, 31b20, 32b1u, 33b1t, 34b1s, 35b1r, 36b1q, 37b1P, 38b1O, 39b1N, 40b1M, 41b1L, 42b1K, 43b1J, 44b1I, 45b1H, 46b1G, 47b1F, 48b1E, 49b1D, 50b1C, 51b1B, 52b1A, 53b19, 54b18, 55b17, 56b16, 57b15, 58b14, 59b13, 60b12, 61b11, 62b10 -del default -# base display (2) -2 62 for i i 62 base next +`del default` + +## base display (2) + +`2 62 for i i 62 base next` + -> stack should be 62b2, 62b3, 62b4, 62b5, 62b6, 62b7, 62b8, 62b9, 62bA, 62bB, 62bC, 62bD, 62bE, 62bF, 62bG, 62bH, 62bI, 62bJ, 62bK, 62bL, 62bM, 62bN, 62bO, 62bP, 62bQ, 62bR, 62bS, 62bT, 62bU, 62bV, 62bW, 62bX, 62bY, 62bZ, 62ba, 62bb, 62bc, 62bd, 62be, 62bf, 62bg, 62bh, 62bi, 62bj, 62bk, 62bl, 62bm, 62bn, 62bo, 62bp, 62bq, 62br, 62bs, 62bt, 62bu, 62bv, 62bw, 62bx, 62by, 62bz, 62b10 -del default -# base display (3) +`del default` + +## base display (3) + +``` 100 dup 3 base == 13455600 dup 5 base == 55756 dup 17 base == 2345321 dup 62 base == --> stack should be 1, 1, 1, 1 -del default +``` -# base display (4) +-> stack should be 1, 1, 1, 1 + +`del default` + +## base display (4) + +``` 100 18 base dup 3 base == dec 13455600 55 base dup 5 base == dec 55756 9 base dup 17 base == dec 2345321 57 base dup 62 base == dec +``` + -> stack should be 1, 1, 1, 1 -del default -# negative base numbers (1) -1000 hex neg +`del default` + +## negative base numbers (1) + +`1000 hex neg` + -> stack should be -0x3e8 -del default -# negative base numbers (2) -1000 7 base neg +`del default` + +## negative base numbers (2) + +`1000 7 base neg` + -> stack should be -7b2626 -del default -# negative base numbers (3) -1000 bin neg +`del default` + +## negative base numbers (3) + +`1000 bin neg` + -> stack should be -0b1111101000 -del default -# negative base numbers (4) --0b1111101000 3 base +`del default` + +## negative base numbers (4) + +`-0b1111101000 3 base` + -> stack should be -3b1101001 -del default -# inf should not be based-represented --1 bin 0 bin / 1 3 base 0 3 base / +`del default` + +## inf should not be based-represented + +`-1 bin 0 bin / 1 3 base 0 3 base /` + -> stack should be -inf, inf -del default -# nan should not be based-represented --0 bin 0 bin / 0 3 base 0 3 base / +`del default` + +## nan should not be based-represented + +`-0 bin 0 bin / 0 3 base 0 3 base /` + -> stack should be nan, nan -del default + +`del default` diff --git a/test/030-branch.md b/test/030-branch.md new file mode 100644 index 0000000..da662a2 --- /dev/null +++ b/test/030-branch.md @@ -0,0 +1,637 @@ +### BRANCH + +`default del` + +## if then else end (1) +`1 if then 'ok' end` + +-> stack should be 'ok' + +`del` + +## if then else end (2) + +`1 if 'before' then 'ok' end` + +-> stack should be 'before', 'ok' + +`del` + +## if then else end (3) + +`0 if then 'ok' end` + +-> stack size should be 0 + +`del` + +## if then else end (4) + +`0 if then 'ok' end` + +-> stack size should be 0 + +`del` + +## if then else end (5) + +`1 if then 'ok' else 'KO' end` + +-> stack should be 'ok' + +`del` + +## if then else end (6) + +`1 if then 'ok' 'dokey' else 'KO' end` + +-> stack should be 'ok', 'dokey' + +`del` + +## if then else end (7) + +`0 if then 'ok' else 'KO' end` + +-> stack should be 'KO' + +`del` + +## if then else end - error case (1) + +`if then end` + +-> error should be 2 + +`del` + +## if then else end - error case (2) + +`0 if then` + +-> error should be 11 + +`del` + +## if then else end - error case (3) + +`0 if end` + +-> error should be 11 + +`del` + +## if then else end - error case (4) + +`0 if end` + +-> error should be 11 + +`del` + +## if then else end - error case (5) + +`then` + +-> error should be 11 + +`del` + +## if then else end - error case (6) + +`1 if` + +-> error should be 11 + +`del` + +## if then else end - error case (7) + +`else` + +-> error should be 11 + +`del` + + +## if then else end - error case (8) + +`end` + +-> error should be 11 + +`del` + +## if then else end - error case (9) + +`"1" if then end` + +-> error should be 3 + +`del` + +## ift (1) + +`1 'ok' ift` + +-> stack should be 'ok' + +`del` + +## ift (2) + +`0 'ok' ift` + +-> stack size should be 0 + +`del` + +## ift (3) + +`'ok' ift` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## ift (4) + +`ift` + +-> error should be 2 + +-> stack size should be 0 + +`del` + +## ifte (1) + +`1 'ok' 'nok' ifte` + +-> stack should be 'ok' + +`del` + +## ifte (2) + +`0 'ok' 'nok' ifte` + +-> stack should be 'nok' + +`del` + +## ifte (3) + +`'ok' 'nok' ifte` + +-> error should be 2 + +-> stack size should be 2 + +`del` + +## ifte (4) + +`'nok' ifte` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## ifte (5) + +`ifte` + +-> error should be 2 + +-> stack size should be 0 + +`del` + +## start next (1) + +`1 2 start 0 next` + +-> stack should be 0, 0 + +`del` + +## start next (2) + +`2 1 start 0 next` + +-> stack size should be 0 + +`del` + +## start next (3) + +`-2 -1 start 0 next` + +-> stack should be 0, 0 + +`del` + +## start next (4) + +`-1 -2 start 0 next` + +-> stack size should be 0 + +`del` + +## start next (5) + +`1 1 start 0 next` + +-> stack should be 0 + +`del` + +## start next - error case (1) + +`1 start next` + +->error should be 2 + +`del` + +## start next - error case (2) + +`start next` + +->error should be 2 + +`del` + +## start next - error case (3) + +`start` + +->error should be 11 + +`del` + +## start next - error case (4) + +`next` + +->error should be 11 + +`del` + +## start next - error case (5) + +`"1" 2 start next` + +->error should be 3 + +`del` + +## start next - error case (5) + +`1 "2" start next` + +->error should be 3 + +`del` + +## for next (1) + +`23 27 for i i next` + +-> stack should be 23, 24, 25, 26, 27 + +`del` + +## for next (2) + +`1 1 for i i next` + +-> stack should be 1 + +`del` + +## for next (3) + +`27 23 for i i next` + +-> stack size should be 0 + +`del` + +## for next (4) + +`-2 -1 for i i next` + +-> stack should be -2, -1 + +`del` + +## for next (5) + +`-1 -2 for i i next` + +-> stack size should be 0 + +`del` + +## for next - error case (1) + +`1 for i i next` + +-> error should be 2 + +`del` + +## for next - error case (2) + +`for i i next` + +-> error should be 2 + +`del` + +## for next - error case (3) + +`"1" 2 for i i next` + +-> error should be 3 + +`del` + +## for next - error case (4) + +`1 "2" for i i next` + +-> error should be 3 + +`del` + +## for next - error case (5) + +`1 2 for i i` + +-> error should be 11 + +`del` + +## for next - error case (6) + +`for` + +-> error should be 11 + +`del` + +## for step (1) + +`23 27 for i i 1 step` + +-> stack should be 23, 24, 25, 26, 27 + +`del` + +## for step (2) + +`0 1 for i i 0.25 step` + +-> stack should be 0, 0.25, 0.5, 0.75, 1 + +`del` + +## for step (3) + +`-1 0 for i i 0.25 step` + +-> stack should be -1, -0.75, -0.5, -0.25, -0 + +`del` + +## for step (4) + +`0 -1 for i i 0.25 step` + +-> stack size should be 0 + +`del` + +## for step (5) + +`0 -1 for i i -0.25 step` + +-> stack size should be 0 + +`del` + +## for step (6) - check boundary integration + +`1 2 for i i 0.2 step` + +-> stack should be 1, 1.2, 1.4, 1.6, 1.8, 2 + +`del` + +## for step (7) - check boundary integration + +`1 2 for i i 0.5 step` + +-> stack should be 1, 1.5, 2 + +`del` + +## for step - error case (1) + +`0 1 for i i "0.5" step` + +-> error should be 3 + +`del` + +## for step - error case (2) + +`step` + +-> error should be 11 + +`del` + +## do..unti (1) + +`do 'ok' unti 1 end` + +-> stack should be 'ok' + +`del` + +## do..unti (2) + +`do unti 1 end` + +-> stack size should be 0 + +`del` + +## do..unti (3) + +`1 'a' sto do a unti a 0 > end` + +-> stack should be 1 + +`del` + +## do..unti (4) + +`1 'a' sto do a 'a' 1 sto+ unti a 3 > end` + +-> stack should be 1, 2, 3 + +`del` + +## do..unti (5) + +`"" 0 'a' sto do 'a' 1 sto+ 0 a for b b ->str + next unti a 3 > end` + +-> stack should be "01012012301234" + +`del` + +## do..unti error case (1) + +`do` + +-> error should be 11 + +`del` + +## do..unti error case (2) + +`do 8 end` + +-> error should be 11 + +`del` + +## do..unti error case (3) + +`unti` + +-> error should be 11 + +`del` + +## do..unti error case (4) + +`do 3 unti` + +-> error should be 11 + +`del` + +## do..unti error case (5) + +`unti 1 end` + +-> error should be 11 + +`del` + +## do..unti error case (6) + +`do 3 repeat 8 end` + +-> error should be 11 + +`del` + +## do..unti error case (7) + +`do 3 until 8 until 9 end` + +-> error should be 11 + +`del` + +## while..repeat (1) + +`while 0 repeat ok end` + +-> stack size should be 0 + +`del` + +## while..repeat (2) + +`2 while dup 0.1 > repeat dup 2 / end` + +-> stack should be 2, 1, 0.5, 0.25, 0.125, 0.0625 + +`del` + +## while..repeat (3) + +`"" 0 'a' sto while a 3 < repeat 'a' 1 sto+ 0 a for b b ->str + next end` + +-> stack should be "010120123" + +`del` + +## while..repeat error case (1) + +`while` + +-> error should be 11 + +`del` + +## while..repeat error case (2) + +`while 3 end` + +-> error should be 11 + +`del` + +## while..repeat error case (3) + +`repeat` + +-> error should be 11 + +`del` + +## while..repeat error case (4) + +`while 1 repeat` + +-> error should be 11 + +`del` + +## while..repeat error case (5) + +`repeat 1 end` + +-> error should be 11 + +`del` + +## while..repeat error case (6) + +`while 3 repeat 8 repeat 9 end` + +-> error should be 11 + +`del` + +## while..repeat error case (7) + +`while 3 until 8 end` + +-> error should be 11 + +`del` diff --git a/test/040-stack.md b/test/040-stack.md new file mode 100644 index 0000000..91441a8 --- /dev/null +++ b/test/040-stack.md @@ -0,0 +1,289 @@ +# STACK TEST + +`default del` + +## entry depth (1) + +`1 depth` + +-> stack size should be 2 + +## entry depth (2) + +`1 del depth` + +-> stack should be 0 + +`del` + +## swap + +`1 2 swap` + +-> stack size should be 2 + +-> stack should be 2, 1 + +`del` + +## swap with filled stack + +`5 6 1 2 swap` + +-> stack size should be 4 + +-> stack should be 5, 6, 2, 1 + +`del` + +## swap error + +`5 swap` + +-> stack size should be 1 + +-> error should 2 + +`del` + +## drop + +`1 2 3 drop` + +-> stack size should be 2 + +-> stack should be 1, 2 + +`del` + +## drop2 + +`1 2 3 drop2` + +-> stack size should be 1 + +-> stack should be 1 + +`del` + +## drop error + +`drop` + +-> error should be 2 + +`del` + +## drop2 error (1) + +`drop2` + +-> error should be 2 + +`del` + +## drop2 error (2) + +`1 drop2` + +-> error should be 2 + +`del` + +## test dup + +`1 dup` + +-> stack size should be 2 + +-> stack should be 1, 1 + +`del` + +## test dup2 + +`1 2 dup2` + +-> stack size should be 4 + +-> stack should be 1, 2, 1, 2 + +`del` + +## test rot + +`1 2 3 rot` + +-> stack size should be 3 + +-> stack should be 2, 3, 1 + +`del` + +## test rot 2 + +`5 6 7 rot rot` + +-> stack should be 7, 5, 6 + +`del` + +## test rot with filled stack + +`5 6 1 2 3 rot` + +-> stack size should be 5 + +-> stack should be 5, 6, 2, 3, 1 + +`del` + +## test depth + +`1 2 3` + +`depth` + +-> stack size should be 4 + +-> stack should be 1, 2, 3, 3 + +`del` + +## test pick + +`1 2 3 4 2 pick` + +-> stack size should be 5 + +-> stack should be 1, 2, 3, 4, 3 + +`0 pick` + +-> error should be 4 + +`7 pick` + +-> error should be 4 + +`erase` + +## test erase + +-> stack size should be 0 + +`erase` + +## test del + +`1 2 3 4 5` + +`del` + +-> stack size should be 0 + +## test dropn + +`1 2 2 dropn` + +-> stack size should be 0 + +`del` + +## test dropn error + +`1 2 3 dropn` + +-> stack size should be 3 + +-> error should be 2 + +`del` + +## test dupn + +`1 2 3 4 3 dupn` + +-> stack should be 1, 2, 3, 4, 2, 3, 4 + +`del` + +## test dupn error + +`1 2 3 4 5 dupn` + +-> stack size should be 5 + +-> error should be 2 + +`del` + +## test roll + +`1 2 3 4 5 4 roll` + +-> stack should be 1, 3, 4, 5, 2 + +`del` + +## test roll with filled stack + +`10 11 1 2 3 4 5 4 roll` + +-> stack should be 10, 11, 1, 3, 4, 5, 2 + +`del` + +## test roll error + +`1 2 3 4 5 6 roll` + +-> stack size should be 6 + +-> error should be 2 + +`del` + +## test rolld + +`10 20 30 40 50 3 rolld` + +-> stack should be 10, 20, 50, 30, 40 + +`del` + +## test rolld with filled stack + +`80 90 10 20 30 40 50 3 rolld` + +-> stack should be 80, 90, 10, 20, 50, 30, 40 + +`del` + +## test rolld error + +`1 2 3 4 5 6 rolld` + +-> stack size should be 6 + +-> error should be 2 + +`del` + +## test over + +`3.14 15.16 over` + +-> stack should be 3.14, 15.16, 3.14 + +`del` + +## test over error + +`2 over` + +-> stack size should be 1 + +-> error should be 2 + +`del` diff --git a/test/05-test.txt b/test/05-test.txt deleted file mode 100644 index 9ff416e..0000000 --- a/test/05-test.txt +++ /dev/null @@ -1,30 +0,0 @@ -## TEST the test framwork -default del - -# testing the stack size 1 --> stack size should be 0 - -# testing the stack size 2 -1 --> stack size should be 1 -del --> stack size should be 0 - -# testing the stack size 3 -1 2 3 4 5 --> stack size should be 5 -del - -# testing stack -1 2 3 --> stack should be 1, 2, 3 -del --> stack should be - -# testing error 1 -del --> error should be 0 - -# testing error 2 -drop --> error should be 2 diff --git a/test/050-real.md b/test/050-real.md new file mode 100644 index 0000000..890af25 --- /dev/null +++ b/test/050-real.md @@ -0,0 +1,753 @@ +# REAL + +`default del` + +## real decimal + +`1` + +-> stack size should be 1 + +-> stack should be 1 + +`del` + +## real decimal (2) + +`2.345` + +-> stack should be 2.345 + +`del` + +## real decimal (3) + +`1 2.345 3 4.9` + +-> stack size should be 4 + +-> stack should be 1, 2.345, 3, 4.9 + +`del` + +## real hex + +`0x1234 0x10.10` + +-> stack should be 0x1234, 0x10 + +`del` + +## real hex (2) + +``` +0x1.234p+12 0x1.01p+4 +dec swap dec swap +``` + +-> stack should be 4660, 16.0625 + +`del` + +## real binary + +`0b11001100` + +-> stack should be 0b11001100 + +`del` + +## real inf, nan + +``` +inf +@inf@ ++inf ++@inf@ +-inf +-@inf@ +nan +@nan@ +``` + +-> stack should be inf, inf, inf, inf, -inf, -inf, nan, nan + +`del` + +## prec (1) + +``` +default +56 prec +pi +``` + +-> stack should be 3.141592653589793 + +`del` + +## prec (2) + +``` +default +100 prec +pi +``` + +-> stack should be 3.14159265358979323846264338328 + +`del` + +## prec error (1) + +`0 prec` + +-> error should be 4 + +`del` + +## prec error (2) + +`0x8000000000000000 prec` + +-> error should be 4 + +`del default` + +## round (1) + +`"nearest" round` + +-> error should be 0 + +`del` + +## round (2) + +`"toward zero" round` + +-> error should be 0 + +`del` + +## round (3) + +`"toward +inf" round` + +-> error should be 0 + +`del` + +## round (4) + +`"toward -inf" round` + +-> error should be 0 + +`del` + +## round (5) + +`"away from zero" round` + +-> error should be 0 + +`del` + +## round (6) + +`round` + +-> error should be 2 + +`del default` + +## add (1) + +`1.2 2.3 +` + +-> stack should be 3.5 + +`del` + +## add (2) + +`1.2 2.3+` + +-> stack should be 3.5 + +`del` + +## add (3) + +`2.3 +` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## add (4) + +`+` + +-> error should be 2 + +`del` + +## sub (1) + +`1.2 2.3 -` + +-> stack should be -1.1 + +`del` + +## sub (2) + +`1.2 2.3-` + +-> stack should be -1.1 + +`del` + +## sub (3) + +`2.3 -` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## sub (4) + +`-` + +-> error should be 2 + +`del` + +## mul (1) + +`1.2 2.3 *` + +-> stack should be 2.76 + +`del` + +## mul (2) + +`1.2 2.3*` + +-> stack should be 2.76 + +`del` + +## mul (3) + +`2.3 *` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## mul (4) + +`*` + +-> error should be 2 + +`del` + +## div (1) + +`1.2 2.3 /` + +-> stack should be 0.52173913043478260869565217391304347826 + +`del` + +## div (2) + +`1.2 2.3/` + +-> stack should be 0.52173913043478260869565217391304347826 + +`del` + +## div (3) + +`2.3 /` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## div (4) + +`/` + +-> error should be 2 + +`del` + +## chs (1) + +`3.14 chs` + +-> stack should be -3.14 + +`del` + +## chs (2) + +`chs` + +-> error should be 2 + +## neg (1) + +`3.14 neg` + +-> stack should be -3.14 + +`del` + +## neg (2) + +`neg` + +-> error should be 2 + +## inv (1) + +`2 inv` + +-> stack should be 0.5 + +`del` + +## inv (2) + +`inv` + +-> error should be 2 + +## % (1) + +`2 30 %` + +-> stack should be 0.6 + +`del` + +## % (2) + +`2 30%` + +-> stack should be 0.6 + +del + +## % (3) + +`2 %` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## % (4) + +`%` + +-> error should be 2 + +`del` + +## %CH (1) + +`2 0.6 %CH` + +-> stack should be 30 + +`del` + +## %CH (2) + +`2 0.6%CH` + +-> stack should be 30 + +`del` + +## %CH (3) + +`2 %CH` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## %CH (4) + +`%CH` + +-> error should be 2 + +`del` + +## ^ (1) + +`2 10 ^` + +-> stack should be 1024 + +`del` + +## ^ (2) + +`2 10^` + +-> stack should be 1024 + +`del` + +## ^ (3) + +`2 ^` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## ^ (4) + +`^` + +-> error should be 2 + +`del` + +## sqrt (1) + +`9 sqrt` + +-> stack should be 3 + +`del` + +## sqrt (2) + +`sqrt` + +-> error should be 3 + +## sq (1) + +`12 sq` + +-> stack should be 144 + +`del` + +## sq (2) + +`sq` + +-> error should be 2 + +## sqr (1) + +`12 sqr` + +-> stack should be 144 + +`del` + +## sqr (2) + +`sqr` + +-> error should be 2 + +## mod (1) + +`9 4 mod` + +-> stack should be 1 + +`del` + +## mod (2) + +`9 mod` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## mod (3) + +`mod` + +-> error should be 2 + +`del` + +## abs (1) + +`-9 abs` + +-> stack should be 9 + +`del` + +## abs (2) + +`9 abs` + +-> stack should be 9 + +`del` + +## abs (3) + +`abs` + +-> error should be 2 + +`del` + +## fact (1) + +`6 fact` + +-> stack should be 720 + +`del` + +## fact (2) + +`'r' fact` + +-> error should be 3 + +-> stack size should be 1 + +`del` + +## fact (3) + +`fact` + +-> error should be 2 + +`del` + +## sign (1) + +`23 sign -34 sign 0 sign` + +-> stack should be 1, -1, 0 + +`del` + +## sign (2) + +`sign` + +-> error should be 2 + +`del` + +## mant (1) + +`123.456 mant -123.456 mant 0 mant` + +-> stack should be 0.123456, 0.123456, 0 + +`del` + +## mant (2) + +`inf mant` + +-> error should be 4 + +`-inf mant` + +-> error should be 4 + +`nan mant` + +-> error should be 4 + +`del` + +## xpon (1) + +`123.456 xpon -123.456 xpon 0 mant` + +-> stack should be 3, 3, 0 + +`del` + +## xpon (2) + +`inf xpon` + +-> error should be 4 + +`-inf xpon` + +-> error should be 4 + +`nan xpon` + +-> error should be 4 + +`del` + +## min (1) + +`1 2 min 4 3 min` + +-> stack should be 1, 3 + +`del` + +## min (2) + +`'a' 'g' min` + +-> error should be 3 + +`del` + +## min (3) + +`1 min` + +-> error should be 2 + +`del` + +## min (4) + +`min` + +-> error should be 2 + +`del` + +## max (1) + +`1 2 max 4 3 max` + +-> stack should be 2, 4 + +`del` + +## max (2) + +`'a' 'g' max` + +-> error should be 3 + +`del` + +## max (3) + +`1 max` + +-> error should be 2 + +`del` + +## max (4) + +`max` + +-> error should be 2 + +`del` + +## ip (1) + +`1.22 ip` + +-> stack should be 1 + +`del` + +## ip (2) + +`-1.22 ip` + +-> stack should be -1 + +`del` + +## fp (1) + +`1.22 fp` + +-> stack should be 0.22 + +`del` + +## fp (2) + +`-1.22 fp` + +-> stack should be -0.22 + +`del` + +## floor (1) + +`1.22 floor` + +-> stack should be 1 + +`del` + +## floor (2) + +`-1.22 floor` + +-> stack should be -2 + +`del` + +## ceil (1) + +`1.22 ceil` + +-> stack should be 2 + +`del` + +## ceil (2) + +`-1.22 ceil` + +-> stack should be -1 + +`del default` diff --git a/test/060-string.md b/test/060-string.md new file mode 100644 index 0000000..cfc9741 --- /dev/null +++ b/test/060-string.md @@ -0,0 +1,307 @@ +# STRING + +`default del` + +## string entry + +`"test string"` + +-> stack size should be 1 + +-> stack should be "test string" + +`del` + +## string entry (2) + +`"test string` + +-> stack size should be 1 + +-> stack should be "test string" + +`del` + +## string entry (3) + +`"` + +-> stack size should be 1 + +-> stack should be "" + +`del` + +## ->str on real (1) + +`1 ->str` + +-> stack should be "1" + +`del` + +## ->str on real (2) + +`1.234 ->str` + +-> stack should be "1.234" + +`del` + +## ->str on real (3) + +`1.234 20 fix ->str` + +-> stack should be "1.23400000000000000000" + +`del` + +## ->str on symbol (1) + +`toto ->str` + +-> stack should be "'toto'" + +`del` + +## ->str on symbol (2) + +`'toto' ->str` + +-> stack should be "'toto'" + +`del default` + +## str-> on real (1) + +`"1" str->` + +-> stack should be 1 + +`del` + +## str-> on real (2) + +`"1 2.345 3 4.9" str->` + +-> stack should be 1, 2.345, 3, 4.9 + +`del` + +## str-> on real (3) + +`4 fix "1 2.345 3 4.9" str->` + +-> stack should be 1.0000, 2.3450, 3.0000, 4.9000 + +`del default` + +## str-> on constant (1) + +`"pi" str->` + +-> stack should be 3.1415926535897932384626433832795028842 + +`del` + +## str-> on constant (2) + +`"'pi' 'e'" str->` + +-> stack should be 'pi', 'e' + +`del` + +## str-> on command (1) + +`"2 dup" str->` + +-> stack should be 2, 2 + +`del` + +## str-> on command (2) + +`"3.14 my_pi sto" str->` + +-> stack size should be 0 + +`my_pi` + +-> stack should be 3.14 + +`del` + +## str-> on program + +`"<< -> n << n >> >>" str->` + +-> stack should be << -> n << n >> >> + +`del` + +## add (1) + +`12 34 "one" "two" +` + +-> stack should be 12, 34, "onetwo" + +`del` + +## add (2) + +`"" "one" + "two" "" +` + +-> stack should be "one", "two" + +`del` + +## add (3) + +`"one" +` + +-> stack size should be 1 + +-> error should be 2 + +`del` + +## chr (1) + +`"" 33 40 for i i chr + next` + +-> stack should be "!"#$%&'(" + +`del` + +## chr (2) + +`-223 chr 0 chr` + +-> stack should be "!", "." + +`del` + +## num (1) + +`"!wait" num` + +-> stack should be 33 + +`del` + +## num (2) + +`"" num` + +-> stack should be 0 + +`del` + +## size (1) + +`"hello" size` + +-> stack should be 5 + +`del` + +## size (2) + +`"" size` + +-> stack should be 0 + +`del` + +## size, str->, ->str + +`"hello" str-> ->str size` + +-> stack should be 7 + +`del` + +## pos (1) + +`"my big string" "big" pos` + +-> stack should be 4 + +`del` + +## pos (2) + +`"my big string" "bOg" pos` + +-> stack should be 0 + +`del` + +## pos (3) + +`"my big string" pos` + +-> error should be 2 + +-> stack size should be 1 + +`del` + +## pos (4) + +`pos` + +-> error should be 2 + +`del` + +## sub (1) + +`"my string to sub" 4 6` + +`sub` + +-> stack should be "str" + +`del` + +## sub (2) + +`"my string to sub" -1 -2 sub` + +-> stack should be "m" + +`del` + +## sub (3) + +`"my string to sub" 0 0 sub` + +-> stack should be "m" + +`del` + +## sub (4) + +`"my string to sub" 6 5 sub` + +-> stack should be "" + +`del` + +## sub (5) + +`"my string to sub" 100 101 sub` + +-> stack should be "" + +`del` + +## sub (6) + +`"my string to sub" 14 100 sub` + +-> stack should be "sub" + +`del` diff --git a/test/70-test.txt b/test/070-test.md similarity index 50% rename from test/70-test.txt rename to test/070-test.md index 9f25b39..41daf0b 100644 --- a/test/70-test.txt +++ b/test/070-test.md @@ -1,287 +1,505 @@ -## TESTS -default del +# TESTS + +`default del` + +## and (1) + +`and` -# and (1) -and -> error should be 2 -1 and + +`1 and` + -> error should be 2 -del -# and (2) -0 0 and +`del` + +## and (2) + +`0 0 and` + -> stack size should be 1 + -> stack should be 0 -del -# and (3) -1 0 and +`del` + +## and (3) + +`1 0 and` + -> stack size should be 1 + -> stack should be 0 -del -# and (4) -0 1 and +`del` + +## and (4) + +`0 1 and` + -> stack size should be 1 + -> stack should be 0 -del -# and (5) -1 1 and +`del` + +## and (5) + +`1 1 and` + -> stack size should be 1 + -> stack should be 1 -del -# or (1) -or +`del` + +## or (1) + +`or` + -> error should be 2 -1 or + +`1 or` + -> error should be 2 -del -# or (2) -0 0 or +`del` + +## or (2) + +`0 0 or` + -> stack size should be 1 + -> stack should be 0 -del -# or (3) -0 1 or +`del` + +## or (3) + +`0 1 or` + -> stack size should be 1 --> stack should be 1 -del -# or (4) -1 0 or +-> stack should be 1 + +`del` + +## or (4) + +`1 0 or` + -> stack size should be 1 --> stack should be 1 -del -# or (5) -1 1 or +-> stack should be 1 + +`del` + +## or (5) + +`1 1 or` + -> stack size should be 1 --> stack should be 1 -del -# xor (1) -xor +-> stack should be 1 + +`del` + +## xor (1) + +`xor` + -> error should be 2 -1 xor + +`1 xor` + -> error should be 2 -del -# xor (2) -0 0 xor +`del` + +## xor (2) + +`0 0 xor` + -> stack size should be 1 + -> stack should be 0 -del -# xor (3) -0 1 xor +`del` + +## xor (3) + +`0 1 xor` + -> stack size should be 1 + -> stack should be 1 -del -# xor (4) -1 0 xor +`del` + +## xor (4) + +`1 0 xor` + -> stack size should be 1 + -> stack should be 1 -del -# xor (5) -1 1 xor +`del` + +## xor (5) + +`1 1 xor` + -> stack size should be 1 + -> stack should be 0 -del -# not (1) -not +`del` + +## not (1) + +`not` + -> error should be 2 -1 not + +`1 not` + -> stack size should be 1 --> stack should be 0 -del -# not (2) -0 not +-> stack should be 0 + +`del` + +## not (2) + +`0 not` + -> stack size should be 1 --> stack should be 1 -del -# > -0 0.1 > --> stack should be 0 -del -0.1 0 > -> stack should be 1 -del -1 1 > --> stack should be 0 -del -# >= -0 0.1 >= --> stack should be 0 -del -0.1 0 >= --> stack should be 1 -del -1 1 >= --> stack should be 1 -del +`del` -# < -0 0.1 < --> stack should be 1 -del -0.1 0 < --> stack should be 0 -del -1 1 < --> stack should be 0 -del +## > -# <= -0 0.1 <= --> stack should be 1 -del -0.1 0 <= --> stack should be 0 -del -1 1 <= --> stack should be 1 -del +`0 0.1 >` -# != -0 0.1 != --> stack should be 1 -del -1 1 != -> stack should be 0 -del -# == -0 0.1 == --> stack should be 0 -del -1 1 == --> stack should be 1 -del +`del` -# same -0 0.1 same --> stack should be 0 -del -1 1 same --> stack should be 1 -del +`0.1 0 >` -# complex != -(1,2) (3,4) != -> stack should be 1 -del -(1,2) (1,0) != --> stack should be 1 -del -(1,2) (0,2) != --> stack should be 1 -del -(1,2) (1,2) != --> stack should be 0 -del -# complex == -(1,2) (3,4) == --> stack should be 0 -del -(1,2) (1,0) == --> stack should be 0 -del -(1,2) (0,2) == --> stack should be 0 -del -(1,2) (1,2) == --> stack should be 1 -del +`del` -# complex same -(1,2) (3,4) same --> stack should be 0 -del -(1,2) (1,0) same --> stack should be 0 -del -(1,2) (0,2) same --> stack should be 0 -del -(1,2) (1,2) same --> stack should be 1 -del +`1 1 >` -# string > -"a" "b" > -> stack should be 0 -del -"b" "a" > --> stack should be 1 -del -"a" "a" > --> stack should be 0 -del -# string >= -"a" "b" >= --> stack should be 0 -del -"b" "a" >= --> stack should be 1 -del -"a" "a" >= --> stack should be 1 -del +`del` -# string < -"a" "b" < --> stack should be 1 -del -"b" "a" < --> stack should be 0 -del -"a" "a" < --> stack should be 0 -del +## >= -# string <= -"a" "b" <= --> stack should be 1 -del -"b" "a" <= --> stack should be 0 -del -"a" "a" <= --> stack should be 1 -del +`0 0.1 >=` -# string != -"a" "b" != --> stack should be 1 -del -"a" "a" != -> stack should be 0 -del -# string == -"a" "b" == --> stack should be 0 -del -"a" "a" == --> stack should be 1 -del +`del` + +`0.1 0 >=` -# string same -"a" "b" same --> stack should be 0 -del -"a" "a" same -> stack should be 1 -del + +`del` + +`1 1 >=` + +-> stack should be 1 + +`del` + +## < + +`0 0.1 <` + +-> stack should be 1 + +`del` + +`0.1 0 <` + +-> stack should be 0 + +`del` + +`1 1 <` + +-> stack should be 0 + +`del` + +## <= + +`0 0.1 <=` + +-> stack should be 1 + +`del` + +`0.1 0 <=` + +-> stack should be 0 + +`del` + +`1 1 <=` + +-> stack should be 1 + +`del` + +## != + +`0 0.1 !=` + +-> stack should be 1 + +`del` + +`1 1 !=` + +-> stack should be 0 + +`del` + +## == + +`0 0.1 ==` + +-> stack should be 0 + +`del` + +`1 1 ==` + +-> stack should be 1 + +`del` + +## same + +`0 0.1 same` + +-> stack should be 0 + +`del` + +`1 1 same` + +-> stack should be 1 + +`del` + +## complex != + +`(1,2) (3,4) !=` + +-> stack should be 1 + +`del` + +`(1,2) (1,0) !=` + +-> stack should be 1 + +`del` + +`(1,2) (0,2) !=` + +-> stack should be 1 + +`del` + +`(1,2) (1,2) !=` + +-> stack should be 0 + +`del` + +## complex == + +`(1,2) (3,4) ==` + +-> stack should be 0 + +`del` + +`(1,2) (1,0) ==` + +-> stack should be 0 + +`del` + +`(1,2) (0,2) ==` + +-> stack should be 0 + +`del` + +`(1,2) (1,2) ==` + +-> stack should be 1 + +`del` + +## complex same + +`(1,2) (3,4) same` + +-> stack should be 0 + +`del` + +`(1,2) (1,0) same` + +-> stack should be 0 + +`del` + +`(1,2) (0,2) same` + +-> stack should be 0 + +`del` + +`(1,2) (1,2) same` + +-> stack should be 1 + +`del` + +## string > + +`"a" "b" >` + +-> stack should be 0 + +`del` + +`"b" "a" >` + +-> stack should be 1 + +`del` + +`"a" "a" >` + +-> stack should be 0 + +`del` + +## string >= + +`"a" "b" >=` + +-> stack should be 0 + +`del` + +`"b" "a" >=` + +-> stack should be 1 + +`del` + +`"a" "a" >=` + +-> stack should be 1 + +`del` + +## string < + +`"a" "b" <` + +-> stack should be 1 + +`del` + +`"b" "a" <` + +-> stack should be 0 + +`del` + +`"a" "a" <` + +-> stack should be 0 + +`del` + +## string <= + +`"a" "b" <=` + +-> stack should be 1 + +`del` + +`"b" "a" <=` + +-> stack should be 0 + +`del` + +`"a" "a" <=` + +-> stack should be 1 + +`del` + +## string != + +`"a" "b" !=` + +-> stack should be 1 + +`del` + +`"a" "a" !=` + +-> stack should be 0 + +`del` + +## string == + +`"a" "b" ==` + +-> stack should be 0 + +`del` + +`"a" "a" ==` + +-> stack should be 1 + +`del` + +## string same + +`"a" "b" same` + +-> stack should be 0 + +`del` + +`"a" "a" same` + +-> stack should be 1 + +`del` diff --git a/test/080-store.md b/test/080-store.md new file mode 100644 index 0000000..63ff43e --- /dev/null +++ b/test/080-store.md @@ -0,0 +1,377 @@ +# STORE + +`default del` + +## symbol entry + +`'test'` + +-> stack size should be 1 + +-> stack should be 'test' + +`del` + +## symbol entry (2) + +`'test` + +-> stack size should be 1 + +-> stack should be 'test' + +`del` + +## symbol entry (3) + +`''` + +-> stack size should be 1 + +-> stack should be '' + +`del` + +## symbol entry (4) + +`'` + +-> stack size should be 1 + +-> stack should be '' + +`del` + +## sto (1) + +`1 'a' sto` + +-> stack size should be 0 + +`'a' a` + +-> stack should be 'a', 1 + +`del` + +## sto (2) + +`2 'a' sto a` + +-> stack should be 2 + +`del` + +## sto (3) + +`3 'b' sto b` + +-> stack should be 3 + +`del` + +## rcl (1) + +`'a' rcl` + +-> stack should be 2 + +`del` + +## rcl (2) + +`'b' rcl` + +-> stack should be 3 + +`del` + +## rcl (2) + +`'var' rcl` + +-> error should be 5 + +-> stack should be 'var' + +`del` + +## sto in prog then rcl + +`3 << 'r' sto >> eval r 'r' rcl` + +-> stack should be 3, 3 + +`del` + +## purge (1) + +`a 'a' purge a` + +-> stack should be 2, 'a' + +`del` + +## purge (2) + +`'a' purge` + +-> error should be 5 + +-> stack size should be 0 + +`del` + +## purge (3) + +`3 'a' sto a 'a' purge` + +-> stack should be 3 + +`del` + +## sto+ (1) + +`8 'a' sto` + +`2 'a' sto+` + +`a` + +-> stack should be 10 + +`del` + +## sto+ (2) + +`2 'a' sto` + +`'a' 2 sto+` + +`a` + +-> stack should be 4 + +`del` + +## sto+ (3) + +`'a' sto+` + +-> stack size should be 1 + +-> error should be 2 + +`del` + +## sto+ (4) + +`3 'zz' sto+` + +-> stack should be 3, 'zz' + +-> error should be 5 + +`del` + +## sto- (1) + +`2 'a' sto` + +`2 'a' sto-` + +`a` + +-> stack should be 0 + +`del` + +## sto- (2) + +`2 'a' sto` + +`'a' 2 sto-` + +`a` + +-> stack should be 0 + +`del` + +## sto- (3) + +`'a' sto-` + +-> stack size should be 1 + +-> error should be 2 + +`del` + +## sto- (4) + +`3 'zz' sto-` + +-> stack should be 3, 'zz' + +-> error should be 5 + +`del` + +## sto* (1) + +`2 'a' sto` + +`3 'a' sto*` + +`a` + +-> stack should be 6 + +`del` + +## sto* (2) + +`2 'a' sto` + +`'a' 3 sto*` + +`a` + +-> stack should be 6 + +`del` + +## sto* (3) + +`'a' sto*` + +-> stack size should be 1 + +-> error should be 2 + +`del` + +## sto* (4) + +`3 'zz' sto*` + +-> stack should be 3, 'zz' + +-> error should be 5 + +`del` + +## sto/ (1) + +`2 'a' sto` + +`6 'a' sto/` + +`a` + +-> stack should be 3 + +`del` + +## sto/ (2) + +`6 'a' sto` + +`'a' 2 sto/` + +`a` + +-> stack should be 3 + +`del` + +## sto/ (2) + +`'a' sto/` + +-> stack size should be 1 + +-> error should be 2 + +`del` + +## sto/ (4) + +`3 'zz' sto/` + +-> stack should be 3, 'zz' + +-> error should be 5 + +`del` + +## sneg (1) + +`7 'a' sto` + +`'a' sneg` + +`a` + +-> stack should be -7 + +`del` + +## sneg (2) + +`sneg` + +-> error should be 2 + +`del` + +## sneg (3) + +`'zz' sneg` + +-> error should be 5 + +-> stack should be 'zz' + +`del` + +## sinv (1) + +`4 'a' sto` + +`'a' sinv` + +`a` + +-> stack should be 0.25 + +`del` + +## sinv (2) + +`sinv` + +-> error should be 2 + +`del` + +## sinv (3) + +`'zz' sinv` + +-> error should be 5 + +-> stack should be 'zz' + +`del` + +## clusr + +`3.14 'abc' sto clusr 'abc' rcl` + +-> error should be 5 + +-> stack should be 'abc' + +`del` diff --git a/test/090-program.md b/test/090-program.md new file mode 100644 index 0000000..7c52f2d --- /dev/null +++ b/test/090-program.md @@ -0,0 +1,93 @@ +# PROGRAM + +`default del` + +## program + +`<< 'one' >>` + +-> stack size should be 1 + +-> stack should be << 'one' >> + +`del` + +## program (2) + +`<< 'one' 2` + +-> stack size should be 1 + +-> stack should be << 'one' 2 >> + +`del` + +## program (3) + +`<<` + +-> stack size should be 1 + +-> stack should be << >> + +`del` + +## program (4) + +`<< << << <<` + +-> stack size should be 1 + +-> stack should be << << << << >> >> >> >> + +`del` + +## program (5) + +`<< -> n << n 2 * >> >>` + +-> stack size should be 1 + +-> stack should be << -> n << n 2 * >> >> + +`del` + +## program imbrication + +`<< 1 << 2 >> >>` + +-> stack should be << 1 << 2 >> >> + +`del` + +## program evaluation + +`<< 1 << 2 >> >> dup eval` + +-> stack should be << 1 << 2 >> >>, 1, << 2 >> + +`del` + +## program 1 arg + +`default` + +`10` + +`<< -> n << 0 1 n for i i 2 * inv + next >> >>` + +`eval` + +-> stack should be 1.4644841269841269841269841269841269841 + +`del` + +## program several args + +`0 1 10 << -> u0 u1 n << u0 u1 1 n start dup2 + rot drop next swap drop >> >> eval` + +`eval` + +-> stack should be 89 + +`del` diff --git a/test/10-mode.txt b/test/10-mode.txt deleted file mode 100644 index 2663ad5..0000000 --- a/test/10-mode.txt +++ /dev/null @@ -1,47 +0,0 @@ -## MODE -default del - -# std (1) -del -38 std --> stack size should be 0 --> error should be 0 -del - -# std (2) -1 3 / --> stack should be 0.33333333333333333333333333333333333333 -del - -# fix (1) -10 fix -1 --> stack should be 1.0000000000 -del - -# fix (2) -1 4 fix --> stack should be 1.0000 -del - -# fix (3) --1 fix --> error should be 4 -del - -# sci (1) -1 12 sci --> stack should be 1.000000000000e+00 -del - -# sci (2) -1 2 sci --> stack should be 1.00e+00 -del - -# sci (3) --1 sci --> error should be 4 -del - -default diff --git a/test/100-complex.md b/test/100-complex.md new file mode 100644 index 0000000..d884b5f --- /dev/null +++ b/test/100-complex.md @@ -0,0 +1,1208 @@ +### COMPLEX + +`default del` + +## entry (1) + +`(1,2) ( 1,2) (1 ,2) (1, 2) (1,2 )` + +-> stack should be (1,2), (1,2), (1,2), (1,2), (1,2) + +`del` + +## entry (2) + +`(1.3,2.444555` + +-> stack should be (1.3,2.444555) + +`del` + +## entry (3) + +`(1,` + +-> stack should be (1,0) + +`del` + +## entry (4) + +`(nan,+inf)` + +-> stack should be (nan,inf) + +`del` + +## entry (5) + +`(0x1234,0x10.10)` + +-> stack should be (0x1.234p+12,0x1.01p+4) + +`del` + +## entry (6) + +`(0b11,0b101)` + +-> stack should be (3,5) + +`del` + +## add (1) + +`(1.2,2.3) (1,2) +` + +-> stack should be (2.2,4.3) + +`del` + +## add (2) + +`(1.2,2.3) (1,2)+` + +-> stack should be (2.2,4.3) + +`del` + +## add (3) + +`(1.2,2.3) 3+` + +-> stack should be (4.2,2.3) + +`del` + +## add (4) + +`3 (1.2,2.3)+` + +-> stack should be (4.2,2.3) + +`del` + +## sub (1) + +`(1.2,2.3) (2,2) -` + +-> stack should be (-0.8,0.3) + +`del` + +## sub (2) + +`(1.2,2.3) (1,2)-` + +-> stack should be (0.2,0.3) + +`del` + +## sub (3) + +`(1.2,2.3) 1-` + +-> stack should be (0.2,2.3) + +`del` + +## sub (4) + +`1 (1.2,2.3) -` + +-> stack should be (-0.2,2.3) + +`del` + +## mul (1) + +`(1,2) (3,4) *` + +-> stack should be (-5,10) + +`del` + +## mul (2) + +`(3,4) (1,2) *` + +-> stack should be (-5,10) + +`del` + +## mul (3) + +`(3,4) 2 *` + +-> stack should be (6,8) + +`del` + +## mul (3) + +`2 (3,4) *` + +-> stack should be (6,8) + +`del` + +## div (1) + +`(1,2) (3,4) /` + +-> stack should be (0.44,0.08) + +`del` + +## div (2) + +`(1,2) 2 /` + +-> stack should be (0.5,1) + +`del` + +## div (3) + +`2 (3,4) /` + +-> stack should be (0.24,-0.32) + +`del` + +## re (1) + +`(1.2,3.4) re` + +-> stack should be 1.2 + +`del` + +## re (2) + +`3 re` + +-> error should be 3 + +`del` + +## re (3) + +`re` + +-> error should be 2 + +`del` + +## im (1) + +`(1.2,3.4) im` + +-> stack should be 3.4 + +`del` + +## im (2) + +`3 re` + +-> error should be 3 + +`del` + +## im (3) + +`re` + +-> error should be 2 + +`del` + +## chs + +`(3.14,6.28) chs` + +-> stack should be (-3.14,-6.28) + +`del` + +## neg + +`(-3.14,-6.28) neg` + +-> stack should be (3.14,6.28) + +`del` + +## inv (1) + +`(2,4) inv` + +-> stack should be (0.1,-0.2) + +`del` + +## inv (2) + +`(0.1,-0.2) inv` + +-> stack should be (2,4) + +`del` + +## abs + +`(3,4) abs` + +-> stack should be 5 + +`del` + +## sign (1) + +`(1,0) sign` + +-> stack should be (1,0) + +`del` + +## sign (2) + +`(0,1) sign` + +-> stack should be (0,1) + +`del` + +## sign (3) + +`(3,-4) sign` + +-> stack should be (0.6,-0.8) + +`del` + +## sq (1) + +`(12,10) sq` + +-> stack should be (44,240) + +`del` + +## sqr (1) + +`(12,10) sq` + +-> stack should be (44,240) + +`del` + +## arg (1) + +`(1,1) arg pi 4 / ==` + +-> stack should be 1 + +`del` + +## arg (2) + +`1000 prec` + +`(-1,1) arg pi 3 * 4 / ==` + +-> stack should be 1 + +`default del` + +## arg (3) + +`1000 prec` + +`(1,-1) arg pi chs 4 / ==` + +-> stack should be 1 + +`default del` + +## arg (4) + +`1000 prec` + +`(-1,-1) arg pi -3 * 4 / ==` + +-> stack should be 1 + +`default del` + +## arg (5) + +`1000 prec` + +`(1,0) arg 0 ==` + +-> stack should be 1 + +`default del` + +## arg (6) + +`1000 prec` + +`(0,1) arg pi 2 / ==` + +-> stack should be 1 + +`default del` + +## arg (7) + +`1000 prec` + +`(-1,0) arg pi ==` + +-> stack should be 1 + +`default del` + +## arg (8) + +`1000 prec` + +`(0,-1) arg pi neg 2 / ==` + +-> stack should be 1 + +`default del` + +## conj + +`(1,2) conj dup conj` + +-> stack should be (1,-2), (1,2) + +`del` + +## r->c (1) + +`1 2 r->c` + +-> stack should be (1,2) + +`del` + +## r->c (2) + +`1 r->c` + +-> error should be 2 + +`del` + +## r->c (3) + +`r->c` + +-> error should be 2 + +`del` + +## r->c (3) + +`'1' '2' r->c` + +-> error should be 3 + +`del` + +## c->r (1) + +`(1,2) c->r` + +-> stack should be 1, 2 + +`del` + +## c->r (2) + +`c->r` + +-> error should be 2 + +`del` + +## c->r (3) + +`'4' c->r` + +-> error should be 3 + +`del` + +## r->p (1) + +`6 fix` + +`(1,2) r->p` + +-> stack should be (2.236068,1.107149) + +`del` + +## r->p (2) + +`19 fix` + +`1 r->p` + +-> error should be 3.000000 + +`del` + +## r->p (3) + +`r->p` + +-> error should be 2 + +`del` + +## r->p (4) + +`'1' '2' r->p` + +-> error should be 3 + +`del` + +## ^ (1) + +`6 fix` + +`(1,2) 2 ^` + +-> stack should be (-3.000000,4.000000) + +`del` + +## ^ (2) + +`(1,2) 4 ^` + +-> stack should be (-7.000000,-24.000000) + +`del` + +## ^ (3) + +`-3 .2 ^` + +-> stack should be (1.007818,0.732222) + +`del` + +## sqrt (1) + +`(3,4) sqrt` + +-> stack should be (2.000000,1.000000) + +`del` + +## sqrt (2) + +`-3 sqrt` + +-> stack should be (-0.000000,1.732051) + +`del` + +## sin (1) + +`(1,2) sin` + +-> stack should be (3.165779,1.959601) + +`del` + +## sin (2) + +`(1,-2) sin` + +-> stack should be (3.165779,-1.959601) + +`del` + +## sin (3) + +`(-1,-2) sin` + +-> stack should be (-3.165779,-1.959601) + +`del` + +## sin (4) + +`(-1,2) sin` + +-> stack should be (-3.165779,1.959601) + +`del` + +## asin (1) + +`(1,2) asin` + +-> stack should be (0.427079,1.528571) + +`del` + +## asin (2) + +`(1,-2) asin` + +-> stack should be (0.427079,-1.528571) + +`del` + +## asin (3) + +`(-1,-2) asin` + +-> stack should be (-0.427079,-1.528571) + +`del` + +## asin (4) + +`(-1,2) asin` + +-> stack should be (-0.427079,1.528571) + +`del` + +## cos (1) + +`(1,2) cos` + +-> stack should be (2.032723,-3.051898) + +`del` + +## cos (2) + +`(1,-2) cos` + +-> stack should be (2.032723,3.051898) + +`del` + +## cos (3) + +`(-1,-2) cos` + +-> stack should be (2.032723,-3.051898) + +`del` + +## cos (4) + +`(-1,2) sin` + +-> stack should be (-3.165779,1.959601) + +`del` + +## acos (1) + +`(1,2) acos` + +-> stack should be (1.143718,-1.528571) + +`del` + +## acos (2) + +`(1,-2) acos` + +-> stack should be (1.143718,1.528571) + +`del` + +## acos (3) + +`(-1,-2) acos` + +-> stack should be (1.997875,1.528571) + +`del` + +## acos (4) + +`(-1,2) acos` + +-> stack should be (1.997875,-1.528571) + +`del` + +## tan (1) + +`(1,2) tan` + +-> stack should be (0.033813,1.014794) + +`del` + +## tan (2) + +`(1,-2) tan` + +-> stack should be (0.033813,-1.014794) + +`del` + +## tan (3) + +`(-1,-2) tan` + +-> stack should be (-0.033813,-1.014794) + +`del` + +## tan (4) + +`(-1,2) tan` + +-> stack should be (-0.033813,1.014794) + +`del` + +## atan (1) + +`(1,2) atan` + +-> stack should be (1.338973,0.402359) + +`del` + +## atan (2) + +`(1,-2) atan` + +-> stack should be (1.338973,-0.402359) + +`del` + +## atan (3) + +`(-1,-2) atan` + +-> stack should be (-1.338973,-0.402359) + +`del` + +## atan (4) + +`(-1,2) atan` + +-> stack should be (-1.338973,0.402359) + +`del` + +## ln (1) + +`(1,2) ln` + +-> stack should be (0.804719,1.107149) + +`del` + +## ln (2) + +`(1,-2) ln` + +-> stack should be (0.804719,-1.107149) + +`del` + + +## ln (3) + +`(-1,-2) ln` + +-> stack should be (0.804719,-2.034444) + +`del` + +## ln (4) + +`(-1,2) ln` + +-> stack should be (0.804719,2.034444) + +`del` + +## lnp1 (1) + +`(1,2) lnp1` + +`(1,2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## lnp1 (2) + +`(1,-2) lnp1` + +`(1,-2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## lnp1 (3) + +`(-1,-2) lnp1` + +`(-1,-2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## lnp1 (4) + +`(-1,2) lnp1` + +`(-1,2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## log (1) + +`(1,2) log` + +-> stack should be (0.804719,1.107149) + +`del` + +## log (2) + +`(1,-2) log` + +-> stack should be (0.804719,-1.107149) + +`del` + +## log (3) + +`(-1,-2) log` + +-> stack should be (0.804719,-2.034444) + +`del` + +## log (4) + +`(-1,2) log` + +-> stack should be (0.804719,2.034444) + +`del` + +## log10 (1) + +`(1,2) log10` + +-> stack should be (0.349485,0.480829) + +`del` + +## log10 (2) + +`(1,-2) log10` + +-> stack should be (0.349485,-0.480829) + +`del` + +## log10 (3) + +`(-1,-2) log10` + +-> stack should be (0.349485,-0.883548) + +`del` + +## log10 (4) + +`(-1,2) log10` + +-> stack should be (0.349485,0.883548) + +`del` + +## log2 (1) + +`(1,2) log2` + +-> stack should be (1.160964,1.597278) + +`del` + +## log2 (2) + +`(1,-2) log2` + +-> stack should be (1.160964,-1.597278) + +`del` + +## log2 (3) + +`(-1,-2) log2` + +-> stack should be (1.160964,-2.935082) + +`del` + +## log2 (4) + +`(-1,2) log2` + +-> stack should be (1.160964,2.935082) + +`del` + +## exp (1) + +`(1,2) exp` + +-> stack should be (-1.131204,2.471727) + +`del` + +## exp (2) + +`(1,-2) exp` + +-> stack should be (-1.131204,-2.471727) + +`del` + +## exp (3) + +`(-1,-2) exp` + +-> stack should be (-0.153092,-0.334512) + +`del` + +## exp (4) + +`(-1,2) exp` + +-> stack should be (-0.153092,0.334512) + +`del` + +## expm (1) + +`(1,2) expm` + +`(1,2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## expm (2) + +`(1,-2) expm` + +`(1,-2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## expm (3) + +`(-1,-2) expm` + +`(-1,-2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## expm (4) + +`(-1,2) expm` + +`(-1,2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## alog2 (1) + +`(1,2) alog2` + +-> stack should be (0.366914,1.966055) + +`del` + +## alog2 (2) + +`(1,-2) alog2` + +-> stack should be (0.366914,-1.966055) + +`del` + +## alog2 (3) + +`(-1,-2) alog2` + +-> stack should be (0.091728,-0.491514) + +`del` + +## alog2 (4) + +`(-1,2) alog2` + +-> stack should be (0.091728,0.491514) + +`del` + +## alog10 (1) + +`(1,2) alog10` + +-> stack should be (-1.070135,-9.942576) + +`del` + +## alog10 (2) + +`(1,-2) alog10` + +-> stack should be (-1.070135,9.942576) + +`del` + +## alog10 (3) + +`(-1,-2) alog10` + +-> stack should be (-0.010701,0.099426) + +`del` + +## alog10 (4) + +`(-1,2) alog10` + +-> stack should be (-0.010701,-0.099426) + +`del` + +## sinh (1) + +`(1,2) sinh` + +-> stack should be (-0.489056,1.403119) + +`del` + +## sinh (2) + +`(1,-2) sinh` + +-> stack should be (-0.489056,-1.403119) + +`del` + +## sinh (3) + +`(-1,-2) sinh` + +-> stack should be (0.489056,-1.403119) + +`del` + +## sinh (4) + +`(-1,2) sinh` + +-> stack should be (0.489056,1.403119) + +`del` + +## asinh (1) + +`(1,2) asinh` + +-> stack should be (1.469352,1.063440) + +`del` + +## asinh (2) + +`(1,-2) asinh` + +-> stack should be (1.469352,-1.063440) + +`del` + +## asinh (3) + +`(-1,-2) asinh` + +-> stack should be (-1.469352,-1.063440) + +`del` + +## asinh (4) + +`(-1,2) asinh` + +-> stack should be (-1.469352,1.063440) + +`del` + +## cosh (1) + +`(1,2) cosh` + +-> stack should be (-0.489056,1.403119) + +`del` + +## cosh (2) + +`(1,-2) cosh` + +-> stack should be (-0.489056,-1.403119) + +`del` + +## cosh (3) + +`(-1,-2) cosh` + +-> stack should be (0.489056,-1.403119) + +`del` + +## cosh (4) + +`(-1,2) cosh` + +-> stack should be (0.489056,1.403119) + +`del` + +## acosh (1) + +`(1,2) acosh` + +-> stack should be (1.528571,1.143718) + +`del` + +## acosh (2) + +`(1,-2) acosh` + +-> stack should be (1.528571,-1.143718) + +`del` + +## acosh (3) + +`(-1,-2) acosh` + +-> stack should be (-1.528571,1.997875) + +`del` + +## acosh (4) + +`(-1,2) acosh` + +-> stack should be (-1.528571,-1.997875) + +`del` + +## tanh (1) + +`(1,2) tanh` + +-> stack should be (0.564133,-0.217934) + +`del` + +## tanh (2) + +`(1,-2) tanh` + +-> stack should be (0.564133,0.217934) + +`del` + +## tanh (3) + +`(-1,-2) tanh` + +-> stack should be (-0.564133,0.217934) + +`del` + +## tanh (4) + +`(-1,2) tanh` + +-> stack should be (-0.564133,-0.217934) + +`del` + +## atanh (1) + +`(1,2) atanh` + +-> stack should be (0.173287,1.178097) + +`del` + +## atanh (2) + +`(1,-2) atanh` + +-> stack should be (0.173287,-1.178097) + +`del` + +## atanh (3) + +`(-1,-2) atanh` + +-> stack should be (-0.173287,-1.178097) + +`del` + +## atanh (4) + +`(-1,2) atanh` + +-> stack should be (-0.173287,1.178097) + +`del` diff --git a/test/100-complex.txt b/test/100-complex.txt deleted file mode 100644 index 52f25b3..0000000 --- a/test/100-complex.txt +++ /dev/null @@ -1,758 +0,0 @@ -## COMPLEX - -default del - -# entry (1) -(1,2) ( 1,2) (1 ,2) (1, 2) (1,2 ) --> stack should be (1,2), (1,2), (1,2), (1,2), (1,2) -del - -# entry (2) -(1.3,2.444555 --> stack should be (1.3,2.444555) -del - -# entry (3) -(1, --> stack should be (1,0) -del - -# entry (4) -(nan,+inf) --> stack should be (nan,inf) -del - -# entry (5) -(0x1234,0x10.10) --> stack should be (0x1.234p+12,0x1.01p+4) -del - -# entry (6) -(0b11,0b101) --> stack should be (3,5) -del - -# add (1) -(1.2,2.3) (1,2) + --> stack should be (2.2,4.3) -del - -# add (2) -(1.2,2.3) (1,2)+ --> stack should be (2.2,4.3) -del - -# add (3) -(1.2,2.3) 3+ --> stack should be (4.2,2.3) -del - -# add (4) -3 (1.2,2.3)+ --> stack should be (4.2,2.3) -del - -# sub (1) -(1.2,2.3) (2,2) - --> stack should be (-0.8,0.3) -del - -# sub (2) -(1.2,2.3) (1,2)- --> stack should be (0.2,0.3) -del - -# sub (3) -(1.2,2.3) 1- --> stack should be (0.2,2.3) -del - -# sub (4) -1 (1.2,2.3) - --> stack should be (-0.2,2.3) -del - -# mul (1) -(1,2) (3,4) * --> stack should be (-5,10) -del - -# mul (2) -(3,4) (1,2) * --> stack should be (-5,10) -del - -# mul (3) -(3,4) 2 * --> stack should be (6,8) -del - -# mul (3) -2 (3,4) * --> stack should be (6,8) -del - -# div (1) -(1,2) (3,4) / --> stack should be (0.44,0.08) -del - -# div (2) -(1,2) 2 / --> stack should be (0.5,1) -del - -# div (3) -2 (3,4) / --> stack should be (0.24,-0.32) -del - -# re (1) -(1.2,3.4) re --> stack should be 1.2 -del - -# re (2) -3 re --> error should be 3 -del - -# re (3) -re --> error should be 2 -del - -# im (1) -(1.2,3.4) im --> stack should be 3.4 -del - -# im (2) -3 re --> error should be 3 -del - -# im (3) -re --> error should be 2 -del - -# chs -(3.14,6.28) chs --> stack should be (-3.14,-6.28) -del - -# neg -(-3.14,-6.28) neg --> stack should be (3.14,6.28) -del - -# inv (1) -(2,4) inv --> stack should be (0.1,-0.2) -del - -# inv (2) -(0.1,-0.2) inv --> stack should be (2,4) -del - -# abs -(3,4) abs --> stack should be 5 -del - -# sign (1) -(1,0) sign --> stack should be (1,0) -del - -# sign (2) -(0,1) sign --> stack should be (0,1) -del - -# sign (3) -(3,-4) sign --> stack should be (0.6,-0.8) -del - -# sq (1) -(12,10) sq --> stack should be (44,240) -del - -# sqr (1) -(12,10) sq --> stack should be (44,240) -del - -# arg (1) -(1,1) arg pi 4 / == --> stack should be 1 -del - -# arg (2) -1000 prec -(-1,1) arg pi 3 * 4 / == --> stack should be 1 -default -del - -# arg (3) -1000 prec -(1,-1) arg pi chs 4 / == --> stack should be 1 -default -del - -# arg (4) -1000 prec -(-1,-1) arg pi -3 * 4 / == --> stack should be 1 -default -del - -# arg (5) -1000 prec -(1,0) arg 0 == --> stack should be 1 -default -del - -# arg (6) -1000 prec -(0,1) arg pi 2 / == --> stack should be 1 -default -del - -# arg (7) -1000 prec -(-1,0) arg pi == --> stack should be 1 -default -del - -# arg (8) -1000 prec -(0,-1) arg pi neg 2 / == --> stack should be 1 -default -del - -# conj -(1,2) conj dup conj --> stack should be (1,-2), (1,2) -del - -# r->c (1) -1 2 r->c --> stack should be (1,2) -del - -# r->c (2) -1 r->c --> error should be 2 -del - -# r->c (3) -r->c --> error should be 2 -del - -# r->c (3) -'1' '2' r->c --> error should be 3 -del - -# c->r (1) -(1,2) c->r --> stack should be 1, 2 -del - -# c->r (2) -c->r --> error should be 2 -del - -# c->r (3) -'4' c->r --> error should be 3 -del - -# r->p (1) -6 fix -(1,2) r->p --> stack should be (2.236068,1.107149) -del - -# r->p (2) -19 fix -1 r->p --> error should be 3.000000 -del - -# r->p (3) -r->p --> error should be 2 -del - -# r->p (4) -'1' '2' r->p --> error should be 3 -del - -# ^ (1) -6 fix -(1,2) 2 ^ --> stack should be (-3.000000,4.000000) -del - -# ^ (2) -(1,2) 4 ^ --> stack should be (-7.000000,-24.000000) -del - -# ^ (3) --3 .2 ^ --> stack should be (1.007818,0.732222) -del - -# sqrt (1) -(3,4) sqrt --> stack should be (2.000000,1.000000) -del - -# sqrt (2) --3 sqrt --> stack should be (-0.000000,1.732051) -del - -# sin (1) -(1,2) sin --> stack should be (3.165779,1.959601) -del - -# sin (2) -(1,-2) sin --> stack should be (3.165779,-1.959601) -del - -# sin (3) -(-1,-2) sin --> stack should be (-3.165779,-1.959601) -del - -# sin (4) -(-1,2) sin --> stack should be (-3.165779,1.959601) -del - -# asin (1) -(1,2) asin --> stack should be (0.427079,1.528571) -del - -# asin (2) -(1,-2) asin --> stack should be (0.427079,-1.528571) -del - -# asin (3) -(-1,-2) asin --> stack should be (-0.427079,-1.528571) -del - -# asin (4) -(-1,2) asin --> stack should be (-0.427079,1.528571) -del - -# cos (1) -(1,2) cos --> stack should be (2.032723,-3.051898) -del - -# cos (2) -(1,-2) cos --> stack should be (2.032723,3.051898) -del - -# cos (3) -(-1,-2) cos --> stack should be (2.032723,-3.051898) -del - -# cos (4) -(-1,2) sin --> stack should be (-3.165779,1.959601) -del - -# acos (1) -(1,2) acos --> stack should be (1.143718,-1.528571) -del - -# acos (2) -(1,-2) acos --> stack should be (1.143718,1.528571) -del - -# acos (3) -(-1,-2) acos --> stack should be (1.997875,1.528571) -del - -# acos (4) -(-1,2) acos --> stack should be (1.997875,-1.528571) -del - -# tan (1) -(1,2) tan --> stack should be (0.033813,1.014794) -del - -# tan (2) -(1,-2) tan --> stack should be (0.033813,-1.014794) -del - -# tan (3) -(-1,-2) tan --> stack should be (-0.033813,-1.014794) -del - -# tan (4) -(-1,2) tan --> stack should be (-0.033813,1.014794) -del - -# atan (1) -(1,2) atan --> stack should be (1.338973,0.402359) -del - -# atan (2) -(1,-2) atan --> stack should be (1.338973,-0.402359) -del - -# atan (3) -(-1,-2) atan --> stack should be (-1.338973,-0.402359) -del - -# atan (4) -(-1,2) atan --> stack should be (-1.338973,0.402359) -del - -# ln (1) -(1,2) ln --> stack should be (0.804719,1.107149) -del - -# ln (2) -(1,-2) ln --> stack should be (0.804719,-1.107149) -del - -# ln (3) -(-1,-2) ln --> stack should be (0.804719,-2.034444) -del - -# ln (4) -(-1,2) ln --> stack should be (0.804719,2.034444) -del - -# lnp1 (1) -(1,2) lnp1 -(1,2) 1 + ln == --> stack should be 1.000000 -del - -# lnp1 (2) -(1,-2) lnp1 -(1,-2) 1 + ln == --> stack should be 1.000000 -del - -# lnp1 (3) -(-1,-2) lnp1 -(-1,-2) 1 + ln == --> stack should be 1.000000 -del - -# lnp1 (4) -(-1,2) lnp1 -(-1,2) 1 + ln == --> stack should be 1.000000 -del - -# log (1) -(1,2) log --> stack should be (0.804719,1.107149) -del - -# log (2) -(1,-2) log --> stack should be (0.804719,-1.107149) -del - -# log (3) -(-1,-2) log --> stack should be (0.804719,-2.034444) -del - -# log (4) -(-1,2) log --> stack should be (0.804719,2.034444) -del - -# log10 (1) -(1,2) log10 --> stack should be (0.349485,0.480829) -del - -# log10 (2) -(1,-2) log10 --> stack should be (0.349485,-0.480829) -del - -# log10 (3) -(-1,-2) log10 --> stack should be (0.349485,-0.883548) -del - -# log10 (4) -(-1,2) log10 --> stack should be (0.349485,0.883548) -del - -# log2 (1) -(1,2) log2 --> stack should be (1.160964,1.597278) -del - -# log2 (2) -(1,-2) log2 --> stack should be (1.160964,-1.597278) -del - -# log2 (3) -(-1,-2) log2 --> stack should be (1.160964,-2.935082) -del - -# log2 (4) -(-1,2) log2 --> stack should be (1.160964,2.935082) -del - -# exp (1) -(1,2) exp --> stack should be (-1.131204,2.471727) -del - -# exp (2) -(1,-2) exp --> stack should be (-1.131204,-2.471727) -del - -# exp (3) -(-1,-2) exp --> stack should be (-0.153092,-0.334512) -del - -# exp (4) -(-1,2) exp --> stack should be (-0.153092,0.334512) -del - -# expm (1) -(1,2) expm -(1,2) exp 1 - == --> stack should be 1.000000 -del - -# expm (2) -(1,-2) expm -(1,-2) exp 1 - == --> stack should be 1.000000 -del - -# expm (3) -(-1,-2) expm -(-1,-2) exp 1 - == --> stack should be 1.000000 -del - -# expm (4) -(-1,2) expm -(-1,2) exp 1 - == --> stack should be 1.000000 -del - -# alog2 (1) -(1,2) alog2 --> stack should be (0.366914,1.966055) -del - -# alog2 (2) -(1,-2) alog2 --> stack should be (0.366914,-1.966055) -del - -# alog2 (3) -(-1,-2) alog2 --> stack should be (0.091728,-0.491514) -del - -# alog2 (4) -(-1,2) alog2 --> stack should be (0.091728,0.491514) -del - -# alog10 (1) -(1,2) alog10 --> stack should be (-1.070135,-9.942576) -del - -# alog10 (2) -(1,-2) alog10 --> stack should be (-1.070135,9.942576) -del - -# alog10 (3) -(-1,-2) alog10 --> stack should be (-0.010701,0.099426) -del - -# alog10 (4) -(-1,2) alog10 --> stack should be (-0.010701,-0.099426) -del - -# sinh (1) -(1,2) sinh --> stack should be (-0.489056,1.403119) -del - -# sinh (2) -(1,-2) sinh --> stack should be (-0.489056,-1.403119) -del - -# sinh (3) -(-1,-2) sinh --> stack should be (0.489056,-1.403119) -del - -# sinh (4) -(-1,2) sinh --> stack should be (0.489056,1.403119) -del - -# asinh (1) -(1,2) asinh --> stack should be (1.469352,1.063440) -del - -# asinh (2) -(1,-2) asinh --> stack should be (1.469352,-1.063440) -del - -# asinh (3) -(-1,-2) asinh --> stack should be (-1.469352,-1.063440) -del - -# asinh (4) -(-1,2) asinh --> stack should be (-1.469352,1.063440) -del - -# cosh (1) -(1,2) cosh --> stack should be (-0.489056,1.403119) -del - -# cosh (2) -(1,-2) cosh --> stack should be (-0.489056,-1.403119) -del - -# cosh (3) -(-1,-2) cosh --> stack should be (0.489056,-1.403119) -del - -# cosh (4) -(-1,2) cosh --> stack should be (0.489056,1.403119) -del - -# acosh (1) -(1,2) acosh --> stack should be (1.528571,1.143718) -del - -# acosh (2) -(1,-2) acosh --> stack should be (1.528571,-1.143718) -del - -# acosh (3) -(-1,-2) acosh --> stack should be (-1.528571,1.997875) -del - -# acosh (4) -(-1,2) acosh --> stack should be (-1.528571,-1.997875) -del - -# tanh (1) -(1,2) tanh --> stack should be (0.564133,-0.217934) -del - -# tanh (2) -(1,-2) tanh --> stack should be (0.564133,0.217934) -del - -# tanh (3) -(-1,-2) tanh --> stack should be (-0.564133,0.217934) -del - -# tanh (4) -(-1,2) tanh --> stack should be (-0.564133,-0.217934) -del - -# atanh (1) -(1,2) atanh --> stack should be (0.173287,1.178097) -del - -# atanh (2) -(1,-2) atanh --> stack should be (0.173287,-1.178097) -del - -# atanh (3) -(-1,-2) atanh --> stack should be (-0.173287,-1.178097) -del - -# atanh (4) -(-1,2) atanh --> stack should be (-0.173287,1.178097) -del diff --git a/test/120-time.txt b/test/110-time.md similarity index 50% rename from test/120-time.txt rename to test/110-time.md index 2364a1f..57b9bf6 100644 --- a/test/120-time.txt +++ b/test/110-time.md @@ -1,25 +1,41 @@ -## date and time -default del +# date and time + +`default del` + +## date + +`date type` -# date -date type -> error should be 0 --> stack should be "number" -del -# time -time type +-> stack should be "number" + +`del` + +## time + +`time type` + -> error should be 0 --> stack should be "number" -del -# ticks (1) -ticks type +-> stack should be "number" + +`del` + +## ticks (1) + +`ticks type` + -> error should be 0 --> stack should be "number" -del -# ticks (2) -ticks ticks - 0 <= +-> stack should be "number" + +`del` + +## ticks (2) + +`ticks ticks - 0 <=` + -> stack should be 1 -del + +`del` diff --git a/test/21-parse-string.txt b/test/21-parse-string.txt deleted file mode 100644 index 0249e41..0000000 --- a/test/21-parse-string.txt +++ /dev/null @@ -1,62 +0,0 @@ -## PARSE STRING -default del - -# type -"hey" type --> stack should be "string" -del - -# void 1 -"" --> stack should be "" -del - -# void 2 -" --> stack should be "" -del - -# string -"abcd" --> stack should be "abcd" -del - -# unterminated -"abcd --> stack should be "abcd" -del - -# unterminated 2 -"abcd" "abc --> stack should be "abcd", "abc" -del - -# spaces -"abc d" --> stack should be "abc d" -del - -# spaces 2 -" abcd " --> stack should be " abcd " -del - -# spaces 3 -" abcd " "def" "gh ij" --> stack should be " abcd ", "def", "gh ij" -del - -# spaces 4 -" . abcd . ;; " --> stack should be " . abcd . ;; " -del - -# spaces 5 -" . abcd . ;; " "ab c --> stack should be " . abcd . ;; ", "ab c" -del - -# nested types -"1.0 swap drop --> stack should be "1.0 swap drop" -del diff --git a/test/22-parse-symbol.txt b/test/22-parse-symbol.txt deleted file mode 100644 index 01a6ee9..0000000 --- a/test/22-parse-symbol.txt +++ /dev/null @@ -1,67 +0,0 @@ -## PARSE SYMBOL -default del - -# type -'hey' type --> stack should be "symbol" -del - -# void 1 -'' --> stack should be '' -del - -# void 2 -' --> stack should be '' -del - -# symbol -'abcd' --> stack should be 'abcd' -del - -# unterminated -'abcd --> stack should be 'abcd' -del - -# unterminated 2 -'abcd' 'abc --> stack should be 'abcd', 'abc' -del - -# spaces -'abc d' --> stack should be 'abc d' -del - -# spaces 2 -' abcd ' --> stack should be ' abcd ' -del - -# spaces 3 -' abcd ' 'def' 'gh ij' --> stack should be ' abcd ', 'def', 'gh ij' -del - -# spaces 4 -' . abcd . ;; ' --> stack should be ' . abcd . ;; ' -del - -# spaces 5 -' . abcd . ;; ' 'ab c --> stack should be ' . abcd . ;; ', 'ab c' -del - -# nested types 1 -'1' --> stack should be '1' -del - -# nested types 2 -'1.0 swap drop --> stack should be '1.0 swap drop' -del diff --git a/test/23-parse-number.txt b/test/23-parse-number.txt deleted file mode 100644 index fde5c19..0000000 --- a/test/23-parse-number.txt +++ /dev/null @@ -1,47 +0,0 @@ -## PARSE NUMBER -default del - -# type -1.0 type --> stack should be "number" -del - -# numb 1 -3.14 +3.14 -3.14 --> stack should be 3.14, 3.14, -3.14 -del - -# spaces - -3.14 -3 .14 --> stack should be -3.14, -3, 0.14 -del - -# exp entry -+3.14e2 --> stack should be 314 -del - -# inf nan -+inf inf -inf nan --> stack should be inf, inf, -inf, nan -del - -# hex -0x10 0X10 --> stack should be 16, 16 -del - -# hex err -0x 0X --> stack should be '0x', '0X' -del - -# bin -0b1101 0b0 --> stack should be 13, 0 -del - -# bin err -0b --> stack should be '0b' -del diff --git a/test/25-parse-other.txt b/test/25-parse-other.txt deleted file mode 100644 index b532ee5..0000000 --- a/test/25-parse-other.txt +++ /dev/null @@ -1,19 +0,0 @@ -## PARSE COMPLEX -default del - -# some command -+ --> error should be 2 -del - -# some command 2 - + --> error should be 2 -del - -# some command 3 - + - --> error should be 2 -del - -# TODO test all keywords with errors diff --git a/test/26-parse-program.txt b/test/26-parse-program.txt deleted file mode 100644 index 4469536..0000000 --- a/test/26-parse-program.txt +++ /dev/null @@ -1,53 +0,0 @@ -## PARSE SYMBOL -default del - -# type -<< I >> type --> stack should be "program" -del - -# prog 1 -<< I am a program >> --> stack should be «I am a program» -del - -# prog 2 -<> --> stack should be «I am a program» -del - -# prog 3 -<< I am a program >> --> stack should be «I am a program» -del - -# prog 4 -«I am a program» --> stack should be «I am a program» -del - -# prog 5 -« I am a program » --> stack should be «I am a program» -del - -# unterminated 1 -<< prog --> stack should be «prog» -del - -# unterminated 2 -« prog --> stack should be «prog» -del - -# unterminated 3 -<< prog> --> stack should be «prog>» -del - -# unterminated 4 -<< -« --> stack should be «», «» -del diff --git a/test/30-branch.txt b/test/30-branch.txt deleted file mode 100644 index 20810b1..0000000 --- a/test/30-branch.txt +++ /dev/null @@ -1,397 +0,0 @@ -## BRANCH -default del - -# if then else end (1) -1 if then 'ok' end --> stack should be 'ok' -del - -# if then else end (2) -1 if 'before' then 'ok' end --> stack should be 'before', 'ok' -del - -# if then else end (3) -0 if then 'ok' end --> stack size should be 0 -del - -# if then else end (4) -0 if then 'ok' end --> stack size should be 0 -del - -# if then else end (5) -1 if then 'ok' else 'KO' end --> stack should be 'ok' -del - -# if then else end (6) -1 if then 'ok' 'dokey' else 'KO' end --> stack should be 'ok', 'dokey' -del - -# if then else end (7) -0 if then 'ok' else 'KO' end --> stack should be 'KO' -del - -# if then else end - error case (1) -if then end --> error should be 2 -del - -# if then else end - error case (2) -0 if then --> error should be 11 -del - -# if then else end - error case (3) -0 if end --> error should be 11 -del - -# if then else end - error case (4) -0 if end --> error should be 11 -del - -# if then else end - error case (5) -then --> error should be 11 -del - -# if then else end - error case (6) -1 if --> error should be 11 -del - -# if then else end - error case (7) -else --> error should be 11 -del - -# if then else end - error case (8) -end --> error should be 11 -del - -# if then else end - error case (9) -"1" if then end --> error should be 3 -del - -# ift (1) -1 'ok' ift --> stack should be 'ok' -del - -# ift (2) -0 'ok' ift --> stack size should be 0 -del - -# ift (3) -'ok' ift --> error should be 2 --> stack size should be 1 -del - -# ift (4) -ift --> error should be 2 --> stack size should be 0 -del - -# ifte (1) -1 'ok' 'nok' ifte --> stack should be 'ok' -del - -# ifte (2) -0 'ok' 'nok' ifte --> stack should be 'nok' -del - -# ifte (3) -'ok' 'nok' ifte --> error should be 2 --> stack size should be 2 -del - -# ifte (4) -'nok' ifte --> error should be 2 --> stack size should be 1 -del - -# ifte (5) -ifte --> error should be 2 --> stack size should be 0 -del - -# start next (1) -1 2 start 0 next --> stack should be 0, 0 -del - -# start next (2) -2 1 start 0 next --> stack size should be 0 -del - -# start next (3) --2 -1 start 0 next --> stack should be 0, 0 -del - -# start next (4) --1 -2 start 0 next --> stack size should be 0 -del - -# start next (5) -1 1 start 0 next --> stack should be 0 -del - -# start next - error case (1) -1 start next -->error should be 2 -del - -# start next - error case (2) -start next -->error should be 2 -del - -# start next - error case (3) -start -->error should be 11 -del - -# start next - error case (4) -next -->error should be 11 -del - -# start next - error case (5) -"1" 2 start next -->error should be 3 -del - -# start next - error case (5) -1 "2" start next -->error should be 3 -del - -# for next (1) -23 27 for i i next --> stack should be 23, 24, 25, 26, 27 -del - -# for next (2) -1 1 for i i next --> stack should be 1 -del - -# for next (3) -27 23 for i i next --> stack size should be 0 -del - -# for next (4) --2 -1 for i i next --> stack should be -2, -1 -del - -# for next (5) --1 -2 for i i next --> stack size should be 0 -del - -# for next - error case (1) -1 for i i next --> error should be 2 -del - -# for next - error case (2) -for i i next --> error should be 2 -del - -# for next - error case (3) -"1" 2 for i i next --> error should be 3 -del - -# for next - error case (4) -1 "2" for i i next --> error should be 3 -del - -# for next - error case (5) -1 2 for i i --> error should be 11 -del - -# for next - error case (6) -for --> error should be 11 -del - -# for step (1) -23 27 for i i 1 step --> stack should be 23, 24, 25, 26, 27 -del - -# for step (2) -0 1 for i i 0.25 step --> stack should be 0, 0.25, 0.5, 0.75, 1 -del - -# for step (3) --1 0 for i i 0.25 step --> stack should be -1, -0.75, -0.5, -0.25, -0 -del - -# for step (4) -0 -1 for i i 0.25 step --> stack size should be 0 -del - -# for step (5) -0 -1 for i i -0.25 step --> stack size should be 0 -del - -# for step (6) - check boundary integration -1 2 for i i 0.2 step --> stack should be 1, 1.2, 1.4, 1.6, 1.8, 2 -del - -# for step (7) - check boundary integration -1 2 for i i 0.5 step --> stack should be 1, 1.5, 2 -del - -# for step - error case (1) -0 1 for i i "0.5" step --> error should be 3 -del - -# for step - error case (2) -step --> error should be 11 -del - -# do..unti (1) -do 'ok' unti 1 end --> stack should be 'ok' -del - -# do..unti (2) -do unti 1 end --> stack size should be 0 -del - -# do..unti (3) -1 'a' sto do a unti a 0 > end --> stack should be 1 -del - -# do..unti (4) -1 'a' sto do a 'a' 1 sto+ unti a 3 > end --> stack should be 1, 2, 3 -del - -# do..unti (5) -"" 0 'a' sto do 'a' 1 sto+ 0 a for b b ->str + next unti a 3 > end --> stack should be "01012012301234" -del - -# do..unti error case (1) -do --> error should be 11 -del - -# do..unti error case (2) -do 8 end --> error should be 11 -del - -# do..unti error case (3) -unti --> error should be 11 -del - -# do..unti error case (4) -do 3 unti --> error should be 11 -del - -# do..unti error case (5) -unti 1 end --> error should be 11 -del - -# do..unti error case (6) -do 3 repeat 8 end --> error should be 11 -del - -# do..unti error case (7) -do 3 until 8 until 9 end --> error should be 11 -del - -# while..repeat (1) -while 0 repeat ok end --> stack size should be 0 -del - -# while..repeat (2) -2 while dup 0.1 > repeat dup 2 / end --> stack should be 2, 1, 0.5, 0.25, 0.125, 0.0625 -del - -# while..repeat (3) -"" 0 'a' sto while a 3 < repeat 'a' 1 sto+ 0 a for b b ->str + next end --> stack should be "010120123" -del - -# while..repeat error case (1) -while --> error should be 11 -del - -# while..repeat error case (2) -while 3 end --> error should be 11 -del - -# while..repeat error case (3) -repeat --> error should be 11 -del - -# while..repeat error case (4) -while 1 repeat --> error should be 11 -del - -# while..repeat error case (5) -repeat 1 end --> error should be 11 -del - -# while..repeat error case (6) -while 3 repeat 8 repeat 9 end --> error should be 11 -del - -# while..repeat error case (7) -while 3 until 8 end --> error should be 11 -del diff --git a/test/40-stack.txt b/test/40-stack.txt deleted file mode 100644 index a19d1d0..0000000 --- a/test/40-stack.txt +++ /dev/null @@ -1,177 +0,0 @@ -## STACK TEST -default del - -# entry depth (1) -1 depth --> stack size should be 2 - -# entry depth (2) -1 del depth --> stack should be 0 -del - -# swap -1 2 swap --> stack size should be 2 --> stack should be 2, 1 -del - -# swap with filled stack -5 6 1 2 swap --> stack size should be 4 --> stack should be 5, 6, 2, 1 -del - -# swap error -5 swap --> stack size should be 1 --> error should 2 -del - -# drop -1 2 3 drop --> stack size should be 2 --> stack should be 1, 2 -del - -# drop2 -1 2 3 -drop2 --> stack size should be 1 --> stack should be 1 -del - -# drop error -drop --> error should be 2 -del - -# drop2 error (1) -drop2 --> error should be 2 -del - -# drop2 error (2) -1 drop2 --> error should be 2 -del - -# test dup -1 dup --> stack size should be 2 --> stack should be 1, 1 -del - -# test dup2 -1 2 dup2 --> stack size should be 4 --> stack should be 1, 2, 1, 2 -del - -# test rot -1 2 3 rot --> stack size should be 3 --> stack should be 2, 3, 1 -del - -# test rot 2 -5 6 7 rot rot --> stack should be 7, 5, 6 -del - -# test rot with filled stack -5 6 1 2 3 rot --> stack size should be 5 --> stack should be 5, 6, 2, 3, 1 -del - -# test depth -1 2 3 -depth --> stack size should be 4 --> stack should be 1, 2, 3, 3 -del - -# test pick -1 2 3 4 2 pick --> stack size should be 5 --> stack should be 1, 2, 3, 4, 3 -0 pick --> error should be 4 -7 pick --> error should be 4 -erase - -# test erase --> stack size should be 0 -erase - -# test del -1 2 3 4 5 -del --> stack size should be 0 - -# test dropn -1 2 2 dropn --> stack size should be 0 -del - -# test dropn error -1 2 3 dropn --> stack size should be 3 --> error should be 2 -del - -# test dupn -1 2 3 4 3 dupn --> stack should be 1, 2, 3, 4, 2, 3, 4 -del - -# test dupn error -1 2 3 4 5 dupn --> stack size should be 5 --> error should be 2 -del - -# test roll -1 2 3 4 5 4 roll --> stack should be 1, 3, 4, 5, 2 -del - -# # test roll with filled stack -# 10 11 1 2 3 4 5 4 roll -# -> stack should be 10, 11, 1, 3, 4, 5, 2 -# del -# -# # test roll error -# 1 2 3 4 5 6 roll -# -> stack size should be 6 -# -> error should be 2 -# del -# -# # test rolld -# 10 20 30 40 50 3 rolld -# -> stack should be 10, 20, 50, 30, 40 -# del -# -# # test rolld with filled stack -# 80 90 10 20 30 40 50 3 rolld -# -> stack should be 80, 90, 10, 20, 50, 30, 40 -# del -# -# # test rolld error -# 1 2 3 4 5 6 rolld -# -> stack size should be 6 -# -> error should be 2 -# del -# -# # test over -# 3.14 15.16 over -# -> stack should be 3.14, 15.16, 3.14 -# del -# -# # test over error -# 2 over -# -> stack size should be 1 -# -> error should be 2 -# del diff --git a/test/50-real.txt b/test/50-real.txt deleted file mode 100644 index 07c6065..0000000 --- a/test/50-real.txt +++ /dev/null @@ -1,470 +0,0 @@ -## REAL - -default del - -# real decimal -1 --> stack size should be 1 --> stack should be 1 -del - -# real decimal (2) -2.345 --> stack should be 2.345 -del - -# real decimal (3) -1 2.345 3 4.9 --> stack size should be 4 --> stack should be 1, 2.345, 3, 4.9 -del - -# real hex -0x1234 0x10.10 --> stack should be 0x1234, 0x10 -del - -# real hex (2) -0x1.234p+12 0x1.01p+4 -dec swap dec swap --> stack should be 4660, 16.0625 -del - -# real binary -0b11001100 --> stack should be 0b11001100 -del - -# real inf, nan -inf -@inf@ -+inf -+@inf@ --inf --@inf@ -nan -@nan@ --> stack should be inf, inf, inf, inf, -inf, -inf, nan, nan -del - -# prec (1) -default -56 prec -pi --> stack should be 3.141592653589793 -del - -# prec (2) -default -100 prec -pi --> stack should be 3.14159265358979323846264338328 -del - -# prec error (1) -0 prec --> error should be 4 -del - -# prec error (2) -0x8000000000000000 prec --> error should be 4 -del default - -# round (1) -"nearest" round --> error should be 0 -del - -# round (2) -"toward zero" round --> error should be 0 -del - -# round (3) -"toward +inf" round --> error should be 0 -del - -# round (4) -"toward -inf" round --> error should be 0 -del - -# round (5) -"away from zero" round --> error should be 0 -del - -# round (6) -round --> error should be 2 -del default - -# add (1) -1.2 2.3 + --> stack should be 3.5 -del - -# add (2) -1.2 2.3+ --> stack should be 3.5 -del - -# add (3) -2.3 + --> error should be 2 --> stack size should be 1 -del - -# add (4) -+ --> error should be 2 -del - -# sub (1) -1.2 2.3 - --> stack should be -1.1 -del - -# sub (2) -1.2 2.3- --> stack should be -1.1 -del - -# sub (3) -2.3 - --> error should be 2 --> stack size should be 1 -del - -# sub (4) -- --> error should be 2 -del - -# mul (1) -1.2 2.3 * --> stack should be 2.76 -del - -# mul (2) -1.2 2.3* --> stack should be 2.76 -del - -# mul (3) -2.3 * --> error should be 2 --> stack size should be 1 -del - -# mul (4) -* --> error should be 2 -del - -# div (1) -1.2 2.3 / --> stack should be 0.52173913043478260869565217391304347826 -del - -# div (2) -1.2 2.3/ --> stack should be 0.52173913043478260869565217391304347826 -del - -# div (3) -2.3 / --> error should be 2 --> stack size should be 1 -del - -# div (4) -/ --> error should be 2 -del - -# chs (1) -3.14 chs --> stack should be -3.14 -del - -# chs (2) -chs --> error should be 2 - -# neg (1) -3.14 neg --> stack should be -3.14 -del - -# neg (2) -neg --> error should be 2 - -# inv (1) -2 inv --> stack should be 0.5 -del - -# inv (2) -inv --> error should be 2 - -# % (1) -2 30 % --> stack should be 0.6 -del - -# % (2) -2 30% --> stack should be 0.6 -del - -# % (3) -2 % --> error should be 2 --> stack size should be 1 -del - -# % (4) -% --> error should be 2 -del - -# %CH (1) -2 0.6 %CH --> stack should be 30 -del - -# %CH (2) -2 0.6%CH --> stack should be 30 -del - -# %CH (3) -2 %CH --> error should be 2 --> stack size should be 1 -del - -# %CH (4) -%CH --> error should be 2 -del - -# ^ (1) -2 10 ^ --> stack should be 1024 -del - -# ^ (2) -2 10^ --> stack should be 1024 -del - -# ^ (3) -2 ^ --> error should be 2 --> stack size should be 1 -del - -# ^ (4) -^ --> error should be 2 -del - -# sqrt (1) -9 sqrt --> stack should be 3 -del - -# sqrt (2) -sqrt --> error should be 3 - -# sq (1) -12 sq --> stack should be 144 -del - -# sq (2) -sq --> error should be 2 - -# sqr (1) -12 sqr --> stack should be 144 -del - -# sqr (2) -sqr --> error should be 2 - -# mod (1) -9 4 mod --> stack should be 1 -del - -# mod (2) -9 mod --> error should be 2 --> stack size should be 1 -del - -# mod (3) -mod --> error should be 2 -del - -# abs (1) --9 abs --> stack should be 9 -del - -# abs (2) -9 abs --> stack should be 9 -del - -# abs (3) -abs --> error should be 2 -del - -# fact (1) -6 fact --> stack should be 720 -del - -# fact (2) -'r' fact --> error should be 3 --> stack size should be 1 -del - -# fact (3) -fact --> error should be 2 -del - -# sign (1) -23 sign -34 sign 0 sign --> stack should be 1, -1, 0 -del - -# sign (2) -sign --> error should be 2 -del - -# mant (1) -123.456 mant -123.456 mant 0 mant --> stack should be 0.123456, 0.123456, 0 -del - -# mant (2) -inf mant --> error should be 4 --inf mant --> error should be 4 -nan mant --> error should be 4 -del - -# xpon (1) -123.456 xpon -123.456 xpon 0 mant --> stack should be 3, 3, 0 -del - -# xpon (2) -inf xpon --> error should be 4 --inf xpon --> error should be 4 -nan xpon --> error should be 4 -del - -# min (1) -1 2 min 4 3 min --> stack should be 1, 3 -del - -# min (2) -'a' 'g' min --> error should be 3 -del - -# min (3) -1 min --> error should be 2 -del - -# min (4) -min --> error should be 2 -del - -# max (1) -1 2 max 4 3 max --> stack should be 2, 4 -del - -# max (2) -'a' 'g' max --> error should be 3 -del - -# max (3) -1 max --> error should be 2 -del - -# max (4) -max --> error should be 2 -del - -# ip (1) -1.22 ip --> stack should be 1 -del - -# ip (2) --1.22 ip --> stack should be -1 -del - -# fp (1) -1.22 fp --> stack should be 0.22 -del - -# fp (2) --1.22 fp --> stack should be -0.22 -del - -# floor (1) -1.22 floor --> stack should be 1 -del - -# floor (2) --1.22 floor --> stack should be -2 -del - -# ceil (1) -1.22 ceil --> stack should be 2 -del - -# ceil (2) --1.22 ceil --> stack should be -1 -del - -default diff --git a/test/60-string.txt b/test/60-string.txt deleted file mode 100644 index 718bc49..0000000 --- a/test/60-string.txt +++ /dev/null @@ -1,213 +0,0 @@ -## STRING -default del - -# string entry -"test string" --> stack size should be 1 --> stack should be "test string" -del - -# string entry (2) -"test string --> stack size should be 1 --> stack should be "test string" -del - -# string entry (3) -" --> stack size should be 1 --> stack should be "" -del - -# ->str on real (1) -1 -->str --> stack should be "1" -del - -# ->str on real (2) -1.234 -->str --> stack should be "1.234" -del - -# ->str on real (3) -1.234 -20 fix -->str --> stack should be "1.23400000000000000000" -del - -# ->str on symbol (1) -toto -->str --> stack should be "'toto'" -del - -# ->str on symbol (2) -'toto' -->str --> stack should be "'toto'" -del - -default - -# str-> on real (1) -"1" -str-> --> stack should be 1 -del - -# str-> on real (2) -"1 2.345 3 4.9" -str-> --> stack should be 1, 2.345, 3, 4.9 -del - -# str-> on real (3) -4 fix -"1 2.345 3 4.9" -str-> --> stack should be 1.0000, 2.3450, 3.0000, 4.9000 -del -default - -# str-> on constant (1) -"pi" -str-> --> stack should be 3.1415926535897932384626433832795028842 -del - -# str-> on constant (2) -"'pi' 'e'" -str-> --> stack should be 'pi', 'e' -del - -# str-> on command (1) -"2 dup" -str-> --> stack should be 2, 2 -del - -# str-> on command (2) -"3.14 my_pi sto" -str-> --> stack size should be 0 -my_pi --> stack should be 3.14 -del - -# str-> on program -"<< -> n << n >> >>" -str-> --> stack should be << -> n << n >> >> -del - -# add (1) -12 34 "one" "two" + --> stack should be 12, 34, "onetwo" -del - -# add (2) -"" "one" + "two" "" + --> stack should be "one", "two" -del - -# add (3) -"one" + --> stack size should be 1 --> error should be 2 -del - -# chr (1) -"" 33 40 for i i chr + next --> stack should be "!"#$%&'(" -del - -# chr (2) --223 chr 0 chr --> stack should be "!", "." -del - -# num (1) -"!wait" num --> stack should be 33 -del - -# num (2) -"" num --> stack should be 0 -del - -# size (1) -"hello" size --> stack should be 5 -del - -# size (2) -"" size --> stack should be 0 -del - -# size, str->, ->str -"hello" str-> ->str size --> stack should be 7 -del - -# pos (1) -"my big string" "big" pos --> stack should be 4 -del - -# pos (2) -"my big string" "bOg" pos --> stack should be 0 -del - -# pos (3) -"my big string" pos --> error should be 2 --> stack size should be 1 -del - -# pos (4) -pos --> error should be 2 -del - -# sub (1) -"my string to sub" 4 6 -sub --> stack should be "str" -del - -# sub (2) -"my string to sub" -1 -2 -sub --> stack should be "m" -del - -# sub (3) -"my string to sub" 0 0 -sub --> stack should be "m" -del - -# sub (4) -"my string to sub" 6 5 -sub --> stack should be "" -del - -# sub (5) -"my string to sub" 100 101 -sub --> stack should be "" -del - -# sub (6) -"my string to sub" 14 100 -sub --> stack should be "sub" -del diff --git a/test/80-store.txt b/test/80-store.txt deleted file mode 100644 index 582931f..0000000 --- a/test/80-store.txt +++ /dev/null @@ -1,226 +0,0 @@ -## STORE -default del - -# symbol entry -'test' --> stack size should be 1 --> stack should be 'test' -del - -# symbol entry (2) -'test --> stack size should be 1 --> stack should be 'test' -del - -# symbol entry (3) -'' --> stack size should be 1 --> stack should be '' -del - -# symbol entry (4) -' --> stack size should be 1 --> stack should be '' -del - -# sto (1) -1 'a' sto --> stack size should be 0 -'a' a --> stack should be 'a', 1 -del - -# sto (2) -2 'a' sto a --> stack should be 2 -del - -# sto (3) -3 'b' sto b --> stack should be 3 -del - -# rcl (1) -'a' rcl --> stack should be 2 -del - -# rcl (2) -'b' rcl --> stack should be 3 -del - -# rcl (2) -'var' rcl --> error should be 5 --> stack should be 'var' -del - -# sto in prog then rcl -3 << 'r' sto >> eval r 'r' rcl --> stack should be 3, 3 -del - -# purge (1) -a 'a' purge a --> stack should be 2, 'a' -del - -# purge (2) -'a' purge --> error should be 5 --> stack size should be 0 -del - -# purge (3) -3 'a' sto a 'a' purge --> stack should be 3 -del - -# sto+ (1) -8 'a' sto -2 'a' sto+ -a --> stack should be 10 -del - -# sto+ (2) -2 'a' sto -'a' 2 sto+ -a --> stack should be 4 -del - -# sto+ (3) -'a' sto+ --> stack size should be 1 --> error should be 2 -del - -# sto+ (4) -3 'zz' sto+ --> stack should be 3, 'zz' --> error should be 5 -del - -# sto- (1) -2 'a' sto -2 'a' sto- -a --> stack should be 0 -del - -# sto- (2) -2 'a' sto -'a' 2 sto- -a --> stack should be 0 -del - -# sto- (3) -'a' sto- --> stack size should be 1 --> error should be 2 -del - -# sto- (4) -3 'zz' sto- --> stack should be 3, 'zz' --> error should be 5 -del - -# sto* (1) -2 'a' sto -3 'a' sto* -a --> stack should be 6 -del - -# sto* (2) -2 'a' sto -'a' 3 sto* -a --> stack should be 6 -del - -# sto* (3) -'a' sto* --> stack size should be 1 --> error should be 2 -del - -# sto* (4) -3 'zz' sto* --> stack should be 3, 'zz' --> error should be 5 -del - -# sto/ (1) -2 'a' sto -6 'a' sto/ -a --> stack should be 3 -del - -# sto/ (2) -6 'a' sto -'a' 2 sto/ -a --> stack should be 3 -del - -# sto/ (2) -'a' sto/ --> stack size should be 1 --> error should be 2 -del - -# sto/ (4) -3 'zz' sto/ --> stack should be 3, 'zz' --> error should be 5 -del - -# sneg (1) -7 'a' sto -'a' sneg -a --> stack should be -7 -del - -# sneg (2) -sneg --> error should be 2 -del - -# sneg (3) -'zz' sneg --> error should be 5 --> stack should be 'zz' -del - -# sinv (1) -4 'a' sto -'a' sinv -a --> stack should be 0.25 -del - -# sinv (2) -sinv --> error should be 2 -del - -# sinv (3) -'zz' sinv --> error should be 5 --> stack should be 'zz' -del - -# clusr -3.14 'abc' sto clusr 'abc' rcl --> error should be 5 --> stack should be 'abc' -del diff --git a/test/90-program.txt b/test/90-program.txt deleted file mode 100644 index 0e63fa0..0000000 --- a/test/90-program.txt +++ /dev/null @@ -1,56 +0,0 @@ -## PROGRAM -default del - -# program -<< 'one' >> --> stack size should be 1 --> stack should be << 'one' >> -del - -# program (2) -<< 'one' 2 --> stack size should be 1 --> stack should be << 'one' 2 >> -del - -# program (3) -<< --> stack size should be 1 --> stack should be << >> -del - -# program (4) -<< << << << --> stack size should be 1 --> stack should be << << << << >> >> >> >> -del - -# program (5) -<< -> n << n 2 * >> >> --> stack size should be 1 --> stack should be << -> n << n 2 * >> >> -del - -# program imbrication -<< 1 << 2 >> >> --> stack should be << 1 << 2 >> >> -del - -# program evaluation -<< 1 << 2 >> >> dup eval --> stack should be << 1 << 2 >> >>, 1, << 2 >> -del - -# program 1 arg -default -10 -<< -> n << 0 1 n for i i 2 * inv + next >> >> -eval --> stack should be 1.4644841269841269841269841269841269841 -del - -# program several args -0 1 10 << -> u0 u1 n << u0 u1 1 n start dup2 + rot drop next swap drop >> >> eval -eval --> stack should be 89 -del diff --git a/test/999-manual-tests.md b/test/999-manual-tests.md new file mode 100644 index 0000000..1632235 --- /dev/null +++ b/test/999-manual-tests.md @@ -0,0 +1,61 @@ +# MANUAL TESTS + +`default del` + +## GENERAL help - please type help and verify help is shown + +-> error should be 0 + +`del` + +## GENERAL h - please type h and verify help is shown + +-> error should be 0 + +`del` + +## GENERAL ? - please type ? and verify help is shown + +-> error should be 0 + +`del` + +## GENERAL quit - please type quit and verify rpn exits + +-> error should be 0 + +`del` + +## GENERAL q - please type q and verify rpn exits + +-> error should be 0 + +del + +## GENERAL exit - please type exit and verify rpn exits + +`-> error should be 0` + +del + +## STORE vars - please type vars and verify variables are shown + +`-> error should be 0` + +del + +## STORE edit - please type edit and verify last line comes under the caret + +-> error should be 0 + +`del` + +## HISTORY - please type history and verify rpn history is shown + +-> error should be 0 + +## MULTILINE EDITING - please type a prog like 1 3 for i[ALT-ENTER]i sq[ALT-ENTER]next[ENTER] and verify output + +-> error should be 0 + +`del` diff --git a/test/999-manual-tests.txt b/test/999-manual-tests.txt deleted file mode 100644 index 56b7cca..0000000 --- a/test/999-manual-tests.txt +++ /dev/null @@ -1,41 +0,0 @@ -## MANUAL TESTS -default del - -# GENERAL help - please type help and verify help is shown --> error should be 0 -del - -# GENERAL h - please type h and verify help is shown --> error should be 0 -del - -# GENERAL ? - please type ? and verify help is shown --> error should be 0 -del - -# GENERAL quit - please type quit and verify rpn exits --> error should be 0 -del - -# GENERAL q - please type q and verify rpn exits --> error should be 0 -del - -# GENERAL exit - please type exit and verify rpn exits --> error should be 0 -del - -# STORE vars - please type vars and verify variables are shown --> error should be 0 -del - -# STORE edit - please type edit and verify last line comes under the caret --> error should be 0 -del - -# HISTORY - please type history and verify rpn history is shown --> error should be 0 - -# MULTILINE EDITING - please type a prog like 1 3 for i[ALT-ENTER]i sq[ALT-ENTER]next[ENTER] and verify output --> error should be 0 -del diff --git a/test/all.md b/test/all.md new file mode 100644 index 0000000..dd3df47 --- /dev/null +++ b/test/all.md @@ -0,0 +1,22 @@ +# Chaining all tests + +@include 005-test-framework.md +@include 010-mode.md +@include 020-general.md +@include 021-parse-string.md +@include 022-parse-symbol.md +@include 023-parse-number.md +@include 024-parse-complex.md +@include 025-parse-other.md +@include 026-parse-program.md +@include 027-base-entry.md +# @include 030-branch.md +# @include 040-stack.md +# @include 050-real.md +# @include 060-string.md +# @include 070-test.md +# @include 080-store.md +# @include 090-program.md +# @include 100-complex.md +# @include 110-time.md +# @include 999-manual-tests.md diff --git a/test/all.txt b/test/all.txt deleted file mode 100644 index 94ace3f..0000000 --- a/test/all.txt +++ /dev/null @@ -1,20 +0,0 @@ -#include 10-mode.txt -#include 20-general.txt -#include 21-parse-string.txt -#include 22-parse-symbol.txt -#include 23-parse-number.txt -#include 24-parse-complex.txt -#include 25-parse-other.txt -#include 26-parse-program.txt -#include 27-base-entry.txt -#include 30-branch.txt -#include 40-stack.txt -#include 50-real.txt -#include 60-string.txt -#include 70-test.txt -#include 80-store.txt -#include 90-program.txt -#include 100-complex.txt -#include 110-base-entry.txt -#include 120-time.txt -#include 999-manual-tests.txt From 236fc940a7a40c0fdd130cfb581c4add716283ad Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 15 Feb 2022 16:57:09 +0100 Subject: [PATCH 06/57] refactoring base entries --- CMakeLists.txt | 1 + Changelog | 15 +++ src/.clang-format | 2 +- src/constant.h | 31 ------ src/mpreal-out.cpp | 202 +++++++++++++++++++++++++++++++++++++ src/mpreal-out.hpp | 11 ++ src/object.cpp | 213 +-------------------------------------- src/object.hpp | 135 ++++++++++++------------- src/parse.cpp | 69 ++++++++----- src/program.cpp | 22 ++-- src/rpn-branch.cpp | 25 ++--- src/rpn-complex.cpp | 2 +- src/rpn-general.cpp | 12 +-- src/rpn-program.cpp | 13 +-- src/rpn-real.cpp | 93 ++++++++++------- src/rpn-stack.cpp | 20 ++-- src/rpn-store.cpp | 14 +-- src/rpn-string.cpp | 3 +- src/rpn-test.cpp | 165 +++++++++++------------------- src/stack.hpp | 49 +++------ test/023-parse-number.md | 54 +++++++++- test/025-parse-other.md | 2 +- test/027-base-entry.md | 46 +++++++-- test/mem_test.sh | 39 +++++++ 24 files changed, 658 insertions(+), 580 deletions(-) create mode 100644 Changelog create mode 100644 src/mpreal-out.cpp create mode 100644 src/mpreal-out.hpp create mode 100755 test/mem_test.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ae1df4..7e6a69c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,6 +53,7 @@ add_executable( rpn ${PROJECT_SOURCE_DIR}/src/main.cpp ${PROJECT_SOURCE_DIR}/src/object.cpp + ${PROJECT_SOURCE_DIR}/src/mpreal-out.cpp ${PROJECT_SOURCE_DIR}/src/program.cpp ${PROJECT_SOURCE_DIR}/src/parse.cpp ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp diff --git a/Changelog b/Changelog new file mode 100644 index 0000000..791009b --- /dev/null +++ b/Changelog @@ -0,0 +1,15 @@ +Changelog + +TODO +- savoir si lorsque erreur il faut enlever ou pas l'argument en erreur de la stack + - normalement non, c'est bon? + +Compatibility is broken on these points +- `<< <<` doesn't input as `<< << >> >>` but as `<< << >>` +- `1 2+` not allowed anymore, keep `1 2 +` + - this correct bad behaviors like `3b114` giving `3b11` and `4` +- complexes are written in the form `(1,2)` instead of `(1, 2)` (the space was removed) + +New +- `« »` are valid as program delimiters. `<<` and `>>` are still valid +- enhanced code quality and memory usage checks diff --git a/src/.clang-format b/src/.clang-format index 26fd6a7..becb115 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -1,5 +1,5 @@ --- -BasedOnStyle: LLVM +BasedOnStyle: google IndentWidth: 4 --- Language: Cpp diff --git a/src/constant.h b/src/constant.h index b150109..a6d2f63 100644 --- a/src/constant.h +++ b/src/constant.h @@ -88,35 +88,4 @@ typedef enum { #define BASE_MIN 2 #define BASE_MAX 62 -// some defs for mpfr -#if _MPFR_EXP_FORMAT == 1 -#define MPFR_EXP_MAX (SHRT_MAX) -#define MPFR_EXP_MIN (SHRT_MIN) -#elif _MPFR_EXP_FORMAT == 2 -#define MPFR_EXP_MAX (INT_MAX) -#define MPFR_EXP_MIN (INT_MIN) -#elif _MPFR_EXP_FORMAT == 3 -#define MPFR_EXP_MAX (LONG_MAX) -#define MPFR_EXP_MIN (LONG_MIN) -#elif _MPFR_EXP_FORMAT == 4 -#define MPFR_EXP_MAX (MPFR_INTMAX_MAX) -#define MPFR_EXP_MIN (MPFR_INTMAX_MIN) -#else -#error "Invalid MPFR Exp format" -#endif - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#define MAX(h, i) ((h) > (i) ? (h) : (i)) - -#define MPFR_EXP_INF (MPFR_EXP_MIN + 3) -#define MPFR_EXP_NAN (MPFR_EXP_MIN + 2) -#define MPFR_EXP(x) ((x)->_mpfr_exp) -#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF) -#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x), 0)) -#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN) -#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF) -#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0) -#define MPFR_IS_POS(x) (MPFR_SIGN(x) > 0) -#define MPFR_PREC(x) ((x)->_mpfr_prec) - #endif diff --git a/src/mpreal-out.cpp b/src/mpreal-out.cpp new file mode 100644 index 0000000..52ad9ed --- /dev/null +++ b/src/mpreal-out.cpp @@ -0,0 +1,202 @@ +#include "mpreal-out.hpp" + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(h, i) ((h) > (i) ? (h) : (i)) + +// some defs for mpfr +#if _MPFR_EXP_FORMAT == 1 +#define MPFR_EXP_MAX (SHRT_MAX) +#define MPFR_EXP_MIN (SHRT_MIN) +#elif _MPFR_EXP_FORMAT == 2 +#define MPFR_EXP_MAX (INT_MAX) +#define MPFR_EXP_MIN (INT_MIN) +#elif _MPFR_EXP_FORMAT == 3 +#define MPFR_EXP_MAX (LONG_MAX) +#define MPFR_EXP_MIN (LONG_MIN) +#elif _MPFR_EXP_FORMAT == 4 +#define MPFR_EXP_MAX (MPFR_INTMAX_MAX) +#define MPFR_EXP_MIN (MPFR_INTMAX_MIN) +#else +#error "Invalid MPFR Exp format" +#endif + +#define MPFR_EXP_INF (MPFR_EXP_MIN + 3) +#define MPFR_EXP_NAN (MPFR_EXP_MIN + 2) +#define MPFR_EXP(x) ((x)->_mpfr_exp) +#define MPFR_IS_SINGULAR(x) (MPFR_EXP(x) <= MPFR_EXP_INF) +#define MPFR_UNLIKELY(x) (__builtin_expect(!!(x), 0)) +#define MPFR_IS_NAN(x) (MPFR_EXP(x) == MPFR_EXP_NAN) +#define MPFR_IS_INF(x) (MPFR_EXP(x) == MPFR_EXP_INF) +#define MPFR_IS_NEG(x) (MPFR_SIGN(x) < 0) +#define MPFR_IS_POS(x) (MPFR_SIGN(x) > 0) +#define MPFR_PREC(x) ((x)->_mpfr_prec) + +ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value) { + // cf std::ostream& mpreal::output(std::ostream& os) const + char* s = NULL; + if (!(mpfr_asprintf(&s, fmt.c_str(), mpreal::get_default_rnd(), value.mpfr_srcptr()) < 0)) { + out << string(s); + mpfr_free_str(s); + } + return out; +} + +static bool is_min(const mpreal& p, mpfr_prec_t prec) { + // see mpfr_vasprintf code + bool ret; + int round_away; + switch (mpreal::get_default_rnd()) { + case MPFR_RNDA: + round_away = 1; + break; + case MPFR_RNDD: + round_away = MPFR_IS_NEG(p.mpfr_srcptr()); + break; + case MPFR_RNDU: + round_away = MPFR_IS_POS(p.mpfr_srcptr()); + break; + case MPFR_RNDN: { + /* compare |p| to y = 0.5*10^(-prec) */ + mpfr_t y; + mpfr_exp_t e = MAX(MPFR_PREC(p.mpfr_srcptr()), 56); + mpfr_init2(y, e + 8); + do { + /* find a lower approximation of + 0.5*10^(-prec) different from |p| */ + e += 8; + mpfr_set_prec(y, e); + mpfr_set_si(y, -prec, MPFR_RNDN); + mpfr_exp10(y, y, MPFR_RNDD); + mpfr_div_2ui(y, y, 1, MPFR_RNDN); + } while (mpfr_cmpabs(y, p.mpfr_srcptr()) == 0); + + round_away = mpfr_cmpabs(y, p.mpfr_srcptr()) < 0; + mpfr_clear(y); + } break; + default: + round_away = 0; + } + + if (round_away) /* round away from zero: the last output digit is '1' */ + ret = true; + else + /* only zeros in fractional part */ + ret = false; + return ret; +} + +static void _out_base(ostream& out, int base) { + if (base == 16) + out << "0x"; + else if (base == 2) + out << "0b"; + else + out << base << "b"; +} + +ostream& _out_singular(ostream& out, int base, const mpreal& value) { + const char* write_after_sign = NULL; // unused for now + int digits = 0; // forced 0 digits after separator + if (MPFR_IS_NAN(value.mpfr_srcptr())) + out << "nan"; + else if (MPFR_IS_INF(value.mpfr_srcptr())) { + if (MPFR_IS_NEG(value.mpfr_srcptr())) out << '-'; + out << "inf"; + } else { + // zero + if (MPFR_IS_NEG(value.mpfr_srcptr())) out << '-'; // signed zero is allowed + if (write_after_sign != NULL) out << write_after_sign; + _out_base(out, base); + out << '0'; + if (digits > 0) { + out << '.'; + for (int i = 0; i < digits; i++) out << '0'; + } + } + return out; +} + +ostream& _out_little_number(ostream& out, int base, const mpreal& value) { + const char* write_after_sign = NULL; // unused for now + int digits = 0; // forced 0 digits after separator + + if (MPFR_IS_NEG(value.mpfr_srcptr())) out << '-'; + if (write_after_sign != NULL) out << write_after_sign; + _out_base(out, base); + out << '0'; + if (digits > 0) { + out << '.'; + for (int i = 0; i < digits - 1; i++) out << '0'; + + if (is_min(value.mpfr_srcptr(), digits)) + out << '1'; + else + out << '0'; + } + return out; +} + +ostream& _out_number(ostream& out, int base, const mpreal& value) { + const char* write_after_sign = NULL; // unused for now + int digits = 0; // forced 0 digits after separator + mpfr_exp_t exp = mpfr_get_exp(value.mpfr_srcptr()); + + char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, value.mpfr_srcptr(), mpreal::get_default_rnd()); + char* print_from; + if (str != NULL) { + int len = strlen(str); + print_from = str; + if (len > 0) { + if (print_from[0] == '-') { + out << print_from[0]; + len--; + print_from++; + } else if (print_from[0] == '+') { + len--; + print_from++; + } + if (write_after_sign != NULL) out << write_after_sign; + if (base == 16) + out << "0x"; + else if (base == 2) + out << "0b"; + else + out << base << "b"; + if (exp < 0) { + out << '0'; + if (digits > 0) { + out << '.'; + for (int i = 0; i < -(int)exp; i++) out << '0'; + out << str; + for (int i = 0; i < (int)(digits - len + exp); i++) out << '0'; + } + } else { + if (exp == 0) + out << '0'; + else + for (int i = 0; i < (int)exp; i++) out << print_from[i]; + if (digits > 0) { + out << '.'; + + int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1; + for (int i = (int)exp; i < remaining + (int)exp; i++) out << print_from[i]; + for (int i = 0; i < (int)(exp + digits - len); i++) out << '0'; + } + } + } + mpfr_free_str(str); + } + return out; +} + +ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value) { + // see mpfr_vasprintf code + int digits = 0; // forced 0 digits after separator + + if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(value.mpfr_srcptr()))) return _out_singular(out, base, value); + + mpfr_exp_t exp = mpfr_get_exp(value.mpfr_srcptr()); + if (exp < -digits) return _out_little_number(out, base, value); + + return _out_number(out, base, value); +} diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp new file mode 100644 index 0000000..f2e8e65 --- /dev/null +++ b/src/mpreal-out.hpp @@ -0,0 +1,11 @@ +#include +#include +using namespace std; + +#define MPFR_USE_NO_MACRO +#include +#include +using namespace mpfr; + +ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); +ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); diff --git a/src/object.cpp b/src/object.cpp index 25126ee..265636d 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -7,217 +7,6 @@ using namespace std; #include #include "object.hpp" -// TODO remove - // number statics number::mode_enum number::s_mode = DEFAULT_MODE; -int number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; - -#if 0 -/// @brief return if a mpfr is higher to a given precision -/// this function is directly copied from mpfr -/// -/// @param p the mpfr to test -/// @param prec the precision -/// @return true p is higher than 10^prec -/// @return false p is lower than 10^prec -/// -static bool is_min(mpfr_t p, mpfr_prec_t prec) { - // see mpfr_vasprintf code - bool ret; - int round_away; - switch (mpreal::get_default_rnd()) { - case MPFR_RNDA: - round_away = 1; - break; - case MPFR_RNDD: - round_away = MPFR_IS_NEG(p); - break; - case MPFR_RNDU: - round_away = MPFR_IS_POS(p); - break; - case MPFR_RNDN: { - /* compare |p| to y = 0.5*10^(-prec) */ - mpfr_t y; - mpfr_exp_t e = MAX(MPFR_PREC(p), 56); - mpfr_init2(y, e + 8); - do { - /* find a lower approximation of - 0.5*10^(-prec) different from |p| */ - e += 8; - mpfr_set_prec(y, e); - mpfr_set_si(y, -prec, MPFR_RNDN); - mpfr_exp10(y, y, MPFR_RNDD); - mpfr_div_2ui(y, y, 1, MPFR_RNDN); - } while (mpfr_cmpabs(y, p) == 0); - - round_away = mpfr_cmpabs(y, p) < 0; - mpfr_clear(y); - } break; - default: - round_away = 0; - } - - if (round_away) /* round away from zero: the last output digit is '1' */ - ret = true; - else - /* only zeros in fractional part */ - ret = false; - return ret; -} - -/// @brief print a mpfr in fixed format according to a base -/// this function is based copied on mpfr library -/// -/// @param stream the stream to write to -/// @param real the real to print -/// @param base the base to print the real -/// @param write_after_sign substring to write between the sign and the real -/// -static void print_fix(FILE* stream, mpfr_t real, int base, const char* write_after_sign = NULL) { - // see mpfr_vasprintf code - mpfr_exp_t exp = mpfr_get_exp(real); - int digits = 0; // forced 0 digits after separator - int i; - - if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(real))) { - if (MPFR_IS_NAN(real)) - fputs("nan", stream); - else if (MPFR_IS_INF(real)) { - if (MPFR_IS_NEG(real)) fputc('-', stream); - fputs("inf", stream); - } else { - // zero - if (MPFR_IS_NEG(real)) fputc('-', stream); // signed zero is allowed - if (write_after_sign != NULL) fputs(write_after_sign, stream); - fputc('0', stream); - if (digits > 0) { - fputc('.', stream); - for (i = 0; i < digits; i++) fputc('0', stream); - } - } - } else if (exp < -digits) { - if (MPFR_IS_NEG(real)) fputc('-', stream); - if (write_after_sign != NULL) fputs(write_after_sign, stream); - fputc('0', stream); - if (digits > 0) { - fputc('.', stream); - for (i = 0; i < digits - 1; i++) fputc('0', stream); - - if (is_min(real, digits)) - fputc('1', stream); - else - fputc('0', stream); - } - } else { - char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, real, mpreal::get_default_rnd()); - char* print_from; - if (str != NULL) { - int len = strlen(str); - print_from = str; - if (len > 0) { - if (print_from[0] == '-') { - fputc(print_from[0], stream); - len--; - print_from++; - } else if (print_from[0] == '+') { - len--; - print_from++; - } - if (write_after_sign != NULL) fputs(write_after_sign, stream); - if (exp < 0) { - fputc('0', stream); - if (digits > 0) { - fputc('.', stream); - for (i = 0; i < -(int)exp; i++) fputc('0', stream); - fputs(str, stream); - for (i = 0; i < (int)(digits - len + exp); i++) fputc('0', stream); - } - } else { - if (exp == 0) - fputc('0', stream); - else - for (i = 0; i < (int)exp; i++) fputc(print_from[i], stream); - if (digits > 0) { - fputc('.', stream); - - int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1; - for (i = (int)exp; i < remaining + (int)exp; i++) fputc(print_from[i], stream); - for (i = 0; i < (int)(exp + digits - len); i++) fputc('0', stream); - } - } - } - mpfr_free_str(str); - } - } -} - -/// @brief show an object representation according to its type -/// -/// @param stream the stream to write to -/// -void object::show(FILE* stream) { - int digits; - char* str; - char base[32]; - - switch (_type) { - case cmd_number: - switch (((number*)this)->repr) { - case number::dec: - mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((number*)this)->_value.mpfr); - break; - case number::hex: - print_fix(stream, ((number*)this)->_value.mpfr, 16, "0x"); - break; - case number::bin: - print_fix(stream, ((number*)this)->_value.mpfr, 2, "0b"); - break; - case number::base: - sprintf(base, "%db", ((number*)this)->_base); - print_fix(stream, ((number*)this)->_value.mpfr, ((number*)this)->_base, base); - break; - default: - fprintf(stream, ""); - break; - } - break; - case cmd_complex: - switch (((complex*)this)->repr) { - case number::dec: - fprintf(stream, "("); - mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->re()->mpfr); - fprintf(stream, ","); - mpfr_fprintf(stream, number::s_mpfr_printf_format.c_str(), ((complex*)this)->im()->mpfr); - fprintf(stream, ")"); - break; - case number::hex: - fprintf(stream, "("); - mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->re()->mpfr); - fprintf(stream, ","); - mpfr_fprintf(stream, string(MPFR_FORMAT_HEX).c_str(), ((complex*)this)->im()->mpfr); - fprintf(stream, ")"); - break; - default: - fprintf(stream, ""); - } - 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; - } -} -#endif +int number::s_digits = DEFAULT_DECIMAL_DIGITS; diff --git a/src/object.hpp b/src/object.hpp index c9401e3..f19b3cd 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -10,17 +10,19 @@ using namespace mpfr; #include using namespace std; +#include "mpreal-out.hpp" + // definitions for objects /// typedef enum { cmd_undef, - cmd_number, // floating point number - cmd_complex, // complex, couple of floating point numbers - cmd_string, // string like "string" - cmd_symbol, // symbol like 'symbol' - cmd_program, // program like << instructions >> - cmd_keyword, // langage keyword - cmd_branch, // langage branch keyword + cmd_number, // floating point number + cmd_complex, // complex, couple of floating point numbers + cmd_string, // string like "string" + cmd_symbol, // symbol like 'symbol' + cmd_program, // program like << instructions >> + cmd_keyword, // langage keyword + cmd_branch, // langage branch keyword cmd_max } cmd_type_t; @@ -38,96 +40,85 @@ struct object { cmd_type_t _type; virtual object* clone() { object* o = new object(); - if (o != nullptr) - *o = *this; + if (o != nullptr) *o = *this; return o; } virtual string name() { return string("object"); } - virtual void show(ostream& out) { out << "(" << name() << " - unknown representation)"; } + virtual ostream& show(ostream& out) { + out << "(" << name() << " - unknown representation)"; + return out; + } + friend ostream& operator<<(ostream& os, object* o) { return o->show(os); } + unsigned int size() { return sizeof(*this); } }; /// @brief stack objects derived from object /// struct number : object { - typedef enum { dec, hex, bin, base } repr_enum; - number(repr_enum repr_ = dec, int base_ = 10) : object(cmd_number), repr(repr_), _base(base_) {} - number(mpreal& value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } - number(long value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } - number(unsigned long value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } - number(double value_, repr_enum repr_ = dec, int base_ = 10) : number(repr_, base_) { value = value_; } + number() : object(cmd_number), base(10) {} + number(mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} + number(long value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} - repr_enum repr; - int _base; // carefull: _base is used only if repr = base + int base; mpreal value; - virtual object* clone() { return new number(this->value, repr, _base); } + virtual object* clone() { return new number(this->value, base); } virtual string name() { return string("number"); } - virtual void show(ostream& out) { - switch (number::s_mode) { - case number::std: // std + precision + base - out << value; - break; - case number::fix: // fixed + precision + base - out << fixed << setprecision(s_decimal_digits) << value; - break; - case number::sci: // sci + precision - out << scientific << setprecision(s_decimal_digits) << value; - break; - default: - object::show(out); - break; - } - } + virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); } // representation mode typedef enum { std, fix, sci } mode_enum; static mode_enum s_mode; // precision - static int s_decimal_digits; + static int s_digits; + + // clang-format off + static string _makeNumberFormat(mode_enum mode, int digits) { + stringstream format; + format<<"%."<& value_, number::repr_enum repr_ = number::dec, int base_ = 10) : ocomplex(repr_, base_) { + ocomplex() : object(cmd_complex), reBase(10), imBase(10) {} + ocomplex(complex& value_, int reb = 10, int imb = 10) : object(cmd_complex), reBase(reb), imBase(imb) { value = value_; } - ocomplex(mpreal& re_, mpreal& im_, number::repr_enum repr_ = number::dec, int base_ = 10) : ocomplex(repr_, base_) { + ocomplex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) : object(cmd_complex), reBase(reb), imBase(imb) { value.real(re_); value.imag(im_); } - number::repr_enum repr; - int _base; + int reBase, imBase; complex value; - virtual object* clone() { return new ocomplex(this->value, repr, _base); } + virtual object* clone() { return new ocomplex(this->value, reBase, imBase); } virtual string name() { return string("complex"); } - virtual void show(ostream& out) { - if (repr != number::dec) { - object::show(out); - return; - } - switch (number::s_mode) { - case number::std: - out.unsetf(ios::floatfield); - out << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; - break; - case number::fix: - out << fixed << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() << ")"; - break; - case number::sci: - out << scientific << setprecision(number::s_decimal_digits) << "(" << value.real() << "," << value.imag() - << ")"; - break; - default: - object::show(out); - break; - } + virtual ostream& show(ostream& out) { + out << '('; + number::showValue(out, value.real(), number::s_mode, number::s_digits, reBase); + out << ','; + number::showValue(out, value.imag(), number::s_mode, number::s_digits, imBase); + return out << ')'; } }; @@ -135,11 +126,13 @@ struct ocomplex : object { /// struct ostring : object { ostring() : object(cmd_string) {} - ostring(const string& value_) : object(cmd_string) { set(value_); } + ostring(const string& value_) : object(cmd_string), value(value_) {} ostring(const char* value_) : object(cmd_string) { value = string(value_); } - void set(const string& value_) { value = value_; } virtual string name() { return string("string"); } - virtual void show(ostream& out) { out << "\"" << value << "\""; } + virtual ostream& show(ostream& out) { + out << "\"" << value << "\""; + return out; + } string value; }; @@ -150,7 +143,10 @@ struct oprogram : object { oprogram(const string& value_) : object(cmd_program) { set(value_); } void set(const string& value_) { value = value_; } virtual string name() { return string("program"); } - virtual void show(ostream& out) { out << "«" << value << "»"; } + virtual ostream& show(ostream& out) { + out << "«" << value << "»"; + return out; + } string value; }; @@ -168,7 +164,10 @@ struct symbol : object { auto_eval = auto_eval_; } virtual string name() { return string("symbol"); } - virtual void show(ostream& out) { out << "'" << value << "'"; } + virtual ostream& show(ostream& out) { + out << "'" << value << "'"; + return out; + } bool auto_eval; string value; }; diff --git a/src/parse.cpp b/src/parse.cpp index 974fa0b..6d99236 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -89,6 +89,8 @@ struct SynElement { string value; mpreal re; mpreal im; + int reBase; + int imBase; program_fn_t fn; bool operator==(SynElement& other) { return type == other.type && value == other.value && (re == other.re || (isnan(re) && isnan(other.re))) && @@ -172,42 +174,62 @@ static bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector= idxStart + 2 && baseStr[1] == 'b') { + int base = stoi(baseStr.substr(0, 1)); + if (base >= BASE_MIN && base <= BASE_MAX) { + idxNumber = 2; + return base; + } } + if (entry.size() >= idxStart + 3) { + baseStr = entry.substr(idxStart, 3); + if (isdigit(baseStr[0]) && isdigit(baseStr[1]) && baseStr[2] == 'b') { + int base = stoi(baseStr.substr(0, 2)); + if (base >= BASE_MIN && base <= BASE_MAX) { + idxNumber = 3; + return base; + } + } + } + return 10; +} - ss.str(input); +static bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal& r, char delim = ' ') { + stringstream ss; + int idxNumber = 0; + string token; + + base = getBase(entry, idx, idxNumber); + + ss.str(entry.substr(idx + idxNumber)); if (getline(ss, token, delim)) { - nextIdx = token.size() + idx + (base != 10 ? 2 : 0); + nextIdx = token.size() + idx + idxNumber; trim(token); if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) return true; else return false; } - nextIdx = token.size() + idx + (base != 10 ? 2 : 0); + nextIdx = token.size() + idx + idxNumber + 1; return false; } static bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { mpreal r; - if (getNumberAt(entry, idx, nextIdx, r)) { - elements.push_back({cmd_number, .re = r}); + int base = 10; + if (getNumberAt(entry, idx, nextIdx, base, r)) { + elements.push_back({cmd_number, .re = r, .reBase = base}); return true; } else { errors.push_back({entry.size(), "unterminated number"}); @@ -218,12 +240,13 @@ static bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { mpreal re, im; + int reBase, imBase = 10; if (idx + 1 == entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol } - if (!getNumberAt(entry, idx + 1, nextIdx, re, ',')) { + if (!getNumberAt(entry, idx + 1, nextIdx, reBase, re, ',')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol @@ -237,12 +260,12 @@ static bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& elements, program& prog) { for (SynElement& element : elements) { switch (element.type) { case cmd_number: - prog.push_back(new number(element.re)); + prog.push_back(new number(element.re, element.reBase)); break; case cmd_complex: - prog.push_back(new ocomplex(element.re, element.im)); + prog.push_back(new ocomplex(element.re, element.im, element.reBase, element.imBase)); break; case cmd_string: prog.push_back(new ostring(element.value)); diff --git a/src/program.cpp b/src/program.cpp index 6f15a4e..c67e2e3 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -34,7 +34,6 @@ program::keyword_t program::s_keywords[] = { // {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, // {cmd_keyword, "sqr", &program::rpn_square, ""}, // {cmd_keyword, "abs", &program::rpn_abs, "absolute value"}, - // {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation"}, // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, // OPERATIONS ON REALS @@ -74,9 +73,10 @@ program::keyword_t program::s_keywords[] = { "+inf\", \"toward -inf\", \"away from zero\"] round"}, {cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default"}, {cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"}, - {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation"}, - // {cmd_keyword, "dec", &program::rpn_dec, "decimal representation"}, - // {cmd_keyword, "bin", &program::rpn_bin, "decimal representation"}, + {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"}, + {cmd_keyword, "dec", &program::rpn_dec, "decimal representation, applies on stack level 0 only"}, + {cmd_keyword, "bin", &program::rpn_bin, "binary representation, applies on stack level 0 only"}, + {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"}, // TESTS {cmd_undef, "", NULL, "\nTEST"}, @@ -638,15 +638,9 @@ ret_value program::get_err(void) { return _err; } /// @param show_separator whether to show a stack level prefix or not /// void program::show_stack(rpnstack& st, bool show_separator) { - if (st.size() == 1) { - st.front()->show(cout); - cout << endl; - } else { - for (int i = st.size() - 1; i >= 0; i--) { - if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; - st[i]->show(cout); - cout << endl; - } + for (int i = st.size() - 1; i >= 0; i--) { + if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; + cout << st[i] << endl; } } @@ -655,6 +649,6 @@ void program::show_stack(rpnstack& st, bool show_separator) { void program::apply_default() { // default float precision, float mode number::s_mode = DEFAULT_MODE; - number::s_decimal_digits = DEFAULT_DECIMAL_DIGITS; + number::s_digits = DEFAULT_DECIMAL_DIGITS; mpreal::set_default_prec(MPFR_DEFAULT_PREC_BITS); } diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index 1f537c1..f43aa9e 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -15,7 +15,7 @@ int program::rpn_if(branch& myobj) { myobj.arg1 = 1; else myobj.arg1 = 0; - (void)_stack->pop_front(); + _stack->pop_front(); return -1; } @@ -72,8 +72,8 @@ int program::rpn_end(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); // check arg - number* arg = (number*)_stack->pop_front(); - if (arg->value == 0) ret = myobj.arg1; + if (_stack->value(0) == 0) ret = myobj.arg1; + _stack->pop(); } // arg2 = index of while+1 in case of while..repeat..end else if (myobj.arg2 != -1) @@ -120,12 +120,12 @@ void program::rpn_ift(void) { if (testee->value != 0) { CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack)); - (void)_stack->pop_front(2); + _stack->pop_front(2); CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); - (void)_calc_stack.pop_front(); + _calc_stack.pop_front(); } else - (void)_stack->pop_front(2); + _stack->pop_front(2); } /// @brief ifte keyword (branch) implementation @@ -150,7 +150,7 @@ void program::rpn_ifte(void) { (void)_stack->pop_front(3); CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); - (void)_calc_stack.pop_front(); + _calc_stack.pop_front(); } /// @brief while keyword (branch) implementation @@ -178,8 +178,8 @@ int program::rpn_repeat(branch& myobj) { // check arg // myobj.arg1 is end+1 - number* arg = (number*)_stack->pop_front(); - if (arg->value == 0) ret = myobj.arg1; + if (_stack->value(0) == 0) ret = myobj.arg1; + _stack->pop(); return ret; } @@ -313,10 +313,10 @@ int program::rpn_step(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - number* step = (number*)_stack->pop_front(); + mpreal step = _stack->value(0); // end of loop if step is negative or zero - if (step->value <= 0) + if (step.toLong() <= 0) ret = -1; else { // arg1 = index of start or for command in program @@ -329,7 +329,8 @@ int program::rpn_step(branch& myobj) { // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - mpfr_add(myobj.farg1->value.mpfr_ptr(), myobj.farg1->value.mpfr_ptr(), step->value.mpfr_ptr(), MPFR_RNDD); + myobj.farg1->value+=step.mpfr_ptr(); + mpfr_add(myobj.farg1->value.mpfr_ptr(), myobj.farg1->value.mpfr_ptr(), step.mpfr_ptr(), MPFR_RNDD); // for command: increment symbol too if (start_or_for->arg1 != -1) { diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index f8e7c36..c9e4b7a 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -40,7 +40,7 @@ void program::rpn_arg() { ARG_MUST_BE_OF_TYPE(0, cmd_complex); // calc atan2(x/y) - complex* cplx = (complex*)_stack->pop_front(); + complex* cplx = (complex*)_stack->front(); number* num = new number(); _calc_stack.push_back(num); diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 8d9a624..b0bdbed 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -55,7 +55,7 @@ void program::rpn_help() { } // bits precision, decimal digits and rounding mode - cout << " with " << number::s_decimal_digits << " digits after the decimal point" << endl; + cout << " with " << number::s_digits << " digits after the decimal point" << endl; cout << "Current floating point precision is " << (int)mpreal::get_default_prec() << " bits" << endl; struct RndStrings { string name; @@ -100,7 +100,7 @@ void program::rpn_std() { if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::std; - number::s_decimal_digits = (int)digits; + number::s_digits = (int)digits; _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); @@ -117,7 +117,7 @@ void program::rpn_fix() { if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::fix; - number::s_decimal_digits = (int)digits; + number::s_digits = (int)digits; _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); @@ -134,7 +134,7 @@ void program::rpn_sci() { if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::sci; - number::s_decimal_digits = (int)digits; + number::s_digits = (int)digits; _stack->pop(); } else ERR_CONTEXT(ret_out_of_range); @@ -166,7 +166,7 @@ void program::rpn_history() { void program::rpn_type() { MIN_ARGUMENTS(1); _stack->push(new ostring(_stack->at(0)->name())); - _stack->del(1); + _stack->erase(1); } /// @brief default keyword implementation @@ -187,7 +187,7 @@ void program::rpn_precision() { // modify digits seen by user if std mode if (number::s_mode == number::std) { // calc max nb of digits user can see with the current bit precision - number::s_decimal_digits = bits2digits(mpreal::get_default_prec()); + number::s_digits = bits2digits(mpreal::get_default_prec()); } _stack->pop(); } else diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index fdb9d22..ab4d1c4 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -39,24 +39,25 @@ void program::rpn_eval(void) { if (IS_ARG_TYPE(0, cmd_symbol)) { // recall a variable object* obj; - string variable(((symbol*)_stack->back())->value); + string variable(((symbol*)_stack->front())->value); + _stack->pop(); // if variable holds a program, run this program if (find_variable(variable, obj)) { if (obj->_type == cmd_program) { - prog_text = ((oprogram*)obj)->value; - (void)_stack->pop_front(); + prog_text = _stack->value(0); + _stack->pop(); run_prog = true; } else { // else recall this variable (i.e. stack its content) - (void)_stack->pop_front(); _stack->push_front(obj); } } else ERR_CONTEXT(ret_unknown_variable); } else if (IS_ARG_TYPE(0, cmd_program)) { // eval a program - prog_text = ((oprogram*)_stack->pop_front())->value; + prog_text = _stack->value(0); + _stack->pop(); run_prog = true; } else ERR_CONTEXT(ret_bad_operand_type); @@ -129,7 +130,7 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { _local_heap[string(((symbol*)(*this)[i])->value)] = _stack->at(0); - (void)_stack->pop_front(); + _stack->pop_front(); } // run the program diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 92a3096..d090cbf 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -175,7 +175,7 @@ void program::rpn_squareroot() { _stack->value(0) = rec_sqrt(_stack->value(0)); } else { // negative number -> square root is compl ex - _stack->push(new ocomplex);// TODO manage new errors + _stack->push(new ocomplex); // TODO manage new errors _stack->value(0) = sqrt(_stack->value(1)); _stack->pop_front(1); } @@ -190,14 +190,60 @@ void program::rpn_squareroot() { void program::rpn_hex() { MIN_ARGUMENTS(1); if (_stack->type(0) == cmd_number) - _stack->obj(0)->repr = number::hex; - else if (_stack->type(0) == cmd_complex) - _stack->obj(0)->repr = number::hex; - else { + _stack->obj(0)->base = 16; + else if (_stack->type(0) == cmd_complex) { + _stack->obj(0)->reBase = 16; + _stack->obj(0)->imBase = 16; + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief bin keyword implementation +/// +void program::rpn_bin() { + MIN_ARGUMENTS(1); + if (_stack->type(0) == cmd_number) + _stack->obj(0)->base = 2; + else if (_stack->type(0) == cmd_complex) { + _stack->obj(0)->reBase = 2; + _stack->obj(0)->imBase = 2; + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief dec keyword implementation +/// +void program::rpn_dec() { + MIN_ARGUMENTS(1); + if (_stack->type(0) == cmd_number) + _stack->obj(0)->base = 10; + else if (_stack->type(0) == cmd_complex) { + _stack->obj(0)->reBase = 10; + _stack->obj(0)->imBase = 10; + } else + ERR_CONTEXT(ret_bad_operand_type); +} + +/// @brief base keyword implementation +/// +void program::rpn_base() { + MIN_ARGUMENTS(2); + + if (_stack->type(1) == cmd_number || _stack->type(1) == cmd_complex) { + int base = (int)_stack->value(0).toLong(); + _stack->pop(); + if (base >= BASE_MIN && base <= BASE_MAX) { + if (_stack->type(0) == cmd_number) + _stack->obj(0)->base = base; + else { + _stack->obj(0)->reBase = base; + _stack->obj(0)->imBase = base; + } + } + else + ERR_CONTEXT(ret_out_of_range); + } else ERR_CONTEXT(ret_bad_operand_type); - return; - } - number::s_decimal_digits = 0; } #if 0 @@ -288,37 +334,6 @@ void program::rpn_abs() { ERR_CONTEXT(ret_bad_operand_type); } -/// @brief bin keyword implementation -/// -void program::rpn_bin() { - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->repr = number::bin; -} - -/// @brief dec keyword implementation -/// -void program::rpn_dec() { - MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ((number*)_stack->back())->repr = number::dec; -} - -/// @brief base keyword implementation -/// -void program::rpn_base() { - MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (mpfr_cmp_d(((number*)_stack->back())->value.mpfr, (double)BASE_MIN) >= 0 && - mpfr_cmp_d(((number*)_stack->back())->value.mpfr, (double)BASE_MAX) <= 0) { - int base = (int)mpfr_get_d(((number*)_stack->pop_front())->value.mpfr, mpreal::get_default_rnd()); - ((number*)_stack->at(0))->_base = base; - ((number*)_stack->at(0))->repr = number::base; - } else - ERR_CONTEXT(ret_out_of_range); -} - /// @brief fact (factorial) keyword implementation /// void program::rpn_fact() { diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 2767283..ec39391 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -5,21 +5,21 @@ void program::rpn_swap(void) { MIN_ARGUMENTS(2); rpnstack::copy_and_push_front(*_stack, 1, *_stack); - (void)_stack->del(2); + _stack->erase(2); } /// @brief drop keyword implementation /// void program::rpn_drop(void) { MIN_ARGUMENTS(1); - (void)_stack->pop_front(); + _stack->pop_front(); } /// @brief drop2 keyword implementation /// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); - (void)_stack->pop_front(2); + _stack->pop_front(2); } /// @brief dropn keyword implementation @@ -28,15 +28,14 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->front())->value.toLong(); + int args = (int)_stack->value(0).toLong(); MIN_ARGUMENTS(args + 1); - - _stack->del(0, args); + _stack->erase(0, args + 1); } /// @brief erase / del keyword implementation /// -void program::rpn_erase(void) { (void)_stack->del(0, _stack->size() - 1); } +void program::rpn_erase(void) { _stack->erase(0, _stack->size()); } /// @brief dup keyword implementation /// @@ -72,7 +71,8 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - unsigned int to_pick = (unsigned int)int(((number*)_stack->pop_front())->value); + unsigned int to_pick = (unsigned int)_stack->value(0); + _stack->pop(); // treat stack depth errors if ((to_pick == 0) || (to_pick > _stack->size())) { @@ -114,7 +114,7 @@ void program::rpn_roll(void) { for (int i = 0; i < args; i++) { rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); - (void)_stack->pop_front(); + _stack->pop_front(); } for (int i = 1; i < args; i++) rpnstack::copy_and_push_front(_calc_stack, args - 1 - i, *_stack); @@ -135,7 +135,7 @@ void program::rpn_rolld(void) { for (int i = 0; i < args; i++) { rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); - (void)_stack->pop_front(); + _stack->pop_front(); } rpnstack::copy_and_push_front(_calc_stack, args - 1, *_stack); diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index c2a0618..cae9b90 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -6,9 +6,8 @@ void program::rpn_sto(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - string name(((symbol*)_stack->pop_front())->value); - (*_heap)[name] = _stack->at(0); - (void)_stack->pop_front(); + (*_heap)[_stack->value(0)] = _stack->at(1); + _stack->pop_front(2); } /// @brief sto+ keyword implementation @@ -201,8 +200,10 @@ void program::rpn_edit(void) { MIN_ARGUMENTS(1); ostringstream st; + // re-write stack objet in a stream - ((object*)_stack->pop_front())->show(st); + _stack->at(1)->show(st); + _stack->pop(); // set it as the linenoise line entry linenoisePreloadBuffer((const char*)st.str().c_str()); @@ -233,8 +234,9 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - string name(((symbol*)_stack->pop_front())->value); - if (!_heap->erase(name)) ERR_CONTEXT(ret_unknown_variable); + //if (_heap->erase(_stack->value(0)) == 0) + // ERR_CONTEXT(ret_unknown_variable); + _stack->pop(); } /// @brief vars keyword implementation diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index d5799c6..6ae8163 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -13,7 +13,8 @@ void program::rpn_instr() { // write the object in stack(0) in a string and remove this obj FILE* tmp = tmpfile(); if (tmp != NULL) { - ((object*)_stack->pop_front())->show(tmp); + _stack->front()->show(tmp); + _stack->pop(); // reserve the correct size on stack unsigned int str_size = (unsigned int)ftell(tmp); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 392e358..c153d68 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -1,16 +1,15 @@ #include "program.hpp" /// @brief compared 2 strings on top of the stack -/// +/// /// @return 0 strings are equal /// @return !0 strings are not equal (see strcmp output) /// long program::cmp_strings_on_stack_top() { - // _stack sould have 2 strings at level 1 and 2 + // _stack should have 2 strings at level 1 and 2 // this function removes these 2 entries long res = (long)static_cast(_stack->at(0))->value.compare(static_cast(_stack->at(1))->value); - (void)_stack->pop_front(); - (void)_stack->pop_front(); + (void)_stack->pop_front(2); return res; } @@ -20,19 +19,15 @@ void program::rpn_sup(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) > 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) > _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -42,19 +37,15 @@ void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) >= 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) >= _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -64,41 +55,31 @@ void program::rpn_inf(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) < 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) < _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } /// @brief <= keyword implementation /// void program::rpn_inf_eq(void) { - MIN_ARGUMENTS(2); - // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) <= 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) <= _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -108,25 +89,20 @@ void program::rpn_diff(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) != 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) != _stack->value(1))); + _stack->erase(1, 2); } // complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - ocomplex* right = (ocomplex*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->pop_front(); - _stack->push_front(new number(left->value != right->value?1L:0L)); + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->push_front(new number(_stack->value(0) != _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -136,25 +112,20 @@ void program::rpn_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->at(0)->_type == cmd_number && _stack->at(1)->_type == cmd_number) { - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp(left->value.mpfr_ptr(), right->value.mpfr_ptr()) == 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { + _stack->push_front(new number(_stack->value(0) == _stack->value(1))); + _stack->erase(1, 2); } // complexes - else if (_stack->at(0)->_type == cmd_complex && _stack->at(1)->_type == cmd_complex) { - ocomplex* right = (ocomplex*)_stack->pop_front(); - ocomplex* left = (ocomplex*)_stack->pop_front(); - _stack->push_front(new number(left->value == right->value?1L:0L)); + else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { + _stack->push_front(new number(_stack->value(0) == _stack->value(1))); + _stack->erase(1, 2); } // strings - else if (_stack->at(0)->_type == cmd_string && _stack->at(1)->_type == cmd_string) + else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { _stack->push_front(new number(cmp_strings_on_stack_top())); - else + _stack->erase(1, 2); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -165,13 +136,11 @@ void program::rpn_test_and(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if ((mpfr_cmp_si(left->value.mpfr_ptr(), 0) != 0) && (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0)) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); + if (_stack->value(0) != 0 && _stack->value(1) != 0) + _stack->push(new number(1)); else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + _stack->push(new number(0)); + _stack->erase(1, 2); } /// @brief or keyword implementation @@ -181,13 +150,11 @@ void program::rpn_test_or(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if ((mpfr_cmp_si(left->value.mpfr_ptr(), 0) != 0) || (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0)) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); + if (_stack->value(0) != 0 || _stack->value(1) != 0) + _stack->push(new number(1)); else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + _stack->push(new number(0)); + _stack->erase(1, 2); } /// @brief xor keyword implementation @@ -197,20 +164,11 @@ void program::rpn_test_xor(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - if (mpfr_cmp_si(left->value.mpfr_ptr(), 0) == 0) { - if (mpfr_cmp_si(right->value.mpfr_ptr(), 0) != 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); - } else { - if (mpfr_cmp_si(right->value.mpfr_ptr(), 0) == 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); - } + if (_stack->value(0) != 0 ^ _stack->value(1) != 0) + _stack->push(new number(1)); + else + _stack->push(new number(0)); + _stack->erase(1, 2); } /// @brief not keyword implementation @@ -219,11 +177,8 @@ void program::rpn_test_not(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - number* left = (number*)_stack->back(); - if (mpfr_cmp_si(left->value.mpfr_ptr(), 0) == 0) - mpfr_set_si(left->value.mpfr_ptr(), 1, mpreal::get_default_rnd()); - else - mpfr_set_si(left->value.mpfr_ptr(), 0, mpreal::get_default_rnd()); + _stack->push(new number(_stack->value(0) == 0?1:0)); + _stack->erase(1, 1); } /// @brief test same implementation diff --git a/src/stack.hpp b/src/stack.hpp index 5eb63e6..04afb78 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -17,7 +17,7 @@ class rpnstack : public deque { rpnstack() {} virtual ~rpnstack() { for_each(begin(), end(), [](object* o) { delete o; }); - erase(begin(), end()); + deque::erase(begin(), end()); } /// @brief copy a whole stack entry and push it back to another stack @@ -29,8 +29,7 @@ class rpnstack : public deque { static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { // carefull: caller must ensure that index_from is correct auto newObj = from[index_from]->clone(); - if (newObj != nullptr) - to.push_front(newObj); + if (newObj != nullptr) to.push_front(newObj); } /// @brief erase a stack entry from it index @@ -38,36 +37,18 @@ class rpnstack : public deque { /// @param first index to start /// @param last index to stop /// - void del(int first = 0, int last = -1) { - if (size() > 0) { - if (last == -1) - erase(begin() + first); - else if (last >= first) - erase(begin() + first, begin() + last + 1); // carefull, deque::erase doesn't include the last element - } + void erase(size_t first = 0, size_t nb = 1) { + size_t last = std::min(first + nb, size()); + for_each(begin() + first, begin() + last, [](object* o) { delete o; }); + deque::erase(begin() + first, begin() + last); } /// @brief pop front several entries /// /// @param levels nb of entries /// - void pop_front(int levels, bool del = true) { - for (int i = 0; i < levels; i++) { - if (del) - delete deque::front(); - deque::pop_front(); - } - } - - /// @brief pop front 1 entry - /// - /// @return retrieved object - /// - object* pop_front() { - object* o = front(); - pop_front(1); - return o; - } + void pop_front(size_t levels = 1) { erase(0, levels); } + void pop() { erase(); } // access helpers cmd_type_t type(int level) { @@ -75,23 +56,19 @@ class rpnstack : public deque { return at(level)->_type; } - template auto obj(int level) { + template + auto obj(int level) { // carefull: caller must ensure that level is correct return static_cast(at(level)); } - template auto& value(int level) { + template + auto& value(int level) { // carefull: caller must ensure that level is correct return static_cast(at(level))->value; } - void pop() { - (void)rpnstack::pop_front(1); - } - - void push(object* o) { - deque::push_front(o); - } + void push(object* o) { deque::push_front(o); } }; /// @brief heap object, storing variables (=named object) diff --git a/test/023-parse-number.md b/test/023-parse-number.md index b4a22b2..68bd595 100644 --- a/test/023-parse-number.md +++ b/test/023-parse-number.md @@ -46,7 +46,7 @@ `0x10 0X10` --> stack should be 16, 16 +-> stack should be 0x10, 0x10 `del` @@ -62,7 +62,7 @@ `0b1101 0b0` --> stack should be 13, 0 +-> stack should be 0b1101, 0b0 `del` @@ -73,3 +73,53 @@ -> stack should be '0b' `del` + +## base + +`del 3b12` + +-> stack should be 3b12 + +## base (2) +`del 0x1e2` + +-> stack should be 0x1e2 + +## base (3) + +`del 0x-1e2 5b-1234 0b-1` + +-> stack should be -0x1e2, -5b1234, -0b1 + +## base err + +`del 0b12` + +-> stack should be '0b12' + +## base err (2) + +`del 1b0` +-> stack should be '1b0' + +`del -1b33` + +-> stack should be '-1b33' + +`del -63b1` + +-> stack should be '-63b1' + +## wrong base errors + +`del 0b0.1100` + +-> stack should be 0b1 + +## particular writings + +`del 10b12345 2b1100` + +-> stack should be 12345, 0b1100 + +`del default` diff --git a/test/025-parse-other.md b/test/025-parse-other.md index aa4389c..2a07708 100644 --- a/test/025-parse-other.md +++ b/test/025-parse-other.md @@ -1,4 +1,4 @@ -# PARSE COMPLEX +# PARSE SOME COMMANDS `default del` diff --git a/test/027-base-entry.md b/test/027-base-entry.md index 8c591b6..f7fa289 100644 --- a/test/027-base-entry.md +++ b/test/027-base-entry.md @@ -182,7 +182,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `3b114` --> stack should be 3b11, 4 +-> stack should be '3b114' `del default` @@ -190,7 +190,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `1b0` --> stack should be 1, 'b0' +-> stack should be '1b0' `del default` @@ -206,7 +206,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `63b20` --> stack should be 63, 'b20' +-> stack should be '63b20' `del default` @@ -214,7 +214,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `2b11001100 0b11001100 ==` --> stack should be 2b1 +-> stack should be 1 `del default` @@ -222,7 +222,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `10b1234 1234 ==` --> stack should be 10b1 +-> stack should be 1 `del default` @@ -230,7 +230,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `16b1234 0x1234 ==` --> stack should be 16b1 +-> stack should be 1 `del default` @@ -276,6 +276,10 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `del default` +## base on complexes + +-> stack should be TODO + ## negative base numbers (1) `1000 hex neg` @@ -323,3 +327,33 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ -> stack should be nan, nan `del default` + +## complex base 16 + +`(0x10,0x20)` + +-> stack should be (0x10,0x20) + +## complex base 16 (2) + +`del (16,32) hex` + +-> stack should be (0x10,0x20) + +## complex base 2 + +`del (0b111,0b110)` + +-> stack should be (0b111,0b110) + +## complex base 2 (2) + +`del (7,6) bin` + +-> stack should be (0b111,0b110) + +## complex multiple bases re / im + +`del (0x10,0b111) dup dup hex swap dec` + +-> stack should be (0x10,0b111), (0x10,0x7), (16,7) diff --git a/test/mem_test.sh b/test/mem_test.sh new file mode 100755 index 0000000..16f2875 --- /dev/null +++ b/test/mem_test.sh @@ -0,0 +1,39 @@ +#!/bin/bash + +rpn=../build/rpn + +FG_RED="\033[0;31m" +FG_GREEN="\033[0;32m" +COLOR_OFF="\033[0m" + +failed=0 + +function checkmem { + echo -n "${*}" + valgrind ${rpn} "${*}" 2>&1 | grep "in use at exit: 0 bytes in 0 blocks" >/dev/null + if [ ${?} -eq 0 ]; then + echo -en " .. ${FG_GREEN}" && echo -n "ok" && echo -e "${COLOR_OFF}" + else + echo -en " .. ${FG_RED}" && echo -n "FAILED" && echo -e "${COLOR_OFF}" + failed=1 + fi +} + +to_test=( + "1.2 \"string\" 'ok' (2,3) << 9 nop >>" # base types inputs + "nop help version uname history quit" # general commands + "38 std 38 fix 38 sci 10 prec 2 default \"toward zero\" round" # modes + "1 2 + 2 3 * / 4 - inv neg chs" # base operations on numbers + "(1,2) (2,3) + (4,5) * (4,2) / (8,8) - inv neg chs" # base operations on complexes + "\"ab\" \" cd\" +" # base operations on strings + "2 3 ^ 2 ^ 2 pow" # usual operations on numbers 1 + "(2,3) (1,1) ^ 2 ^ 2 (2,3) ^" # usual operations on complexes 1 + "1 2 3 swap" # stack operations +) + +echo "\nPOURQUOI NE PAS FAIRE UN TEST DE CHAQUE test.md PLUTOT ?\n" +echo "rpn memory check" +for i in ${!to_test[@]}; do + checkmem "${to_test[$i]}" +done +exit ${failed} From 51c5a4e0f245c841e89260f38ac99af33f2deeff Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Wed, 16 Feb 2022 16:03:26 +0100 Subject: [PATCH 07/57] refactoring branches --- CMakeLists.txt | 2 +- Changelog | 6 + src/object.hpp | 50 +++--- src/parse.cpp | 12 +- src/program.cpp | 18 +- src/program.hpp | 4 + src/rpn-branch.cpp | 123 ++++++------- src/rpn-store.cpp | 16 +- ...n-test-core.cpp => rpn-test-framework.cpp} | 0 src/rpn-test.cpp | 18 +- src/stack.hpp | 7 +- test/027-base-entry.md | 2 +- test/030-branch.md | 162 +++++++++++------- test/all.md | 2 +- test/mem_test.sh | 16 +- 15 files changed, 242 insertions(+), 196 deletions(-) rename src/{rpn-test-core.cpp => rpn-test-framework.cpp} (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e6a69c..f72dd57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/rpn-store.cpp #${PROJECT_SOURCE_DIR}/src/rpn-string.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-test-core.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cpp #${PROJECT_SOURCE_DIR}/src/rpn-time.cpp #${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp diff --git a/Changelog b/Changelog index 791009b..7bd740d 100644 --- a/Changelog +++ b/Changelog @@ -9,6 +9,12 @@ Compatibility is broken on these points - `1 2+` not allowed anymore, keep `1 2 +` - this correct bad behaviors like `3b114` giving `3b11` and `4` - complexes are written in the form `(1,2)` instead of `(1, 2)` (the space was removed) +- removed useless 'unti', 'repea', 'whil' (existing for HP28S compatibility), causing parsing problems +- syntax error code is now 12 instead of 11 +- `test` command can also take a symbol as a parameter ; if the symbol contains a valid +- à l'affichage le préfixe des chiffres en base 2 est 0b et pas 2b (la saisie 2bxxx est toutefois permise) +- à l'affichage le préfixe des chiffres en base 16 est 0x et pas 16b (la saisie 16bxxx est toutefois permise) +- à l'affichage les chiffres en base 10 pas de préfixe 10b (la saisie 10bxxx est toutefois permise) New - `« »` are valid as program delimiters. `<<` and `>>` are still valid diff --git a/src/object.hpp b/src/object.hpp index f19b3cd..1b2853d 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -64,7 +64,7 @@ struct number : object { int base; mpreal value; - virtual object* clone() { return new number(this->value, base); } + virtual object* clone() { return new number(value, base); } virtual string name() { return string("number"); } virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); } @@ -111,7 +111,7 @@ struct ocomplex : object { int reBase, imBase; complex value; - virtual object* clone() { return new ocomplex(this->value, reBase, imBase); } + virtual object* clone() { return new ocomplex(value, reBase, imBase); } virtual string name() { return string("complex"); } virtual ostream& show(ostream& out) { out << '('; @@ -128,6 +128,7 @@ struct ostring : object { ostring() : object(cmd_string) {} ostring(const string& value_) : object(cmd_string), value(value_) {} ostring(const char* value_) : object(cmd_string) { value = string(value_); } + virtual object* clone() { return new ostring(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { out << "\"" << value << "\""; @@ -140,8 +141,8 @@ struct ostring : object { /// struct oprogram : object { oprogram() : object(cmd_program) {} - oprogram(const string& value_) : object(cmd_program) { set(value_); } - void set(const string& value_) { value = value_; } + oprogram(const string& value_) : object(cmd_program), value(value_) {} + virtual object* clone() { return new oprogram(value); } virtual string name() { return string("program"); } virtual ostream& show(ostream& out) { out << "«" << value << "»"; @@ -153,22 +154,15 @@ struct oprogram : object { /// @brief object symbol /// struct symbol : object { - symbol(bool auto_eval_ = true) : object(cmd_symbol), auto_eval(auto_eval_) {} - symbol(const string& value_, bool auto_eval_ = true) : object(cmd_symbol) { set(value_, auto_eval_); } - void set(string& value_, bool auto_eval_) { - value = value_; - auto_eval = auto_eval_; - } - void set(const string& value_, bool auto_eval_) { - value = value_; - auto_eval = auto_eval_; - } + symbol(bool autoEval_ = true) : object(cmd_symbol), autoEval(autoEval_) {} + symbol(const string& value_, bool autoEval_ = true) : object(cmd_symbol), value(value_), autoEval(autoEval_) {} + virtual object* clone() { return new symbol(value, autoEval); } virtual string name() { return string("symbol"); } virtual ostream& show(ostream& out) { out << "'" << value << "'"; return out; } - bool auto_eval; + bool autoEval; string value; }; @@ -176,11 +170,8 @@ struct symbol : object { /// struct keyword : object { keyword() : object(cmd_keyword) {} - keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword) { set(fn_, value_); } - void set(program_fn_t fn_, const string& value_) { - fn = fn_; - value = value_; - } + keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword), fn(fn_), value(value_) {} + virtual object* clone() { return new keyword(fn, value); } virtual string name() { return string("keyword"); } program_fn_t fn; string value; @@ -190,22 +181,27 @@ struct keyword : object { /// struct branch : object { branch() : object(cmd_branch) {} - branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { set(fn_, value_); } - virtual string name() { return string("branch"); } - // - void set(branch_fn_t fn_, const string& value_) { + branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { fn = fn_; arg1 = -1; arg2 = -1; arg3 = -1; - farg1 = NULL; - farg2 = NULL; arg_bool = 0; value = value_; } + branch(branch& other) : object(cmd_branch) { + fn = other.fn; + arg1 = other.arg1; + arg2 = other.arg2; + arg3 = other.arg3; + arg_bool = other.arg_bool; + value = other.value; + } + virtual object* clone() { return new branch(*this); } + virtual string name() { return string("branch"); } branch_fn_t fn; int arg1, arg2, arg3; - number *farg1, *farg2; + mpreal firstIndex, lastIndex; bool arg_bool; string value; }; diff --git a/src/parse.cpp b/src/parse.cpp index 6d99236..90e1cfb 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -92,16 +92,12 @@ struct SynElement { int reBase; int imBase; program_fn_t fn; - bool operator==(SynElement& other) { - return type == other.type && value == other.value && (re == other.re || (isnan(re) && isnan(other.re))) && - (im == other.im || (isnan(im) && isnan(other.im))); - } + bool autoEval; }; struct SynError { size_t indx; string err; - bool operator==(SynError& other) { return err == other.err; } }; struct ReservedWord { @@ -138,7 +134,7 @@ static bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector> token; - elements.push_back({cmd_symbol, token}); + elements.push_back({cmd_symbol, .value = token, .autoEval = true}); nextIdx = token.size() + idx; return true; } @@ -356,7 +352,7 @@ static bool progFromElements(vector& elements, program& prog) { prog.push_back(new ostring(element.value)); break; case cmd_symbol: - prog.push_back(new symbol(element.value)); + prog.push_back(new symbol(element.value, element.autoEval)); break; case cmd_program: prog.push_back(new oprogram(element.value)); diff --git a/src/program.cpp b/src/program.cpp index c67e2e3..179b667 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -141,11 +141,8 @@ program::keyword_t program::s_keywords[] = { " ifte"}, {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, - {cmd_branch, "unti", (program_fn_t)&program::rpn_until, ""}, {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, - {cmd_branch, "whil", (program_fn_t)&program::rpn_while, ""}, {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, - {cmd_branch, "repea", (program_fn_t)&program::rpn_repeat, ""}, // STORE {cmd_undef, "", NULL, "\nSTORE"}, @@ -233,7 +230,12 @@ ret_value program::run(rpnstack& stk, heap& hp) { // branches for 'if' ret = preprocess(); - if (ret != ret_ok) return ret; + if (ret != ret_ok) { + // free allocated + for (object* o : *this) delete o; + _local_heap.clear(); + return ret; + } // iterate commands for (int i = 0; (go_out == false) && (interrupt_now == false) && (i < (int)size());) { @@ -271,7 +273,6 @@ ret_value program::run(rpnstack& stk, heap& hp) { break; } i++; - delete o; break; } @@ -293,19 +294,22 @@ ret_value program::run(rpnstack& stk, heap& hp) { i = next_cmd; // new direction break; } - delete o; break; } default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - stk.push_front(o); + stk.push_front(o->clone()); i++; break; } } + // free allocated + for (object* o : *this) delete o; + _local_heap.clear(); + if (interrupt_now) { fprintf(stderr, "\nInterrupted\n"); interrupt_now = false; diff --git a/src/program.hpp b/src/program.hpp index 17cf5e9..dc61672 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -49,6 +49,10 @@ class program : public deque { _parent_prog = parent_prog; interrupt_now = false; } + virtual ~program() { + _local_heap.clear(); + clear(); + } // parser static ret_value parse(string& entry, program& prog); diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index f43aa9e..b30b5e5 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -11,11 +11,11 @@ int program::rpn_if(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - if (((number*)_stack->at(0))->value != 0) + if (_stack->value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; - _stack->pop_front(); + _stack->pop(); return -1; } @@ -30,7 +30,7 @@ int program::rpn_then(branch& myobj) { // myobj.arg3 = index of if // if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1) - branch* if_cmd = (branch*)(*this)[myobj.arg3]; + branch* if_cmd = (branch*)at(myobj.arg3); if (if_cmd->arg1 == 1) return myobj.arg1; else @@ -49,7 +49,7 @@ int program::rpn_else(branch& myobj) { // myobj.arg3 = index of if // if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1) - branch* if_cmd = (branch*)(*this)[myobj.arg3]; + branch* if_cmd = (branch*)at(myobj.arg3); if (if_cmd->arg1 == 1) return myobj.arg2; else @@ -116,16 +116,11 @@ void program::rpn_ift(void) { // check ift arg // arg is true if number != 0 or if is nan or +/-inf - number* testee = ((number*)_stack->at(1)); - - if (testee->value != 0) { - CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack)); - _stack->pop_front(2); - - CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); - _calc_stack.pop_front(); - } else + if (_stack->value(1) != 0) { + _stack->erase(1); + } else { _stack->pop_front(2); + } } /// @brief ifte keyword (branch) implementation @@ -139,18 +134,13 @@ void program::rpn_ifte(void) { ARG_MUST_BE_OF_TYPE(2, cmd_number); // check ifte arg - // arg is true if number != 0 or if is nan or +/-inf - number* testee = ((number*)_stack->at(2)); - - if (testee->value != 0) - CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 2, _calc_stack)); - else - CHECK_MPFR(rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack)); - - (void)_stack->pop_front(3); - - CHECK_MPFR(rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack)); - _calc_stack.pop_front(); + if (_stack->value(2) != 0) { + _stack->erase(2); + _stack->pop(); + } else { + _stack->erase(2); + _stack->erase(1); + } } /// @brief while keyword (branch) implementation @@ -197,18 +187,13 @@ int program::rpn_start(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); - // farg2 = last value of start command - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - myobj.farg2 = (number*)_calc_stack.back(); - _stack->pop_front(); - - // farg1 = first value of start command - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - myobj.farg1 = (number*)_calc_stack.back(); - _stack->pop_front(); + // loop boundaries + myobj.firstIndex = _stack->value(1); + myobj.lastIndex = _stack->value(0); + _stack->pop_front(2); // test value - if (myobj.farg1->value > myobj.farg2->value) + if (myobj.firstIndex > myobj.lastIndex) // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' @@ -230,31 +215,31 @@ int program::rpn_for(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); - symbol* sym = (symbol*)(*this)[myobj.arg1]; + symbol* sym = (symbol*)at(myobj.arg1); // arg1 = loop variable index - // farg2 = last value of for command - // arg1 = index of symbol to increase - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - myobj.farg2 = (number*)_calc_stack.back(); - _stack->pop_front(); - - // farg1 = first value of for command - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - myobj.farg1 = (number*)_calc_stack.back(); - _stack->pop_front(); + // loop boundaries + myobj.firstIndex = _stack->value(1); + myobj.lastIndex = _stack->value(0); // test value - if (myobj.farg1->value > myobj.farg2->value) + if (myobj.firstIndex > myobj.lastIndex) // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' ret = myobj.arg2 + 1; else { // store symbol with first value - _local_heap[sym->value] = myobj.farg1; + auto it = _local_heap.find(sym->value); + if (it != _local_heap.end()) { + delete it->second; + _local_heap.erase(it); + } + _local_heap[sym->value] = _stack->obj(1)->clone(); ret = myobj.arg1 + 1; } + _stack->pop_front(2); + return ret; } @@ -265,33 +250,32 @@ int program::rpn_for(branch& myobj) { /// @return -1 the next object index to run in the current program is the current+1 /// int program::rpn_next(branch& myobj) { - // arg1 = index of start or for command in program - // farg1 = current count - branch* start_or_for = (branch*)(*this)[myobj.arg1]; + // arg1 = loop variable index + // firstIndex = current point in the loop + branch* start_or_for = (branch*)at(myobj.arg1); if (!myobj.arg_bool) { myobj.arg_bool = true; - myobj.farg1 = start_or_for->farg1; + myobj.firstIndex = start_or_for->firstIndex; } // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - myobj.farg1->value++; + mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), mpreal(1).mpfr_srcptr(), MPFR_RNDD); // for command: increment symbol too if (start_or_for->arg1 != -1) { object* obj; unsigned int size; - symbol* var = (symbol*)(*this)[start_or_for->arg1]; + symbol* var = (symbol*)at(start_or_for->arg1); - // increase symbol variable - _local_heap[var->value] = myobj.farg1; + // store symbol variable (asserted existing in the local heap) + ((number*)_local_heap[var->value])->value = myobj.firstIndex; } // test value - if (myobj.farg1->value > start_or_for->farg2->value) { + if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - _calc_stack.pop_front(2); return -1; } else { // for command: next instruction will be after symbol variable @@ -314,39 +298,38 @@ int program::rpn_step(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); mpreal step = _stack->value(0); + _stack->pop(); // end of loop if step is negative or zero - if (step.toLong() <= 0) + if (step <= 0) ret = -1; else { - // arg1 = index of start or for command in program - // farg1 = current count - branch* start_or_for = (branch*)(*this)[myobj.arg1]; + // arg1 = loop variable index + // firstIndex = current count + branch* start_or_for = (branch*)at(myobj.arg1); if (!myobj.arg_bool) { myobj.arg_bool = true; - myobj.farg1 = start_or_for->farg1; + myobj.firstIndex = start_or_for->firstIndex; } // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - myobj.farg1->value+=step.mpfr_ptr(); - mpfr_add(myobj.farg1->value.mpfr_ptr(), myobj.farg1->value.mpfr_ptr(), step.mpfr_ptr(), MPFR_RNDD); + mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD); // for command: increment symbol too if (start_or_for->arg1 != -1) { object* obj; unsigned int size; - symbol* var = (symbol*)(*this)[start_or_for->arg1]; + symbol* var = (symbol*)at(start_or_for->arg1); // increase symbol variable - _local_heap[var->value] = myobj.farg1; - } + ((number*)_local_heap[var->value])->value = myobj.firstIndex; + } // test loop value is out of range - if (myobj.farg1->value > start_or_for->farg2->value) { + if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - _calc_stack.pop_front(2); ret = -1; } else { // for command: next instruction will be after symbol variable diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index cae9b90..bf01990 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -6,7 +6,13 @@ void program::rpn_sto(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - (*_heap)[_stack->value(0)] = _stack->at(1); + // store symbol with first value + auto it = _heap->find(_stack->value(0)); + if (it != _heap->end()) { + delete it->second; + _heap->erase(it); + } + (*_heap)[_stack->value(0)] = _stack->at(1)->clone(); _stack->pop_front(2); } @@ -214,18 +220,18 @@ void program::rpn_edit(void) { /// @param symb the smlbol to recall and autoeval /// void program::auto_rcl(symbol* symb) { - if (symb->auto_eval) { + if (symb->autoEval) { object* obj; string variable(symb->value); // mind the order of heaps if (find_variable(variable, obj)) { - _stack->push_front(obj); + _stack->push_front(obj->clone()); if (obj->_type == cmd_program) rpn_eval(); } else - _stack->push_front(symb); + _stack->push_front(symb->clone()); } else - _stack->push_front(symb); + _stack->push_front(symb->clone()); } /// @brief purge keyword implementation diff --git a/src/rpn-test-core.cpp b/src/rpn-test-framework.cpp similarity index 100% rename from src/rpn-test-core.cpp rename to src/rpn-test-framework.cpp diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index c153d68..3d6b3a8 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -8,7 +8,7 @@ long program::cmp_strings_on_stack_top() { // _stack should have 2 strings at level 1 and 2 // this function removes these 2 entries - long res = (long)static_cast(_stack->at(0))->value.compare(static_cast(_stack->at(1))->value); + long res = (long)static_cast(_stack->at(1))->value.compare(static_cast(_stack->at(0))->value); (void)_stack->pop_front(2); return res; } @@ -20,7 +20,7 @@ void program::rpn_sup(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) > _stack->value(1))); + _stack->push_front(new number(_stack->value(1) > _stack->value(0))); _stack->erase(1, 2); } // strings @@ -38,7 +38,7 @@ void program::rpn_sup_eq(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) >= _stack->value(1))); + _stack->push_front(new number(_stack->value(1) >= _stack->value(0))); _stack->erase(1, 2); } // strings @@ -56,7 +56,7 @@ void program::rpn_inf(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) < _stack->value(1))); + _stack->push_front(new number(_stack->value(1) < _stack->value(0))); _stack->erase(1, 2); } // strings @@ -72,7 +72,7 @@ void program::rpn_inf(void) { void program::rpn_inf_eq(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) <= _stack->value(1))); + _stack->push_front(new number(_stack->value(1) <= _stack->value(0))); _stack->erase(1, 2); } // strings @@ -90,12 +90,12 @@ void program::rpn_diff(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) != _stack->value(1))); + _stack->push_front(new number(_stack->value(1) != _stack->value(0))); _stack->erase(1, 2); } // complexes else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->push_front(new number(_stack->value(0) != _stack->value(1))); + _stack->push_front(new number(_stack->value(1) != _stack->value(0))); _stack->erase(1, 2); } // strings @@ -113,12 +113,12 @@ void program::rpn_eq(void) { // numbers if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(0) == _stack->value(1))); + _stack->push_front(new number(_stack->value(1) == _stack->value(0))); _stack->erase(1, 2); } // complexes else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->push_front(new number(_stack->value(0) == _stack->value(1))); + _stack->push_front(new number(_stack->value(1) == _stack->value(0))); _stack->erase(1, 2); } // strings diff --git a/src/stack.hpp b/src/stack.hpp index 04afb78..fa91a16 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -76,7 +76,12 @@ class rpnstack : public deque { class heap : public map { public: heap() {} - virtual ~heap() {} + virtual ~heap() { clear(); } + + void clear() { + for_each(begin(), end(), [](auto it) { delete it.second; }); + map::erase(begin(), end()); + } /// @brief get a variable /// diff --git a/test/027-base-entry.md b/test/027-base-entry.md index f7fa289..d81fcd8 100644 --- a/test/027-base-entry.md +++ b/test/027-base-entry.md @@ -238,7 +238,7 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `2 62 for i 62 i base next` --> stack should be 2b111110, 3b2022, 4b332, 5b222, 6b142, 7b116, 8b76, 9b68, 10b62, 11b57, 12b52, 13b4a, 14b46, 15b42, 16b3e, 17b3b, 18b38, 19b35, 20b32, 21b2k, 22b2i, 23b2g, 24b2e, 25b2c, 26b2a, 27b28, 28b26, 29b24, 30b22, 31b20, 32b1u, 33b1t, 34b1s, 35b1r, 36b1q, 37b1P, 38b1O, 39b1N, 40b1M, 41b1L, 42b1K, 43b1J, 44b1I, 45b1H, 46b1G, 47b1F, 48b1E, 49b1D, 50b1C, 51b1B, 52b1A, 53b19, 54b18, 55b17, 56b16, 57b15, 58b14, 59b13, 60b12, 61b11, 62b10 +-> stack should be 0b111110, 3b2022, 4b332, 5b222, 6b142, 7b116, 8b76, 9b68, 62, 11b57, 12b52, 13b4a, 14b46, 15b42, 0x3e, 17b3b, 18b38, 19b35, 20b32, 21b2k, 22b2i, 23b2g, 24b2e, 25b2c, 26b2a, 27b28, 28b26, 29b24, 30b22, 31b20, 32b1u, 33b1t, 34b1s, 35b1r, 36b1q, 37b1P, 38b1O, 39b1N, 40b1M, 41b1L, 42b1K, 43b1J, 44b1I, 45b1H, 46b1G, 47b1F, 48b1E, 49b1D, 50b1C, 51b1B, 52b1A, 53b19, 54b18, 55b17, 56b16, 57b15, 58b14, 59b13, 60b12, 61b11, 62b10 `del default` diff --git a/test/030-branch.md b/test/030-branch.md index da662a2..0d7d39b 100644 --- a/test/030-branch.md +++ b/test/030-branch.md @@ -69,7 +69,7 @@ `0 if then` --> error should be 11 +-> error should be 12 `del` @@ -77,7 +77,7 @@ `0 if end` --> error should be 11 +-> error should be 12 `del` @@ -85,7 +85,7 @@ `0 if end` --> error should be 11 +-> error should be 12 `del` @@ -93,7 +93,7 @@ `then` --> error should be 11 +-> error should be 12 `del` @@ -101,7 +101,7 @@ `1 if` --> error should be 11 +-> error should be 12 `del` @@ -109,7 +109,7 @@ `else` --> error should be 11 +-> error should be 12 `del` @@ -118,7 +118,7 @@ `end` --> error should be 11 +-> error should be 12 `del` @@ -252,11 +252,51 @@ `del` +## start next - cloning objects (1) + +`1 2 start 'ok' next` + +-> stack should be 'ok', 'ok' + +`del` + +## start next - cloning objects (2) + +`1 2 start ok next` + +-> stack should be 'ok', 'ok' + +`del` + +## start next - cloning objects (3) + +`1 2 start "ok" next` + +-> stack should be "ok", "ok" + +`del` + +## start next - cloning objects (4) + +`1 2 start (1,2) next` + +-> stack should be (1,2), (1,2) + +`del` + +## start next - cloning objects (5) + +`1 2 start «ok» next` + +-> stack should be «ok», «ok» + +`del` + ## start next - error case (1) `1 start next` -->error should be 2 +-> error should be 2 `del` @@ -264,7 +304,7 @@ `start next` -->error should be 2 +-> error should be 2 `del` @@ -272,7 +312,7 @@ `start` -->error should be 11 +-> error should be 12 `del` @@ -280,7 +320,7 @@ `next` -->error should be 11 +-> error should be 12 `del` @@ -288,15 +328,15 @@ `"1" 2 start next` -->error should be 3 +-> error should be 3 `del` -## start next - error case (5) +## start next - error case (6) `1 "2" start next` -->error should be 3 +-> error should be 3 `del` @@ -340,6 +380,14 @@ `del` +## for next - loop variable overwrite + +`123 'i' sto 1 2 for i i next` + +-> stack should be 1, 2 + +`del` + ## for next - error case (1) `1 for i i next` @@ -376,7 +424,7 @@ `1 2 for i i` --> error should be 11 +-> error should be 12 `del` @@ -384,7 +432,7 @@ `for` --> error should be 11 +-> error should be 12 `del` @@ -456,103 +504,95 @@ `step` --> error should be 11 +-> error should be 12 `del` -## do..unti (1) +## do..until (1) -`do 'ok' unti 1 end` +`do 'ok' until 1 end` -> stack should be 'ok' `del` -## do..unti (2) +## do..until (2) -`do unti 1 end` +`do until 1 end` -> stack size should be 0 `del` -## do..unti (3) +## do..until (3) -`1 'a' sto do a unti a 0 > end` +`3 do 1 - 'ok' swap dup until 0 == end drop` --> stack should be 1 +-> stack should be 'ok', 'ok', 'ok' `del` -## do..unti (4) +## do..until (4) -`1 'a' sto do a 'a' 1 sto+ unti a 3 > end` +`1 'a' sto do a 1 + 'a' sto until a 3 > end a` --> stack should be 1, 2, 3 +-> stack should be 4 `del` -## do..unti (5) - -`"" 0 'a' sto do 'a' 1 sto+ 0 a for b b ->str + next unti a 3 > end` - --> stack should be "01012012301234" - -`del` - -## do..unti error case (1) +## do..until error case (1) `do` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (2) +## do..until error case (2) `do 8 end` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (3) +## do..until error case (3) -`unti` +`until` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (4) +## do..until error case (4) -`do 3 unti` +`do 3 until` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (5) +## do..until error case (5) -`unti 1 end` +`until 1 end` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (6) +## do..until error case (6) `do 3 repeat 8 end` --> error should be 11 +-> error should be 12 `del` -## do..unti error case (7) +## do..until error case (7) `do 3 until 8 until 9 end` --> error should be 11 +-> error should be 12 `del` @@ -574,9 +614,9 @@ ## while..repeat (3) -`"" 0 'a' sto while a 3 < repeat 'a' 1 sto+ 0 a for b b ->str + next end` +`0 'a' sto while a 3 < repeat a 1 + 'a' sto 100 0 a for b b + next end` --> stack should be "010120123" +-> stack should be 101, 103, 106 `del` @@ -584,7 +624,7 @@ `while` --> error should be 11 +-> error should be 12 `del` @@ -592,7 +632,7 @@ `while 3 end` --> error should be 11 +-> error should be 12 `del` @@ -600,7 +640,7 @@ `repeat` --> error should be 11 +-> error should be 12 `del` @@ -608,7 +648,7 @@ `while 1 repeat` --> error should be 11 +-> error should be 12 `del` @@ -616,7 +656,7 @@ `repeat 1 end` --> error should be 11 +-> error should be 12 `del` @@ -624,7 +664,7 @@ `while 3 repeat 8 repeat 9 end` --> error should be 11 +-> error should be 12 `del` @@ -632,6 +672,6 @@ `while 3 until 8 end` --> error should be 11 +-> error should be 12 `del` diff --git a/test/all.md b/test/all.md index dd3df47..4535d1c 100644 --- a/test/all.md +++ b/test/all.md @@ -10,7 +10,7 @@ @include 025-parse-other.md @include 026-parse-program.md @include 027-base-entry.md -# @include 030-branch.md +@include 030-branch.md # @include 040-stack.md # @include 050-real.md # @include 060-string.md diff --git a/test/mem_test.sh b/test/mem_test.sh index 16f2875..0825106 100755 --- a/test/mem_test.sh +++ b/test/mem_test.sh @@ -19,7 +19,7 @@ function checkmem { fi } -to_test=( +quick_tests=( "1.2 \"string\" 'ok' (2,3) << 9 nop >>" # base types inputs "nop help version uname history quit" # general commands "38 std 38 fix 38 sci 10 prec 2 default \"toward zero\" round" # modes @@ -31,9 +31,15 @@ to_test=( "1 2 3 swap" # stack operations ) -echo "\nPOURQUOI NE PAS FAIRE UN TEST DE CHAQUE test.md PLUTOT ?\n" -echo "rpn memory check" -for i in ${!to_test[@]}; do - checkmem "${to_test[$i]}" +functional_tests=($(cat all.md | grep "^@include" | awk '{print $2}')) + +echo "Quick rpn memory checks" +for i in ${!quick_tests[@]}; do + checkmem "${quick_tests[$i]}" +done + +echo "Functional rpn memory checks" +for i in ${!functional_tests[@]}; do + checkmem "${functional_tests[$i]} test" done exit ${failed} From 42a9065d5208e7573f3ff2ab59ffb9dcaa2b2eda Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Wed, 16 Feb 2022 17:36:26 +0100 Subject: [PATCH 08/57] refactoring stack --- Changelog | 1 + src/program.hpp | 3 --- src/rpn-stack.cpp | 53 ++++++++++++++--------------------------------- src/stack.hpp | 3 +-- test/040-stack.md | 8 +++---- test/all.md | 2 +- 6 files changed, 23 insertions(+), 47 deletions(-) diff --git a/Changelog b/Changelog index 7bd740d..183b293 100644 --- a/Changelog +++ b/Changelog @@ -19,3 +19,4 @@ Compatibility is broken on these points New - `« »` are valid as program delimiters. `<<` and `>>` are still valid - enhanced code quality and memory usage checks +- some bugs (dupn, roll, rolld wrongly leaving the front arg in case of error) diff --git a/src/program.hpp b/src/program.hpp index dc61672..587e4a0 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -93,9 +93,6 @@ class program : public deque { // local heap for local loop variables (for..next) heap _local_heap; - // calc stack internally used by branch and calc commands - rpnstack _calc_stack; - // parent prog for inheriting heaps program* _parent_prog; diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index ec39391..1fe1491 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -12,7 +12,7 @@ void program::rpn_swap(void) { /// void program::rpn_drop(void) { MIN_ARGUMENTS(1); - _stack->pop_front(); + _stack->pop(); } /// @brief drop2 keyword implementation @@ -50,10 +50,10 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->value.toLong(); - MIN_ARGUMENTS(args + 1); - _stack->pop_front(); + int args = (int)((number*)_stack->front())->value.toLong(); + _stack->pop(); + MIN_ARGUMENTS(args); for (int i = 0; i < args; i++) rpnstack::copy_and_push_front(*_stack, args - 1, *_stack); } @@ -88,14 +88,8 @@ void program::rpn_pick(void) { void program::rpn_rot(void) { MIN_ARGUMENTS(3); - rpnstack::copy_and_push_front(*_stack, 2, _calc_stack); - rpnstack::copy_and_push_front(*_stack, 1, _calc_stack); - rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); - (void)_stack->pop_front(3); - rpnstack::copy_and_push_front(_calc_stack, 1, *_stack); - rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); - rpnstack::copy_and_push_front(_calc_stack, 2, *_stack); - _calc_stack.pop_front(3); + rpnstack::copy_and_push_front(*_stack, 2, *_stack); + _stack->erase(3); } /// @brief depth keyword implementation @@ -108,19 +102,12 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->value.toLong(); - MIN_ARGUMENTS(args + 1); - _stack->pop_front(); + size_t args = (int)((number*)_stack->front())->value; + _stack->pop(); + MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) { - rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); - _stack->pop_front(); - } - - for (int i = 1; i < args; i++) rpnstack::copy_and_push_front(_calc_stack, args - 1 - i, *_stack); - rpnstack::copy_and_push_front(_calc_stack, args - 1, *_stack); - - _calc_stack.pop_front(args); + rpnstack::copy_and_push_front(*_stack, args - 1, *_stack); + _stack->erase(args); } /// @brief rolld keyword implementation @@ -129,20 +116,12 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->back())->value.toLong(); - MIN_ARGUMENTS(args + 1); - _stack->pop_front(); + int args = (int)((number*)_stack->front())->value.toLong(); + _stack->pop(); + MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) { - rpnstack::copy_and_push_front(*_stack, 0, _calc_stack); - _stack->pop_front(); - } - - rpnstack::copy_and_push_front(_calc_stack, args - 1, *_stack); - - for (int i = 1; i < args; i++) rpnstack::copy_and_push_front(_calc_stack, i - 1, *_stack); - - _calc_stack.pop_front(args); + _stack->insert(_stack->begin()+args, _stack->at(0)->clone()); + _stack->pop(); } /// @brief over keyword implementation diff --git a/src/stack.hpp b/src/stack.hpp index fa91a16..6e14732 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -28,8 +28,7 @@ class rpnstack : public deque { /// static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { // carefull: caller must ensure that index_from is correct - auto newObj = from[index_from]->clone(); - if (newObj != nullptr) to.push_front(newObj); + to.push_front(from[index_from]->clone()); } /// @brief erase a stack entry from it index diff --git a/test/040-stack.md b/test/040-stack.md index 91441a8..3d776c2 100644 --- a/test/040-stack.md +++ b/test/040-stack.md @@ -42,7 +42,7 @@ -> stack size should be 1 --> error should 2 +-> error should be 2 `del` @@ -212,7 +212,7 @@ `1 2 3 4 5 dupn` --> stack size should be 5 +-> stack size should be 4 -> error should be 2 @@ -238,7 +238,7 @@ `1 2 3 4 5 6 roll` --> stack size should be 6 +-> stack size should be 5 -> error should be 2 @@ -264,7 +264,7 @@ `1 2 3 4 5 6 rolld` --> stack size should be 6 +-> stack size should be 5 -> error should be 2 diff --git a/test/all.md b/test/all.md index 4535d1c..4e50d65 100644 --- a/test/all.md +++ b/test/all.md @@ -11,7 +11,7 @@ @include 026-parse-program.md @include 027-base-entry.md @include 030-branch.md -# @include 040-stack.md +@include 040-stack.md # @include 050-real.md # @include 060-string.md # @include 070-test.md From 84b5ce9e62a4ab7e59896237d879d90c2482c4b1 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 17 Feb 2022 16:33:51 +0100 Subject: [PATCH 09/57] parser fix for numbers and real functions --- CMakeLists.txt | 2 +- Changelog | 7 ++ src/object.hpp | 2 +- src/parse.cpp | 64 +++++------ src/program.cpp | 37 +++---- src/rpn-real.cpp | 60 +++++------ src/rpn-trig.cpp | 224 ++++++--------------------------------- test/023-parse-number.md | 5 + test/027-base-entry.md | 14 ++- test/050-real.md | 105 +++++------------- test/all.md | 2 +- 11 files changed, 159 insertions(+), 363 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f72dd57..6f87c92 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -68,7 +68,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cpp #${PROJECT_SOURCE_DIR}/src/rpn-time.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp diff --git a/Changelog b/Changelog index 183b293..f48ead5 100644 --- a/Changelog +++ b/Changelog @@ -10,6 +10,7 @@ Compatibility is broken on these points - this correct bad behaviors like `3b114` giving `3b11` and `4` - complexes are written in the form `(1,2)` instead of `(1, 2)` (the space was removed) - removed useless 'unti', 'repea', 'whil' (existing for HP28S compatibility), causing parsing problems +- removed 'sqr' function, please use 'sq' instead - syntax error code is now 12 instead of 11 - `test` command can also take a symbol as a parameter ; if the symbol contains a valid - à l'affichage le préfixe des chiffres en base 2 est 0b et pas 2b (la saisie 2bxxx est toutefois permise) @@ -20,3 +21,9 @@ New - `« »` are valid as program delimiters. `<<` and `>>` are still valid - enhanced code quality and memory usage checks - some bugs (dupn, roll, rolld wrongly leaving the front arg in case of error) +- added `norm` as a synonym of `abs` + +cas de tests à ajouter: +ab Xb 1b +ax 0X 3X +0x12pa1 \ No newline at end of file diff --git a/src/object.hpp b/src/object.hpp index 1b2853d..aacae29 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -58,7 +58,7 @@ struct object { /// struct number : object { number() : object(cmd_number), base(10) {} - number(mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} + number(const mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} number(long value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} int base; diff --git a/src/parse.cpp b/src/parse.cpp index 90e1cfb..60b9294 100644 --- a/src/parse.cpp +++ b/src/parse.cpp @@ -1,3 +1,5 @@ +#include + #include "program.hpp" /// @brief completion callback as asked by linenoise-ng @@ -170,31 +172,21 @@ static bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector= idxStart + 2 && baseStr[1] == 'b') { - int base = stoi(baseStr.substr(0, 1)); - if (base >= BASE_MIN && base <= BASE_MAX) { - idxNumber = 2; - return base; - } - } - if (entry.size() >= idxStart + 3) { - baseStr = entry.substr(idxStart, 3); - if (isdigit(baseStr[0]) && isdigit(baseStr[1]) && baseStr[2] == 'b') { - int base = stoi(baseStr.substr(0, 2)); - if (base >= BASE_MIN && base <= BASE_MAX) { - idxNumber = 3; - return base; - } +static int getBase(string& entry, int idxStart, bool& positive) { + regex baseRegex("([+-])?((0[xX])|([0-9][0-9]?[bB]))"); + smatch match; + if (regex_search(entry, match, baseRegex) && match.size() >= 5) { + string sign = match[1].str(); + string base = match[2].str(); + // sign out, permits expressions like -0xAB3F + positive = sign.size() > 0 && sign[0] == '-' ? false : true; + // base + entry = entry.substr(base.size() + sign.size()); + if (base[1] == 'X' || base[1] == 'x') return 16; + if (base.size() > 0) { + int b = stoi(base.substr(0, base.size() - 1)); + if (b == 0) b = 2; // admit "0b" as binary suffix + return b; } } return 10; @@ -204,19 +196,21 @@ static bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m stringstream ss; int idxNumber = 0; string token; + bool positive = true; - base = getBase(entry, idx, idxNumber); - - ss.str(entry.substr(idx + idxNumber)); + ss.str(entry.substr(idx)); if (getline(ss, token, delim)) { - nextIdx = token.size() + idx + idxNumber; + nextIdx = token.size() + idx + 1; + base = getBase(token, idx, positive); + if (base < BASE_MIN || base > BASE_MAX) return false; trim(token); - if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) + if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { + if (!positive) r = -r; return true; - else + } else return false; } - nextIdx = token.size() + idx + idxNumber + 1; + nextIdx = token.size() + idx + 1; return false; } @@ -249,14 +243,14 @@ static bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector= entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol } - if (!getNumberAt(entry, i + 1, nextIdx, imBase, im, ')')) { + if (!getNumberAt(entry, i, nextIdx, imBase, im, ')')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol diff --git a/src/program.cpp b/src/program.cpp index 179b667..883e960 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -31,16 +31,16 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "^", &program::rpn_power, "power"}, {cmd_keyword, "pow", &program::rpn_power, ""}, {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, - // {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, - // {cmd_keyword, "sqr", &program::rpn_square, ""}, - // {cmd_keyword, "abs", &program::rpn_abs, "absolute value"}, + {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, + {cmd_keyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, + {cmd_keyword, "norm", &program::rpn_abs, ""}, // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, // OPERATIONS ON REALS {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, - //{cmd_keyword, "%", &program::rpn_purcent, "purcent"}, - //{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, - // {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, + {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, + {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, + {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, // {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, // {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, // {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, @@ -69,8 +69,9 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"}, {cmd_keyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec"}, {cmd_keyword, "round", &program::rpn_round, - "set float rounding mode.\n\tex: [\"nearest\", \"toward zero\", \"toward " - "+inf\", \"toward -inf\", \"away from zero\"] round"}, + "set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward " + "+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"] round"}, + {cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default"}, {cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"}, {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"}, @@ -166,16 +167,16 @@ program::keyword_t program::s_keywords[] = { ">>"}, // TRIG ON REALS AND COMPLEXES - // {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, - // {cmd_keyword, "pi", &program::rpn_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::rpn_d2r, "convert degrees to radians"}, - // {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, + {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, + {cmd_keyword, "pi", &program::rpn_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::rpn_d2r, "convert degrees to radians"}, + {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES // {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index d090cbf..5953012 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -150,6 +150,7 @@ void program::rpn_inv() { /// @brief power keyword implementation /// void program::rpn_power() { + MIN_ARGUMENTS(2); if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { _stack->value(1) = pow(_stack->value(1), _stack->value(0)); _stack->pop(); @@ -170,9 +171,10 @@ void program::rpn_power() { /// @brief sqrt keyword implementation /// void program::rpn_squareroot() { + MIN_ARGUMENTS(1); if (_stack->type(0) == cmd_number) { if (_stack->value(0) >= 0) { - _stack->value(0) = rec_sqrt(_stack->value(0)); + _stack->value(0) = sqrt(_stack->value(0)); } else { // negative number -> square root is compl ex _stack->push(new ocomplex); // TODO manage new errors @@ -239,40 +241,20 @@ void program::rpn_base() { _stack->obj(0)->reBase = base; _stack->obj(0)->imBase = base; } - } - else + } else ERR_CONTEXT(ret_out_of_range); } else ERR_CONTEXT(ret_bad_operand_type); } -#if 0 - -/// @brief sq keyword implementation -/// -void program::rpn_square() { - MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_sqr(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - rpn_dup(); - rpn_mul(); - } else - ERR_CONTEXT(ret_bad_operand_type); -} - /// @brief % (purcent) keyword implementation /// void program::rpn_purcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - left->value *= right->value; - left->value /= 100; + _stack->value(1) *= _stack->value(0) / 100; + _stack->pop(); } /// @brief %CH keyword implementation @@ -281,10 +263,21 @@ void program::rpn_purcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - right->value *= 100; - left->value /= right->value; + _stack->value(1) = (_stack->value(0) * 100) / _stack->value(1); + _stack->pop(); +} + +/// @brief sq keyword implementation +/// +void program::rpn_square() { + MIN_ARGUMENTS(1); + + if (_stack->type(0) == cmd_number) + _stack->value(0) *= _stack->value(0); + else if (_stack->at(0)->_type == cmd_complex) + _stack->value(0) *= _stack->value(0); + else + ERR_CONTEXT(ret_bad_operand_type); } /// @brief mod keyword implementation @@ -293,21 +286,18 @@ void program::rpn_modulo() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_fmod(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); + _stack->value(1) = fmod(_stack->value(1), _stack->value(0)); + _stack->pop(); } -#endif #if 0 + /// @brief abs keyword implementation /// void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { + if (_stack->type(0) == cmd_number) { number* left = (number*)_stack->back(); CHECK_MPFR(mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); } else if (_stack->at(0)->_type == cmd_complex) { diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 1088797..07d14a6 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -3,9 +3,7 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - number* pi; - _stack->push_front(pi = static_cast(new number)); - CHECK_MPFR(mpfr_const_pi(pi->_value.mpfr, mpreal::get_default_rnd())); + _stack->push_front(new number(const_pi())); } /// @brief d->r keyword implementation @@ -13,15 +11,8 @@ void program::rpn_pi(void) { void program::rpn_d2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - // add pi on stack - rpn_pi(); - - floating_t* pi = &((number*)_stack->pop_front())->_value; - floating_t* left = &((number*)_stack->at(0))->_value; - - CHECK_MPFR(mpfr_mul(left->mpfr, left->mpfr, pi->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_div_si(left->mpfr, left->mpfr, 180, mpreal::get_default_rnd())); + _stack->value(0) *= const_pi(); + _stack->value(0) /= 180; } /// @brief r->d keyword implementation @@ -29,15 +20,8 @@ void program::rpn_d2r(void) { void program::rpn_r2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - // add pi on stack - rpn_pi(); - - floating_t* pi = &((number*)_stack->pop_front())->_value; - floating_t* left = &((number*)_stack->at(0))->_value; - - CHECK_MPFR(mpfr_div(left->mpfr, left->mpfr, pi->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul_si(left->mpfr, left->mpfr, 180, mpreal::get_default_rnd())); + _stack->value(0) /= const_pi(); + _stack->value(0) *= 180; } /// @brief sin keyword implementation @@ -45,32 +29,11 @@ void program::rpn_r2d(void) { void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_sin(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // sin(x+iy)=sin(x)cosh(y)+icos(x)sinh(y) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - number* num = static_cast(new number); - _stack->push_front(num); - floating_t* tmp = &num->_value; - floating_t* x = ((complex*)_calc_stack.at(1))->re(); - floating_t* y = ((complex*)_calc_stack.at(1))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - CHECK_MPFR(mpfr_cos(im->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(2); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = sin(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = sin(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -79,37 +42,11 @@ void program::rpn_sin(void) { void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_asin(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - number* num; - complex* i; - - // asin(z)=-iln(iz+sqrt(1-z*z)) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - i = (complex*)_calc_stack.at(0); - CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, mpreal::get_default_rnd())); - - rpn_dup(); - rpn_square(); - _stack->push_front(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_minus(); - rpn_neg(); - rpn_squareroot(); - rpn_swap(); - rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); - rpn_mul(); - rpn_plus(); - rpn_ln(); - rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); - rpn_mul(); - rpn_neg(); - _calc_stack.pop_front(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = asin(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = asin(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -118,33 +55,11 @@ void program::rpn_asin(void) { void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_cos(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // cos(x+iy) = cos(x)cosh(y) - isin(x)sinh(y) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - number* num = static_cast(new number); - _stack->push_front(num); - floating_t* tmp = &num->_value; - floating_t* x = ((complex*)_calc_stack.at(1))->re(); - floating_t* y = ((complex*)_calc_stack.at(1))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - CHECK_MPFR(mpfr_cos(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - CHECK_MPFR(mpfr_sin(im->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sinh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_neg(im->mpfr, im->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(2); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = cos(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = cos(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -153,20 +68,11 @@ void program::rpn_cos(void) { void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_acos(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // acos(z)=pi/2-asin(z) - rpn_asin(); - rpn_pi(); - number* num; - _stack->push_front(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); - rpn_div(); - rpn_minus(); - rpn_neg(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = acos(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = acos(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -175,42 +81,11 @@ void program::rpn_acos(void) { void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_tan(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // tan(x+iy) = (sin(2x)+isinh(2y)) / cosh(2y)+cos(2x) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - number* num = static_cast(new number); - _stack->push_front(num); - floating_t* tmp = &num->_value; - floating_t* x = ((complex*)_calc_stack.at(1))->re(); - floating_t* y = ((complex*)_calc_stack.at(1))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - // x->2x - CHECK_MPFR(mpfr_mul_si(x->mpfr, x->mpfr, 2, mpreal::get_default_rnd())); - // y->2y - CHECK_MPFR(mpfr_mul_si(y->mpfr, y->mpfr, 2, mpreal::get_default_rnd())); - - // sin(2x)+sinh(2y) - CHECK_MPFR(mpfr_sin(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sinh(im->mpfr, y->mpfr, mpreal::get_default_rnd())); - - // cosh(2y)+cos(2x) - CHECK_MPFR(mpfr_cosh(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cos(x->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_add(tmp->mpfr, tmp->mpfr, x->mpfr, mpreal::get_default_rnd())); - - // sin(2x)+sinh(2y) / (cosh(2y)+cos(2x)) - CHECK_MPFR(mpfr_div(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_div(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(2); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = tan(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = tan(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -219,39 +94,10 @@ void program::rpn_tan(void) { void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_atan(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - number* num; - complex* i; - - // atan(z)=0.5i(ln((1-iz)/(1+iz)) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - i = (complex*)_calc_stack.at(0); - CHECK_MPFR(mpfr_set_d(i->re()->mpfr, 0.0, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 1.0, mpreal::get_default_rnd())); - - rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); - rpn_mul(); - _stack->push_front(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_minus(); // iz-1 - rpn_neg(); // 1-iz - rpn_dup(); - rpn_neg(); // iz-1 - _stack->push_front(num = static_cast(new number)); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); - rpn_plus(); // iz+1 - rpn_div(); - - rpn_ln(); - CHECK_MPFR(mpfr_set_d(i->im()->mpfr, 0.5, mpreal::get_default_rnd())); - rpnstack::copy_and_push_front(_calc_stack, 0, *_stack); - rpn_mul(); - - _calc_stack.pop_front(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = atan(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = atan(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/test/023-parse-number.md b/test/023-parse-number.md index 68bd595..72183d8 100644 --- a/test/023-parse-number.md +++ b/test/023-parse-number.md @@ -122,4 +122,9 @@ -> stack should be 12345, 0b1100 +## hex powers +`del 0x10p3 -0x2p4` + +-> stack should be 0x80, -0x20 + `del default` diff --git a/test/027-base-entry.md b/test/027-base-entry.md index d81fcd8..fbe7435 100644 --- a/test/027-base-entry.md +++ b/test/027-base-entry.md @@ -276,10 +276,6 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `del default` -## base on complexes - --> stack should be TODO - ## negative base numbers (1) `1000 hex neg` @@ -312,6 +308,16 @@ nan @nan@ -nan inf -inf @inf@ -@inf@ `del default` +## base on complexes + +``` +(0b110,0x102) dup bin swap dup hex dup 5 base +``` + +-> stack should be (0b110,0b100000010), (0b110,0x102), (0x6,0x102), (5b11,5b2013) + +`del default` + ## inf should not be based-represented `-1 bin 0 bin / 1 3 base 0 3 base /` diff --git a/test/050-real.md b/test/050-real.md index 890af25..4645051 100644 --- a/test/050-real.md +++ b/test/050-real.md @@ -116,7 +116,7 @@ pi ## round (1) -`"nearest" round` +`"nearest (even)" round` -> error should be 0 @@ -156,6 +156,22 @@ pi ## round (6) +`"faithful rounding" round` + +-> error should be 0 + +`del` + +## round (7) + +`"nearest (away from zero)" round` + +-> error should be 0 + +`del` + +## round error + `round` -> error should be 2 @@ -172,14 +188,6 @@ pi ## add (2) -`1.2 2.3+` - --> stack should be 3.5 - -`del` - -## add (3) - `2.3 +` -> error should be 2 @@ -188,7 +196,7 @@ pi `del` -## add (4) +## add (3) `+` @@ -206,14 +214,6 @@ pi ## sub (2) -`1.2 2.3-` - --> stack should be -1.1 - -`del` - -## sub (3) - `2.3 -` -> error should be 2 @@ -222,7 +222,7 @@ pi `del` -## sub (4) +## sub (3) `-` @@ -240,14 +240,6 @@ pi ## mul (2) -`1.2 2.3*` - --> stack should be 2.76 - -`del` - -## mul (3) - `2.3 *` -> error should be 2 @@ -256,7 +248,7 @@ pi `del` -## mul (4) +## mul (3) `*` @@ -272,16 +264,9 @@ pi `del` + ## div (2) -`1.2 2.3/` - --> stack should be 0.52173913043478260869565217391304347826 - -`del` - -## div (3) - `2.3 /` -> error should be 2 @@ -290,7 +275,7 @@ pi `del` -## div (4) +## div (3) `/` @@ -350,14 +335,6 @@ pi ## % (2) -`2 30%` - --> stack should be 0.6 - -del - -## % (3) - `2 %` -> error should be 2 @@ -366,7 +343,7 @@ del `del` -## % (4) +## % (3) `%` @@ -384,14 +361,6 @@ del ## %CH (2) -`2 0.6%CH` - --> stack should be 30 - -`del` - -## %CH (3) - `2 %CH` -> error should be 2 @@ -400,7 +369,7 @@ del `del` -## %CH (4) +## %CH (3) `%CH` @@ -418,14 +387,6 @@ del ## ^ (2) -`2 10^` - --> stack should be 1024 - -`del` - -## ^ (3) - `2 ^` -> error should be 2 @@ -434,7 +395,7 @@ del `del` -## ^ (4) +## ^ (3) `^` @@ -454,7 +415,7 @@ del `sqrt` --> error should be 3 +-> error should be 2 ## sq (1) @@ -470,20 +431,6 @@ del -> error should be 2 -## sqr (1) - -`12 sqr` - --> stack should be 144 - -`del` - -## sqr (2) - -`sqr` - --> error should be 2 - ## mod (1) `9 4 mod` diff --git a/test/all.md b/test/all.md index 4e50d65..dd75843 100644 --- a/test/all.md +++ b/test/all.md @@ -12,7 +12,7 @@ @include 027-base-entry.md @include 030-branch.md @include 040-stack.md -# @include 050-real.md +@include 050-real.md # @include 060-string.md # @include 070-test.md # @include 080-store.md From 33815ddca14c2039c4db2bdb16fe72405e5ba373 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 17 Feb 2022 18:08:25 +0100 Subject: [PATCH 10/57] real tests pass --- Changelog | 16 ++-- src/mpreal-out.cpp | 1 + src/program.cpp | 20 ++--- src/rpn-real.cpp | 166 +++++++-------------------------------- test/023-parse-number.md | 9 ++- test/050-real.md | 4 +- 6 files changed, 60 insertions(+), 156 deletions(-) diff --git a/Changelog b/Changelog index f48ead5..1514d67 100644 --- a/Changelog +++ b/Changelog @@ -7,23 +7,25 @@ TODO Compatibility is broken on these points - `<< <<` doesn't input as `<< << >> >>` but as `<< << >>` - `1 2+` not allowed anymore, keep `1 2 +` - - this correct bad behaviors like `3b114` giving `3b11` and `4` -- complexes are written in the form `(1,2)` instead of `(1, 2)` (the space was removed) -- removed useless 'unti', 'repea', 'whil' (existing for HP28S compatibility), causing parsing problems -- removed 'sqr' function, please use 'sq' instead + - this corrects bad behaviors like `3b114` giving `3b11` and `4` +- complexes are written in the form `(1,2)` instead of `(1, 2)` (space is removed) +- removed useless 'unti', 'repea', 'whil' (existing for HP28S compatibility) +- removed 'sqr' function, please use 'sq' instead (existing for HP28S compatibility) - syntax error code is now 12 instead of 11 - `test` command can also take a symbol as a parameter ; if the symbol contains a valid - à l'affichage le préfixe des chiffres en base 2 est 0b et pas 2b (la saisie 2bxxx est toutefois permise) - à l'affichage le préfixe des chiffres en base 16 est 0x et pas 16b (la saisie 16bxxx est toutefois permise) - à l'affichage les chiffres en base 10 pas de préfixe 10b (la saisie 10bxxx est toutefois permise) +- `mant` and `xpon` now give binary significand and exponent, as it is the norm (see frexp in math.h, cmath for example) +- `dupn`, `roll`, `rolld` are not leaving anymore their argument in front of the stack in case of error +- entering the sign after the base (ex: 0x-1e2) is allowed New -- `« »` are valid as program delimiters. `<<` and `>>` are still valid +- `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid - enhanced code quality and memory usage checks -- some bugs (dupn, roll, rolld wrongly leaving the front arg in case of error) - added `norm` as a synonym of `abs` cas de tests à ajouter: ab Xb 1b ax 0X 3X -0x12pa1 \ No newline at end of file +0x12pa1 diff --git a/src/mpreal-out.cpp b/src/mpreal-out.cpp index 52ad9ed..0c58a3e 100644 --- a/src/mpreal-out.cpp +++ b/src/mpreal-out.cpp @@ -43,6 +43,7 @@ ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& valu static bool is_min(const mpreal& p, mpfr_prec_t prec) { // see mpfr_vasprintf code + // TODO here use mpreal functions like <=0, isinf etc bool ret; int round_away; switch (mpreal::get_default_rnd()) { diff --git a/src/program.cpp b/src/program.cpp index 883e960..959c0a6 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -34,22 +34,22 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, {cmd_keyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, {cmd_keyword, "norm", &program::rpn_abs, ""}, - // {cmd_keyword, "sign", &program::rpn_sign, "1 if number at stack level 1 is > 0, 0 if == 0, -1 if <= 0"}, + {cmd_keyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, // OPERATIONS ON REALS {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, - // {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, - // {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, - // {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, - // {cmd_keyword, "floor", &program::rpn_floor, "largest number <="}, - // {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="}, - // {cmd_keyword, "ip", &program::rpn_ip, "integer part"}, - // {cmd_keyword, "fp", &program::rpn_fp, "fractional part"}, - // {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"}, - // {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, + {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, + {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, + {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, + {cmd_keyword, "floor", &program::rpn_floor, "largest number <="}, + {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="}, + {cmd_keyword, "ip", &program::rpn_ip, "integer part"}, + {cmd_keyword, "fp", &program::rpn_fp, "fractional part"}, + {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"}, + {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, // OPERATIONS ON COMPLEXES // {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 5953012..7f8463c 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -230,7 +230,6 @@ void program::rpn_dec() { /// void program::rpn_base() { MIN_ARGUMENTS(2); - if (_stack->type(1) == cmd_number || _stack->type(1) == cmd_complex) { int base = (int)_stack->value(0).toLong(); _stack->pop(); @@ -271,7 +270,6 @@ void program::rpn_purcentCH() { /// void program::rpn_square() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) _stack->value(0) *= _stack->value(0); else if (_stack->at(0)->_type == cmd_complex) @@ -290,37 +288,15 @@ void program::rpn_modulo() { _stack->pop(); } -#if 0 - /// @brief abs keyword implementation /// void program::rpn_abs() { MIN_ARGUMENTS(1); - - if (_stack->type(0) == cmd_number) { - number* left = (number*)_stack->back(); - CHECK_MPFR(mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // 1. copy out -> calc x2+iy2 - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - // 2. calc x2+iy2 - ocomplex* cplx = (ocomplex*)_calc_stack.back(); - CHECK_MPFR(mpfr_mul(cplx->re.mpfr, cplx->re.mpfr, cplx->re.mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(cplx->im.mpfr, cplx->im.mpfr, cplx->im.mpfr, mpreal::get_default_rnd())); - - // 3. new real on stack - _stack->push_front(new number); - number* module = (number*)_stack->back(); - - // 4. set it to |x2+y2| then take sqrt - CHECK_MPFR(mpfr_set(module->value.mpfr, cplx->re.mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_add(module->value.mpfr, module->value.mpfr, cplx->im.mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sqrt(module->value.mpfr, module->value.mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = abs(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = norm(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -329,33 +305,19 @@ void program::rpn_abs() { void program::rpn_fact() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - // fact(n) = gamma(n+1) - number* left = (number*)_stack->back(); - number* right; - _stack->push_front(right = new number); - right->value = 1L; - rpn_plus(); - - CHECK_MPFR(mpfr_gamma(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); + _stack->value(0) = gamma(_stack->value(0) + 1); } /// @brief sign keyword implementation /// void program::rpn_sign() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - // fact(n) = gamma(n+1) - number* left = (number*)_stack->back(); - int result = mpfr_sgn(left->value.mpfr); - left->value = (long)result; - } else if (_stack->at(0)->_type == cmd_complex) { - // calc x/sqrt(x*x+y*y) +iy/sqrt(x*x+y*y) - rpn_dup(); - rpn_abs(); - rpn_div(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = sgn(_stack->value(0)); + else if (_stack->at(0)->_type == cmd_complex) + _stack->value(0) = _stack->value(0) / norm(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -364,33 +326,12 @@ void program::rpn_sign() { void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - if (mpfr_number_p(left->value.mpfr)) { - if (mpfr_zero_p(left->value.mpfr)) - left->value = 0.0; - else { - mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd()); - - number* one; - _stack->push_front(one = new number); - number* ten; - _stack->push_front(ten = new number); - ten->value = 10L; - - one->value = 1L; - while (mpfr_greaterequal_p(left->value.mpfr, one->value.mpfr)) - mpfr_div(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - - one->value = 0.1; - while (mpfr_less_p(left->value.mpfr, one->value.mpfr)) - mpfr_mul(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - - _calc_stack.pop_front(2); - } - } else + if (!isfinite(_stack->value(0))) { ERR_CONTEXT(ret_out_of_range); + return; + } + mp_exp_t exp; + _stack->value(0) = frexp(_stack->value(0), &exp); } /// @brief xpon keyword implementation @@ -398,41 +339,13 @@ void program::rpn_mant() { void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - if (mpfr_number_p(left->value.mpfr)) { - if (mpfr_zero_p(left->value.mpfr)) - left->value = 0.0; - else { - double exponant = 0.0; - mpfr_abs(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd()); - - number* one; - _stack->push_front(one = new number); - number* ten; - _stack->push_front(ten = new number); - ten->value = 10L; - - one->value = 1L; - while (mpfr_greaterequal_p(left->value.mpfr, one->value.mpfr)) { - mpfr_div(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - exponant += 1.0; - } - - one->value = 0.1; - while (mpfr_less_p(left->value.mpfr, one->value.mpfr)) { - mpfr_mul(left->value.mpfr, left->value.mpfr, ten->value.mpfr, mpreal::get_default_rnd()); - exponant -= 1.0; - } - - left->value = exponant; - - _calc_stack.pop_front(); - _calc_stack.pop_front(); - } - } else + if (!isfinite(_stack->value(0))) { ERR_CONTEXT(ret_out_of_range); + return; + } + mp_exp_t exp; + (void)frexp(_stack->value(0), &exp); + _stack->value(0) = exp; } /// @brief floor keyword implementation @@ -440,10 +353,7 @@ void program::rpn_xpon() { void program::rpn_floor() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_floor(left->value.mpfr, left->value.mpfr)); + _stack->value(0) = floor(_stack->value(0)); } /// @brief ceil keyword implementation @@ -451,10 +361,7 @@ void program::rpn_floor() { void program::rpn_ceil() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_ceil(left->value.mpfr, left->value.mpfr)); + _stack->value(0) = ceil(_stack->value(0)); } /// @brief fp keyword implementation @@ -462,10 +369,7 @@ void program::rpn_ceil() { void program::rpn_fp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_frac(left->value.mpfr, left->value.mpfr, mpreal::get_default_rnd())); + _stack->value(0) = frac(_stack->value(0)); } /// @brief ip keyword implementation @@ -473,10 +377,7 @@ void program::rpn_fp() { void program::rpn_ip() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_trunc(left->value.mpfr, left->value.mpfr)); + _stack->value(0) = trunc(_stack->value(0)); } /// @brief min keyword implementation @@ -485,11 +386,8 @@ void program::rpn_min() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_min(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); + _stack->value(0) = min(_stack->value(0), _stack->value(1)); + _stack->erase(1); } /// @brief max keyword implementation @@ -498,10 +396,6 @@ void program::rpn_max() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - number* right = (number*)_stack->pop_front(); - number* left = (number*)_stack->back(); - - CHECK_MPFR(mpfr_max(left->value.mpfr, left->value.mpfr, right->value.mpfr, mpreal::get_default_rnd())); + _stack->value(0) = max(_stack->value(0), _stack->value(1)); + _stack->erase(1); } -#endif diff --git a/test/023-parse-number.md b/test/023-parse-number.md index 72183d8..df2178d 100644 --- a/test/023-parse-number.md +++ b/test/023-parse-number.md @@ -91,6 +91,12 @@ -> stack should be -0x1e2, -5b1234, -0b1 +## base (4) + +`del -0x1e2 -5b1234 -0b1` + +-> stack should be -0x1e2, -5b1234, -0b1 + ## base err `del 0b12` @@ -113,8 +119,9 @@ ## wrong base errors `del 0b0.1100` +`ab Xb 1b ax 0X 3X` --> stack should be 0b1 +-> stack should be 0b1, 'ab', 'Xb', '1b', 'ax', '0X', '3X' ## particular writings diff --git a/test/050-real.md b/test/050-real.md index 4645051..2f2c3e8 100644 --- a/test/050-real.md +++ b/test/050-real.md @@ -527,7 +527,7 @@ pi `123.456 mant -123.456 mant 0 mant` --> stack should be 0.123456, 0.123456, 0 +-> stack should be 0.9645, -0.9645, 0 `del` @@ -551,7 +551,7 @@ pi `123.456 xpon -123.456 xpon 0 mant` --> stack should be 3, 3, 0 +-> stack should be 7, 7, 0 `del` From 789dfef1190ef9b52fed43c61570622992e508b3 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 17 Feb 2022 19:04:40 +0100 Subject: [PATCH 11/57] string tests pass --- CMakeLists.txt | 2 +- Changelog | 15 +++----- src/object.hpp | 15 ++------ src/program.cpp | 30 ++++++++------- src/rpn-string.cpp | 95 +++++++++++----------------------------------- test/060-string.md | 6 +-- test/all.md | 2 +- 7 files changed, 52 insertions(+), 113 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6f87c92..d6c1dc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,7 +64,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/rpn-real.cpp ${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp ${PROJECT_SOURCE_DIR}/src/rpn-store.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-string.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-string.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cpp #${PROJECT_SOURCE_DIR}/src/rpn-time.cpp diff --git a/Changelog b/Changelog index 1514d67..8e82062 100644 --- a/Changelog +++ b/Changelog @@ -9,23 +9,20 @@ Compatibility is broken on these points - `1 2+` not allowed anymore, keep `1 2 +` - this corrects bad behaviors like `3b114` giving `3b11` and `4` - complexes are written in the form `(1,2)` instead of `(1, 2)` (space is removed) -- removed useless 'unti', 'repea', 'whil' (existing for HP28S compatibility) -- removed 'sqr' function, please use 'sq' instead (existing for HP28S compatibility) +- removed useless `unti`, `repea`, `whil` (existing for HP28S compatibility) +- removed `sqr` function, please use `sq` instead (existing for HP28S compatibility) - syntax error code is now 12 instead of 11 - `test` command can also take a symbol as a parameter ; if the symbol contains a valid -- à l'affichage le préfixe des chiffres en base 2 est 0b et pas 2b (la saisie 2bxxx est toutefois permise) +- the binary prefix is 0b on display, but can be 0b, 0B, 2b or 2B at input +- the hex prefix is 0x on display, but can be 0x, 0X or 16B at input +- entering the sign after the base (ex: 0x-1e2) is allowed - à l'affichage le préfixe des chiffres en base 16 est 0x et pas 16b (la saisie 16bxxx est toutefois permise) - à l'affichage les chiffres en base 10 pas de préfixe 10b (la saisie 10bxxx est toutefois permise) - `mant` and `xpon` now give binary significand and exponent, as it is the norm (see frexp in math.h, cmath for example) - `dupn`, `roll`, `rolld` are not leaving anymore their argument in front of the stack in case of error -- entering the sign after the base (ex: 0x-1e2) is allowed +- `sub` now only accepts boundaries between 1 and the string length New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid - enhanced code quality and memory usage checks - added `norm` as a synonym of `abs` - -cas de tests à ajouter: -ab Xb 1b -ax 0X 3X -0x12pa1 diff --git a/src/object.hpp b/src/object.hpp index aacae29..dfd0d7c 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -130,10 +130,7 @@ struct ostring : object { ostring(const char* value_) : object(cmd_string) { value = string(value_); } virtual object* clone() { return new ostring(value); } virtual string name() { return string("string"); } - virtual ostream& show(ostream& out) { - out << "\"" << value << "\""; - return out; - } + virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } string value; }; @@ -144,10 +141,7 @@ struct oprogram : object { oprogram(const string& value_) : object(cmd_program), value(value_) {} virtual object* clone() { return new oprogram(value); } virtual string name() { return string("program"); } - virtual ostream& show(ostream& out) { - out << "«" << value << "»"; - return out; - } + virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } string value; }; @@ -158,10 +152,7 @@ struct symbol : object { symbol(const string& value_, bool autoEval_ = true) : object(cmd_symbol), value(value_), autoEval(autoEval_) {} virtual object* clone() { return new symbol(value, autoEval); } virtual string name() { return string("symbol"); } - virtual ostream& show(ostream& out) { - out << "'" << value << "'"; - return out; - } + virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } bool autoEval; string value; }; diff --git a/src/program.cpp b/src/program.cpp index 959c0a6..eb632fd 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -112,16 +112,15 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, // STRING - // {cmd_undef, "", NULL, "\nSTRING"}, - // {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, - // {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, - // {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, - // {cmd_keyword, "num", &program::rpn_num, - // "return ASCII code of the first character of the string in stack level 1 " - // "as a real number"}, - // {cmd_keyword, "size", &program::rpn_strsize, "return the length of the string"}, - // {cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, - // {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, + {cmd_undef, "", NULL, "\nSTRING"}, + {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, + {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, + {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, + {cmd_keyword, "num", &program::rpn_num, + "return ASCII code of the first character of the string in stack level 1 as a real number"}, + {cmd_keyword, "size", &program::rpn_strsize, "return the length of the string"}, + {cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, + {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, // BRANCH {cmd_undef, "", NULL, "\nBRANCH"}, @@ -643,10 +642,13 @@ ret_value program::get_err(void) { return _err; } /// @param show_separator whether to show a stack level prefix or not /// void program::show_stack(rpnstack& st, bool show_separator) { - for (int i = st.size() - 1; i >= 0; i--) { - if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; - cout << st[i] << endl; - } + if (st.size() == 1) + cout << st[0] << endl; + else + for (int i = st.size() - 1; i >= 0; i--) { + if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; + cout << st[i] << endl; + } } /// @brief apply default precision mode and digits diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 6ae8163..93c951f 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -9,32 +9,10 @@ void program::rpn_instr() { // stringify only if not already a string if (_stack->at(0)->_type != cmd_string) { - // TODO really ugly, to change - // write the object in stack(0) in a string and remove this obj - FILE* tmp = tmpfile(); - if (tmp != NULL) { - _stack->front()->show(tmp); - _stack->pop(); - - // reserve the correct size on stack - unsigned int str_size = (unsigned int)ftell(tmp); - char* buf = (char*)malloc(str_size); - if (buf == nullptr) { - ERR_CONTEXT(ret_out_of_memory); - goto destroy_file; - } - - // fill the obj - rewind(tmp); - if (fread(buf, str_size, 1, tmp) != 1) ERR_CONTEXT(ret_runtime_error); - _stack->push_front(new ostring(buf)); - - destroy_file: - char filePath[PATH_MAX]; - fclose(tmp); - if (fcntl(fileno(tmp), 12 /*F_GETPATH*/, filePath) != -1) remove(filePath); - } else - ERR_CONTEXT(ret_runtime_error); + stringstream ss; + ss << _stack->at(0); + _stack->pop(); + _stack->push(new ostring(ss.str())); } } @@ -44,9 +22,9 @@ void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - string entry(((ostring*)_stack->pop_front())->_value); - + string entry(_stack->value(0)); program prog; + _stack->pop(); // make program from string in stack level 1 if (program::parse(entry, prog) == ret_ok) @@ -59,9 +37,8 @@ void program::rpn_strout() { void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - - // get arg as number % 256 - char the_chr = (char)mpfr_get_d(((number*)_stack->pop_front())->_value.mpfr, mpreal::get_default_rnd()); + char the_chr = (char)(int)_stack->value(0); + _stack->pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; _stack->push_front(new ostring(string(1, the_chr))); } @@ -71,9 +48,11 @@ void program::rpn_chr() { void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - - double the_chr = (double)((ostring*)_stack->pop_front())->_value[0]; - _stack->push_front(new number(the_chr)); + if (_stack->value(0).size() > 0) + _stack->push_front(new number(_stack->value(0)[0])); + else + _stack->push_front(new number(0)); + _stack->erase(1); } /// @brief size keyword implementation @@ -81,9 +60,8 @@ void program::rpn_num() { void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - - double len = ((ostring*)_stack->pop_front())->_value.size(); - _stack->push_front(new number(len)); + _stack->push_front(new number(_stack->value(0).size())); + _stack->erase(1); } /// @brief pos keyword implementation @@ -93,7 +71,7 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(1, cmd_string); - size_t pos = static_cast(_stack->at(1))->_value.find(((ostring*)_stack->at(0))->_value); + size_t pos = _stack->value(1).find(_stack->value(0)) + 1; _stack->pop_front(2); _stack->push_front(new number(pos)); } @@ -101,45 +79,16 @@ void program::rpn_strpos() { /// @brief sub keyword implementation /// void program::rpn_strsub() { -#if 0 MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_string); - long first = long(((number*)_stack->at(1))->_value) - 1; - long last = long(((number*)_stack->at(0))->_value) - 1; - long len = ((ostring*)_stack->at(2))->_len; - bool result_is_void = false; + size_t first = (size_t)_stack->value(1); + size_t len = (size_t)_stack->value(0) - first + 1; + first--; - _stack->pop_front(2); - - if (first < 0) first = 0; - if (last < 0) last = 0; - if (first > len && last > len) - result_is_void = true; - else { - if (first > len) first = len - 1; - if (last > len) last = len - 1; - if (first > last) result_is_void = true; - } - - if (!result_is_void) { - unsigned int str_size = last - first + 1; - ostring* str = (ostring*)_calc_stack.allocate_back(str_size + 1 + sizeof(ostring), cmd_string); - str->_len = str_size; - - memcpy(((ostring*)_calc_stack.back())->_value, ((ostring*)_stack->at(0))->_value + first, str_size); - ((ostring*)_calc_stack.back())->_value[str_size] = 0; - - _stack->pop_front(); - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_front(); - } else { - _stack->pop_front(); - ostring* str = (ostring*)_stack->allocate_back(1 + sizeof(ostring), cmd_string); - str->_len = 0; - str->_value[0] = 0; - } -#endif + if (first > _stack->value(2).size()) first = len = 0; + _stack->push(new ostring(_stack->value(2).substr(first, len))); + _stack->erase(1, 3); } diff --git a/test/060-string.md b/test/060-string.md index cfc9741..0a9c1da 100644 --- a/test/060-string.md +++ b/test/060-string.md @@ -136,7 +136,7 @@ `"<< -> n << n >> >>" str->` --> stack should be << -> n << n >> >> +-> stack should be «-> n << n >>» `del` @@ -270,7 +270,7 @@ `"my string to sub" -1 -2 sub` --> stack should be "m" +-> stack should be "" `del` @@ -278,7 +278,7 @@ `"my string to sub" 0 0 sub` --> stack should be "m" +-> stack should be "" `del` diff --git a/test/all.md b/test/all.md index dd75843..a010e71 100644 --- a/test/all.md +++ b/test/all.md @@ -13,7 +13,7 @@ @include 030-branch.md @include 040-stack.md @include 050-real.md -# @include 060-string.md +@include 060-string.md # @include 070-test.md # @include 080-store.md # @include 090-program.md From 80bcb82d3f4279982e8dac99b3bccf85fab30b1b Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 18 Feb 2022 00:27:06 +0100 Subject: [PATCH 12/57] logical test tests pass --- src/rpn-test.cpp | 12 ++++++------ test/all.md | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 3d6b3a8..993c631 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -25,7 +25,7 @@ void program::rpn_sup(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() == 1)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); @@ -43,7 +43,7 @@ void program::rpn_sup_eq(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() != -1)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); @@ -61,7 +61,7 @@ void program::rpn_inf(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() == -1)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); @@ -77,7 +77,7 @@ void program::rpn_inf_eq(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() != 1)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); @@ -100,7 +100,7 @@ void program::rpn_diff(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() != 0)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); @@ -123,7 +123,7 @@ void program::rpn_eq(void) { } // strings else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top())); + _stack->push_front(new number(cmp_strings_on_stack_top() == 0)); _stack->erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); diff --git a/test/all.md b/test/all.md index a010e71..2cecc93 100644 --- a/test/all.md +++ b/test/all.md @@ -14,7 +14,7 @@ @include 040-stack.md @include 050-real.md @include 060-string.md -# @include 070-test.md +@include 070-test.md # @include 080-store.md # @include 090-program.md # @include 100-complex.md From f8cbae6d55d8d0c89ddb771eaa734327cebb6ded Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 18 Feb 2022 17:41:27 +0100 Subject: [PATCH 13/57] store tests pass, better swap, rot, roll, rolld --- Changelog | 28 ----- Changelog.md | 40 +++++++ src/constant.h | 12 +-- src/program.cpp | 12 +-- src/rpn-stack.cpp | 22 ++-- src/rpn-store.cpp | 210 +++++++++++++------------------------ src/rpn-test-framework.cpp | 7 +- src/stack.hpp | 5 +- test/027-base-entry.md | 2 +- test/030-branch.md | 54 +++++----- test/040-stack.md | 2 +- test/070-test.md | 2 +- test/080-store.md | 66 ++---------- test/all.md | 2 +- test/mem_test.sh | 8 +- 15 files changed, 189 insertions(+), 283 deletions(-) delete mode 100644 Changelog create mode 100644 Changelog.md diff --git a/Changelog b/Changelog deleted file mode 100644 index 8e82062..0000000 --- a/Changelog +++ /dev/null @@ -1,28 +0,0 @@ -Changelog - -TODO -- savoir si lorsque erreur il faut enlever ou pas l'argument en erreur de la stack - - normalement non, c'est bon? - -Compatibility is broken on these points -- `<< <<` doesn't input as `<< << >> >>` but as `<< << >>` -- `1 2+` not allowed anymore, keep `1 2 +` - - this corrects bad behaviors like `3b114` giving `3b11` and `4` -- complexes are written in the form `(1,2)` instead of `(1, 2)` (space is removed) -- removed useless `unti`, `repea`, `whil` (existing for HP28S compatibility) -- removed `sqr` function, please use `sq` instead (existing for HP28S compatibility) -- syntax error code is now 12 instead of 11 -- `test` command can also take a symbol as a parameter ; if the symbol contains a valid -- the binary prefix is 0b on display, but can be 0b, 0B, 2b or 2B at input -- the hex prefix is 0x on display, but can be 0x, 0X or 16B at input -- entering the sign after the base (ex: 0x-1e2) is allowed -- à l'affichage le préfixe des chiffres en base 16 est 0x et pas 16b (la saisie 16bxxx est toutefois permise) -- à l'affichage les chiffres en base 10 pas de préfixe 10b (la saisie 10bxxx est toutefois permise) -- `mant` and `xpon` now give binary significand and exponent, as it is the norm (see frexp in math.h, cmath for example) -- `dupn`, `roll`, `rolld` are not leaving anymore their argument in front of the stack in case of error -- `sub` now only accepts boundaries between 1 and the string length - -New -- `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid -- enhanced code quality and memory usage checks -- added `norm` as a synonym of `abs` diff --git a/Changelog.md b/Changelog.md new file mode 100644 index 0000000..ed82a69 --- /dev/null +++ b/Changelog.md @@ -0,0 +1,40 @@ +Changelog + +- Better parser (now called lexer) +- Use of mpreal instead of raw mpfr for calc on reals +- Use of C++ complex class +- Removing old memory management, efficient but poorly maintainable +- Enhanced code quality and memory usage checks +- Added CircleCI checks: passing functional tests and valgrind mem checks at each pull request +- SonarCloud integration, Sonar way profile +- clang-format now based on google style +- [google c++ style guide](https://google.github.io/styleguide/cppguide.html) applied +- Test files are now markdown (.md) files, tests result are slightly changed +- Delivery as flatpak and snap + +New +- `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid +- added `norm` as a synonym of `abs` +- `test` command can also take a symbol as a parameter ; if the symbol contains a valid +- entering the sign after the base (ex: 0x-1e2) is allowed + +Compatibility is broken on these points +- `<< <<` doesn't input as `<< << >> >>` but as `<< << >>` +- `1 2+` not allowed anymore, keep `1 2 +`, this corrects bad behaviors like `3b114` pushing `3b11` and `4` +- complexes are written in the form `(1,2)` instead of `(1, 2)` (space is removed) +- removed useless `unti`, `repea`, `whil` (prev.existing for HP28S compatibility) +- removed `sqr` function, please use `sq` instead (prev.existing for HP28S compatibility) +- the binary prefix is always 0b on display, but still can be 0b, 0B, 2b or 2B at input +- the hex prefix is always 0x on display, but still can be 0x, 0X or 16B at input +- `mant` and `xpon` now give binary significand and exponent, as it is the norm in standard libs (libC, standard C++, mpfr, gmp) +- `dupn`, `roll`, `rolld` are not leaving anymore their argument in front of the stack in case of error +- `sub` now only accepts boundaries between 1 and the string length +- rpn is not delivered as deb and rpm anymore, since it is too much bound to particular OS +- `sto/` bug correction: 3 'a' sto/ now correctly does a/3 -> a (although it did 3/a -> a) +- `sto+` `sto-` `sto*` `sto/` don't accept anymore the syntax `'varname' value stoX`, but only `value 'varname' stoX`, ex: `3 'a' sto*` + +missing tests +- nested loops / if / while / do + access to local variables +- les arguments d'une fonction en erreur doivent ils êre consommés ? + ex embettant : sto+ +- sto+ * - / : ajouter des cas de test avec type incorrects \ No newline at end of file diff --git a/src/constant.h b/src/constant.h index a6d2f63..6297526 100644 --- a/src/constant.h +++ b/src/constant.h @@ -55,7 +55,6 @@ typedef enum { ret_missing_operand, ret_bad_operand_type, ret_out_of_range, - ret_bad_value, ret_unknown_variable, ret_internal, ret_deadly, @@ -67,14 +66,15 @@ typedef enum { ret_runtime_error, ret_abort_current_entry, ret_out_of_memory, + ret_bad_value, ret_max } ret_value; -#define RET_VALUE_STRINGS \ - { \ - "ok", "unknown command", "missing operand", "bad operand type", "out of range", "bad value", \ - "unknown variable", "internal error, aborting", "deadly", "goodbye", "not implemented", "no operation", \ - "syntax error", "division by zero", "runtime error", "aborted current entry", "out of memory" \ +#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", "aborted current entry", "out of memory", "bad value", \ } // command types diff --git a/src/program.cpp b/src/program.cpp index eb632fd..39f0478 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -152,12 +152,12 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "vars", &program::rpn_vars, "list all variables"}, {cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"}, {cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"}, - // {cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, - // {cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, - // {cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, - // {cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, - // {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, - // {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, + {cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, + {cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, + {cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, + {cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, + {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, + {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, // PROGRAM {cmd_undef, "", NULL, "\nPROGRAM"}, {cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 1fe1491..77c37f3 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -4,8 +4,9 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_front(*_stack, 1, *_stack); - _stack->erase(2); + object* tmp = _stack->front(); + _stack->erase(0, 1, false); + _stack->insert(_stack->begin() + 1, tmp); } /// @brief drop keyword implementation @@ -87,9 +88,9 @@ void program::rpn_pick(void) { /// void program::rpn_rot(void) { MIN_ARGUMENTS(3); - - rpnstack::copy_and_push_front(*_stack, 2, *_stack); - _stack->erase(3); + object* tmp = _stack->at(2); + _stack->erase(2, 1, false); + _stack->insert(_stack->begin(), tmp); } /// @brief depth keyword implementation @@ -106,8 +107,9 @@ void program::rpn_roll(void) { _stack->pop(); MIN_ARGUMENTS(args); - rpnstack::copy_and_push_front(*_stack, args - 1, *_stack); - _stack->erase(args); + object* tmp = _stack->at(args - 1); + _stack->erase(args - 1, 1, false); + _stack->insert(_stack->begin(), tmp); } /// @brief rolld keyword implementation @@ -120,8 +122,9 @@ void program::rpn_rolld(void) { _stack->pop(); MIN_ARGUMENTS(args); - _stack->insert(_stack->begin()+args, _stack->at(0)->clone()); - _stack->pop(); + object* tmp = _stack->at(0); + _stack->erase(0, 1, false); + _stack->insert(_stack->begin() + args - 1, tmp); } /// @brief over keyword implementation @@ -131,3 +134,4 @@ void program::rpn_over(void) { rpnstack::copy_and_push_front(*_stack, 1, *_stack); } + diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index bf01990..f82e0a1 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -7,7 +7,7 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); // store symbol with first value - auto it = _heap->find(_stack->value(0)); + const auto it = _heap->find(_stack->value(0)); if (it != _heap->end()) { delete it->second; _heap->erase(it); @@ -18,169 +18,103 @@ void program::rpn_sto(void) { /// @brief sto+ keyword implementation /// -#if 0 void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); - - if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_plus(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { - // copy value, get variable value on stack level 1, - // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - rpn_plus(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); // TODO is rcl the good one? it will recall local variables too + rpn_rot(); + rpn_plus(); + rpn_swap(); + rpn_sto(); } /// @brief sto- keyword implementation /// void program::rpn_stosub(void) { MIN_ARGUMENTS(2); - - if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_minus(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { - // copy value, get variable value on stack level 1, - // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - rpn_minus(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); + rpn_rot(); + rpn_minus(); + rpn_swap(); + rpn_sto(); } /// @brief sto* keyword implementation /// void program::rpn_stomul(void) { MIN_ARGUMENTS(2); - - if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_mul(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { - // copy value, get variable value on stack level 1, - // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - rpn_mul(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); + rpn_rot(); + rpn_mul(); + rpn_swap(); + rpn_sto(); } /// @brief sto/ keyword implementation /// void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); - - if (_stack->at(0)->_type == cmd_symbol && _stack->at(1)->_type == cmd_number) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_div(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else if (_stack->at(1)->_type == cmd_symbol && _stack->at(0)->_type == cmd_number) { - // copy value, get variable value on stack level 1, - // put back value on stack level 1, make op then modify variable - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - rpn_div(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); + rpn_rot(); + rpn_div(); + rpn_swap(); + rpn_sto(); } /// @brief stosneg keyword implementation /// void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_symbol) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_neg(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); + rpn_neg(); + rpn_swap(); + rpn_sto(); } /// @brief sinv keyword implementation /// void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_symbol) { - // get variable value on stack level 1, make op then modify variable - string variable(((symbol*)_stack->back())->value); - rpn_rcl(); - if (_err == ret_ok) { - rpn_inv(); - (*_heap)[variable] = _stack->at(0); - _stack->pop_front(); - } - } else - ERR_CONTEXT(ret_bad_operand_type); + ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + if (_heap->find(_stack->value(0)) == _heap->end()) { + ERR_CONTEXT(ret_unknown_variable); + return; + } + rpn_dup(); + rpn_rcl(); + rpn_inv(); + rpn_swap(); + rpn_sto(); } -#endif /// @brief rcl keyword implementation /// @@ -190,12 +124,12 @@ void program::rpn_rcl(void) { // recall a variable object* obj; - string variable(((symbol*)_stack->back())->value); + string variable(_stack->value(0)); // mind the order of heaps if (find_variable(variable, obj)) { (void)_stack->pop_front(); - _stack->push_front(obj); + _stack->push_front(obj->clone()); } else ERR_CONTEXT(ret_unknown_variable); } @@ -208,7 +142,7 @@ void program::rpn_edit(void) { ostringstream st; // re-write stack objet in a stream - _stack->at(1)->show(st); + _stack->at(0)->show(st); _stack->pop(); // set it as the linenoise line entry @@ -240,8 +174,12 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - //if (_heap->erase(_stack->value(0)) == 0) - // ERR_CONTEXT(ret_unknown_variable); + const auto i = _heap->find(_stack->value(0)); + if (i != _heap->end()) { + delete i->second; + _heap->erase(i); + } else + ERR_CONTEXT(ret_unknown_variable); _stack->pop(); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 1ad6c54..28b07c1 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -31,7 +31,10 @@ void program::test_get_stack(string& stack_is, rpnstack& stk) { /// @param steps_failed failed steps nb /// void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) { - cout << title << ": run " << tests << " tests: " << tests - tests_failed << " passed, "; + //cout << title << ": run " << tests << " tests: " << tests - tests_failed << " passed, "; + if (!title.empty()) + cout << title << ": "; + cout <<"run " << tests << " tests: " << tests - tests_failed << " passed, "; if (tests_failed > 0) cout << FG_RED; cout << tests_failed << " failed"; if (tests_failed > 0) cout << COLOR_OFF; @@ -245,7 +248,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // conclusion: show and keep for total if (tests != 0) { - test_show_result(test_filename, tests, tests_failed, steps, steps_failed); + test_show_result("", tests, tests_failed, steps, steps_failed); total_tests += tests; total_tests_failed += tests_failed; diff --git a/src/stack.hpp b/src/stack.hpp index 6e14732..731b843 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -36,9 +36,10 @@ class rpnstack : public deque { /// @param first index to start /// @param last index to stop /// - void erase(size_t first = 0, size_t nb = 1) { + void erase(size_t first = 0, size_t nb = 1, bool del = true) { size_t last = std::min(first + nb, size()); - for_each(begin() + first, begin() + last, [](object* o) { delete o; }); + if (del) + for_each(begin() + first, begin() + last, [](object* o) { delete o; }); deque::erase(begin() + first, begin() + last); } diff --git a/test/027-base-entry.md b/test/027-base-entry.md index fbe7435..83c4342 100644 --- a/test/027-base-entry.md +++ b/test/027-base-entry.md @@ -1,4 +1,4 @@ -# fix entry +# REAL AND COMPLEX NUJMERICAL ENTRIES `default del` diff --git a/test/030-branch.md b/test/030-branch.md index 0d7d39b..a34486c 100644 --- a/test/030-branch.md +++ b/test/030-branch.md @@ -1,4 +1,4 @@ -### BRANCH +# BRANCH `default del` @@ -69,7 +69,7 @@ `0 if then` --> error should be 12 +-> error should be 11 `del` @@ -77,7 +77,7 @@ `0 if end` --> error should be 12 +-> error should be 11 `del` @@ -85,7 +85,7 @@ `0 if end` --> error should be 12 +-> error should be 11 `del` @@ -93,7 +93,7 @@ `then` --> error should be 12 +-> error should be 11 `del` @@ -101,7 +101,7 @@ `1 if` --> error should be 12 +-> error should be 11 `del` @@ -109,7 +109,7 @@ `else` --> error should be 12 +-> error should be 11 `del` @@ -118,7 +118,7 @@ `end` --> error should be 12 +-> error should be 11 `del` @@ -312,7 +312,7 @@ `start` --> error should be 12 +-> error should be 11 `del` @@ -320,7 +320,7 @@ `next` --> error should be 12 +-> error should be 11 `del` @@ -424,7 +424,7 @@ `1 2 for i i` --> error should be 12 +-> error should be 11 `del` @@ -432,7 +432,7 @@ `for` --> error should be 12 +-> error should be 11 `del` @@ -504,7 +504,7 @@ `step` --> error should be 12 +-> error should be 11 `del` @@ -544,7 +544,7 @@ `do` --> error should be 12 +-> error should be 11 `del` @@ -552,7 +552,7 @@ `do 8 end` --> error should be 12 +-> error should be 11 `del` @@ -560,7 +560,7 @@ `until` --> error should be 12 +-> error should be 11 `del` @@ -568,7 +568,7 @@ `do 3 until` --> error should be 12 +-> error should be 11 `del` @@ -576,7 +576,7 @@ `until 1 end` --> error should be 12 +-> error should be 11 `del` @@ -584,7 +584,7 @@ `do 3 repeat 8 end` --> error should be 12 +-> error should be 11 `del` @@ -592,7 +592,7 @@ `do 3 until 8 until 9 end` --> error should be 12 +-> error should be 11 `del` @@ -624,7 +624,7 @@ `while` --> error should be 12 +-> error should be 11 `del` @@ -632,7 +632,7 @@ `while 3 end` --> error should be 12 +-> error should be 11 `del` @@ -640,7 +640,7 @@ `repeat` --> error should be 12 +-> error should be 11 `del` @@ -648,7 +648,7 @@ `while 1 repeat` --> error should be 12 +-> error should be 11 `del` @@ -656,7 +656,7 @@ `repeat 1 end` --> error should be 12 +-> error should be 11 `del` @@ -664,7 +664,7 @@ `while 3 repeat 8 repeat 9 end` --> error should be 12 +-> error should be 11 `del` @@ -672,6 +672,6 @@ `while 3 until 8 end` --> error should be 12 +-> error should be 11 `del` diff --git a/test/040-stack.md b/test/040-stack.md index 3d776c2..6ad69ff 100644 --- a/test/040-stack.md +++ b/test/040-stack.md @@ -1,4 +1,4 @@ -# STACK TEST +# STACK `default del` diff --git a/test/070-test.md b/test/070-test.md index 41daf0b..91fd83f 100644 --- a/test/070-test.md +++ b/test/070-test.md @@ -1,4 +1,4 @@ -# TESTS +# LOGICAL TESTS `default del` diff --git a/test/080-store.md b/test/080-store.md index 63ff43e..98d9da6 100644 --- a/test/080-store.md +++ b/test/080-store.md @@ -86,7 +86,7 @@ `del` -## rcl (2) +## rcl (3) `'var' rcl` @@ -132,11 +132,7 @@ ## sto+ (1) -`8 'a' sto` - -`2 'a' sto+` - -`a` +`8 'a' sto 2 'a' sto+ a` -> stack should be 10 @@ -144,18 +140,6 @@ ## sto+ (2) -`2 'a' sto` - -`'a' 2 sto+` - -`a` - --> stack should be 4 - -`del` - -## sto+ (3) - `'a' sto+` -> stack size should be 1 @@ -164,7 +148,7 @@ `del` -## sto+ (4) +## sto+ (3) `3 'zz' sto+` @@ -188,18 +172,6 @@ ## sto- (2) -`2 'a' sto` - -`'a' 2 sto-` - -`a` - --> stack should be 0 - -`del` - -## sto- (3) - `'a' sto-` -> stack size should be 1 @@ -208,7 +180,7 @@ `del` -## sto- (4) +## sto- (3) `3 'zz' sto-` @@ -232,18 +204,6 @@ ## sto* (2) -`2 'a' sto` - -`'a' 3 sto*` - -`a` - --> stack should be 6 - -`del` - -## sto* (3) - `'a' sto*` -> stack size should be 1 @@ -252,7 +212,7 @@ `del` -## sto* (4) +## sto* (3) `3 'zz' sto*` @@ -266,23 +226,11 @@ `2 'a' sto` -`6 'a' sto/` +`4 'a' sto/` `a` --> stack should be 3 - -`del` - -## sto/ (2) - -`6 'a' sto` - -`'a' 2 sto/` - -`a` - --> stack should be 3 +-> stack should be 0.5 `del` diff --git a/test/all.md b/test/all.md index 2cecc93..265056f 100644 --- a/test/all.md +++ b/test/all.md @@ -15,7 +15,7 @@ @include 050-real.md @include 060-string.md @include 070-test.md -# @include 080-store.md +@include 080-store.md # @include 090-program.md # @include 100-complex.md # @include 110-time.md diff --git a/test/mem_test.sh b/test/mem_test.sh index 0825106..6768be1 100755 --- a/test/mem_test.sh +++ b/test/mem_test.sh @@ -33,10 +33,10 @@ quick_tests=( functional_tests=($(cat all.md | grep "^@include" | awk '{print $2}')) -echo "Quick rpn memory checks" -for i in ${!quick_tests[@]}; do - checkmem "${quick_tests[$i]}" -done +# echo "Quick rpn memory checks" +# for i in ${!quick_tests[@]}; do +# checkmem "${quick_tests[$i]}" +# done echo "Functional rpn memory checks" for i in ${!functional_tests[@]}; do From f7b95c68a233a825cb0e692eaa067c75c5585aa9 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 19 Feb 2022 16:32:05 +0100 Subject: [PATCH 14/57] program test pass --- Changelog.md | 8 ++++-- src/rpn-program.cpp | 6 ++--- test/030-branch.md | 32 ++++++++++++++++++++++ test/090-program.md | 65 +++++++++++++++++++++++++++++++++++++++------ test/all.md | 2 +- 5 files changed, 99 insertions(+), 14 deletions(-) diff --git a/Changelog.md b/Changelog.md index ed82a69..9979c50 100644 --- a/Changelog.md +++ b/Changelog.md @@ -12,6 +12,8 @@ Changelog - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap +grosse perte en performances (!) + New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid - added `norm` as a synonym of `abs` @@ -19,7 +21,7 @@ New - entering the sign after the base (ex: 0x-1e2) is allowed Compatibility is broken on these points -- `<< <<` doesn't input as `<< << >> >>` but as `<< << >>` +- `<< <<` input doesn't lead to `««»»` but to `«<< »`, preventing to eval the real program content - `1 2+` not allowed anymore, keep `1 2 +`, this corrects bad behaviors like `3b114` pushing `3b11` and `4` - complexes are written in the form `(1,2)` instead of `(1, 2)` (space is removed) - removed useless `unti`, `repea`, `whil` (prev.existing for HP28S compatibility) @@ -37,4 +39,6 @@ missing tests - nested loops / if / while / do + access to local variables - les arguments d'une fonction en erreur doivent ils êre consommés ? ex embettant : sto+ -- sto+ * - / : ajouter des cas de test avec type incorrects \ No newline at end of file +- sto+ * - / : ajouter des cas de test avec type incorrects +- `10 -> n << n >>` plante +- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante \ No newline at end of file diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index ab4d1c4..79b3f40 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -1,7 +1,7 @@ #include "program.hpp" -/// @brief find variable by its name in local heap, parens heaps, global heap -/// +/// @brief find variable by its name in local heap, successive parents heaps, global heap +/// /// @param variable the variable name to find /// @param obj the variable object found /// @return true variable was found @@ -129,7 +129,7 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[string(((symbol*)(*this)[i])->value)] = _stack->at(0); + _local_heap[string(((symbol*)(*this)[i])->value)] = _stack->at(0)->clone(); _stack->pop_front(); } diff --git a/test/030-branch.md b/test/030-branch.md index a34486c..de4cadc 100644 --- a/test/030-branch.md +++ b/test/030-branch.md @@ -388,6 +388,14 @@ `del` +## nested for next + +`1 2 for i 0 1 for j i (1,0) * j (0,1) * + next next` + +-> stack should be (1,0), (1,1), (2,0), (2,1) + +`del` + ## for next - error case (1) `1 for i i next` @@ -492,6 +500,14 @@ `del` +## nested for step + +`0 2 for i 0 6 for j i (1,0) * j (0,1) * + 3 step 2 step` + +-> stack should be (0,0), (0,3), (0,6), (2,0), (2,3), (2,6) + +`del` + ## for step - error case (1) `0 1 for i i "0.5" step` @@ -540,6 +556,14 @@ `del` +## nexted do..until + +`1 'i' sto do 0 'j' sto do i (1,0) * j (0,1) * + 1 'j' sto+ until j 1 > end 1 'i' sto+ until i 2 > end` + +-> stack should be (1,0), (1,1), (2,0), (2,1) + +`del` + ## do..until error case (1) `do` @@ -620,6 +644,14 @@ `del` +## nested while .. repeat + +`1 'i' sto while i 2 <= repeat 0 'j' sto while j 1 <= repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` + +-> stack should be (1,0), (1,1), (2,0), (2,1) + +`del` + ## while..repeat error case (1) `while` diff --git a/test/090-program.md b/test/090-program.md index 7c52f2d..119d833 100644 --- a/test/090-program.md +++ b/test/090-program.md @@ -8,7 +8,7 @@ -> stack size should be 1 --> stack should be << 'one' >> +-> stack should be «'one'» `del` @@ -18,7 +18,7 @@ -> stack size should be 1 --> stack should be << 'one' 2 >> +-> stack should be «'one' 2» `del` @@ -28,7 +28,7 @@ -> stack size should be 1 --> stack should be << >> +-> stack should be «» `del` @@ -38,7 +38,7 @@ -> stack size should be 1 --> stack should be << << << << >> >> >> >> +-> stack should be «<< << <<» `del` @@ -48,7 +48,7 @@ -> stack size should be 1 --> stack should be << -> n << n 2 * >> >> +-> stack should be «-> n << n 2 * >>» `del` @@ -56,7 +56,7 @@ `<< 1 << 2 >> >>` --> stack should be << 1 << 2 >> >> +-> stack should be «1 << 2 >>» `del` @@ -64,7 +64,7 @@ `<< 1 << 2 >> >> dup eval` --> stack should be << 1 << 2 >> >>, 1, << 2 >> +-> stack should be «1 << 2 >>», 1, «2» `del` @@ -82,7 +82,7 @@ `del` -## program several args +## nested programs `0 1 10 << -> u0 u1 n << u0 u1 1 n start dup2 + rot drop next swap drop >> >> eval` @@ -91,3 +91,52 @@ -> stack should be 89 `del` + +## fibo + +``` +«dup 1 > if then dup 1 - fibo swap 2 - fibo + else 1 == if then 1 else 0 end end» 'fibo' sto +7 fibo +13 == if then 'ok!' end +``` + +-> stack should be 'ok!' + +`del` + +## nested programs with local variables + +``` +100 +10 +«dup2 * -> a b c << a b + c / -> d << << -> sym << sym ->str " is " + sym rcl ->str + >> >> 'stringify' sto 'a' stringify 'b' stringify 'c' stringify 'd' stringify >> >>» +eval +``` + +-> stack should be "'a' is 100", "'b' is 10", "'c' is 1000", "'d' is 0.11" + +`del` + +## local variables multiple entries + +`1 2 3 << -> a b c << "a is " a ->str + "b is " b ->str + "c is " c ->str + >> >> eval` + +-> stack should be "a is 1", "b is 2", "c is 3" + +`del` + +## local variables separation (1) + +`123 'n' sto 1 << -> n << "n is " n ->str + >> >> eval` + +-> stack should be "n is 1" + +`del` + +## local variables separation (2) + +`123 'n' sto 2 << -> n << n sq << -> n << "n is " n ->str + >> >> >> eval >> eval` + +-> stack should be "n is 4" + +`del` diff --git a/test/all.md b/test/all.md index 265056f..d725ba7 100644 --- a/test/all.md +++ b/test/all.md @@ -16,7 +16,7 @@ @include 060-string.md @include 070-test.md @include 080-store.md -# @include 090-program.md +@include 090-program.md # @include 100-complex.md # @include 110-time.md # @include 999-manual-tests.md From 949a1a064882c8584890d6953eedd911101f5af3 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 15:58:15 +0100 Subject: [PATCH 15/57] complex pass (except floating point base numbers) --- CMakeLists.txt | 2 +- Changelog.md | 12 +- src/program.cpp | 18 +- src/rpn-complex.cpp | 105 +---- src/rpn-real.cpp | 29 +- test/005-test-framework.md | 2 +- test/026-parse-program.md | 2 +- test/027-base-entry.md | 2 +- test/100-complex.md | 763 +++---------------------------------- test/110-time.md | 2 +- test/120-trig.md | 37 ++ test/130-logs.md | 498 ++++++++++++++++++++++++ test/all.md | 4 +- 13 files changed, 643 insertions(+), 833 deletions(-) create mode 100644 test/120-trig.md create mode 100644 test/130-logs.md diff --git a/CMakeLists.txt b/CMakeLists.txt index d6c1dc1..660637f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/program.cpp ${PROJECT_SOURCE_DIR}/src/parse.cpp ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp #${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp ${PROJECT_SOURCE_DIR}/src/rpn-program.cpp diff --git a/Changelog.md b/Changelog.md index 9979c50..c468386 100644 --- a/Changelog.md +++ b/Changelog.md @@ -13,6 +13,11 @@ Changelog - Delivery as flatpak and snap grosse perte en performances (!) +- v2.3.2 fibo: 0,01s user 0,01s system 97% cpu 0,017 total +- v3.0.0 fibo: 2,60s user 0,00s system 99% cpu 2,611 total +- facteur 150 environ +cf https://gmplib.org/manual/Custom-Allocation +cf https://www.geeksforgeeks.org/overloading-new-delete-operator-c/ New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid @@ -34,11 +39,14 @@ Compatibility is broken on these points - rpn is not delivered as deb and rpm anymore, since it is too much bound to particular OS - `sto/` bug correction: 3 'a' sto/ now correctly does a/3 -> a (although it did 3/a -> a) - `sto+` `sto-` `sto*` `sto/` don't accept anymore the syntax `'varname' value stoX`, but only `value 'varname' stoX`, ex: `3 'a' sto*` +- incomplete entry `(1,` not available anymore +- signed zero is the sign of zero is subject to change compared to previous version, for example `-3 sqrt` now equals `(0.000000,1.732051)` instead of `(-0.000000,1.732051)` -missing tests +missing tests / problems - nested loops / if / while / do + access to local variables - les arguments d'une fonction en erreur doivent ils êre consommés ? ex embettant : sto+ - sto+ * - / : ajouter des cas de test avec type incorrects - `10 -> n << n >>` plante -- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante \ No newline at end of file +- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante +- real: ln, lnp1, log, log10, log2, exp, expm, alog2, alog10, sinh, asinh, cosh, acosh, tanh, atanh diff --git a/src/program.cpp b/src/program.cpp index 39f0478..2450c5a 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -52,15 +52,15 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, // OPERATIONS ON COMPLEXES - // {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, - // {cmd_keyword, "re", &program::rpn_re, "complex real part"}, - // {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, - // {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, - // {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"}, - // {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, - // {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, - // {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, - // {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, + {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, + {cmd_keyword, "re", &program::rpn_re, "complex real part"}, + {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, + {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, + {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"}, + {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, + {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, + {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, + {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, // MODE {cmd_undef, "", NULL, "\nMODE"}, diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index c9e4b7a..e2456f2 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -6,14 +6,8 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - number* re = new number(); - _stack->push_front(re); - CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.at(0))->re()->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_front(); + _stack->push_front(new number(real(_stack->value(0)))); + _stack->erase(1); } /// @brief im keyword implementation @@ -22,14 +16,8 @@ void program::rpn_re() { void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - number* im = new number(); - _stack->push_front(im); - CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.at(0))->im()->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_front(); + _stack->push_front(new number(imag(_stack->value(0)))); + _stack->erase(1); } /// @brief arg keyword implementation @@ -38,16 +26,8 @@ void program::rpn_im() { void program::rpn_arg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - // calc atan2(x/y) - complex* cplx = (complex*)_stack->front(); - number* num = new number(); - _calc_stack.push_back(num); - - CHECK_MPFR(mpfr_atan2(num->_value.mpfr, cplx->im()->mpfr, cplx->re()->mpfr, mpreal::get_default_rnd())); - - rpnstack::copy_and_push_front(_calc_stack, _calc_stack.size() - 1, *_stack); - _calc_stack.pop_front(); + _stack->push_front(new number(arg(_stack->value(0)))); + _stack->erase(1); } /// @brief conj keyword implementation @@ -56,9 +36,7 @@ void program::rpn_arg() { void program::rpn_conj() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - complex* cplx = (complex*)_stack->back(); - CHECK_MPFR(mpfr_neg(cplx->im()->mpfr, cplx->im()->mpfr, mpreal::get_default_rnd())); + _stack->value(0) = conj(_stack->value(0)); } /// @brief r2c keyword implementation @@ -68,17 +46,8 @@ void program::rpn_r2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - - rpnstack::copy_and_push_front(*_stack, _stack->size() - 2, _calc_stack); - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - _stack->pop_front(); - - complex* cplx = new complex(); - _stack->push_front(cplx); - CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_calc_stack.at(1))->_value.mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_calc_stack.at(0))->_value.mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_front(2); + _stack->push(new ocomplex(_stack->value(1), _stack->value(0), _stack->obj(1)->reBase, _stack->obj(0)->reBase)); + _stack->erase(1, 2); } /// @brief c2r keyword implementation @@ -87,18 +56,9 @@ void program::rpn_r2c() { void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - - number* re = new number(); - _stack->push_front(re); - number* im = new number(); - _stack->push_front(im); - - CHECK_MPFR(mpfr_set(re->_value.mpfr, ((complex*)_calc_stack.back())->re()->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_set(im->_value.mpfr, ((complex*)_calc_stack.back())->im()->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_front(); + _stack->push(new number(real(_stack->value(0)), _stack->obj(0)->reBase)); + _stack->push(new number(imag(_stack->value(1)), _stack->obj(1)->imBase)); + _stack->erase(2); } /// @brief r2p keyword implementation @@ -107,20 +67,10 @@ void program::rpn_c2r() { void program::rpn_r2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - rpn_dup(); - rpn_dup(); - rpn_arg(); - - complex* cplx = (complex*)_stack->at(1); - CHECK_MPFR(mpfr_set(cplx->im()->mpfr, ((number*)_stack->back())->_value.mpfr, mpreal::get_default_rnd())); - _stack->pop_front(); - - rpn_swap(); - rpn_abs(); - cplx = (complex*)_stack->at(1); - CHECK_MPFR(mpfr_set(cplx->re()->mpfr, ((number*)_stack->back())->_value.mpfr, mpreal::get_default_rnd())); - _stack->pop_front(); + mpreal rho = abs(_stack->value(0)); + mpreal theta = arg(_stack->value(0)); + _stack->value(0).real(rho); + _stack->value(0).imag(theta); } /// @brief p2r keyword implementation @@ -129,26 +79,5 @@ void program::rpn_r2p() { void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _calc_stack.push_back(new number()); - - // assert complex is polar - complex* rhotheta = (complex*)_calc_stack.at(1); - number* tmp = (number*)_calc_stack.at(0); - complex* result = (complex*)_stack->back(); - - // calc cos(theta) - CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cos(tmp->_value.mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); - - // calc rcos(theta) - CHECK_MPFR(mpfr_mul(result->re()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); - - // calc sin(theta) - CHECK_MPFR(mpfr_set(tmp->_value.mpfr, rhotheta->im()->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sin(tmp->_value.mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); - - // calc rsin(theta) - CHECK_MPFR(mpfr_mul(result->im()->mpfr, rhotheta->re()->mpfr, tmp->_value.mpfr, mpreal::get_default_rnd())); + _stack->value(0) = polar(abs(_stack->value(0)), arg(_stack->value(0))); } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 7f8463c..16d32c3 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -152,8 +152,15 @@ void program::rpn_inv() { void program::rpn_power() { MIN_ARGUMENTS(2); if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->value(1) = pow(_stack->value(1), _stack->value(0)); - _stack->pop(); + if (_stack->value(1) >= 0) { + _stack->value(1) = pow(_stack->value(1), _stack->value(0)); + _stack->pop(); + } else { + mpreal zero; + _stack->push(new ocomplex(_stack->value(1), zero, _stack->obj(1)->base)); + _stack->value(0) = pow(_stack->value(0), _stack->value(1)); + _stack->erase(1, 2); + } } else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { _stack->value(1) = pow(_stack->value(1), _stack->value(0)); _stack->pop(); @@ -176,10 +183,11 @@ void program::rpn_squareroot() { if (_stack->value(0) >= 0) { _stack->value(0) = sqrt(_stack->value(0)); } else { - // negative number -> square root is compl ex - _stack->push(new ocomplex); // TODO manage new errors - _stack->value(0) = sqrt(_stack->value(1)); - _stack->pop_front(1); + // negative number -> square root is complex + mpreal zero; + _stack->push(new ocomplex(_stack->value(0), zero, _stack->obj(0)->base)); // TODO manage new errors + _stack->value(0) = sqrt(_stack->value(0)); + _stack->erase(1); } } else if (_stack->type(0) == cmd_complex) _stack->value(0) = sqrt(_stack->value(0)); @@ -294,9 +302,10 @@ void program::rpn_abs() { MIN_ARGUMENTS(1); if (_stack->type(0) == cmd_number) _stack->value(0) = abs(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = norm(_stack->value(0)); - else + else if (_stack->type(0) == cmd_complex) { + _stack->push(new number(abs(_stack->value(0)))); + _stack->erase(1); + } else ERR_CONTEXT(ret_bad_operand_type); } @@ -316,7 +325,7 @@ void program::rpn_sign() { if (_stack->type(0) == cmd_number) _stack->value(0) = sgn(_stack->value(0)); else if (_stack->at(0)->_type == cmd_complex) - _stack->value(0) = _stack->value(0) / norm(_stack->value(0)); + _stack->value(0) = _stack->value(0) / abs(_stack->value(0)); else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/test/005-test-framework.md b/test/005-test-framework.md index 1847485..9824bac 100644 --- a/test/005-test-framework.md +++ b/test/005-test-framework.md @@ -1,4 +1,4 @@ -# TEST the test framwork +# TEST FRAMEWORK `default del` diff --git a/test/026-parse-program.md b/test/026-parse-program.md index c44903b..4ca722b 100644 --- a/test/026-parse-program.md +++ b/test/026-parse-program.md @@ -1,4 +1,4 @@ -# PARSE SYMBOL +# PARSE PROGRAM `default del ` diff --git a/test/027-base-entry.md b/test/027-base-entry.md index 83c4342..fc8ef4f 100644 --- a/test/027-base-entry.md +++ b/test/027-base-entry.md @@ -1,4 +1,4 @@ -# REAL AND COMPLEX NUJMERICAL ENTRIES +# REAL AND COMPLEX NUMERICAL ENTRIES `default del` diff --git a/test/100-complex.md b/test/100-complex.md index d884b5f..5a92b22 100644 --- a/test/100-complex.md +++ b/test/100-complex.md @@ -1,4 +1,4 @@ -### COMPLEX +# COMPLEX `default del` @@ -22,7 +22,7 @@ `(1,` --> stack should be (1,0) +-> stack should be '(1,' `del` @@ -46,7 +46,7 @@ `(0b11,0b101)` --> stack should be (3,5) +-> stack should be (0b11,0b101) `del` @@ -60,23 +60,15 @@ ## add (2) -`(1.2,2.3) (1,2)+` - --> stack should be (2.2,4.3) - -`del` - -## add (3) - -`(1.2,2.3) 3+` +`(1.2,2.3) 3 +` -> stack should be (4.2,2.3) `del` -## add (4) +## add (3) -`3 (1.2,2.3)+` +`3 (1.2,2.3) +` -> stack should be (4.2,2.3) @@ -92,25 +84,17 @@ ## sub (2) -`(1.2,2.3) (1,2)-` - --> stack should be (0.2,0.3) - -`del` - -## sub (3) - -`(1.2,2.3) 1-` +`(1.2,2.3) 1 -` -> stack should be (0.2,2.3) `del` -## sub (4) +## sub (3) `1 (1.2,2.3) -` --> stack should be (-0.2,2.3) +-> stack should be (-0.2,-2.3) `del` @@ -394,13 +378,21 @@ ## r->c (2) +`0x12 0b1101 r->c` + +-> stack should be (0x12,0b1101) + +`del` + +## r->c error (1) + `1 r->c` -> error should be 2 `del` -## r->c (3) +## r->c error (2) `r->c` @@ -408,7 +400,7 @@ `del` -## r->c (3) +## r->c error (3) `'1' '2' r->c` @@ -426,13 +418,21 @@ ## c->r (2) +`(0x12,0b1101) c->r` + +-> stack should be 0x12, 0b1101 + +`del` + +## c->r error (2) + `c->r` -> error should be 2 `del` -## c->r (3) +## c->r error (2) `'4' c->r` @@ -502,6 +502,22 @@ `del` +## ^ (4) + +`-3 (1,2) ^` + +-> stack should be (0.003284,-0.004539) + +`del` + +## ^ (5) + +`(1,2) (1,2) ^` + +-> stack should be (-0.222517,0.100709) + +`del` + ## sqrt (1) `(3,4) sqrt` @@ -514,695 +530,6 @@ `-3 sqrt` --> stack should be (-0.000000,1.732051) - -`del` - -## sin (1) - -`(1,2) sin` - --> stack should be (3.165779,1.959601) - -`del` - -## sin (2) - -`(1,-2) sin` - --> stack should be (3.165779,-1.959601) - -`del` - -## sin (3) - -`(-1,-2) sin` - --> stack should be (-3.165779,-1.959601) - -`del` - -## sin (4) - -`(-1,2) sin` - --> stack should be (-3.165779,1.959601) - -`del` - -## asin (1) - -`(1,2) asin` - --> stack should be (0.427079,1.528571) - -`del` - -## asin (2) - -`(1,-2) asin` - --> stack should be (0.427079,-1.528571) - -`del` - -## asin (3) - -`(-1,-2) asin` - --> stack should be (-0.427079,-1.528571) - -`del` - -## asin (4) - -`(-1,2) asin` - --> stack should be (-0.427079,1.528571) - -`del` - -## cos (1) - -`(1,2) cos` - --> stack should be (2.032723,-3.051898) - -`del` - -## cos (2) - -`(1,-2) cos` - --> stack should be (2.032723,3.051898) - -`del` - -## cos (3) - -`(-1,-2) cos` - --> stack should be (2.032723,-3.051898) - -`del` - -## cos (4) - -`(-1,2) sin` - --> stack should be (-3.165779,1.959601) - -`del` - -## acos (1) - -`(1,2) acos` - --> stack should be (1.143718,-1.528571) - -`del` - -## acos (2) - -`(1,-2) acos` - --> stack should be (1.143718,1.528571) - -`del` - -## acos (3) - -`(-1,-2) acos` - --> stack should be (1.997875,1.528571) - -`del` - -## acos (4) - -`(-1,2) acos` - --> stack should be (1.997875,-1.528571) - -`del` - -## tan (1) - -`(1,2) tan` - --> stack should be (0.033813,1.014794) - -`del` - -## tan (2) - -`(1,-2) tan` - --> stack should be (0.033813,-1.014794) - -`del` - -## tan (3) - -`(-1,-2) tan` - --> stack should be (-0.033813,-1.014794) - -`del` - -## tan (4) - -`(-1,2) tan` - --> stack should be (-0.033813,1.014794) - -`del` - -## atan (1) - -`(1,2) atan` - --> stack should be (1.338973,0.402359) - -`del` - -## atan (2) - -`(1,-2) atan` - --> stack should be (1.338973,-0.402359) - -`del` - -## atan (3) - -`(-1,-2) atan` - --> stack should be (-1.338973,-0.402359) - -`del` - -## atan (4) - -`(-1,2) atan` - --> stack should be (-1.338973,0.402359) - -`del` - -## ln (1) - -`(1,2) ln` - --> stack should be (0.804719,1.107149) - -`del` - -## ln (2) - -`(1,-2) ln` - --> stack should be (0.804719,-1.107149) - -`del` - - -## ln (3) - -`(-1,-2) ln` - --> stack should be (0.804719,-2.034444) - -`del` - -## ln (4) - -`(-1,2) ln` - --> stack should be (0.804719,2.034444) - -`del` - -## lnp1 (1) - -`(1,2) lnp1` - -`(1,2) 1 + ln ==` - --> stack should be 1.000000 - -`del` - -## lnp1 (2) - -`(1,-2) lnp1` - -`(1,-2) 1 + ln ==` - --> stack should be 1.000000 - -`del` - -## lnp1 (3) - -`(-1,-2) lnp1` - -`(-1,-2) 1 + ln ==` - --> stack should be 1.000000 - -`del` - -## lnp1 (4) - -`(-1,2) lnp1` - -`(-1,2) 1 + ln ==` - --> stack should be 1.000000 - -`del` - -## log (1) - -`(1,2) log` - --> stack should be (0.804719,1.107149) - -`del` - -## log (2) - -`(1,-2) log` - --> stack should be (0.804719,-1.107149) - -`del` - -## log (3) - -`(-1,-2) log` - --> stack should be (0.804719,-2.034444) - -`del` - -## log (4) - -`(-1,2) log` - --> stack should be (0.804719,2.034444) - -`del` - -## log10 (1) - -`(1,2) log10` - --> stack should be (0.349485,0.480829) - -`del` - -## log10 (2) - -`(1,-2) log10` - --> stack should be (0.349485,-0.480829) - -`del` - -## log10 (3) - -`(-1,-2) log10` - --> stack should be (0.349485,-0.883548) - -`del` - -## log10 (4) - -`(-1,2) log10` - --> stack should be (0.349485,0.883548) - -`del` - -## log2 (1) - -`(1,2) log2` - --> stack should be (1.160964,1.597278) - -`del` - -## log2 (2) - -`(1,-2) log2` - --> stack should be (1.160964,-1.597278) - -`del` - -## log2 (3) - -`(-1,-2) log2` - --> stack should be (1.160964,-2.935082) - -`del` - -## log2 (4) - -`(-1,2) log2` - --> stack should be (1.160964,2.935082) - -`del` - -## exp (1) - -`(1,2) exp` - --> stack should be (-1.131204,2.471727) - -`del` - -## exp (2) - -`(1,-2) exp` - --> stack should be (-1.131204,-2.471727) - -`del` - -## exp (3) - -`(-1,-2) exp` - --> stack should be (-0.153092,-0.334512) - -`del` - -## exp (4) - -`(-1,2) exp` - --> stack should be (-0.153092,0.334512) - -`del` - -## expm (1) - -`(1,2) expm` - -`(1,2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## expm (2) - -`(1,-2) expm` - -`(1,-2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## expm (3) - -`(-1,-2) expm` - -`(-1,-2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## expm (4) - -`(-1,2) expm` - -`(-1,2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## alog2 (1) - -`(1,2) alog2` - --> stack should be (0.366914,1.966055) - -`del` - -## alog2 (2) - -`(1,-2) alog2` - --> stack should be (0.366914,-1.966055) - -`del` - -## alog2 (3) - -`(-1,-2) alog2` - --> stack should be (0.091728,-0.491514) - -`del` - -## alog2 (4) - -`(-1,2) alog2` - --> stack should be (0.091728,0.491514) - -`del` - -## alog10 (1) - -`(1,2) alog10` - --> stack should be (-1.070135,-9.942576) - -`del` - -## alog10 (2) - -`(1,-2) alog10` - --> stack should be (-1.070135,9.942576) - -`del` - -## alog10 (3) - -`(-1,-2) alog10` - --> stack should be (-0.010701,0.099426) - -`del` - -## alog10 (4) - -`(-1,2) alog10` - --> stack should be (-0.010701,-0.099426) - -`del` - -## sinh (1) - -`(1,2) sinh` - --> stack should be (-0.489056,1.403119) - -`del` - -## sinh (2) - -`(1,-2) sinh` - --> stack should be (-0.489056,-1.403119) - -`del` - -## sinh (3) - -`(-1,-2) sinh` - --> stack should be (0.489056,-1.403119) - -`del` - -## sinh (4) - -`(-1,2) sinh` - --> stack should be (0.489056,1.403119) - -`del` - -## asinh (1) - -`(1,2) asinh` - --> stack should be (1.469352,1.063440) - -`del` - -## asinh (2) - -`(1,-2) asinh` - --> stack should be (1.469352,-1.063440) - -`del` - -## asinh (3) - -`(-1,-2) asinh` - --> stack should be (-1.469352,-1.063440) - -`del` - -## asinh (4) - -`(-1,2) asinh` - --> stack should be (-1.469352,1.063440) - -`del` - -## cosh (1) - -`(1,2) cosh` - --> stack should be (-0.489056,1.403119) - -`del` - -## cosh (2) - -`(1,-2) cosh` - --> stack should be (-0.489056,-1.403119) - -`del` - -## cosh (3) - -`(-1,-2) cosh` - --> stack should be (0.489056,-1.403119) - -`del` - -## cosh (4) - -`(-1,2) cosh` - --> stack should be (0.489056,1.403119) - -`del` - -## acosh (1) - -`(1,2) acosh` - --> stack should be (1.528571,1.143718) - -`del` - -## acosh (2) - -`(1,-2) acosh` - --> stack should be (1.528571,-1.143718) - -`del` - -## acosh (3) - -`(-1,-2) acosh` - --> stack should be (-1.528571,1.997875) - -`del` - -## acosh (4) - -`(-1,2) acosh` - --> stack should be (-1.528571,-1.997875) - -`del` - -## tanh (1) - -`(1,2) tanh` - --> stack should be (0.564133,-0.217934) - -`del` - -## tanh (2) - -`(1,-2) tanh` - --> stack should be (0.564133,0.217934) - -`del` - -## tanh (3) - -`(-1,-2) tanh` - --> stack should be (-0.564133,0.217934) - -`del` - -## tanh (4) - -`(-1,2) tanh` - --> stack should be (-0.564133,-0.217934) - -`del` - -## atanh (1) - -`(1,2) atanh` - --> stack should be (0.173287,1.178097) - -`del` - -## atanh (2) - -`(1,-2) atanh` - --> stack should be (0.173287,-1.178097) - -`del` - -## atanh (3) - -`(-1,-2) atanh` - --> stack should be (-0.173287,-1.178097) - -`del` - -## atanh (4) - -`(-1,2) atanh` - --> stack should be (-0.173287,1.178097) +-> stack should be (0.000000,1.732051) `del` diff --git a/test/110-time.md b/test/110-time.md index 57b9bf6..b246c05 100644 --- a/test/110-time.md +++ b/test/110-time.md @@ -1,4 +1,4 @@ -# date and time +# DATE AND TIME `default del` diff --git a/test/120-trig.md b/test/120-trig.md new file mode 100644 index 0000000..e38f16a --- /dev/null +++ b/test/120-trig.md @@ -0,0 +1,37 @@ +# TRIGONOMETRY + +`del default` + +## pi + +`6 fix pi` + +-> stack should be 3.141593 + +`del default` + +## real sin asin + +`0 sin pi 2 / sin pi 6 / sin` +`0 asin 0 == 1 asin pi 2 / == 0.5 asin pi 6 / ==` + +-> stack should be 0, 1, 0.5, 1, 1, 1 + +`del` + +## real cos acos + +`0 cos pi 3 / cos` +`1 acos 0 == 0.5 acos pi 3 / ==` + +-> stack should be 1, 0.5, 1, 1 + +`del` + +## real tan atan + +`pi 4 / tan 1 == 1 atan pi 4 / ==` + +-> stack should be 1, 1 + +`del` diff --git a/test/130-logs.md b/test/130-logs.md new file mode 100644 index 0000000..9d0f693 --- /dev/null +++ b/test/130-logs.md @@ -0,0 +1,498 @@ +# LOGARITHMS + +## complex ln (1) + +`(1,2) ln` + +-> stack should be (0.804719,1.107149) + +`del` + +## complex ln (2) + +`(1,-2) ln` + +-> stack should be (0.804719,-1.107149) + +`del` + + +## complex ln (3) + +`(-1,-2) ln` + +-> stack should be (0.804719,-2.034444) + +`del` + +## complex ln (4) + +`(-1,2) ln` + +-> stack should be (0.804719,2.034444) + +`del` + +## complex lnp1 (1) + +`(1,2) lnp1` + +`(1,2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## complex lnp1 (2) + +`(1,-2) lnp1` + +`(1,-2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## complex lnp1 (3) + +`(-1,-2) lnp1` + +`(-1,-2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## complex lnp1 (4) + +`(-1,2) lnp1` + +`(-1,2) 1 + ln ==` + +-> stack should be 1.000000 + +`del` + +## complex log (1) + +`(1,2) log` + +-> stack should be (0.804719,1.107149) + +`del` + +## complex log (2) + +`(1,-2) log` + +-> stack should be (0.804719,-1.107149) + +`del` + +## complex log (3) + +`(-1,-2) log` + +-> stack should be (0.804719,-2.034444) + +`del` + +## complex log (4) + +`(-1,2) log` + +-> stack should be (0.804719,2.034444) + +`del` + +## complex log10 (1) + +`(1,2) log10` + +-> stack should be (0.349485,0.480829) + +`del` + +## complex log10 (2) + +`(1,-2) log10` + +-> stack should be (0.349485,-0.480829) + +`del` + +## complex log10 (3) + +`(-1,-2) log10` + +-> stack should be (0.349485,-0.883548) + +`del` + +## complex log10 (4) + +`(-1,2) log10` + +-> stack should be (0.349485,0.883548) + +`del` + +## complex log2 (1) + +`(1,2) log2` + +-> stack should be (1.160964,1.597278) + +`del` + +## complex log2 (2) + +`(1,-2) log2` + +-> stack should be (1.160964,-1.597278) + +`del` + +## complex log2 (3) + +`(-1,-2) log2` + +-> stack should be (1.160964,-2.935082) + +`del` + +## complex log2 (4) + +`(-1,2) log2` + +-> stack should be (1.160964,2.935082) + +`del` + +## complex exp (1) + +`(1,2) exp` + +-> stack should be (-1.131204,2.471727) + +`del` + +## complex exp (2) + +`(1,-2) exp` + +-> stack should be (-1.131204,-2.471727) + +`del` + +## complex exp (3) + +`(-1,-2) exp` + +-> stack should be (-0.153092,-0.334512) + +`del` + +## complex exp (4) + +`(-1,2) exp` + +-> stack should be (-0.153092,0.334512) + +`del` + +## complex expm (1) + +`(1,2) expm` + +`(1,2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## complex expm (2) + +`(1,-2) expm` + +`(1,-2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## complex expm (3) + +`(-1,-2) expm` + +`(-1,-2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## complex expm (4) + +`(-1,2) expm` + +`(-1,2) exp 1 - ==` + +-> stack should be 1.000000 + +`del` + +## complex alog2 (1) + +`(1,2) alog2` + +-> stack should be (0.366914,1.966055) + +`del` + +## complex alog2 (2) + +`(1,-2) alog2` + +-> stack should be (0.366914,-1.966055) + +`del` + +## complex alog2 (3) + +`(-1,-2) alog2` + +-> stack should be (0.091728,-0.491514) + +`del` + +## complex alog2 (4) + +`(-1,2) alog2` + +-> stack should be (0.091728,0.491514) + +`del` + +## complex alog10 (1) + +`(1,2) alog10` + +-> stack should be (-1.070135,-9.942576) + +`del` + +## complex alog10 (2) + +`(1,-2) alog10` + +-> stack should be (-1.070135,9.942576) + +`del` + +## complex alog10 (3) + +`(-1,-2) alog10` + +-> stack should be (-0.010701,0.099426) + +`del` + +## complex alog10 (4) + +`(-1,2) alog10` + +-> stack should be (-0.010701,-0.099426) + +`del` + +## complex sinh (1) + +`(1,2) sinh` + +-> stack should be (-0.489056,1.403119) + +`del` + +## complex sinh (2) + +`(1,-2) sinh` + +-> stack should be (-0.489056,-1.403119) + +`del` + +## complex sinh (3) + +`(-1,-2) sinh` + +-> stack should be (0.489056,-1.403119) + +`del` + +## complex sinh (4) + +`(-1,2) sinh` + +-> stack should be (0.489056,1.403119) + +`del` + +## complex asinh (1) + +`(1,2) asinh` + +-> stack should be (1.469352,1.063440) + +`del` + +## complex asinh (2) + +`(1,-2) asinh` + +-> stack should be (1.469352,-1.063440) + +`del` + +## complex asinh (3) + +`(-1,-2) asinh` + +-> stack should be (-1.469352,-1.063440) + +`del` + +## complex asinh (4) + +`(-1,2) asinh` + +-> stack should be (-1.469352,1.063440) + +`del` + +## complex cosh (1) + +`(1,2) cosh` + +-> stack should be (-0.489056,1.403119) + +`del` + +## complex cosh (2) + +`(1,-2) cosh` + +-> stack should be (-0.489056,-1.403119) + +`del` + +## complex cosh (3) + +`(-1,-2) cosh` + +-> stack should be (0.489056,-1.403119) + +`del` + +## complex cosh (4) + +`(-1,2) cosh` + +-> stack should be (0.489056,1.403119) + +`del` + +## complex acosh (1) + +`(1,2) acosh` + +-> stack should be (1.528571,1.143718) + +`del` + +## complex acosh (2) + +`(1,-2) acosh` + +-> stack should be (1.528571,-1.143718) + +`del` + +## complex acosh (3) + +`(-1,-2) acosh` + +-> stack should be (-1.528571,1.997875) + +`del` + +## complex acosh (4) + +`(-1,2) acosh` + +-> stack should be (-1.528571,-1.997875) + +`del` + +## complex tanh (1) + +`(1,2) tanh` + +-> stack should be (0.564133,-0.217934) + +`del` + +## complex tanh (2) + +`(1,-2) tanh` + +-> stack should be (0.564133,0.217934) + +`del` + +## complex tanh (3) + +`(-1,-2) tanh` + +-> stack should be (-0.564133,0.217934) + +`del` + +## complex tanh (4) + +`(-1,2) tanh` + +-> stack should be (-0.564133,-0.217934) + +`del` + +## complex atanh (1) + +`(1,2) atanh` + +-> stack should be (0.173287,1.178097) + +`del` + +## complex atanh (2) + +`(1,-2) atanh` + +-> stack should be (0.173287,-1.178097) + +`del` + +## complex atanh (3) + +`(-1,-2) atanh` + +-> stack should be (-0.173287,-1.178097) + +`del` + +## complex atanh (4) + +`(-1,2) atanh` + +-> stack should be (-0.173287,1.178097) + +`del` diff --git a/test/all.md b/test/all.md index d725ba7..cf58cee 100644 --- a/test/all.md +++ b/test/all.md @@ -17,6 +17,8 @@ @include 070-test.md @include 080-store.md @include 090-program.md -# @include 100-complex.md +@include 100-complex.md # @include 110-time.md +# @include 120-trig.md +# @include 120-logs.md # @include 999-manual-tests.md From af5b3def4c8d78d6553d02109ce631f3a812df75 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 17:43:49 +0100 Subject: [PATCH 16/57] time tests pass --- CMakeLists.txt | 2 +- src/program.cpp | 8 ++++---- src/rpn-time.cpp | 17 +++++++---------- test/all.md | 4 ++-- 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 660637f..6e3b7b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/rpn-string.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-time.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-time.cpp ${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp diff --git a/src/program.cpp b/src/program.cpp index 2450c5a..b0ed4d7 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -199,10 +199,10 @@ program::keyword_t program::s_keywords[] = { // {cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"}, // TIME AND DATE - // {cmd_undef, "", NULL, "\nTIME AND DATE"}, - // {cmd_keyword, "time", &program::rpn_time, "time in local format"}, - // {cmd_keyword, "date", &program::rpn_date, "date in local format"}, - // {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, + {cmd_undef, "", NULL, "\nTIME AND DATE"}, + {cmd_keyword, "time", &program::rpn_time, "time in local format"}, + {cmd_keyword, "date", &program::rpn_date, "date in local format"}, + {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, // end {cmd_max, "", NULL, ""}, diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index b30f503..ff984c1 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -19,10 +19,9 @@ void program::rpn_time() { ((double)tm->tm_sec) * 1000000.0 + (double)(ts.tv_nsec / 1000); // push it - number* num; - _stack->push_front(num = static_cast(new number(date))); - // division is done here because of real precision) - CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 10000000000.0, mpreal::get_default_rnd())); + // division after push for real precision + _stack->push(new number(date)); + _stack->value(0) /= 10000000000.0; } else ERR_CONTEXT(ret_internal); } @@ -44,9 +43,9 @@ void program::rpn_date() { // push it number* num; - _stack->push_front(num = static_cast(new number(date))); - // division is done here because of real precision) - CHECK_MPFR(mpfr_div_d(num->_value.mpfr, num->_value.mpfr, 1000000.0, mpreal::get_default_rnd())); + // division after push for real precision + _stack->push(new number(date)); + _stack->value(0) /= 1000000.0; } else ERR_CONTEXT(ret_internal); } @@ -65,9 +64,7 @@ void program::rpn_ticks() { if (tm != NULL) { // date in µs date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); - - // push it - _stack->push_front(static_cast(new number(date))); + _stack->push(new number(date)); } else ERR_CONTEXT(ret_internal); } diff --git a/test/all.md b/test/all.md index cf58cee..3ccdaf0 100644 --- a/test/all.md +++ b/test/all.md @@ -18,7 +18,7 @@ @include 080-store.md @include 090-program.md @include 100-complex.md -# @include 110-time.md +@include 110-time.md # @include 120-trig.md -# @include 120-logs.md +# @include 130-logs.md # @include 999-manual-tests.md From 4aa71db351ea14a709c146e09421c4486474bf56 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 18:53:00 +0100 Subject: [PATCH 17/57] trig and log tests pass --- CMakeLists.txt | 2 +- Changelog.md | 1 + src/program.cpp | 38 ++-- src/rpn-logs.cpp | 340 +++++++----------------------- test/120-trig.md | 86 +++++++- test/130-logs.md | 531 +++++++++++------------------------------------ test/all.md | 4 +- 7 files changed, 299 insertions(+), 703 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e3b7b4..1b33886 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp ${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp - #${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp + ${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp ${PROJECT_SOURCE_DIR}/src/rpn-program.cpp ${PROJECT_SOURCE_DIR}/src/rpn-real.cpp ${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp diff --git a/Changelog.md b/Changelog.md index c468386..ced12be 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Changelog - [google c++ style guide](https://google.github.io/styleguide/cppguide.html) applied - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap +- it seems cosh was giving sinh (!) grosse perte en performances (!) - v2.3.2 fibo: 0,01s user 0,01s system 97% cpu 0,017 total diff --git a/src/program.cpp b/src/program.cpp index b0ed4d7..e3242bc 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -178,25 +178,25 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES - // {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, - // {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, - // {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, - // {cmd_keyword, "log", &program::rpn_ln, ""}, - // {cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, - // {cmd_keyword, "exp", &program::rpn_exp, "exponential"}, - // {cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, - // {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"}, - // {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"}, - // {cmd_keyword, "exp10", &program::rpn_alog10, ""}, - // {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"}, - // {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"}, - // {cmd_keyword, "exp2", &program::rpn_alog2, ""}, - // {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"}, + {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, + {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, + {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, + {cmd_keyword, "log", &program::rpn_ln, ""}, + {cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, + {cmd_keyword, "exp", &program::rpn_exp, "exponential"}, + {cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, + {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"}, + {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"}, + {cmd_keyword, "exp10", &program::rpn_alog10, ""}, + {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"}, + {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"}, + {cmd_keyword, "exp2", &program::rpn_alog2, ""}, + {cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"}, + {cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"}, + {cmd_keyword, "cosh", &program::rpn_cosh, "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"}, // TIME AND DATE {cmd_undef, "", NULL, "\nTIME AND DATE"}, diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index d280128..9521abb 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -2,28 +2,17 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { - number* euler = new number(); - _stack->push_front(euler); - euler->_value = 1L; - CHECK_MPFR(mpfr_exp(euler->_value.mpfr, euler->_value.mpfr, mpreal::get_default_rnd())); -} +void program::rpn_e(void) { _stack->push(new number(const_euler())); } /// @brief log10 keyword implementation /// void program::rpn_log10() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - // log10(z)=ln(z)/ln(10) - rpn_ln(); - - number* ten = new number(); - _stack->push_front(ten); - CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, mpreal::get_default_rnd())); - rpn_ln(); - rpn_div(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = log10(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = log10(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -31,33 +20,23 @@ void program::rpn_log10() { /// void program::rpn_alog10() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - floating_t* left = &((number*)_stack->at(0))->_value; - number* ten = new number(); - _stack->push_front(ten); - CHECK_MPFR(mpfr_set_d(ten->_value.mpfr, 10.0, mpreal::get_default_rnd())); - rpn_ln(); - rpn_mul(); - rpn_exp(); - } + if (_stack->type(0) == cmd_number) + _stack->value(0) = exp(log(mpreal(10)) * _stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = exp(log(mpreal(10)) * _stack->value(0)); + else + ERR_CONTEXT(ret_bad_operand_type); } /// @brief log2 keyword implementation /// void program::rpn_log2() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - // log2(z)=ln(z)/ln(2) - rpn_ln(); - - number* two = new number(); - _stack->push_front(two); - CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, mpreal::get_default_rnd())); - rpn_ln(); - rpn_div(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = log(_stack->value(0)) / const_log2(); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = log(_stack->value(0)) / const_log2(); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -65,62 +44,23 @@ void program::rpn_log2() { /// void program::rpn_alog2() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - floating_t* left = &((number*)_stack->at(0))->_value; - number* two = new number(); - _stack->push_front(two); - CHECK_MPFR(mpfr_set_d(two->_value.mpfr, 2.0, mpreal::get_default_rnd())); - rpn_ln(); - rpn_mul(); - rpn_exp(); - } + if (_stack->type(0) == cmd_number) + _stack->value(0) = exp(const_log2() * _stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = exp(const_log2() * _stack->value(0)); + else + ERR_CONTEXT(ret_bad_operand_type); } /// @brief ln keyword implementation /// void program::rpn_ln() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - number* left = (number*)_stack->back(); - - // x<0 -> ln(x) = ln(-x)+i*pi - if (mpfr_cmp_si(left->_value.mpfr, 0) < 0) { - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - _stack->pop_front(); - left = (number*)_calc_stack.back(); - - complex* cplx = new complex(); - _stack->push_front(cplx); - CHECK_MPFR(mpfr_neg(cplx->re()->mpfr, left->_value.mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_log(cplx->re()->mpfr, cplx->re()->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_const_pi(cplx->im()->mpfr, mpreal::get_default_rnd())); - _calc_stack.pop_front(); - } else - CHECK_MPFR(mpfr_log(left->_value.mpfr, left->_value.mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // ln(x+iy) = 0.5*ln(x*x+y*y) + i atan(x/y) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - floating_t* x = ((complex*)_calc_stack.at(0))->re(); - floating_t* y = ((complex*)_calc_stack.at(0))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - // 1. atan(x/y) - CHECK_MPFR(mpfr_atan2(im->mpfr, y->mpfr, x->mpfr, mpreal::get_default_rnd())); - - // 2. 0.5*ln(x*x+y*y) - CHECK_MPFR(mpfr_mul(x->mpfr, x->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_add(re->mpfr, x->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_log(re->mpfr, re->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul_d(re->mpfr, re->mpfr, 0.5, mpreal::get_default_rnd())); - - _calc_stack.pop_front(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = log(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = log(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -128,28 +68,11 @@ void program::rpn_ln() { /// void program::rpn_exp() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_exp(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // exp(x)*(cos(y)+i sin(y)) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - floating_t* x = ((complex*)_calc_stack.at(0))->re(); - floating_t* y = ((complex*)_calc_stack.at(0))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - CHECK_MPFR(mpfr_cos(re->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sin(im->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_exp(x->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, x->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = exp(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = exp(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -157,16 +80,11 @@ void program::rpn_exp() { /// void program::rpn_expm() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - // exp(x)-1 - rpn_exp(); - - number* one = new number(); - _stack->push_front(one); - CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_minus(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = exp(_stack->value(0)) - mpreal(1); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = exp(_stack->value(0)) - mpreal(1); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -174,16 +92,11 @@ void program::rpn_expm() { /// void program::rpn_lnp1() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number || _stack->at(0)->_type == cmd_complex) { - // ln(x+1) - number* one = new number(); - _stack->push_front(one); - CHECK_MPFR(mpfr_set_d(one->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_plus(); - - rpn_ln(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = log(_stack->value(0) + 1); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = log(_stack->value(0) + mpreal(1)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -191,33 +104,11 @@ void program::rpn_lnp1() { /// void program::rpn_sinh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_sinh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // sinh(x+iy)=sinh(x)cos(y)+icosh(x)sin(y) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - number* num = new number(); - _stack->push_front(num); - floating_t* tmp = &num->_value; - floating_t* x = ((complex*)_calc_stack.at(1))->re(); - floating_t* y = ((complex*)_calc_stack.at(1))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - CHECK_MPFR(mpfr_sinh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - CHECK_MPFR(mpfr_cosh(im->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(2); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = sinh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = sinh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -225,22 +116,11 @@ void program::rpn_sinh() { /// void program::rpn_asinh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_asinh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // asinh(z)=ln(z+sqrt(1+z*z)) - rpn_dup(); - rpn_square(); - number* num = new number(); - _stack->push_front(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_plus(); - rpn_squareroot(); - rpn_plus(); - rpn_ln(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = asinh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = asinh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -248,33 +128,11 @@ void program::rpn_asinh() { /// void program::rpn_cosh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_cosh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // acosh(x+iy)=cosh(x)cos(y)+isinh(x)sin(y) - rpnstack::copy_and_push_front(*_stack, _stack->size() - 1, _calc_stack); - - number* num = new number(); - _stack->push_front(num); - floating_t* tmp = &num->_value; - floating_t* x = ((complex*)_calc_stack.at(1))->re(); - floating_t* y = ((complex*)_calc_stack.at(1))->im(); - - floating_t* re = ((complex*)_stack->at(0))->re(); - floating_t* im = ((complex*)_stack->at(0))->im(); - - CHECK_MPFR(mpfr_cosh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_cos(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(re->mpfr, re->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - CHECK_MPFR(mpfr_sinh(im->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_sin(tmp->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(im->mpfr, im->mpfr, tmp->mpfr, mpreal::get_default_rnd())); - - _calc_stack.pop_front(2); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = cosh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = cosh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -282,27 +140,11 @@ void program::rpn_cosh() { /// void program::rpn_acosh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_acosh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // acosh(z)=ln(z+sqrt(z+1)sqrt(z-1)) - rpn_dup(); - number* num = new number(); - _stack->push_front(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_plus(); - rpn_dup(); - num = (number*)new number(); - _stack->push_front(num); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 2.0, mpreal::get_default_rnd())); - rpn_minus(); - rpn_mul(); - rpn_squareroot(); - rpn_plus(); - rpn_ln(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = acosh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = acosh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -310,29 +152,11 @@ void program::rpn_acosh() { /// void program::rpn_tanh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_tanh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // tanh(x+iy)=(tanh(x)+itan(y)) / (1 + itanh(x)tan(y)) - rpn_dup(); - - floating_t* x = ((complex*)_stack->at(1))->re(); - floating_t* y = ((complex*)_stack->at(1))->im(); - - floating_t* re = ((complex*)_stack->at(1))->re(); - floating_t* im = ((complex*)_stack->at(1))->im(); - - CHECK_MPFR(mpfr_tanh(re->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_tan(im->mpfr, y->mpfr, mpreal::get_default_rnd())); - - CHECK_MPFR(mpfr_tanh(x->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_tan(y->mpfr, y->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_mul(y->mpfr, y->mpfr, x->mpfr, mpreal::get_default_rnd())); - CHECK_MPFR(mpfr_set_d(x->mpfr, 1.0, mpreal::get_default_rnd())); - rpn_div(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = tanh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = tanh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } @@ -340,28 +164,10 @@ void program::rpn_tanh() { /// void program::rpn_atanh() { MIN_ARGUMENTS(1); - - if (_stack->at(0)->_type == cmd_number) { - floating_t* left = &((number*)_stack->at(0))->_value; - CHECK_MPFR(mpfr_atanh(left->mpfr, left->mpfr, mpreal::get_default_rnd())); - } else if (_stack->at(0)->_type == cmd_complex) { - // atanh(z)=0.5*ln((1+z)/(1-z)) - rpn_dup(); - - number* num; - _stack->push_front(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_plus(); - rpn_swap(); - _stack->push_front(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 1.0, mpreal::get_default_rnd())); - rpn_minus(); - rpn_neg(); - rpn_div(); - rpn_ln(); - _stack->push_front(num = new number); - CHECK_MPFR(mpfr_set_d(num->_value.mpfr, 0.5, mpreal::get_default_rnd())); - rpn_mul(); - } else + if (_stack->type(0) == cmd_number) + _stack->value(0) = atanh(_stack->value(0)); + else if (_stack->type(0) == cmd_complex) + _stack->value(0) = atanh(_stack->value(0)); + else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/test/120-trig.md b/test/120-trig.md index e38f16a..7dba352 100644 --- a/test/120-trig.md +++ b/test/120-trig.md @@ -1,37 +1,105 @@ # TRIGONOMETRY -`del default` +`del default 6 fix` ## pi -`6 fix pi` +`pi` -> stack should be 3.141593 -`del default` +`del` -## real sin asin +## d->r + +`180 d->r pi ==` + +-> stack should be 1.000000 + +`del` + +## r->d + +`pi r->d 180 ==` + +-> stack should be 1.000000 + +`del` + +## sin asin `0 sin pi 2 / sin pi 6 / sin` `0 asin 0 == 1 asin pi 2 / == 0.5 asin pi 6 / ==` --> stack should be 0, 1, 0.5, 1, 1, 1 +-> stack should be 0.000000, 1.000000, 0.500000, 1.000000, 1.000000, 1.000000 `del` -## real cos acos +## cos acos `0 cos pi 3 / cos` `1 acos 0 == 0.5 acos pi 3 / ==` --> stack should be 1, 0.5, 1, 1 +-> stack should be 1.000000, 0.500000, 1.000000, 1.000000 `del` -## real tan atan +## tan atan `pi 4 / tan 1 == 1 atan pi 4 / ==` --> stack should be 1, 1 +-> stack should be 1.000000, 1.000000 + +`del` + +## sin asin + +`(1,2) sin (3.165779,1.959601) asin` + +-> stack should be (3.165779,1.959601), (1.000000,2.000000) + +`del` + +## cos acos + +`(1,2) cos (2.032723,-3.051898) acos` + +-> stack should be (2.032723,-3.051898), (1.000000,2.000000) + +`del` + +## tan atan + +`(1,2) tan (0.033813,1.014794) atan` + +-> stack should be (0.033813,1.014794), (1.000004,1.999996) + +`del` + +## sin asin cos acos tan atan error + +`'ok' sin` + +-> error should be 3 + +`asin` + +-> error should be 3 + +`cos` + +-> error should be 3 + +`acos` + +-> error should be 3 + +`tan` + +-> error should be 3 + +`atan` + +-> error should be 3 `del` diff --git a/test/130-logs.md b/test/130-logs.md index 9d0f693..c5b2a1d 100644 --- a/test/130-logs.md +++ b/test/130-logs.md @@ -1,498 +1,219 @@ # LOGARITHMS -## complex ln (1) +`del default 6 fix` -`(1,2) ln` +## euler constant --> stack should be (0.804719,1.107149) +`e` + +-> stack should be 0.577216 `del` -## complex ln (2) +## ln log exp -`(1,-2) ln` +`2 ln exp` --> stack should be (0.804719,-1.107149) +`2 log exp` + +-> stack should be 2.000000, 2.000000 + +`del` + +## lnp1 expm + +`4 lnp1 expm` + +-> stack should be 4.000000 `del` -## complex ln (3) +## log10 alog10 exp10 -`(-1,-2) ln` +`5 log10 alog10` --> stack should be (0.804719,-2.034444) +`5 log10 exp10` + +-> stack should be 5.000000, 5.000000 `del` -## complex ln (4) +## log2 alog2 exp2 -`(-1,2) ln` +`6 log2 alog2` --> stack should be (0.804719,2.034444) +`6 log2 exp2` + +-> stack should be 6.000000, 6.000000 `del` -## complex lnp1 (1) +## sinh asinh -`(1,2) lnp1` - -`(1,2) 1 + ln ==` +`1 sinh asinh` -> stack should be 1.000000 `del` -## complex lnp1 (2) +## cosh acosh -`(1,-2) lnp1` +`1.1 cosh acosh` -`(1,-2) 1 + ln ==` - --> stack should be 1.000000 +-> stack should be 1.100000 `del` -## complex lnp1 (3) +## tanh atanh -`(-1,-2) lnp1` +`1.2 tanh atanh` -`(-1,-2) 1 + ln ==` - --> stack should be 1.000000 +-> stack should be 1.200000 `del` -## complex lnp1 (4) +## complex ln exp -`(-1,2) lnp1` +`(-1,-2) ln exp` -`(-1,2) 1 + ln ==` - --> stack should be 1.000000 +-> stack should be (-1.000000,-2.000000) `del` -## complex log (1) +## complex log exp -`(1,2) log` +`(1,2) log exp` --> stack should be (0.804719,1.107149) +-> stack should be (1.000000,2.000000) `del` -## complex log (2) +## complex lnp1 expm -`(1,-2) log` +`(1,2) lnp1 expm` --> stack should be (0.804719,-1.107149) +-> stack should be (1.000000,2.000000) `del` -## complex log (3) +## complex log10 alog10 -`(-1,-2) log` +`(1,-2) log10 alog10` --> stack should be (0.804719,-2.034444) +-> stack should be (1.000000,-2.000000) `del` -## complex log (4) -`(-1,2) log` +## complex log2 alog2 --> stack should be (0.804719,2.034444) +`(-1,-2) log2 alog2` + +-> stack should be (-1.000000,-2.000000) `del` -## complex log10 (1) +## complex sinh asinh -`(1,2) log10` +`(1,1.5) sinh asinh` --> stack should be (0.349485,0.480829) +-> stack should be (1.000000,1.500000) `del` -## complex log10 (2) +## complex cosh acosh -`(1,-2) log10` +`(1,2) cosh acosh` --> stack should be (0.349485,-0.480829) +-> stack should be (1.000000,2.000000) `del` -## complex log10 (3) +## complex tanh atanh -`(-1,-2) log10` +`(1,1.5) tanh atanh` --> stack should be (0.349485,-0.883548) +-> stack should be (1.000000,1.500000) `del` -## complex log10 (4) +## ln log lnp1 exp expm error -`(-1,2) log10` +`'ok' ln` --> stack should be (0.349485,0.883548) +-> error should be 3 + +`log` + +-> error should be 3 + +`lnp1` + +-> error should be 3 + +`exp` + +-> error should be 3 + +`expm` + +-> error should be 3 `del` -## complex log2 (1) +## log10 alog10 exp10 log2 alog2 exp2 error -`(1,2) log2` +`'ok' log10` --> stack should be (1.160964,1.597278) +-> error should be 3 + +`alog10` + +-> error should be 3 + +`exp10` + +-> error should be 3 + +`log2` + +-> error should be 3 + +`alog2` + +-> error should be 3 + +`exp2` + +-> error should be 3 `del` -## complex log2 (2) +## sinh asinh cosh acosh tanh atanh error -`(1,-2) log2` +`'ok' sinh` --> stack should be (1.160964,-1.597278) - -`del` - -## complex log2 (3) - -`(-1,-2) log2` - --> stack should be (1.160964,-2.935082) - -`del` - -## complex log2 (4) - -`(-1,2) log2` - --> stack should be (1.160964,2.935082) - -`del` - -## complex exp (1) - -`(1,2) exp` - --> stack should be (-1.131204,2.471727) - -`del` - -## complex exp (2) - -`(1,-2) exp` - --> stack should be (-1.131204,-2.471727) - -`del` - -## complex exp (3) - -`(-1,-2) exp` - --> stack should be (-0.153092,-0.334512) - -`del` - -## complex exp (4) - -`(-1,2) exp` - --> stack should be (-0.153092,0.334512) - -`del` - -## complex expm (1) - -`(1,2) expm` - -`(1,2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## complex expm (2) - -`(1,-2) expm` - -`(1,-2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## complex expm (3) - -`(-1,-2) expm` - -`(-1,-2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## complex expm (4) - -`(-1,2) expm` - -`(-1,2) exp 1 - ==` - --> stack should be 1.000000 - -`del` - -## complex alog2 (1) - -`(1,2) alog2` - --> stack should be (0.366914,1.966055) - -`del` - -## complex alog2 (2) - -`(1,-2) alog2` - --> stack should be (0.366914,-1.966055) - -`del` - -## complex alog2 (3) - -`(-1,-2) alog2` - --> stack should be (0.091728,-0.491514) - -`del` - -## complex alog2 (4) - -`(-1,2) alog2` - --> stack should be (0.091728,0.491514) - -`del` - -## complex alog10 (1) - -`(1,2) alog10` - --> stack should be (-1.070135,-9.942576) - -`del` - -## complex alog10 (2) - -`(1,-2) alog10` - --> stack should be (-1.070135,9.942576) - -`del` - -## complex alog10 (3) - -`(-1,-2) alog10` - --> stack should be (-0.010701,0.099426) - -`del` - -## complex alog10 (4) - -`(-1,2) alog10` - --> stack should be (-0.010701,-0.099426) - -`del` - -## complex sinh (1) - -`(1,2) sinh` - --> stack should be (-0.489056,1.403119) - -`del` - -## complex sinh (2) - -`(1,-2) sinh` - --> stack should be (-0.489056,-1.403119) - -`del` - -## complex sinh (3) - -`(-1,-2) sinh` - --> stack should be (0.489056,-1.403119) - -`del` - -## complex sinh (4) - -`(-1,2) sinh` - --> stack should be (0.489056,1.403119) - -`del` - -## complex asinh (1) - -`(1,2) asinh` - --> stack should be (1.469352,1.063440) - -`del` - -## complex asinh (2) - -`(1,-2) asinh` - --> stack should be (1.469352,-1.063440) - -`del` - -## complex asinh (3) - -`(-1,-2) asinh` - --> stack should be (-1.469352,-1.063440) - -`del` - -## complex asinh (4) - -`(-1,2) asinh` - --> stack should be (-1.469352,1.063440) - -`del` - -## complex cosh (1) - -`(1,2) cosh` - --> stack should be (-0.489056,1.403119) - -`del` - -## complex cosh (2) - -`(1,-2) cosh` - --> stack should be (-0.489056,-1.403119) - -`del` - -## complex cosh (3) - -`(-1,-2) cosh` - --> stack should be (0.489056,-1.403119) - -`del` - -## complex cosh (4) - -`(-1,2) cosh` - --> stack should be (0.489056,1.403119) - -`del` - -## complex acosh (1) - -`(1,2) acosh` - --> stack should be (1.528571,1.143718) - -`del` - -## complex acosh (2) - -`(1,-2) acosh` - --> stack should be (1.528571,-1.143718) - -`del` - -## complex acosh (3) - -`(-1,-2) acosh` - --> stack should be (-1.528571,1.997875) - -`del` - -## complex acosh (4) - -`(-1,2) acosh` - --> stack should be (-1.528571,-1.997875) - -`del` - -## complex tanh (1) - -`(1,2) tanh` - --> stack should be (0.564133,-0.217934) - -`del` - -## complex tanh (2) - -`(1,-2) tanh` - --> stack should be (0.564133,0.217934) - -`del` - -## complex tanh (3) - -`(-1,-2) tanh` - --> stack should be (-0.564133,0.217934) - -`del` - -## complex tanh (4) - -`(-1,2) tanh` - --> stack should be (-0.564133,-0.217934) - -`del` - -## complex atanh (1) - -`(1,2) atanh` - --> stack should be (0.173287,1.178097) - -`del` - -## complex atanh (2) - -`(1,-2) atanh` - --> stack should be (0.173287,-1.178097) - -`del` - -## complex atanh (3) - -`(-1,-2) atanh` - --> stack should be (-0.173287,-1.178097) - -`del` - -## complex atanh (4) - -`(-1,2) atanh` - --> stack should be (-0.173287,1.178097) +-> error should be 3 + +`asinh` + +-> error should be 3 + +`cosh` + +-> error should be 3 + +`acosh` + +-> error should be 3 + +`tanh` + +-> error should be 3 + +`atanh` + +-> error should be 3 `del` diff --git a/test/all.md b/test/all.md index 3ccdaf0..e799c1a 100644 --- a/test/all.md +++ b/test/all.md @@ -19,6 +19,6 @@ @include 090-program.md @include 100-complex.md @include 110-time.md -# @include 120-trig.md -# @include 130-logs.md +@include 120-trig.md +@include 130-logs.md # @include 999-manual-tests.md From 12b83f69affc50ab08ad917d58d6fb63d2ad7dd1 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 19:07:55 +0100 Subject: [PATCH 18/57] manual tests ok, vars corrected --- src/rpn-store.cpp | 12 ++++++------ src/stack.hpp | 1 + test/020-general.md | 18 +++++++++++++++++ test/999-manual-tests.md | 42 +++------------------------------------- test/all.md | 2 +- 5 files changed, 29 insertions(+), 46 deletions(-) diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index f82e0a1..b9f50d0 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -193,18 +193,18 @@ void program::rpn_vars(void) { // heap variables for (int i = 0; i < (int)_heap->size(); i++) { (void)_heap->get_by_index(i, name, obj); - printf("var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); + cout<<"var "<name()<<", value "; obj->show(cout); - printf("\n"); + cout<_local_heap.size(); i++) { (void)parent->_local_heap.get_by_index(i, name, obj); - printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); + cout<<"var "<name()<<", value "; obj->show(cout); - printf("\n"); + cout<_parent_prog; } @@ -212,9 +212,9 @@ void program::rpn_vars(void) { // local variables for (int i = 0; i < (int)_local_heap.size(); i++) { (void)_local_heap.get_by_index(i, name, obj); - printf("local var %d: name '%s', type %s, value ", i + 1, name.c_str(), obj->name()); + cout<<"var "<name()<<", value "; obj->show(cout); - printf("\n"); + cout< { for (; num > 0; num--, i++) ; obj = i->second; + name = i->first; return true; } else return false; diff --git a/test/020-general.md b/test/020-general.md index eef03f8..ea4056e 100644 --- a/test/020-general.md +++ b/test/020-general.md @@ -39,3 +39,21 @@ -> error should be 0 `del` + +## quit + +`q` + +-> error should be 8 + +## quit (2) + +`quit` + +-> error should be 8 + +## exit + +`exit` + +-> error should be 8 diff --git a/test/999-manual-tests.md b/test/999-manual-tests.md index 1632235..4a05471 100644 --- a/test/999-manual-tests.md +++ b/test/999-manual-tests.md @@ -2,54 +2,20 @@ `default del` -## GENERAL help - please type help and verify help is shown +## GENERAL help - please type help, h or ? and verify help is shown -> error should be 0 -`del` - -## GENERAL h - please type h and verify help is shown - --> error should be 0 - -`del` - -## GENERAL ? - please type ? and verify help is shown - --> error should be 0 - -`del` - -## GENERAL quit - please type quit and verify rpn exits - --> error should be 0 - -`del` - -## GENERAL q - please type q and verify rpn exits - --> error should be 0 - -del - -## GENERAL exit - please type exit and verify rpn exits - -`-> error should be 0` - -del - ## STORE vars - please type vars and verify variables are shown -`-> error should be 0` +`vars` -del +-> error should be 0 ## STORE edit - please type edit and verify last line comes under the caret -> error should be 0 -`del` - ## HISTORY - please type history and verify rpn history is shown -> error should be 0 @@ -57,5 +23,3 @@ del ## MULTILINE EDITING - please type a prog like 1 3 for i[ALT-ENTER]i sq[ALT-ENTER]next[ENTER] and verify output -> error should be 0 - -`del` diff --git a/test/all.md b/test/all.md index e799c1a..a835675 100644 --- a/test/all.md +++ b/test/all.md @@ -21,4 +21,4 @@ @include 110-time.md @include 120-trig.md @include 130-logs.md -# @include 999-manual-tests.md +@include 999-manual-tests.md From b90c382b24f005b33a314fa66afc5aea388fa78a Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 23:41:16 +0100 Subject: [PATCH 19/57] set missing rnd default in rpn_default --- src/program.cpp | 3 +++ test/120-trig.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/program.cpp b/src/program.cpp index e3242bc..7ff07cc 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -658,4 +658,7 @@ void program::apply_default() { number::s_mode = DEFAULT_MODE; number::s_digits = DEFAULT_DECIMAL_DIGITS; mpreal::set_default_prec(MPFR_DEFAULT_PREC_BITS); + + static mp_rnd_t def_rnd = mpreal::get_default_rnd(); + mpreal::set_default_rnd(def_rnd); } diff --git a/test/120-trig.md b/test/120-trig.md index 7dba352..47698b3 100644 --- a/test/120-trig.md +++ b/test/120-trig.md @@ -1,6 +1,6 @@ # TRIGONOMETRY -`del default 6 fix` +`del default 6 fix 128 prec` ## pi From e0c862eaaa94f041cb99874050b6aea425e4f8f9 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 23:51:33 +0100 Subject: [PATCH 20/57] removed norm as abs synonym (a norm is squared abs) --- Changelog.md | 7 +------ src/program.cpp | 1 - 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Changelog.md b/Changelog.md index ced12be..ef06fb3 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,7 +22,6 @@ cf https://www.geeksforgeeks.org/overloading-new-delete-operator-c/ New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid -- added `norm` as a synonym of `abs` - `test` command can also take a symbol as a parameter ; if the symbol contains a valid - entering the sign after the base (ex: 0x-1e2) is allowed @@ -44,10 +43,6 @@ Compatibility is broken on these points - signed zero is the sign of zero is subject to change compared to previous version, for example `-3 sqrt` now equals `(0.000000,1.732051)` instead of `(-0.000000,1.732051)` missing tests / problems -- nested loops / if / while / do + access to local variables -- les arguments d'une fonction en erreur doivent ils êre consommés ? +- les arguments d'une fonction en erreur doivent ils être consommés ? ex embettant : sto+ -- sto+ * - / : ajouter des cas de test avec type incorrects -- `10 -> n << n >>` plante - `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante -- real: ln, lnp1, log, log10, log2, exp, expm, alog2, alog10, sinh, asinh, cosh, acosh, tanh, atanh diff --git a/src/program.cpp b/src/program.cpp index 7ff07cc..b681af2 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -33,7 +33,6 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, {cmd_keyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, - {cmd_keyword, "norm", &program::rpn_abs, ""}, {cmd_keyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, // OPERATIONS ON REALS From e1d69e88766161d16d2549fa9f978e8d1e888932 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sun, 20 Feb 2022 23:55:06 +0100 Subject: [PATCH 21/57] test framework accepts script names as string again --- Changelog.md | 1 - src/rpn-test-framework.cpp | 5 ++--- test/mem_test.sh | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Changelog.md b/Changelog.md index ef06fb3..5e744a6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,7 +22,6 @@ cf https://www.geeksforgeeks.org/overloading-new-delete-operator-c/ New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid -- `test` command can also take a symbol as a parameter ; if the symbol contains a valid - entering the sign after the base (ex: 0x-1e2) is allowed Compatibility is broken on these points diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 28b07c1..696be58 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -50,15 +50,14 @@ void program::test_show_result(string title, int tests, int tests_failed, int st /// void program::rpn_test() { MIN_ARGUMENTS(1); - //TODO go back to string - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, cmd_string); int total_tests = 0; int total_tests_failed = 0; int total_steps = 0; int total_steps_failed = 0; - string test_filename = _stack->value(0); + string test_filename = _stack->value(0); _stack->pop(); cout << endl << "rpn version is " << version << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); diff --git a/test/mem_test.sh b/test/mem_test.sh index 6768be1..5c143f1 100755 --- a/test/mem_test.sh +++ b/test/mem_test.sh @@ -40,6 +40,6 @@ functional_tests=($(cat all.md | grep "^@include" | awk '{print $2}')) echo "Functional rpn memory checks" for i in ${!functional_tests[@]}; do - checkmem "${functional_tests[$i]} test" + checkmem "\"${functional_tests[$i]}\" test" done exit ${failed} From f84a64da414d07a352a816033c68ec9f4ff04fd5 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 00:03:16 +0100 Subject: [PATCH 22/57] Changelog update + add TODO.md --- Changelog.md | 16 +++++++--------- TODO.md | 6 ++++++ 2 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 TODO.md diff --git a/Changelog.md b/Changelog.md index 5e744a6..6f2cf35 100644 --- a/Changelog.md +++ b/Changelog.md @@ -23,6 +23,7 @@ cf https://www.geeksforgeeks.org/overloading-new-delete-operator-c/ New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid - entering the sign after the base (ex: 0x-1e2) is allowed +- rpn is delivered as flatpak and snap packages to be compatible with a maximum of Linux distribs. rpm and deb are no longer generated Compatibility is broken on these points - `<< <<` input doesn't lead to `««»»` but to `«<< »`, preventing to eval the real program content @@ -32,16 +33,13 @@ Compatibility is broken on these points - removed `sqr` function, please use `sq` instead (prev.existing for HP28S compatibility) - the binary prefix is always 0b on display, but still can be 0b, 0B, 2b or 2B at input - the hex prefix is always 0x on display, but still can be 0x, 0X or 16B at input -- `mant` and `xpon` now give binary significand and exponent, as it is the norm in standard libs (libC, standard C++, mpfr, gmp) +- `mant` and `xpon` now give binary (and not decimal) significand and exponent, as it is the norm in standard libs (libC, standard C++, mpfr, gmp) - `dupn`, `roll`, `rolld` are not leaving anymore their argument in front of the stack in case of error -- `sub` now only accepts boundaries between 1 and the string length -- rpn is not delivered as deb and rpm anymore, since it is too much bound to particular OS -- `sto/` bug correction: 3 'a' sto/ now correctly does a/3 -> a (although it did 3/a -> a) - `sto+` `sto-` `sto*` `sto/` don't accept anymore the syntax `'varname' value stoX`, but only `value 'varname' stoX`, ex: `3 'a' sto*` -- incomplete entry `(1,` not available anymore +- incomplete entry `(1,` is not available anymore - signed zero is the sign of zero is subject to change compared to previous version, for example `-3 sqrt` now equals `(0.000000,1.732051)` instead of `(-0.000000,1.732051)` -missing tests / problems -- les arguments d'une fonction en erreur doivent ils être consommés ? - ex embettant : sto+ -- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante +Debug +- `sub` now only accepts boundaries between 1 and the string length +- `sto/` behavior: sto/ now correctly stores variable / constant and not constant / variable +- `cosh` now returns the hyp cosinus instead of the hyp sinus (!) diff --git a/TODO.md b/TODO.md new file mode 100644 index 0000000..ba08ba0 --- /dev/null +++ b/TODO.md @@ -0,0 +1,6 @@ +TODO + +missing tests / problems +- les arguments d'une fonction en erreur doivent ils être consommés ? + ex embettant : sto+ +- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante From 328bdf3c584392c320beb88942f97996b1148510 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 01:07:04 +0100 Subject: [PATCH 23/57] main cleanup --- src/debug.h | 86 ------------------------------------------------- src/escape.h | 19 ----------- src/main.cpp | 55 ++++++++++++++++--------------- src/program.hpp | 1 - 4 files changed, 29 insertions(+), 132 deletions(-) delete mode 100644 src/debug.h diff --git a/src/debug.h b/src/debug.h deleted file mode 100644 index 4f18731..0000000 --- a/src/debug.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef DEBUG_H -#define DEBUG_H - -#include - -static void dump8(unsigned char* to_dump, unsigned long offset, unsigned long size) { - const int block_size = 1; - const int block_per_line = 16; - int max_line = size / block_size; - unsigned char mychar; - int i; - int j; - for (i = 0; i < max_line; i++) { - if ((i % block_per_line) == 0) { - if (i > 0) { - printf(" "); - for (j = i - block_per_line; j < i; j++) { - mychar = *(to_dump + j); - if ((mychar < 32) || (mychar >= 127)) mychar = '.'; - printf("%c", mychar); - } - } - printf("\n%08lX:", offset + i * block_size); - } - printf(" %02hhX", *(to_dump + i)); - } - if (i > 0) { - printf(" "); - for (j = (i >= block_per_line) ? (i - block_per_line) : 0; j < i; j++) { - mychar = *(to_dump + j); - if ((mychar < 32) || (mychar >= 127)) mychar = '.'; - printf("%c", mychar); - } - } - printf("\n"); -} - -// -#define TRACE(...) \ - do { \ - printf(__VA_ARGS__); \ - } while (0) - -// chrono -#include - -static int chrono_next = 0; -static struct { - struct timespec ts_point; - char comment[256]; -} chrono_point[24]; - -static void chrono_start() { - clock_gettime(CLOCK_REALTIME, &chrono_point[0].ts_point); - strcpy(chrono_point[0].comment, "START"); - chrono_next = 1; -} - -static void chrono_add(const char* comment) { - clock_gettime(CLOCK_REALTIME, &chrono_point[chrono_next].ts_point); - strcpy(chrono_point[chrono_next].comment, comment); - chrono_next++; -} - -static uint64_t chrono_diff_us(struct timespec* ts_from, struct timespec* ts_to) { - uint64_t from = (uint64_t)ts_from->tv_sec * 1000000UL + ((uint64_t)ts_from->tv_nsec) / 1000UL; - uint64_t to = (uint64_t)ts_to->tv_sec * 1000000UL + ((uint64_t)ts_to->tv_nsec) / 1000UL; - return to - from; -} - -static void chrono_all_print(void) { - for (int i = 1; i < chrono_next; i++) { - printf("CHRONO [%lu us] %s\n", chrono_diff_us(&chrono_point[i - 1].ts_point, &chrono_point[i].ts_point), - chrono_point[i].comment); - } -} - -static void chrono_print(int chrono) { - if (chrono >= 1) { - printf("CHRONO [%lu us] %s\n", - chrono_diff_us(&chrono_point[chrono - 1].ts_point, &chrono_point[chrono].ts_point), - chrono_point[chrono].comment); - } -} - -#endif diff --git a/src/escape.h b/src/escape.h index 14686a3..ba20c2c 100644 --- a/src/escape.h +++ b/src/escape.h @@ -7,31 +7,12 @@ #define FG_BLACK "\33[30m" #define FG_RED "\33[31m" #define FG_GREEN "\33[32m" -#define FG_YELLOW "\33[33m" -#define FG_BLUE "\33[34m" -#define FG_MAJENTA "\33[35m" -#define FG_CYAN "\33[36m" -#define FG_WHITE "\33[37m" // background colors -#define BG_BLACK "\33[40m" -#define BG_RED "\33[41m" -#define BG_GREEN "\33[42m" -#define BG_YELLOW "\33[43m" -#define BG_BLUE "\33[44m" -#define BG_MAJENTA "\33[45m" -#define BG_CYAN "\33[46m" -#define BG_WHITE "\33[47m" - #define COLOR_OFF "\33[m" // attributes #define ATTR_BOLD "\33[1m" -#define ATTR_UNDERSCORE "\33[4m" -#define ATTR_BLINK "\33[5m" -#define ATTR_REVERSE "\33[7m" -#define ATTR_CONCEALED "\33[8m" - #define ATTR_OFF "\33[0m" #endif diff --git a/src/main.cpp b/src/main.cpp index e577899..dad36a1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,5 +1,3 @@ -// std c -#include #include #include #include @@ -8,43 +6,48 @@ #include #include +#include +#include +using namespace std; + // internal includes #include "program.hpp" -static heap s_global_heap; -static rpnstack s_global_stack; -static program* s_prog_to_interrupt = NULL; +static heap _global_heap; +static stack _global_stack; +static program* _prog_to_interrupt = NULL; /// @brief actions to be done at rpn exit /// -void exit_interactive_rpn() { +static void exit_interactive_rpn() { struct passwd* pw = getpwuid(getuid()); if (pw != NULL) { - char history_path[PATH_MAX]; - sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE); + stringstream history_path; + history_path << pw->pw_dir << '/' << HISTORY_FILE; // trunc current history - ofstream history(history_path, ios_base::out | ios_base::trunc); + ofstream history(history_path.str(), ios_base::out | ios_base::trunc); history.close(); // save it - if (linenoiseHistorySave(history_path) != 0) - fprintf(stderr, "warning, could not save %s (errno=%d, '%s')\n", history_path, errno, strerror(errno)); + if (linenoiseHistorySave(history_path.str()) != 0) + cerr << "warning, could not save " << history_path.str() << " (errno=" << errno << " '" + << strerror(errno) "')" << endl; linenoiseHistoryFree(); } } /// @brief actions to be done at rpn exit /// -void init_interactive_rpn() { +static void init_interactive_rpn() { struct passwd* pw = getpwuid(getuid()); if (pw != NULL) { - char history_path[PATH_MAX]; - sprintf(history_path, "%s/%s", pw->pw_dir, HISTORY_FILE); + stringstream history_path; + history_path << pw->pw_dir << '/' << HISTORY_FILE; // don't care about errors linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES); - linenoiseHistoryLoad(history_path); + linenoiseHistoryLoad(history_path.str()); } } @@ -55,9 +58,9 @@ void init_interactive_rpn() { /// @param context see POSIX sigaction /// static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { - if (s_prog_to_interrupt != NULL) { - s_prog_to_interrupt->stop(); - s_prog_to_interrupt = NULL; + if (_prog_to_interrupt != NULL) { + _prog_to_interrupt->stop(); + _prog_to_interrupt = NULL; } exit_interactive_rpn(); @@ -70,9 +73,9 @@ static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { /// @param context see POSIX sigaction /// static void segv_handler(int sig, siginfo_t* siginfo, void* context) { - fprintf(stderr, "Internal error\n"); - s_prog_to_interrupt->stop(); - s_prog_to_interrupt = NULL; + cerr << "Internal error" << endl; + _prog_to_interrupt->stop(); + _prog_to_interrupt = NULL; } /// @brief setup signals handlers to stop with honours @@ -82,7 +85,7 @@ static void segv_handler(int sig, siginfo_t* siginfo, void* context) { static void catch_signals(program* prog) { struct sigaction act = {0}; - s_prog_to_interrupt = prog; + _prog_to_interrupt = prog; act.sa_sigaction = &ctrlc_handler; act.sa_flags = SA_SIGINFO; @@ -128,10 +131,10 @@ int main(int argc, char* argv[]) { catch_signals(&prog); // run it - if (prog.run(s_global_stack, s_global_heap) == ret_good_bye) + if (prog.run(_global_stack, _global_heap) == ret_good_bye) go_on = false; else - program::show_stack(s_global_stack); + program::show_stack(_global_stack); break; } } @@ -160,8 +163,8 @@ int main(int argc, char* argv[]) { catch_signals(&prog); // run it - ret = prog.run(s_global_stack, s_global_heap); - program::show_stack(s_global_stack, false); + ret = prog.run(_global_stack, _global_heap); + program::show_stack(_global_stack, false); } } diff --git a/src/program.hpp b/src/program.hpp index 587e4a0..6551426 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -24,7 +24,6 @@ using namespace std; // internal includes #include "constant.h" -#include "debug.h" #include "escape.h" #include "object.hpp" #include "stack.hpp" From 06a103fa8f3b67afbd65a8f6df574299fc4fe417 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 01:40:23 +0100 Subject: [PATCH 24/57] some c++ better practices --- src/main.cpp | 28 +++++++++++----------------- src/program.cpp | 12 ++---------- src/program.hpp | 8 +++----- src/rpn-program.cpp | 12 ++++++------ src/rpn-store.cpp | 4 ++-- src/rpn-string.cpp | 4 ++-- src/rpn-test-framework.cpp | 4 ++-- 7 files changed, 28 insertions(+), 44 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index dad36a1..3921eee 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,6 @@ #include #include #include -#include -#include -#include -#include #include #include @@ -14,7 +10,7 @@ using namespace std; #include "program.hpp" static heap _global_heap; -static stack _global_stack; +static rpnstack _global_stack; static program* _prog_to_interrupt = NULL; /// @brief actions to be done at rpn exit @@ -30,9 +26,9 @@ static void exit_interactive_rpn() { history.close(); // save it - if (linenoiseHistorySave(history_path.str()) != 0) - cerr << "warning, could not save " << history_path.str() << " (errno=" << errno << " '" - << strerror(errno) "')" << endl; + if (linenoiseHistorySave(history_path.str().c_str()) != 0) + cerr << "warning, could not save " << history_path.str() << " [errno=" << errno << ' ' << strerror(errno) + << "']" << endl; linenoiseHistoryFree(); } } @@ -47,7 +43,7 @@ static void init_interactive_rpn() { // don't care about errors linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES); - linenoiseHistoryLoad(history_path.str()); + linenoiseHistoryLoad(history_path.str().c_str()); } } @@ -90,12 +86,12 @@ static void catch_signals(program* prog) { act.sa_sigaction = &ctrlc_handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, NULL) < 0) - (void)fprintf(stderr, "Warning, Ctrl-C cannot be catched [errno=%d '%s']", errno, strerror(errno)); + cerr << "Warning, Ctrl-C cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; act.sa_sigaction = &segv_handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGSEGV, &act, NULL) < 0) - (void)fprintf(stderr, "Warning, SIGSEGV cannot be catched [errno=%d '%s']", errno, strerror(errno)); + cerr << "Warning, SIGSEGV cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; } /// @brief rpn entry point @@ -119,7 +115,7 @@ int main(int argc, char* argv[]) { // entry loop while (go_on) { // make program from interactive entry - program prog; + program prog(&_global_stack, &_global_heap); switch (program::entry(prog)) { case ret_good_bye: go_on = false; @@ -131,7 +127,7 @@ int main(int argc, char* argv[]) { catch_signals(&prog); // run it - if (prog.run(_global_stack, _global_heap) == ret_good_bye) + if (prog.run() == ret_good_bye) go_on = false; else program::show_stack(_global_stack); @@ -144,7 +140,7 @@ int main(int argc, char* argv[]) { } // run with cmd line arguments else { - program prog; + program prog(&_global_stack, &_global_heap); string entry; int i; @@ -157,13 +153,11 @@ int main(int argc, char* argv[]) { // make program ret = program::parse(entry, prog); if (ret == ret_ok) { - string separator = ""; - // user could stop prog with CtrlC catch_signals(&prog); // run it - ret = prog.run(_global_stack, _global_heap); + ret = prog.run(); program::show_stack(_global_stack, false); } } diff --git a/src/program.cpp b/src/program.cpp index b681af2..66ca36d 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -209,21 +209,13 @@ program::keyword_t program::s_keywords[] = { /// @brief run a program on a stack and a heap /// -/// @param stk the stack, storing prog result -/// @param hp the heap, storing variables /// @return ret_value see this type /// -ret_value program::run(rpnstack& stk, heap& hp) { +ret_value program::run() { 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 = ""; @@ -299,7 +291,7 @@ ret_value program::run(rpnstack& stk, heap& hp) { default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - stk.push_front(o->clone()); + _stack->push_front(o->clone()); i++; break; } diff --git a/src/program.hpp b/src/program.hpp index 6551426..b89c9ec 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -44,8 +44,7 @@ struct if_layout_t { //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque { public: - program(program* parent_prog = NULL) { - _parent_prog = parent_prog; + program(rpnstack* stk, heap* hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { interrupt_now = false; } virtual ~program() { @@ -60,9 +59,8 @@ class program : public deque { static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type); // running - ret_value run(rpnstack& stk, heap& hp); + ret_value run(); void stop(); - // bool compare_keyword(keyword* k, const char* str_to_compare, int len); bool compare_branch(branch* b, const char* str_to_compare, int len); ret_value preprocess(void); @@ -93,7 +91,7 @@ class program : public deque { heap _local_heap; // parent prog for inheriting heaps - program* _parent_prog; + program* _parent; int stack_size() { return _stack->size(); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 79b3f40..abe92ae 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -9,7 +9,7 @@ /// bool program::find_variable(string& variable, object*& obj) { bool found = false; - program* parent = _parent_prog; + program* parent = _parent; if (_local_heap.get(variable, obj)) found = true; @@ -19,7 +19,7 @@ bool program::find_variable(string& variable, object*& obj) { found = true; break; } - parent = parent->_parent_prog; + parent = parent->_parent; } if (!found) { if (_heap->get(variable, obj)) found = true; @@ -64,12 +64,12 @@ void program::rpn_eval(void) { // run prog if any if (run_prog) { - program prog(this); + program prog(_stack, _heap, this); // make program from entry if (program::parse(prog_text, prog) == ret_ok) { // run it - prog.run(*_stack, *_heap); + prog.run(); } } } @@ -135,12 +135,12 @@ int program::rpn_inprog(branch& myobj) { // run the program string entry(((oprogram*)(*this)[myobj.arg1 + count_symbols + 1])->value); - program prog(this); + program prog(_stack, _heap, this); // make the program from entry if (program::parse(entry, prog) == ret_ok) { // run it - prog.run(*_stack, *_heap); + prog.run(); } // point on next command diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index b9f50d0..7f6e037 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -187,7 +187,7 @@ void program::rpn_purge(void) { /// void program::rpn_vars(void) { object* obj; - program* parent = _parent_prog; + program* parent = _parent; string name; // heap variables @@ -206,7 +206,7 @@ void program::rpn_vars(void) { obj->show(cout); cout<_parent_prog; + parent = parent->_parent; } // local variables diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 93c951f..83e1b9d 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -23,13 +23,13 @@ void program::rpn_strout() { ARG_MUST_BE_OF_TYPE(0, cmd_string); string entry(_stack->value(0)); - program prog; + program prog(_stack, _heap); _stack->pop(); // make program from string in stack level 1 if (program::parse(entry, prog) == ret_ok) // run it - prog.run(*_stack, *_heap); + prog.run(); } /// @brief chr keyword implementation diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 696be58..bbb2572 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -227,11 +227,11 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // parse entry and run line entry = regex_replace(entry, regex("`"), ""); if (!entry.empty()) { - program prog; + program prog(&stk, &hp); ret = program::parse(entry, prog); if (ret == ret_ok) { // run it - (void)prog.run(stk, hp); + (void)prog.run(); last_err = (int)prog.get_err(); } } From bff2a3ec0c1e1fa62824d3f9a67252c3b3c765d3 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 01:42:52 +0100 Subject: [PATCH 25/57] heap by reference --- src/main.cpp | 4 ++-- src/program.hpp | 4 ++-- src/rpn-program.cpp | 2 +- src/rpn-store.cpp | 32 ++++++++++++++++---------------- src/rpn-test-framework.cpp | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3921eee..caad6f2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,7 @@ int main(int argc, char* argv[]) { // entry loop while (go_on) { // make program from interactive entry - program prog(&_global_stack, &_global_heap); + program prog(&_global_stack, _global_heap); switch (program::entry(prog)) { case ret_good_bye: go_on = false; @@ -140,7 +140,7 @@ int main(int argc, char* argv[]) { } // run with cmd line arguments else { - program prog(&_global_stack, &_global_heap); + program prog(&_global_stack, _global_heap); string entry; int i; diff --git a/src/program.hpp b/src/program.hpp index b89c9ec..8351c6e 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -44,7 +44,7 @@ struct if_layout_t { //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque { public: - program(rpnstack* stk, heap* hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { + program(rpnstack* stk, heap& hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { interrupt_now = false; } virtual ~program() { @@ -85,7 +85,7 @@ class program : public deque { rpnstack* _stack; // global heap (sto, rcl) - heap* _heap; + heap& _heap; // local heap for local loop variables (for..next) heap _local_heap; diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index abe92ae..3efb4d8 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -22,7 +22,7 @@ bool program::find_variable(string& variable, object*& obj) { parent = parent->_parent; } if (!found) { - if (_heap->get(variable, obj)) found = true; + if (_heap.get(variable, obj)) found = true; } } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 7f6e037..09c9a26 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -7,12 +7,12 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); // store symbol with first value - const auto it = _heap->find(_stack->value(0)); - if (it != _heap->end()) { + const auto it = _heap.find(_stack->value(0)); + if (it != _heap.end()) { delete it->second; - _heap->erase(it); + _heap.erase(it); } - (*_heap)[_stack->value(0)] = _stack->at(1)->clone(); + _heap[_stack->value(0)] = _stack->at(1)->clone(); _stack->pop_front(2); } @@ -21,7 +21,7 @@ void program::rpn_sto(void) { void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -38,7 +38,7 @@ void program::rpn_stoadd(void) { void program::rpn_stosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -55,7 +55,7 @@ void program::rpn_stosub(void) { void program::rpn_stomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -72,7 +72,7 @@ void program::rpn_stomul(void) { void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -89,7 +89,7 @@ void program::rpn_stodiv(void) { void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -105,7 +105,7 @@ void program::rpn_stoneg(void) { void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap->find(_stack->value(0)) == _heap->end()) { + if (_heap.find(_stack->value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -174,10 +174,10 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - const auto i = _heap->find(_stack->value(0)); - if (i != _heap->end()) { + const auto i = _heap.find(_stack->value(0)); + if (i != _heap.end()) { delete i->second; - _heap->erase(i); + _heap.erase(i); } else ERR_CONTEXT(ret_unknown_variable); _stack->pop(); @@ -191,8 +191,8 @@ void program::rpn_vars(void) { string name; // heap variables - for (int i = 0; i < (int)_heap->size(); i++) { - (void)_heap->get_by_index(i, name, obj); + for (int i = 0; i < (int)_heap.size(); i++) { + (void)_heap.get_by_index(i, name, obj); cout<<"var "<name()<<", value "; obj->show(cout); cout<clear(); } +void program::rpn_clusr(void) { _heap.clear(); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index bbb2572..57fedd9 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -227,7 +227,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // parse entry and run line entry = regex_replace(entry, regex("`"), ""); if (!entry.empty()) { - program prog(&stk, &hp); + program prog(&stk, hp); ret = program::parse(entry, prog); if (ret == ret_ok) { // run it From 8542890b61655b082ec807cbbee8711a7804bc56 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 02:03:37 +0100 Subject: [PATCH 26/57] stack by reference --- src/main.cpp | 4 +- src/program.cpp | 2 +- src/program.hpp | 12 +- src/rpn-branch.cpp | 46 +++---- src/rpn-complex.cpp | 34 ++--- src/rpn-general.cpp | 28 ++-- src/rpn-logs.cpp | 114 +++++++-------- src/rpn-program.cpp | 18 +-- src/rpn-real.cpp | 276 ++++++++++++++++++------------------- src/rpn-stack.cpp | 66 ++++----- src/rpn-store.cpp | 38 ++--- src/rpn-string.cpp | 46 +++---- src/rpn-test-framework.cpp | 6 +- src/rpn-test.cpp | 116 ++++++++-------- src/rpn-time.cpp | 10 +- src/rpn-trig.cpp | 58 ++++---- src/stack.hpp | 4 +- 17 files changed, 439 insertions(+), 439 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index caad6f2..9d881b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,7 +115,7 @@ int main(int argc, char* argv[]) { // entry loop while (go_on) { // make program from interactive entry - program prog(&_global_stack, _global_heap); + program prog(_global_stack, _global_heap); switch (program::entry(prog)) { case ret_good_bye: go_on = false; @@ -140,7 +140,7 @@ int main(int argc, char* argv[]) { } // run with cmd line arguments else { - program prog(&_global_stack, _global_heap); + program prog(_global_stack, _global_heap); string entry; int i; diff --git a/src/program.cpp b/src/program.cpp index 66ca36d..97a8f5c 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -291,7 +291,7 @@ ret_value program::run() { default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - _stack->push_front(o->clone()); + _stack.push_front(o->clone()); i++; break; } diff --git a/src/program.hpp b/src/program.hpp index 8351c6e..a22939c 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -44,7 +44,7 @@ struct if_layout_t { //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque { public: - program(rpnstack* stk, heap& hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { + program(rpnstack& stk, heap& hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { interrupt_now = false; } virtual ~program() { @@ -82,7 +82,7 @@ class program : public deque { string _err_context; // global stack holding results for user - rpnstack* _stack; + rpnstack& _stack; // global heap (sto, rcl) heap& _heap; @@ -93,7 +93,7 @@ class program : public deque { // parent prog for inheriting heaps program* _parent; - int stack_size() { return _stack->size(); } + int stack_size() { return _stack.size(); } private: static const char* s_ret_value_string[ret_max]; @@ -296,14 +296,14 @@ class program : public deque { } while (0) #define ARG_MUST_BE_OF_TYPE(num, type) do { \ - if (_stack->at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } \ + if (_stack.at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } \ } while (0) #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { \ - if (_stack->at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } \ + if (_stack.at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } \ } while (0) -#define IS_ARG_TYPE(num, type) (_stack->at(num)->_type == (type)) +#define IS_ARG_TYPE(num, type) (_stack.at(num)->_type == (type)) #define CHECK_MPFR(op) do { (void)(op); } while (0) diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index b30b5e5..167758b 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -11,11 +11,11 @@ int program::rpn_if(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - if (_stack->value(0) != 0) + if (_stack.value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; - _stack->pop(); + _stack.pop(); return -1; } @@ -72,8 +72,8 @@ int program::rpn_end(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); // check arg - if (_stack->value(0) == 0) ret = myobj.arg1; - _stack->pop(); + if (_stack.value(0) == 0) ret = myobj.arg1; + _stack.pop(); } // arg2 = index of while+1 in case of while..repeat..end else if (myobj.arg2 != -1) @@ -116,10 +116,10 @@ void program::rpn_ift(void) { // check ift arg // arg is true if number != 0 or if is nan or +/-inf - if (_stack->value(1) != 0) { - _stack->erase(1); + if (_stack.value(1) != 0) { + _stack.erase(1); } else { - _stack->pop_front(2); + _stack.pop_front(2); } } @@ -134,12 +134,12 @@ void program::rpn_ifte(void) { ARG_MUST_BE_OF_TYPE(2, cmd_number); // check ifte arg - if (_stack->value(2) != 0) { - _stack->erase(2); - _stack->pop(); + if (_stack.value(2) != 0) { + _stack.erase(2); + _stack.pop(); } else { - _stack->erase(2); - _stack->erase(1); + _stack.erase(2); + _stack.erase(1); } } @@ -168,8 +168,8 @@ int program::rpn_repeat(branch& myobj) { // check arg // myobj.arg1 is end+1 - if (_stack->value(0) == 0) ret = myobj.arg1; - _stack->pop(); + if (_stack.value(0) == 0) ret = myobj.arg1; + _stack.pop(); return ret; } @@ -188,9 +188,9 @@ int program::rpn_start(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); // loop boundaries - myobj.firstIndex = _stack->value(1); - myobj.lastIndex = _stack->value(0); - _stack->pop_front(2); + myobj.firstIndex = _stack.value(1); + myobj.lastIndex = _stack.value(0); + _stack.pop_front(2); // test value if (myobj.firstIndex > myobj.lastIndex) @@ -218,8 +218,8 @@ int program::rpn_for(branch& myobj) { symbol* sym = (symbol*)at(myobj.arg1); // arg1 = loop variable index // loop boundaries - myobj.firstIndex = _stack->value(1); - myobj.lastIndex = _stack->value(0); + myobj.firstIndex = _stack.value(1); + myobj.lastIndex = _stack.value(0); // test value if (myobj.firstIndex > myobj.lastIndex) @@ -234,11 +234,11 @@ int program::rpn_for(branch& myobj) { delete it->second; _local_heap.erase(it); } - _local_heap[sym->value] = _stack->obj(1)->clone(); + _local_heap[sym->value] = _stack.obj(1).clone(); ret = myobj.arg1 + 1; } - _stack->pop_front(2); + _stack.pop_front(2); return ret; } @@ -297,8 +297,8 @@ int program::rpn_step(branch& myobj) { MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - mpreal step = _stack->value(0); - _stack->pop(); + mpreal step = _stack.value(0); + _stack.pop(); // end of loop if step is negative or zero if (step <= 0) diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index e2456f2..3444fbc 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -6,8 +6,8 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->push_front(new number(real(_stack->value(0)))); - _stack->erase(1); + _stack.push_front(new number(real(_stack.value(0)))); + _stack.erase(1); } /// @brief im keyword implementation @@ -16,8 +16,8 @@ void program::rpn_re() { void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->push_front(new number(imag(_stack->value(0)))); - _stack->erase(1); + _stack.push_front(new number(imag(_stack.value(0)))); + _stack.erase(1); } /// @brief arg keyword implementation @@ -26,8 +26,8 @@ void program::rpn_im() { void program::rpn_arg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->push_front(new number(arg(_stack->value(0)))); - _stack->erase(1); + _stack.push_front(new number(arg(_stack.value(0)))); + _stack.erase(1); } /// @brief conj keyword implementation @@ -36,7 +36,7 @@ void program::rpn_arg() { void program::rpn_conj() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->value(0) = conj(_stack->value(0)); + _stack.value(0) = conj(_stack.value(0)); } /// @brief r2c keyword implementation @@ -46,8 +46,8 @@ void program::rpn_r2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->push(new ocomplex(_stack->value(1), _stack->value(0), _stack->obj(1)->reBase, _stack->obj(0)->reBase)); - _stack->erase(1, 2); + _stack.push(new ocomplex(_stack.value(1), _stack.value(0), _stack.obj(1).reBase, _stack.obj(0).reBase)); + _stack.erase(1, 2); } /// @brief c2r keyword implementation @@ -56,9 +56,9 @@ void program::rpn_r2c() { void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->push(new number(real(_stack->value(0)), _stack->obj(0)->reBase)); - _stack->push(new number(imag(_stack->value(1)), _stack->obj(1)->imBase)); - _stack->erase(2); + _stack.push(new number(real(_stack.value(0)), _stack.obj(0).reBase)); + _stack.push(new number(imag(_stack.value(1)), _stack.obj(1).imBase)); + _stack.erase(2); } /// @brief r2p keyword implementation @@ -67,10 +67,10 @@ void program::rpn_c2r() { void program::rpn_r2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - mpreal rho = abs(_stack->value(0)); - mpreal theta = arg(_stack->value(0)); - _stack->value(0).real(rho); - _stack->value(0).imag(theta); + mpreal rho = abs(_stack.value(0)); + mpreal theta = arg(_stack.value(0)); + _stack.value(0).real(rho); + _stack.value(0).imag(theta); } /// @brief p2r keyword implementation @@ -79,5 +79,5 @@ void program::rpn_r2p() { void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack->value(0) = polar(abs(_stack->value(0)), arg(_stack->value(0))); + _stack.value(0) = polar(abs(_stack.value(0)), arg(_stack.value(0))); } diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index b0bdbed..06b113e 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -95,13 +95,13 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack->value(0)); + double digits = double(_stack.value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::std; number::s_digits = (int)digits; - _stack->pop(); + _stack.pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -112,13 +112,13 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack->value(0)); + double digits = double(_stack.value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::fix; number::s_digits = (int)digits; - _stack->pop(); + _stack.pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -129,24 +129,24 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack->value(0)); + double digits = double(_stack.value(0)); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::sci; number::s_digits = (int)digits; - _stack->pop(); + _stack.pop(); } else ERR_CONTEXT(ret_out_of_range); } /// @brief version keyword implementation /// -void program::rpn_version() { _stack->push_front(new ostring(version)); } +void program::rpn_version() { _stack.push_front(new ostring(version)); } /// @brief uname keyword implementation /// -void program::rpn_uname() { _stack->push_front(new ostring(uname)); } +void program::rpn_uname() { _stack.push_front(new ostring(uname)); } /// @brief history keyword implementation /// @@ -165,8 +165,8 @@ void program::rpn_history() { /// void program::rpn_type() { MIN_ARGUMENTS(1); - _stack->push(new ostring(_stack->at(0)->name())); - _stack->erase(1); + _stack.push(new ostring(_stack.at(0)->name())); + _stack.erase(1); } /// @brief default keyword implementation @@ -180,7 +180,7 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - unsigned long prec = _stack->value(0).toULong(); + unsigned long prec = _stack.value(0).toULong(); if (prec >= (unsigned long)MPFR_PREC_MIN && prec <= (unsigned long)MPFR_PREC_MAX) { mpreal::set_default_prec(prec); @@ -189,7 +189,7 @@ void program::rpn_precision() { // calc max nb of digits user can see with the current bit precision number::s_digits = bits2digits(mpreal::get_default_prec()); } - _stack->pop(); + _stack.pop(); } else ERR_CONTEXT(ret_out_of_range); } @@ -202,10 +202,10 @@ void program::rpn_round() { map matchRound{MPFR_ROUND_STRINGS}; - auto found = matchRound.find(_stack->value(0)); + auto found = matchRound.find(_stack.value(0)); if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else ERR_CONTEXT(ret_out_of_range); - _stack->pop(); + _stack.pop(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 9521abb..4b6582e 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -2,16 +2,16 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { _stack->push(new number(const_euler())); } +void program::rpn_e(void) { _stack.push(new number(const_euler())); } /// @brief log10 keyword implementation /// void program::rpn_log10() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = log10(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = log10(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = log10(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = log10(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -20,10 +20,10 @@ void program::rpn_log10() { /// void program::rpn_alog10() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = exp(log(mpreal(10)) * _stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = exp(log(mpreal(10)) * _stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -32,10 +32,10 @@ void program::rpn_alog10() { /// void program::rpn_log2() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = log(_stack->value(0)) / const_log2(); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = log(_stack->value(0)) / const_log2(); + if (_stack.type(0) == cmd_number) + _stack.value(0) = log(_stack.value(0)) / const_log2(); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = log(_stack.value(0)) / const_log2(); else ERR_CONTEXT(ret_bad_operand_type); } @@ -44,10 +44,10 @@ void program::rpn_log2() { /// void program::rpn_alog2() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = exp(const_log2() * _stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = exp(const_log2() * _stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = exp(const_log2() * _stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = exp(const_log2() * _stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -56,10 +56,10 @@ void program::rpn_alog2() { /// void program::rpn_ln() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = log(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = log(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = log(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = log(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -68,10 +68,10 @@ void program::rpn_ln() { /// void program::rpn_exp() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = exp(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = exp(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = exp(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = exp(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -80,10 +80,10 @@ void program::rpn_exp() { /// void program::rpn_expm() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = exp(_stack->value(0)) - mpreal(1); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = exp(_stack->value(0)) - mpreal(1); + if (_stack.type(0) == cmd_number) + _stack.value(0) = exp(_stack.value(0)) - mpreal(1); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = exp(_stack.value(0)) - mpreal(1); else ERR_CONTEXT(ret_bad_operand_type); } @@ -92,10 +92,10 @@ void program::rpn_expm() { /// void program::rpn_lnp1() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = log(_stack->value(0) + 1); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = log(_stack->value(0) + mpreal(1)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = log(_stack.value(0) + 1); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = log(_stack.value(0) + mpreal(1)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -104,10 +104,10 @@ void program::rpn_lnp1() { /// void program::rpn_sinh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = sinh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = sinh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = sinh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = sinh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -116,10 +116,10 @@ void program::rpn_sinh() { /// void program::rpn_asinh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = asinh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = asinh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = asinh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = asinh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -128,10 +128,10 @@ void program::rpn_asinh() { /// void program::rpn_cosh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = cosh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = cosh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = cosh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = cosh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -140,10 +140,10 @@ void program::rpn_cosh() { /// void program::rpn_acosh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = acosh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = acosh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = acosh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = acosh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -152,10 +152,10 @@ void program::rpn_acosh() { /// void program::rpn_tanh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = tanh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = tanh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = tanh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = tanh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -164,10 +164,10 @@ void program::rpn_tanh() { /// void program::rpn_atanh() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = atanh(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = atanh(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = atanh(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = atanh(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 3efb4d8..8dbf217 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -39,25 +39,25 @@ void program::rpn_eval(void) { if (IS_ARG_TYPE(0, cmd_symbol)) { // recall a variable object* obj; - string variable(((symbol*)_stack->front())->value); - _stack->pop(); + string variable(_stack.value(0)); + _stack.pop(); // if variable holds a program, run this program if (find_variable(variable, obj)) { if (obj->_type == cmd_program) { - prog_text = _stack->value(0); - _stack->pop(); + prog_text = _stack.value(0); + _stack.pop(); run_prog = true; } else { // else recall this variable (i.e. stack its content) - _stack->push_front(obj); + _stack.push_front(obj); } } else ERR_CONTEXT(ret_unknown_variable); } else if (IS_ARG_TYPE(0, cmd_program)) { // eval a program - prog_text = _stack->value(0); - _stack->pop(); + prog_text = _stack.value(0); + _stack.pop(); run_prog = true; } else ERR_CONTEXT(ret_bad_operand_type); @@ -129,8 +129,8 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[string(((symbol*)(*this)[i])->value)] = _stack->at(0)->clone(); - _stack->pop_front(); + _local_heap[string(((symbol*)(*this)[i])->value)] = _stack.at(0)->clone(); + _stack.pop_front(); } // run the program diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 16d32c3..e1b6257 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -6,30 +6,30 @@ void program::rpn_plus() { MIN_ARGUMENTS(2); // strings - if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->value(1) += _stack->value(0); - _stack->pop(); + if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.value(1) += _stack.value(0); + _stack.pop(); } // numbers - else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->value(1) += _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.value(1) += _stack.value(0); + _stack.pop(); } // complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->value(1) += _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.value(1) += _stack.value(0); + _stack.pop(); } // complex+number - else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { - _stack->value(1) += _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + _stack.value(1) += _stack.value(0); + _stack.pop(); } // number+complex - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack->value(1) += _stack->value(0); - _stack->pop(); + _stack.value(1) += _stack.value(0); + _stack.pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -40,25 +40,25 @@ void program::rpn_minus() { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->value(1) -= _stack->value(0); - _stack->pop(); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.value(1) -= _stack.value(0); + _stack.pop(); } // complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->value(1) -= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.value(1) -= _stack.value(0); + _stack.pop(); } // subbing complex-number - else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { - _stack->value(1) -= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + _stack.value(1) -= _stack.value(0); + _stack.pop(); } // number-complex - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack->value(1) = _stack->value(0) - _stack->value(1); - _stack->pop(); + _stack.value(1) = _stack.value(0) - _stack.value(1); + _stack.pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -69,25 +69,25 @@ void program::rpn_mul() { MIN_ARGUMENTS(2); // mutiplying numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->value(1) *= _stack->value(0); - _stack->pop(); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.value(1) *= _stack.value(0); + _stack.pop(); } // mutiplying complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->value(1) *= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.value(1) *= _stack.value(0); + _stack.pop(); } // mutiplying complex*number - else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { - _stack->value(1) *= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + _stack.value(1) *= _stack.value(0); + _stack.pop(); } // mutiplying number*complex - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack->value(1) *= _stack->value(0); - _stack->pop(); + _stack.value(1) *= _stack.value(0); + _stack.pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -98,25 +98,25 @@ void program::rpn_div() { MIN_ARGUMENTS(2); // dividing numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->value(1) /= _stack->value(0); - _stack->pop(); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.value(1) /= _stack.value(0); + _stack.pop(); } // dividing complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->value(1) /= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.value(1) /= _stack.value(0); + _stack.pop(); } // dividing complex/number - else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { - _stack->value(1) /= _stack->value(0); - _stack->pop(); + else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + _stack.value(1) /= _stack.value(0); + _stack.pop(); } // dividing number/complex - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack->value(1) = _stack->value(0) / _stack->value(1); - _stack->pop(); + _stack.value(1) = _stack.value(0) / _stack.value(1); + _stack.pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -126,10 +126,10 @@ void program::rpn_div() { void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = -_stack->value(0); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = -_stack->value(0); + if (_stack.type(0) == cmd_number) + _stack.value(0) = -_stack.value(0); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = -_stack.value(0); else ERR_CONTEXT(ret_bad_operand_type); } @@ -139,10 +139,10 @@ void program::rpn_neg() { void program::rpn_inv() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = 1 / _stack->value(0); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = mpreal{1} / _stack->value(0); + if (_stack.type(0) == cmd_number) + _stack.value(0) = 1 / _stack.value(0); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = mpreal{1} / _stack.value(0); else ERR_CONTEXT(ret_bad_operand_type); } @@ -151,26 +151,26 @@ void program::rpn_inv() { /// void program::rpn_power() { MIN_ARGUMENTS(2); - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - if (_stack->value(1) >= 0) { - _stack->value(1) = pow(_stack->value(1), _stack->value(0)); - _stack->pop(); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.value(1) >= 0) { + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + _stack.pop(); } else { mpreal zero; - _stack->push(new ocomplex(_stack->value(1), zero, _stack->obj(1)->base)); - _stack->value(0) = pow(_stack->value(0), _stack->value(1)); - _stack->erase(1, 2); + _stack.push(new ocomplex(_stack.value(1), zero, _stack.obj(1).base)); + _stack.value(0) = pow(_stack.value(0), _stack.value(1)); + _stack.erase(1, 2); } - } else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->value(1) = pow(_stack->value(1), _stack->value(0)); - _stack->pop(); - } else if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_complex) { - _stack->value(1) = pow(_stack->value(1), _stack->value(0)); - _stack->pop(); - } else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + _stack.pop(); + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + _stack.pop(); + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack->value(1) = pow(_stack->value(0), _stack->value(1)); - _stack->pop(); + _stack.value(1) = pow(_stack.value(0), _stack.value(1)); + _stack.pop(); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -179,18 +179,18 @@ void program::rpn_power() { /// void program::rpn_squareroot() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) { - if (_stack->value(0) >= 0) { - _stack->value(0) = sqrt(_stack->value(0)); + if (_stack.type(0) == cmd_number) { + if (_stack.value(0) >= 0) { + _stack.value(0) = sqrt(_stack.value(0)); } else { // negative number -> square root is complex mpreal zero; - _stack->push(new ocomplex(_stack->value(0), zero, _stack->obj(0)->base)); // TODO manage new errors - _stack->value(0) = sqrt(_stack->value(0)); - _stack->erase(1); + _stack.push(new ocomplex(_stack.value(0), zero, _stack.obj(0).base)); // TODO manage new errors + _stack.value(0) = sqrt(_stack.value(0)); + _stack.erase(1); } - } else if (_stack->type(0) == cmd_complex) - _stack->value(0) = sqrt(_stack->value(0)); + } else if (_stack.type(0) == cmd_complex) + _stack.value(0) = sqrt(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -199,11 +199,11 @@ void program::rpn_squareroot() { /// void program::rpn_hex() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->obj(0)->base = 16; - else if (_stack->type(0) == cmd_complex) { - _stack->obj(0)->reBase = 16; - _stack->obj(0)->imBase = 16; + if (_stack.type(0) == cmd_number) + _stack.obj(0).base = 16; + else if (_stack.type(0) == cmd_complex) { + _stack.obj(0).reBase = 16; + _stack.obj(0).imBase = 16; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -212,11 +212,11 @@ void program::rpn_hex() { /// void program::rpn_bin() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->obj(0)->base = 2; - else if (_stack->type(0) == cmd_complex) { - _stack->obj(0)->reBase = 2; - _stack->obj(0)->imBase = 2; + if (_stack.type(0) == cmd_number) + _stack.obj(0).base = 2; + else if (_stack.type(0) == cmd_complex) { + _stack.obj(0).reBase = 2; + _stack.obj(0).imBase = 2; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -225,11 +225,11 @@ void program::rpn_bin() { /// void program::rpn_dec() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->obj(0)->base = 10; - else if (_stack->type(0) == cmd_complex) { - _stack->obj(0)->reBase = 10; - _stack->obj(0)->imBase = 10; + if (_stack.type(0) == cmd_number) + _stack.obj(0).base = 10; + else if (_stack.type(0) == cmd_complex) { + _stack.obj(0).reBase = 10; + _stack.obj(0).imBase = 10; } else ERR_CONTEXT(ret_bad_operand_type); } @@ -238,15 +238,15 @@ void program::rpn_dec() { /// void program::rpn_base() { MIN_ARGUMENTS(2); - if (_stack->type(1) == cmd_number || _stack->type(1) == cmd_complex) { - int base = (int)_stack->value(0).toLong(); - _stack->pop(); + if (_stack.type(1) == cmd_number || _stack.type(1) == cmd_complex) { + int base = (int)_stack.value(0).toLong(); + _stack.pop(); if (base >= BASE_MIN && base <= BASE_MAX) { - if (_stack->type(0) == cmd_number) - _stack->obj(0)->base = base; + if (_stack.type(0) == cmd_number) + _stack.obj(0).base = base; else { - _stack->obj(0)->reBase = base; - _stack->obj(0)->imBase = base; + _stack.obj(0).reBase = base; + _stack.obj(0).imBase = base; } } else ERR_CONTEXT(ret_out_of_range); @@ -260,8 +260,8 @@ void program::rpn_purcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->value(1) *= _stack->value(0) / 100; - _stack->pop(); + _stack.value(1) *= _stack.value(0) / 100; + _stack.pop(); } /// @brief %CH keyword implementation @@ -270,18 +270,18 @@ void program::rpn_purcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->value(1) = (_stack->value(0) * 100) / _stack->value(1); - _stack->pop(); + _stack.value(1) = (_stack.value(0) * 100) / _stack.value(1); + _stack.pop(); } /// @brief sq keyword implementation /// void program::rpn_square() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) *= _stack->value(0); - else if (_stack->at(0)->_type == cmd_complex) - _stack->value(0) *= _stack->value(0); + if (_stack.type(0) == cmd_number) + _stack.value(0) *= _stack.value(0); + else if (_stack.at(0)->_type == cmd_complex) + _stack.value(0) *= _stack.value(0); else ERR_CONTEXT(ret_bad_operand_type); } @@ -292,19 +292,19 @@ void program::rpn_modulo() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->value(1) = fmod(_stack->value(1), _stack->value(0)); - _stack->pop(); + _stack.value(1) = fmod(_stack.value(1), _stack.value(0)); + _stack.pop(); } /// @brief abs keyword implementation /// void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = abs(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) { - _stack->push(new number(abs(_stack->value(0)))); - _stack->erase(1); + if (_stack.type(0) == cmd_number) + _stack.value(0) = abs(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) { + _stack.push(new number(abs(_stack.value(0)))); + _stack.erase(1); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -315,17 +315,17 @@ void program::rpn_fact() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); // fact(n) = gamma(n+1) - _stack->value(0) = gamma(_stack->value(0) + 1); + _stack.value(0) = gamma(_stack.value(0) + 1); } /// @brief sign keyword implementation /// void program::rpn_sign() { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = sgn(_stack->value(0)); - else if (_stack->at(0)->_type == cmd_complex) - _stack->value(0) = _stack->value(0) / abs(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = sgn(_stack.value(0)); + else if (_stack.at(0)->_type == cmd_complex) + _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -335,12 +335,12 @@ void program::rpn_sign() { void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - if (!isfinite(_stack->value(0))) { + if (!isfinite(_stack.value(0))) { ERR_CONTEXT(ret_out_of_range); return; } mp_exp_t exp; - _stack->value(0) = frexp(_stack->value(0), &exp); + _stack.value(0) = frexp(_stack.value(0), &exp); } /// @brief xpon keyword implementation @@ -348,13 +348,13 @@ void program::rpn_mant() { void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - if (!isfinite(_stack->value(0))) { + if (!isfinite(_stack.value(0))) { ERR_CONTEXT(ret_out_of_range); return; } mp_exp_t exp; - (void)frexp(_stack->value(0), &exp); - _stack->value(0) = exp; + (void)frexp(_stack.value(0), &exp); + _stack.value(0) = exp; } /// @brief floor keyword implementation @@ -362,7 +362,7 @@ void program::rpn_xpon() { void program::rpn_floor() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) = floor(_stack->value(0)); + _stack.value(0) = floor(_stack.value(0)); } /// @brief ceil keyword implementation @@ -370,7 +370,7 @@ void program::rpn_floor() { void program::rpn_ceil() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) = ceil(_stack->value(0)); + _stack.value(0) = ceil(_stack.value(0)); } /// @brief fp keyword implementation @@ -378,7 +378,7 @@ void program::rpn_ceil() { void program::rpn_fp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) = frac(_stack->value(0)); + _stack.value(0) = frac(_stack.value(0)); } /// @brief ip keyword implementation @@ -386,7 +386,7 @@ void program::rpn_fp() { void program::rpn_ip() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) = trunc(_stack->value(0)); + _stack.value(0) = trunc(_stack.value(0)); } /// @brief min keyword implementation @@ -395,8 +395,8 @@ void program::rpn_min() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->value(0) = min(_stack->value(0), _stack->value(1)); - _stack->erase(1); + _stack.value(0) = min(_stack.value(0), _stack.value(1)); + _stack.erase(1); } /// @brief max keyword implementation @@ -405,6 +405,6 @@ void program::rpn_max() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack->value(0) = max(_stack->value(0), _stack->value(1)); - _stack->erase(1); + _stack.value(0) = max(_stack.value(0), _stack.value(1)); + _stack.erase(1); } diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 77c37f3..8b864bc 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -4,23 +4,23 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - object* tmp = _stack->front(); - _stack->erase(0, 1, false); - _stack->insert(_stack->begin() + 1, tmp); + object* tmp = _stack.front(); + _stack.erase(0, 1, false); + _stack.insert(_stack.begin() + 1, tmp); } /// @brief drop keyword implementation /// void program::rpn_drop(void) { MIN_ARGUMENTS(1); - _stack->pop(); + _stack.pop(); } /// @brief drop2 keyword implementation /// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); - _stack->pop_front(2); + _stack.pop_front(2); } /// @brief dropn keyword implementation @@ -29,20 +29,20 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)_stack->value(0).toLong(); + int args = (int)_stack.value(0).toLong(); MIN_ARGUMENTS(args + 1); - _stack->erase(0, args + 1); + _stack.erase(0, args + 1); } /// @brief erase / del keyword implementation /// -void program::rpn_erase(void) { _stack->erase(0, _stack->size()); } +void program::rpn_erase(void) { _stack.erase(0, _stack.size()); } /// @brief dup keyword implementation /// void program::rpn_dup(void) { MIN_ARGUMENTS(1); - rpnstack::copy_and_push_front(*_stack, 0, *_stack); + rpnstack::copy_and_push_front(_stack, 0, _stack); } /// @brief dupn keyword implementation @@ -51,19 +51,19 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->front())->value.toLong(); - _stack->pop(); + int args = (int)((number*)_stack.front())->value.toLong(); + _stack.pop(); MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) rpnstack::copy_and_push_front(*_stack, args - 1, *_stack); + for (int i = 0; i < args; i++) rpnstack::copy_and_push_front(_stack, args - 1, _stack); } /// @brief dup2 keyword implementation /// void program::rpn_dup2(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_front(*_stack, 1, *_stack); - rpnstack::copy_and_push_front(*_stack, 1, *_stack); + rpnstack::copy_and_push_front(_stack, 1, _stack); + rpnstack::copy_and_push_front(_stack, 1, _stack); } /// @brief pick keyword implementation @@ -72,30 +72,30 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - unsigned int to_pick = (unsigned int)_stack->value(0); - _stack->pop(); + unsigned int to_pick = (unsigned int)_stack.value(0); + _stack.pop(); // treat stack depth errors - if ((to_pick == 0) || (to_pick > _stack->size())) { + if ((to_pick == 0) || (to_pick > _stack.size())) { ERR_CONTEXT(ret_out_of_range); return; } - rpnstack::copy_and_push_front(*_stack, to_pick - 1, *_stack); + rpnstack::copy_and_push_front(_stack, to_pick - 1, _stack); } /// @brief rot keyword implementation /// void program::rpn_rot(void) { MIN_ARGUMENTS(3); - object* tmp = _stack->at(2); - _stack->erase(2, 1, false); - _stack->insert(_stack->begin(), tmp); + object* tmp = _stack.at(2); + _stack.erase(2, 1, false); + _stack.insert(_stack.begin(), tmp); } /// @brief depth keyword implementation /// -void program::rpn_depth(void) { _stack->push_front(new number(_stack->size())); } +void program::rpn_depth(void) { _stack.push_front(new number(_stack.size())); } /// @brief roll keyword implementation /// @@ -103,13 +103,13 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - size_t args = (int)((number*)_stack->front())->value; - _stack->pop(); + size_t args = (int)((number*)_stack.front())->value; + _stack.pop(); MIN_ARGUMENTS(args); - object* tmp = _stack->at(args - 1); - _stack->erase(args - 1, 1, false); - _stack->insert(_stack->begin(), tmp); + object* tmp = _stack.at(args - 1); + _stack.erase(args - 1, 1, false); + _stack.insert(_stack.begin(), tmp); } /// @brief rolld keyword implementation @@ -118,13 +118,13 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack->front())->value.toLong(); - _stack->pop(); + int args = (int)((number*)_stack.front())->value.toLong(); + _stack.pop(); MIN_ARGUMENTS(args); - object* tmp = _stack->at(0); - _stack->erase(0, 1, false); - _stack->insert(_stack->begin() + args - 1, tmp); + object* tmp = _stack.at(0); + _stack.erase(0, 1, false); + _stack.insert(_stack.begin() + args - 1, tmp); } /// @brief over keyword implementation @@ -132,6 +132,6 @@ void program::rpn_rolld(void) { void program::rpn_over(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_front(*_stack, 1, *_stack); + rpnstack::copy_and_push_front(_stack, 1, _stack); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 09c9a26..4a424c8 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -7,13 +7,13 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); // store symbol with first value - const auto it = _heap.find(_stack->value(0)); + const auto it = _heap.find(_stack.value(0)); if (it != _heap.end()) { delete it->second; _heap.erase(it); } - _heap[_stack->value(0)] = _stack->at(1)->clone(); - _stack->pop_front(2); + _heap[_stack.value(0)] = _stack.at(1)->clone(); + _stack.pop_front(2); } /// @brief sto+ keyword implementation @@ -21,7 +21,7 @@ void program::rpn_sto(void) { void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -38,7 +38,7 @@ void program::rpn_stoadd(void) { void program::rpn_stosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -55,7 +55,7 @@ void program::rpn_stosub(void) { void program::rpn_stomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -72,7 +72,7 @@ void program::rpn_stomul(void) { void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -89,7 +89,7 @@ void program::rpn_stodiv(void) { void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -105,7 +105,7 @@ void program::rpn_stoneg(void) { void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack->value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { ERR_CONTEXT(ret_unknown_variable); return; } @@ -124,12 +124,12 @@ void program::rpn_rcl(void) { // recall a variable object* obj; - string variable(_stack->value(0)); + string variable(_stack.value(0)); // mind the order of heaps if (find_variable(variable, obj)) { - (void)_stack->pop_front(); - _stack->push_front(obj->clone()); + (void)_stack.pop_front(); + _stack.push_front(obj->clone()); } else ERR_CONTEXT(ret_unknown_variable); } @@ -142,8 +142,8 @@ void program::rpn_edit(void) { ostringstream st; // re-write stack objet in a stream - _stack->at(0)->show(st); - _stack->pop(); + _stack.at(0)->show(st); + _stack.pop(); // set it as the linenoise line entry linenoisePreloadBuffer((const char*)st.str().c_str()); @@ -160,12 +160,12 @@ void program::auto_rcl(symbol* symb) { // mind the order of heaps if (find_variable(variable, obj)) { - _stack->push_front(obj->clone()); + _stack.push_front(obj->clone()); if (obj->_type == cmd_program) rpn_eval(); } else - _stack->push_front(symb->clone()); + _stack.push_front(symb->clone()); } else - _stack->push_front(symb->clone()); + _stack.push_front(symb->clone()); } /// @brief purge keyword implementation @@ -174,13 +174,13 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - const auto i = _heap.find(_stack->value(0)); + const auto i = _heap.find(_stack.value(0)); if (i != _heap.end()) { delete i->second; _heap.erase(i); } else ERR_CONTEXT(ret_unknown_variable); - _stack->pop(); + _stack.pop(); } /// @brief vars keyword implementation diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 83e1b9d..c4b4ad6 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -8,11 +8,11 @@ void program::rpn_instr() { MIN_ARGUMENTS(1); // stringify only if not already a string - if (_stack->at(0)->_type != cmd_string) { + if (_stack.type(0) != cmd_string) { stringstream ss; - ss << _stack->at(0); - _stack->pop(); - _stack->push(new ostring(ss.str())); + ss << _stack.at(0); + _stack.pop(); + _stack.push(new ostring(ss.str())); } } @@ -22,9 +22,9 @@ void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - string entry(_stack->value(0)); + string entry(_stack.value(0)); program prog(_stack, _heap); - _stack->pop(); + _stack.pop(); // make program from string in stack level 1 if (program::parse(entry, prog) == ret_ok) @@ -37,10 +37,10 @@ void program::rpn_strout() { void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - char the_chr = (char)(int)_stack->value(0); - _stack->pop(); + char the_chr = (char)(int)_stack.value(0); + _stack.pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; - _stack->push_front(new ostring(string(1, the_chr))); + _stack.push_front(new ostring(string(1, the_chr))); } /// @brief num keyword implementation @@ -48,11 +48,11 @@ void program::rpn_chr() { void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - if (_stack->value(0).size() > 0) - _stack->push_front(new number(_stack->value(0)[0])); + if (_stack.value(0).size() > 0) + _stack.push_front(new number(_stack.value(0)[0])); else - _stack->push_front(new number(0)); - _stack->erase(1); + _stack.push_front(new number(0)); + _stack.erase(1); } /// @brief size keyword implementation @@ -60,8 +60,8 @@ void program::rpn_num() { void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - _stack->push_front(new number(_stack->value(0).size())); - _stack->erase(1); + _stack.push_front(new number(_stack.value(0).size())); + _stack.erase(1); } /// @brief pos keyword implementation @@ -71,9 +71,9 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(1, cmd_string); - size_t pos = _stack->value(1).find(_stack->value(0)) + 1; - _stack->pop_front(2); - _stack->push_front(new number(pos)); + size_t pos = _stack.value(1).find(_stack.value(0)) + 1; + _stack.pop_front(2); + _stack.push_front(new number(pos)); } /// @brief sub keyword implementation @@ -84,11 +84,11 @@ void program::rpn_strsub() { ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_string); - size_t first = (size_t)_stack->value(1); - size_t len = (size_t)_stack->value(0) - first + 1; + size_t first = (size_t)_stack.value(1); + size_t len = (size_t)_stack.value(0) - first + 1; first--; - if (first > _stack->value(2).size()) first = len = 0; - _stack->push(new ostring(_stack->value(2).substr(first, len))); - _stack->erase(1, 3); + if (first > _stack.value(2).size()) first = len = 0; + _stack.push(new ostring(_stack.value(2).substr(first, len))); + _stack.erase(1, 3); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 57fedd9..a127bdb 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -57,8 +57,8 @@ void program::rpn_test() { int total_steps = 0; int total_steps_failed = 0; - string test_filename = _stack->value(0); - _stack->pop(); + string test_filename = _stack.value(0); + _stack.pop(); cout << endl << "rpn version is " << version << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); @@ -227,7 +227,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // parse entry and run line entry = regex_replace(entry, regex("`"), ""); if (!entry.empty()) { - program prog(&stk, hp); + program prog(stk, hp); ret = program::parse(entry, prog); if (ret == ret_ok) { // run it diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 993c631..feaefe9 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -8,8 +8,8 @@ long program::cmp_strings_on_stack_top() { // _stack should have 2 strings at level 1 and 2 // this function removes these 2 entries - long res = (long)static_cast(_stack->at(1))->value.compare(static_cast(_stack->at(0))->value); - (void)_stack->pop_front(2); + long res = (long)_stack.value(1).compare(_stack.value(0)); + (void)_stack.pop_front(2); return res; } @@ -19,14 +19,14 @@ void program::rpn_sup(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) > _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) > _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() == 1)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() == 1)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -37,14 +37,14 @@ void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) >= _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) >= _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() != -1)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() != -1)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -55,14 +55,14 @@ void program::rpn_inf(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) < _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) < _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() == -1)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() == -1)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -71,14 +71,14 @@ void program::rpn_inf(void) { /// void program::rpn_inf_eq(void) { // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) <= _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) <= _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() != 1)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() != 1)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -89,19 +89,19 @@ void program::rpn_diff(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) != _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) != _stack.value(0))); + _stack.erase(1, 2); } // complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->push_front(new number(_stack->value(1) != _stack->value(0))); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.push_front(new number(_stack.value(1) != _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() != 0)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() != 0)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -112,19 +112,19 @@ void program::rpn_eq(void) { MIN_ARGUMENTS(2); // numbers - if (_stack->type(0) == cmd_number && _stack->type(1) == cmd_number) { - _stack->push_front(new number(_stack->value(1) == _stack->value(0))); - _stack->erase(1, 2); + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + _stack.push_front(new number(_stack.value(1) == _stack.value(0))); + _stack.erase(1, 2); } // complexes - else if (_stack->type(0) == cmd_complex && _stack->type(1) == cmd_complex) { - _stack->push_front(new number(_stack->value(1) == _stack->value(0))); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + _stack.push_front(new number(_stack.value(1) == _stack.value(0))); + _stack.erase(1, 2); } // strings - else if (_stack->type(0) == cmd_string && _stack->type(1) == cmd_string) { - _stack->push_front(new number(cmp_strings_on_stack_top() == 0)); - _stack->erase(1, 2); + else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmp_strings_on_stack_top() == 0)); + _stack.erase(1, 2); } else ERR_CONTEXT(ret_bad_operand_type); } @@ -136,11 +136,11 @@ void program::rpn_test_and(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack->value(0) != 0 && _stack->value(1) != 0) - _stack->push(new number(1)); + if (_stack.value(0) != 0 && _stack.value(1) != 0) + _stack.push(new number(1)); else - _stack->push(new number(0)); - _stack->erase(1, 2); + _stack.push(new number(0)); + _stack.erase(1, 2); } /// @brief or keyword implementation @@ -150,11 +150,11 @@ void program::rpn_test_or(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack->value(0) != 0 || _stack->value(1) != 0) - _stack->push(new number(1)); + if (_stack.value(0) != 0 || _stack.value(1) != 0) + _stack.push(new number(1)); else - _stack->push(new number(0)); - _stack->erase(1, 2); + _stack.push(new number(0)); + _stack.erase(1, 2); } /// @brief xor keyword implementation @@ -164,11 +164,11 @@ void program::rpn_test_xor(void) { ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack->value(0) != 0 ^ _stack->value(1) != 0) - _stack->push(new number(1)); + if (_stack.value(0) != 0 ^ _stack.value(1) != 0) + _stack.push(new number(1)); else - _stack->push(new number(0)); - _stack->erase(1, 2); + _stack.push(new number(0)); + _stack.erase(1, 2); } /// @brief not keyword implementation @@ -177,8 +177,8 @@ void program::rpn_test_not(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->push(new number(_stack->value(0) == 0?1:0)); - _stack->erase(1, 1); + _stack.push(new number(_stack.value(0) == 0?1:0)); + _stack.erase(1, 1); } /// @brief test same implementation diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index ff984c1..cb75cec 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -20,8 +20,8 @@ void program::rpn_time() { // push it // division after push for real precision - _stack->push(new number(date)); - _stack->value(0) /= 10000000000.0; + _stack.push(new number(date)); + _stack.value(0) /= 10000000000.0; } else ERR_CONTEXT(ret_internal); } @@ -44,8 +44,8 @@ void program::rpn_date() { // push it number* num; // division after push for real precision - _stack->push(new number(date)); - _stack->value(0) /= 1000000.0; + _stack.push(new number(date)); + _stack.value(0) /= 1000000.0; } else ERR_CONTEXT(ret_internal); } @@ -64,7 +64,7 @@ void program::rpn_ticks() { if (tm != NULL) { // date in µs date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); - _stack->push(new number(date)); + _stack.push(new number(date)); } else ERR_CONTEXT(ret_internal); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 07d14a6..3bec3d6 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -3,7 +3,7 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - _stack->push_front(new number(const_pi())); + _stack.push_front(new number(const_pi())); } /// @brief d->r keyword implementation @@ -11,8 +11,8 @@ void program::rpn_pi(void) { void program::rpn_d2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) *= const_pi(); - _stack->value(0) /= 180; + _stack.value(0) *= const_pi(); + _stack.value(0) /= 180; } /// @brief r->d keyword implementation @@ -20,8 +20,8 @@ void program::rpn_d2r(void) { void program::rpn_r2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack->value(0) /= const_pi(); - _stack->value(0) *= 180; + _stack.value(0) /= const_pi(); + _stack.value(0) *= 180; } /// @brief sin keyword implementation @@ -29,10 +29,10 @@ void program::rpn_r2d(void) { void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = sin(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = sin(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = sin(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = sin(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -42,10 +42,10 @@ void program::rpn_sin(void) { void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = asin(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = asin(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = asin(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = asin(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -55,10 +55,10 @@ void program::rpn_asin(void) { void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = cos(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = cos(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = cos(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = cos(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -68,10 +68,10 @@ void program::rpn_cos(void) { void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = acos(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = acos(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = acos(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = acos(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -81,10 +81,10 @@ void program::rpn_acos(void) { void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = tan(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = tan(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = tan(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = tan(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } @@ -94,10 +94,10 @@ void program::rpn_tan(void) { void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack->type(0) == cmd_number) - _stack->value(0) = atan(_stack->value(0)); - else if (_stack->type(0) == cmd_complex) - _stack->value(0) = atan(_stack->value(0)); + if (_stack.type(0) == cmd_number) + _stack.value(0) = atan(_stack.value(0)); + else if (_stack.type(0) == cmd_complex) + _stack.value(0) = atan(_stack.value(0)); else ERR_CONTEXT(ret_bad_operand_type); } diff --git a/src/stack.hpp b/src/stack.hpp index 7e7a995..8e30ebb 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -57,9 +57,9 @@ class rpnstack : public deque { } template - auto obj(int level) { + auto& obj(int level) { // carefull: caller must ensure that level is correct - return static_cast(at(level)); + return static_cast(*at(level)); } template From 1faf101dd84160e6eebdf4f26907ab1bc82d8baa Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Mon, 21 Feb 2022 15:22:37 +0100 Subject: [PATCH 27/57] Add lexer and input classes --- CMakeLists.txt | 3 +- src/constant.h | 40 --- src/{parse.cpp => lexer.cpp} | 516 ++++++++++++----------------------- src/lexer.hpp | 73 +++++ src/main.cpp | 50 ++-- src/object.cpp | 6 - src/object.hpp | 8 +- src/program.cpp | 117 ++++++-- src/program.hpp | 48 ++-- src/rpn-general.cpp | 87 +++--- src/rpn-logs.cpp | 28 +- src/rpn-program.cpp | 32 +-- src/rpn-real.cpp | 36 +-- src/rpn-stack.cpp | 2 +- src/rpn-store.cpp | 21 +- src/rpn-string.cpp | 2 +- src/rpn-test-framework.cpp | 9 +- src/rpn-test.cpp | 12 +- src/rpn-time.cpp | 12 +- src/rpn-trig.cpp | 12 +- src/version.h | 23 +- 21 files changed, 524 insertions(+), 613 deletions(-) rename src/{parse.cpp => lexer.cpp} (54%) create mode 100644 src/lexer.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1b33886..2eca5a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,7 +55,8 @@ add_executable( ${PROJECT_SOURCE_DIR}/src/object.cpp ${PROJECT_SOURCE_DIR}/src/mpreal-out.cpp ${PROJECT_SOURCE_DIR}/src/program.cpp - ${PROJECT_SOURCE_DIR}/src/parse.cpp + ${PROJECT_SOURCE_DIR}/src/lexer.cpp + ${PROJECT_SOURCE_DIR}/src/input.cpp ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp ${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp diff --git a/src/constant.h b/src/constant.h index 6297526..8ee2408 100644 --- a/src/constant.h +++ b/src/constant.h @@ -10,7 +10,6 @@ // default mode and number of printed digits // #define DEFAULT_MODE number::std -#define MPFR_DEFAULT_FORMAT "%.xxRg" /* directly calculated from 128 bits precision ceil(128 * log10(2)) - 1 = 38 */ @@ -19,34 +18,9 @@ // MPFR related defaults // -// rounding method -#define MPFR_DEFAULT_RND MPFR_RNDN -#define MPFR_ROUND_STRINGS \ - {"nearest (even)", MPFR_RNDN}, {"toward zero", MPFR_RNDZ}, {"toward +inf", MPFR_RNDU}, {"toward -inf", MPFR_RNDD}, \ - {"away from zero", MPFR_RNDA}, {"faithful rounding", MPFR_RNDF}, { \ - "nearest (away from zero)", MPFR_RNDNA \ - } - // 128 bits significand precision #define MPFR_DEFAULT_PREC_BITS 128 -// constants -// - -// commands and entry related constants -#define MAX_COMMAND_LENGTH 24 -#define AUTOCOMPLETE_KEY '\t' -#define SHOW_STACK_SEPARATOR "> " -#define PROMPT "rpn> " -#define MULTILINE_PROMPT "> " - -// show formats -#define MPFR_FORMAT_BEG "%." -#define MPFR_FORMAT_STD "Rg" -#define MPFR_FORMAT_FIX "Rf" -#define MPFR_FORMAT_SCI "Re" -#define MPFR_FORMAT_HEX "%Ra" - // return values, used by all classes // typedef enum { @@ -70,20 +44,6 @@ typedef enum { 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", "aborted current entry", "out of memory", "bad value", \ - } - -// command types -// - -// history -#define HISTORY_FILE ".rpn_history" -#define HISTORY_FILE_MAX_LINES (100) - // base min and max #define BASE_MIN 2 #define BASE_MAX 62 diff --git a/src/parse.cpp b/src/lexer.cpp similarity index 54% rename from src/parse.cpp rename to src/lexer.cpp index 60b9294..bde5fa1 100644 --- a/src/parse.cpp +++ b/src/lexer.cpp @@ -1,299 +1,10 @@ #include +using namespace std; -#include "program.hpp" +#include "lexer.hpp" -/// @brief completion callback as asked by linenoise-ng -/// this is called by linenoise-ng whenever the user enters TAB -/// -/// @param text the text after wich the user entered TAB -/// @param lc the completion object to add strings with linenoiseAddCompletion() -/// -void program::entry_completion_generator(const char* text, linenoiseCompletions* lc) { - int i = 0; - int text_len = strnlen(text, 6); - - // propose all keywords - if (text_len == 0) { - while (program::s_keywords[i].type != cmd_max) { - if (program::s_keywords[i].fn != NULL) - // add all keywords - linenoiseAddCompletion(lc, program::s_keywords[i].name); - i++; - } - } - // propose keywords matching to text begining - else { - while (program::s_keywords[i].type != cmd_max) { - if (program::s_keywords[i].fn != NULL) { - // compare list entry with text, return if match - if (strncmp(program::s_keywords[i].name, text, text_len) == 0) - linenoiseAddCompletion(lc, program::s_keywords[i].name); - } - i++; - } - } -} - -/// @brief interactive entry and decoding -/// -/// @param prog the program to add entered objects -/// @return ret_value see this type -/// -ret_value program::entry(program& prog) { - string entry_str; - char* entry; - int entry_len; - int total_entry_len; - ret_value ret = ret_max; - bool multiline = false; - - // linenoise for entry - linenoiseSetCompletionCallback(entry_completion_generator); - - while (ret == ret_max) { - // get user entry - if (multiline) - entry = linenoise(MULTILINE_PROMPT, &entry_len); - else - entry = linenoise(PROMPT, &entry_len); - - // Ctrl-C - if (linenoiseKeyType() == 1) { - if (entry_len > 0 || multiline) - ret = ret_abort_current_entry; - else - ret = ret_good_bye; - } else if (linenoiseKeyType() == 3) { - multiline = true; - if (entry != NULL) entry_str += entry; - entry_str += " "; - } else { - if (entry != NULL) { - entry_str += entry; - - // parse it - ret = parse(entry_str, prog); - - // keep history - if (entry[0] != 0) (void)linenoiseHistoryAdd(entry_str.c_str()); - } else - ret = ret_internal; - } - - free(entry); - } - - return ret; -} - -struct SynElement { - cmd_type_t type; - string value; - mpreal re; - mpreal im; - int reBase; - int imBase; - program_fn_t fn; - bool autoEval; -}; - -struct SynError { - size_t indx; - string err; -}; - -struct ReservedWord { - cmd_type_t type; - program_fn_t fn; -}; - -static map _keywordsMap; - -static void trim(string& s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); - s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); -} - -static bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, - vector& elements) { - // here we are sure that entry[0] is at least '"' - for (size_t i = idx + 1; i < entry.size(); i++) { - if (entry[i] == '"') { - if (entry[i] - 1 != '\\') { - elements.push_back({cmd_string, .value = entry.substr(idx + 1, i - idx - 1)}); - nextIdx = i + 1; - return true; - } - } - } - elements.push_back({cmd_string, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); - nextIdx = entry.size(); - return true; -} - -static bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, - vector& elements) { - // here we are sure that entry[0] is at least '\'' - for (size_t i = idx + 1; i < entry.size(); i++) { - if (entry[i] == '\'') { - elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, i - idx - 1), .autoEval = false}); - nextIdx = i + 1; - return true; - } - } - elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); - nextIdx = entry.size(); - return true; -} - -static bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, - vector& elements) { - // here we are sure that entry is at least "<<" - // find last ">>" or "»" - int countNested = 0; - for (size_t i = idx + 2; i < entry.size() - 1; i++) { - if ((entry[i] == '<' && entry[i + 1] == '<') || (entry.substr(i, 2) == "«")) - countNested++; - else if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { - if (countNested == 0) { - string prg = entry.substr(idx + 2, i - idx - 2); - trim(prg); - elements.push_back({cmd_program, .value = prg}); - nextIdx = i + 2; - return true; - } else - countNested--; - } - } - string prg = entry.substr(idx + 2, entry.size() - idx - 2); - trim(prg); - elements.push_back({cmd_program, .value = prg}); - nextIdx = entry.size(); - return true; -} - -static int getBase(string& entry, int idxStart, bool& positive) { - regex baseRegex("([+-])?((0[xX])|([0-9][0-9]?[bB]))"); - smatch match; - if (regex_search(entry, match, baseRegex) && match.size() >= 5) { - string sign = match[1].str(); - string base = match[2].str(); - // sign out, permits expressions like -0xAB3F - positive = sign.size() > 0 && sign[0] == '-' ? false : true; - // base - entry = entry.substr(base.size() + sign.size()); - if (base[1] == 'X' || base[1] == 'x') return 16; - if (base.size() > 0) { - int b = stoi(base.substr(0, base.size() - 1)); - if (b == 0) b = 2; // admit "0b" as binary suffix - return b; - } - } - return 10; -} - -static bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal& r, char delim = ' ') { - stringstream ss; - int idxNumber = 0; - string token; - bool positive = true; - - ss.str(entry.substr(idx)); - if (getline(ss, token, delim)) { - nextIdx = token.size() + idx + 1; - base = getBase(token, idx, positive); - if (base < BASE_MIN || base > BASE_MAX) return false; - trim(token); - if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { - if (!positive) r = -r; - return true; - } else - return false; - } - nextIdx = token.size() + idx + 1; - return false; -} - -static bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, - vector& elements) { - mpreal r; - int base = 10; - if (getNumberAt(entry, idx, nextIdx, base, r)) { - elements.push_back({cmd_number, .re = r, .reBase = base}); - return true; - } else { - errors.push_back({entry.size(), "unterminated number"}); - return false; - } -} - -static bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& errors, - vector& elements) { - mpreal re, im; - int reBase, imBase = 10; - if (idx + 1 == entry.size()) { - elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); - return true; // complex format error, return a symbol - } - if (!getNumberAt(entry, idx + 1, nextIdx, reBase, re, ',')) { - elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); - return true; // complex format error, return a symbol - } - - size_t i = nextIdx; - //while (i < entry.size() && entry[i] != ',') i++; - if (i >= entry.size()) { - elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); - return true; // complex format error, return a symbol - } - - if (!getNumberAt(entry, i, nextIdx, imBase, im, ')')) { - elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); - return true; // complex format error, return a symbol - } - elements.push_back({cmd_complex, .re = re, .im = im, .reBase = reBase, .imBase = imBase}); - nextIdx++; - return true; -} - -static bool parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, - map& keywords) { - stringstream ss(entry.substr(idx)); - string token; - ss >> token; - - auto resa = keywords.find(token); - if (resa != keywords.end()) { - elements.push_back({resa->second.type, .value = token, .fn = resa->second.fn}); - nextIdx = token.size() + idx; - return true; - } - return false; -} - -static bool parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements) { - stringstream ss(entry.substr(idx)); - string token; - ss >> token; - elements.push_back({cmd_symbol, .value = token, .autoEval = true}); - nextIdx = token.size() + idx; - return true; -} - -/// @brief lexical analysis of an entry string -/// -/// @param entry the entry string -/// @param elements syntax elements vector -/// @param errors errors vector -/// @param keywords reserved keywords -/// @return false=errors, the lexer must stop -/// -static bool lexer(string& entry, vector& elements, vector& errors, - map& keywords) { +bool Lexer::lexer(string& entry, map& keywords, vector& elements, + vector& errors) { size_t jump; for (size_t i = 0; i < entry.size(); i++) { if (isspace(entry[i])) continue; @@ -332,60 +43,177 @@ static bool lexer(string& entry, vector& elements, vector& return true; } -static bool progFromElements(vector& elements, program& prog) { - // TODO control elements creation - for (SynElement& element : elements) { - switch (element.type) { - case cmd_number: - prog.push_back(new number(element.re, element.reBase)); - break; - case cmd_complex: - prog.push_back(new ocomplex(element.re, element.im, element.reBase, element.imBase)); - break; - case cmd_string: - prog.push_back(new ostring(element.value)); - break; - case cmd_symbol: - prog.push_back(new symbol(element.value, element.autoEval)); - break; - case cmd_program: - prog.push_back(new oprogram(element.value)); - break; - case cmd_keyword: - prog.push_back(new keyword(element.fn, element.value)); - break; - case cmd_branch: - prog.push_back(new branch((branch_fn_t)element.fn, element.value)); - break; - default: - return false; +void Lexer::trim(string& s) { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch) { return !std::isspace(ch); })); + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); +} + +bool Lexer::parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry[0] is at least '"' + for (size_t i = idx + 1; i < entry.size(); i++) { + if (entry[i] == '"') { + if (entry[i] - 1 != '\\') { + elements.push_back({cmd_string, .value = entry.substr(idx + 1, i - idx - 1)}); + nextIdx = i + 1; + return true; + } } } + elements.push_back({cmd_string, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); + nextIdx = entry.size(); return true; } -/// @brief parse an entry string: cut it into objects chunks and add them to a program -/// -/// @param entry the entry string -/// @param prog the program to be filled -/// @return ret_value see this type -/// -ret_value program::parse(string& entry, program& prog) { - vector elements; - vector errors; - ret_value ret = ret_ok; - - // prepare map for finding reserved keywords - if (_keywordsMap.size() == 0) - for (int i = 0; s_keywords[i].type != cmd_max; i++) - _keywordsMap[s_keywords[i].name] = {s_keywords[i].type, s_keywords[i].fn}; - - // separate the entry string - if (lexer(entry, elements, errors, _keywordsMap)) { - // make objects from parsed elements - if (!progFromElements(elements, prog)) prog.show_error(ret_unknown_err, "error creating program from entry"); - } else - for (SynError& err : errors) prog.show_syntax_error(err.err.c_str()); - - return ret; +bool Lexer::parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry[0] is at least '\'' + for (size_t i = idx + 1; i < entry.size(); i++) { + if (entry[i] == '\'') { + elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, i - idx - 1), .autoEval = false}); + nextIdx = i + 1; + return true; + } + } + elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); + nextIdx = entry.size(); + return true; +} + +bool Lexer::parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + // here we are sure that entry is at least "<<" + // find last ">>" or "»" + int countNested = 0; + for (size_t i = idx + 2; i < entry.size() - 1; i++) { + if ((entry[i] == '<' && entry[i + 1] == '<') || (entry.substr(i, 2) == "«")) + countNested++; + else if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { + if (countNested == 0) { + string prg = entry.substr(idx + 2, i - idx - 2); + trim(prg); + elements.push_back({cmd_program, .value = prg}); + nextIdx = i + 2; + return true; + } else + countNested--; + } + } + string prg = entry.substr(idx + 2, entry.size() - idx - 2); + trim(prg); + elements.push_back({cmd_program, .value = prg}); + nextIdx = entry.size(); + return true; +} + +int Lexer::getBaseAt(string& entry, int idxStart, bool& positive) { + regex baseRegex("([+-])?((0[xX])|([0-9][0-9]?[bB]))"); + smatch match; + if (regex_search(entry, match, baseRegex) && match.size() >= 5) { + string sign = match[1].str(); + string base = match[2].str(); + // sign out, permits expressions like -0xAB3F + positive = sign.size() > 0 && sign[0] == '-' ? false : true; + // base + entry = entry.substr(base.size() + sign.size()); + if (base[1] == 'X' || base[1] == 'x') return 16; + if (base.size() > 0) { + int b = stoi(base.substr(0, base.size() - 1)); + if (b == 0) b = 2; // admit "0b" as binary suffix + return b; + } + } + return 10; +} + +bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal& r, char delim) { + stringstream ss; + int idxNumber = 0; + string token; + bool positive = true; + + ss.str(entry.substr(idx)); + if (getline(ss, token, delim)) { + nextIdx = token.size() + idx + 1; + base = getBaseAt(token, idx, positive); + if (base < BASE_MIN || base > BASE_MAX) return false; + trim(token); + if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { + if (!positive) r = -r; + return true; + } else + return false; + } + nextIdx = token.size() + idx + 1; + return false; +} + +bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + mpreal r; + int base = 10; + if (getNumberAt(entry, idx, nextIdx, base, r)) { + elements.push_back({cmd_number, .re = r, .reBase = base}); + return true; + } else { + errors.push_back({entry.size(), "unterminated number"}); + return false; + } +} + +bool Lexer::parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements) { + mpreal re, im; + int reBase, imBase = 10; + if (idx + 1 == entry.size()) { + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol + } + if (!getNumberAt(entry, idx + 1, nextIdx, reBase, re, ',')) { + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol + } + + size_t i = nextIdx; + // while (i < entry.size() && entry[i] != ',') i++; + if (i >= entry.size()) { + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol + } + + if (!getNumberAt(entry, i, nextIdx, imBase, im, ')')) { + elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + nextIdx = entry.size(); + return true; // complex format error, return a symbol + } + elements.push_back({cmd_complex, .re = re, .im = im, .reBase = reBase, .imBase = imBase}); + nextIdx++; + return true; +} + +bool Lexer::parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, + map& keywords) { + stringstream ss(entry.substr(idx)); + string token; + ss >> token; + + auto resa = keywords.find(token); + if (resa != keywords.end()) { + elements.push_back({resa->second.type, .value = token, .fn = resa->second.fn}); + nextIdx = token.size() + idx; + return true; + } + return false; +} + +bool Lexer::parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements) { + stringstream ss(entry.substr(idx)); + string token; + ss >> token; + elements.push_back({cmd_symbol, .value = token, .autoEval = true}); + nextIdx = token.size() + idx; + return true; } diff --git a/src/lexer.hpp b/src/lexer.hpp new file mode 100644 index 0000000..4491910 --- /dev/null +++ b/src/lexer.hpp @@ -0,0 +1,73 @@ +#ifndef _PARSER_HPP_ +#define _PARSER_HPP_ + +#include +#include +using namespace std; + +#define MPFR_USE_NO_MACRO +#include +#include +using namespace mpfr; + +#include "constant.h" +#include "object.hpp" + +class Lexer { + public: + // a structure to describe a syntaxical element and its value + struct SynElement { + cmd_type_t type; + string value; + mpreal re; + mpreal im; + int reBase; + int imBase; + program_fn_t fn; + bool autoEval; + }; + + struct SynError { + size_t indx; + string err; + }; + + struct ReservedWord { + cmd_type_t type; + program_fn_t fn; + }; + + Lexer() {} + + /// @brief lexical analysis of an entry string + /// + /// @param[in] entry the entry to lex + /// @param[out] elements syntax elements vector + /// @param[out] errors errors vector + /// @param[in] keywords reserved keywords + /// @return false=errors, the lexer must stop + /// + bool lexer(string& entry, map& keywords, vector& elements, + vector& errors); + + private: + bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements); + bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements); + bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements); + bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements); + bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& errors, + vector& elements); + bool parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, + map& keywords); + bool parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements); + + void trim(string& s); + int getBaseAt(string& entry, int idxStart, bool& positive); + bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal& r, char delim = ' '); +}; + +#endif diff --git a/src/main.cpp b/src/main.cpp index 9d881b3..f92355b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -7,19 +6,20 @@ using namespace std; // internal includes +#include "input.hpp" #include "program.hpp" static heap _global_heap; static rpnstack _global_stack; -static program* _prog_to_interrupt = NULL; +static program* _prog_to_interrupt = nullptr; /// @brief actions to be done at rpn exit /// static void exit_interactive_rpn() { struct passwd* pw = getpwuid(getuid()); - if (pw != NULL) { + if (pw != nullptr) { stringstream history_path; - history_path << pw->pw_dir << '/' << HISTORY_FILE; + history_path << pw->pw_dir << "/.rpn_history"; // trunc current history ofstream history(history_path.str(), ios_base::out | ios_base::trunc); @@ -37,12 +37,12 @@ static void exit_interactive_rpn() { /// static void init_interactive_rpn() { struct passwd* pw = getpwuid(getuid()); - if (pw != NULL) { + if (pw != nullptr) { stringstream history_path; - history_path << pw->pw_dir << '/' << HISTORY_FILE; + history_path << pw->pw_dir << "/.rpn_history"; // don't care about errors - linenoiseHistorySetMaxLen(HISTORY_FILE_MAX_LINES); + linenoiseHistorySetMaxLen(100); linenoiseHistoryLoad(history_path.str().c_str()); } } @@ -54,9 +54,9 @@ static void init_interactive_rpn() { /// @param context see POSIX sigaction /// static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { - if (_prog_to_interrupt != NULL) { + if (_prog_to_interrupt != nullptr) { _prog_to_interrupt->stop(); - _prog_to_interrupt = NULL; + _prog_to_interrupt = nullptr; } exit_interactive_rpn(); @@ -71,12 +71,12 @@ static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { static void segv_handler(int sig, siginfo_t* siginfo, void* context) { cerr << "Internal error" << endl; _prog_to_interrupt->stop(); - _prog_to_interrupt = NULL; + _prog_to_interrupt = nullptr; } /// @brief setup signals handlers to stop with honours /// -/// @param prog the prog to catch the signals to, must be checked not NULL by user +/// @param prog the prog to catch the signals to, must be checked not nullptr by user /// static void catch_signals(program* prog) { struct sigaction act = {0}; @@ -85,12 +85,12 @@ static void catch_signals(program* prog) { act.sa_sigaction = &ctrlc_handler; act.sa_flags = SA_SIGINFO; - if (sigaction(SIGINT, &act, NULL) < 0) + if (sigaction(SIGINT, &act, nullptr) < 0) cerr << "Warning, Ctrl-C cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; act.sa_sigaction = &segv_handler; act.sa_flags = SA_SIGINFO; - if (sigaction(SIGSEGV, &act, NULL) < 0) + if (sigaction(SIGSEGV, &act, nullptr) < 0) cerr << "Warning, SIGSEGV cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; } @@ -116,30 +116,28 @@ int main(int argc, char* argv[]) { while (go_on) { // make program from interactive entry program prog(_global_stack, _global_heap); - switch (program::entry(prog)) { - case ret_good_bye: - go_on = false; - break; - case ret_abort_current_entry: - break; - default: + string entry; + switch (Input(entry, program::getAutocompletionWords()).status) { + case Input::ok: // user could stop prog with CtrlC catch_signals(&prog); - // run it - if (prog.run() == ret_good_bye) + if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye) go_on = false; else program::show_stack(_global_stack); break; + case Input::ctrlc: + go_on = false; + break; + default: + break; } } // manage history and exit exit_interactive_rpn(); - } - // run with cmd line arguments - else { + } else { // run with cmd line arguments program prog(_global_stack, _global_heap); string entry; int i; @@ -151,7 +149,7 @@ int main(int argc, char* argv[]) { } // make program - ret = program::parse(entry, prog); + ret = prog.parse(entry); if (ret == ret_ok) { // user could stop prog with CtrlC catch_signals(&prog); diff --git a/src/object.cpp b/src/object.cpp index 265636d..e9af391 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1,10 +1,4 @@ -#include -#include -using namespace std; - #include "constant.h" -#define MPFR_USE_NO_MACRO -#include #include "object.hpp" // number statics diff --git a/src/object.hpp b/src/object.hpp index dfd0d7c..6b83186 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,13 +1,14 @@ #ifndef OBJECT_HPP #define OBJECT_HPP +#define MPFR_USE_NO_MACRO +#include #include using namespace mpfr; -#include -#include -#include #include +#include +#include using namespace std; #include "mpreal-out.hpp" @@ -127,7 +128,6 @@ struct ocomplex : object { struct ostring : object { ostring() : object(cmd_string) {} ostring(const string& value_) : object(cmd_string), value(value_) {} - ostring(const char* value_) : object(cmd_string) { value = string(value_); } virtual object* clone() { return new ostring(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } diff --git a/src/program.cpp b/src/program.cpp index 97a8f5c..8ec91b0 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,12 +1,9 @@ #include "program.hpp" -//< return type strings -const char* program::s_ret_value_string[ret_max] = RET_VALUE_STRINGS; - //< language reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef) -program::keyword_t program::s_keywords[] = { +vector program::_keywords{ // GENERAL - {cmd_undef, "", NULL, "\nGENERAL"}, + {cmd_undef, "", nullptr, "\nGENERAL"}, {cmd_keyword, "nop", &program::rpn_nop, "no operation"}, {cmd_keyword, "help", &program::rpn_help, "this help message"}, {cmd_keyword, "h", &program::rpn_help, ""}, @@ -20,7 +17,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "history", &program::rpn_history, "see commands history"}, // USUAL OPERATIONS ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, + {cmd_undef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, {cmd_keyword, "+", &program::rpn_plus, "addition"}, {cmd_keyword, "-", &program::rpn_minus, "substraction"}, {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, @@ -36,7 +33,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, // OPERATIONS ON REALS - {cmd_undef, "", NULL, "\nOPERATIONS ON REALS"}, + {cmd_undef, "", nullptr, "\nOPERATIONS ON REALS"}, {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, @@ -51,7 +48,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, // OPERATIONS ON COMPLEXES - {cmd_undef, "", NULL, "\nOPERATIONS ON COMPLEXES"}, + {cmd_undef, "", nullptr, "\nOPERATIONS ON COMPLEXES"}, {cmd_keyword, "re", &program::rpn_re, "complex real part"}, {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, @@ -62,7 +59,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, // MODE - {cmd_undef, "", NULL, "\nMODE"}, + {cmd_undef, "", nullptr, "\nMODE"}, {cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"}, {cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"}, {cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"}, @@ -79,7 +76,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"}, // TESTS - {cmd_undef, "", NULL, "\nTEST"}, + {cmd_undef, "", nullptr, "\nTEST"}, {cmd_keyword, ">", &program::rpn_sup, "binary operator >"}, {cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="}, {cmd_keyword, "<", &program::rpn_inf, "binary operator <"}, @@ -93,7 +90,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"}, // STACK - {cmd_undef, "", NULL, "\nSTACK"}, + {cmd_undef, "", nullptr, "\nSTACK"}, {cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"}, {cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"}, {cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"}, @@ -111,7 +108,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, // STRING - {cmd_undef, "", NULL, "\nSTRING"}, + {cmd_undef, "", nullptr, "\nSTRING"}, {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, @@ -122,7 +119,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, // BRANCH - {cmd_undef, "", NULL, "\nBRANCH"}, + {cmd_undef, "", nullptr, "\nBRANCH"}, {cmd_branch, "if", (program_fn_t)&program::rpn_if, "if then else " "end"}, @@ -144,7 +141,7 @@ program::keyword_t program::s_keywords[] = { {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, // STORE - {cmd_undef, "", NULL, "\nSTORE"}, + {cmd_undef, "", nullptr, "\nSTORE"}, {cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"}, {cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"}, {cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"}, @@ -158,14 +155,14 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, // PROGRAM - {cmd_undef, "", NULL, "\nPROGRAM"}, + {cmd_undef, "", nullptr, "\nPROGRAM"}, {cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, {cmd_branch, "->", (program_fn_t)&program::rpn_inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> " ">>"}, // TRIG ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nTRIG ON REALS AND COMPLEXES"}, + {cmd_undef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"}, {cmd_keyword, "pi", &program::rpn_pi, "pi constant"}, {cmd_keyword, "sin", &program::rpn_sin, "sinus"}, {cmd_keyword, "asin", &program::rpn_asin, "arg sinus"}, @@ -177,7 +174,7 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES - {cmd_undef, "", NULL, "\nLOGS ON REALS AND COMPLEXES"}, + {cmd_undef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"}, {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, {cmd_keyword, "log", &program::rpn_ln, ""}, @@ -198,15 +195,25 @@ program::keyword_t program::s_keywords[] = { {cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"}, // TIME AND DATE - {cmd_undef, "", NULL, "\nTIME AND DATE"}, + {cmd_undef, "", nullptr, "\nTIME AND DATE"}, {cmd_keyword, "time", &program::rpn_time, "time in local format"}, {cmd_keyword, "date", &program::rpn_date, "date in local format"}, {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, - - // end - {cmd_max, "", NULL, ""}, }; +/// keywords map for lexer +map program::_keywordsMap; + +/// autocompletion vector for linenoise autocompletion +vector program::_autocompletionWords; + +vector& program::getAutocompletionWords() { + if (_autocompletionWords.empty()) + for (auto& kw : _keywords) + if (!kw.name.empty()) _autocompletionWords.push_back(kw.name); + return _autocompletionWords; +} + /// @brief run a program on a stack and a heap /// /// @return ret_value see this type @@ -302,7 +309,7 @@ ret_value program::run() { _local_heap.clear(); if (interrupt_now) { - fprintf(stderr, "\nInterrupted\n"); + cerr << endl << "Interrupted" << endl; interrupt_now = false; } @@ -561,15 +568,75 @@ ret_value program::preprocess(void) { return ret_ok; } +/// @brief parse an entry string: cut it into objects chunks and add them to a program +/// +/// @param entry the entry string +/// @param prog the program to be filled +/// @return ret_value see this type +/// +ret_value program::parse(string& entry) { + vector elements; + vector errors; + ret_value ret = ret_ok; + + // prepare map for finding reserved keywords + if (_keywordsMap.empty()) + for (auto& kw : _keywords) + if (!kw.name.empty()) _keywordsMap[kw.name] = {kw.type, kw.fn}; + + // separate the entry string + if (lexer(entry, _keywordsMap, elements, errors)) { + // make objects from parsed elements + for (Lexer::SynElement& element : elements) { + switch (element.type) { + case cmd_number: + push_back(new number(element.re, element.reBase)); + break; + case cmd_complex: + push_back(new ocomplex(element.re, element.im, element.reBase, element.imBase)); + break; + case cmd_string: + push_back(new ostring(element.value)); + break; + case cmd_symbol: + push_back(new symbol(element.value, element.autoEval)); + break; + case cmd_program: + push_back(new oprogram(element.value)); + break; + case cmd_keyword: + push_back(new keyword(element.fn, element.value)); + break; + case cmd_branch: + push_back(new branch((branch_fn_t)element.fn, element.value)); + break; + default: + show_error(ret_unknown_err, "error creating program from entry"); + } + } + } else + for (SynError& err : errors) show_syntax_error(err.err.c_str()); + + return ret; +} + /// @brief show the last error set /// /// @return ret_value see this type /// ret_value program::show_error() { ret_value ret; - + // clang-format off + vector errorStrings {"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", "aborted current entry", "out of memory", + "bad value"}; + // clang-format on // show last recorded error - cerr << _err_context << ": error " << _err << ": " << s_ret_value_string[_err] << endl; + if ((size_t)_err < errorStrings.size()) + cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl; + else + cerr << _err_context << " (unknown error code)" << endl; switch (_err) { case ret_internal: case ret_deadly: @@ -637,7 +704,7 @@ void program::show_stack(rpnstack& st, bool show_separator) { cout << st[0] << endl; else for (int i = st.size() - 1; i >= 0; i--) { - if (show_separator) cout << i + 1 << SHOW_STACK_SEPARATOR; + if (show_separator) cout << i + 1 << "> "; cout << st[i] << endl; } } diff --git a/src/program.hpp b/src/program.hpp index a22939c..1c98f09 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -1,33 +1,21 @@ #ifndef PROGRAM_HPP #define PROGRAM_HPP -// std c -#include -#include -#include -#include - // std c++ #include -#include -#include -#include -#include #include using namespace std; -// external libs #define MPFR_USE_NO_MACRO #include - -#include "linenoise.h" +#include +using namespace mpfr; // internal includes #include "constant.h" -#include "escape.h" #include "object.hpp" #include "stack.hpp" -#include "version.h" +#include "lexer.hpp" //< convinient structure to preprocess a program struct if_layout_t { @@ -42,7 +30,7 @@ struct if_layout_t { }; //< program class: the class containing a string parser, all the programs keywords, a stack for running the program -class program : public deque { +class program : public deque, public Lexer { public: program(rpnstack& stk, heap& hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { interrupt_now = false; @@ -53,9 +41,7 @@ class program : public deque { } // parser - static ret_value parse(string& entry, program& prog); - static ret_value entry(program& prog); - static void entry_completion_generator(const char* text, linenoiseCompletions* lc); + ret_value parse(string& entry); static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type); // running @@ -74,6 +60,8 @@ class program : public deque { static void apply_default(); + static vector& getAutocompletionWords(); + private: bool interrupt_now; @@ -96,16 +84,16 @@ class program : public deque { int stack_size() { return _stack.size(); } private: - static const char* s_ret_value_string[ret_max]; - // keywords struct keyword_t { cmd_type_t type; - char name[MAX_COMMAND_LENGTH]; + string name; program_fn_t fn; string comment; }; - static keyword_t s_keywords[]; + static vector _keywords; + static map _keywordsMap; + static vector _autocompletionWords; // keywords implementation //// @@ -285,26 +273,22 @@ class program : public deque { // convenience macros for rpn_xx function // carefull : some of these macros modify program flow -#define ERR_CONTEXT(err) do { _err = (err); _err_context = __FUNCTION__; } while (0) +#define setErrorContext(err) do { _err = (err); _err_context = __FUNCTION__; } while (0) #define MIN_ARGUMENTS(num) do { \ - if (stack_size() < (num)) { ERR_CONTEXT(ret_missing_operand); return; } \ + if (stack_size() < (num)) { setErrorContext(ret_missing_operand); return; } \ } while (0) #define MIN_ARGUMENTS_RET(num, ret) do { \ - if (stack_size() < (num)) { ERR_CONTEXT(ret_missing_operand); return (ret); } \ + if (stack_size() < (num)) { setErrorContext(ret_missing_operand); return (ret); } \ } while (0) #define ARG_MUST_BE_OF_TYPE(num, type) do { \ - if (_stack.at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return; } \ + if (_stack.at(num)->_type != (type)) { setErrorContext(ret_bad_operand_type); return; } \ } while (0) #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { \ - if (_stack.at(num)->_type != (type)) { ERR_CONTEXT(ret_bad_operand_type); return (ret); } \ + if (_stack.at(num)->_type != (type)) { setErrorContext(ret_bad_operand_type); return (ret); } \ } while (0) -#define IS_ARG_TYPE(num, type) (_stack.at(num)->_type == (type)) - -#define CHECK_MPFR(op) do { (void)(op); } while (0) - #endif diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 06b113e..c19a934 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -1,4 +1,34 @@ +#include + +#include "escape.h" +#include "linenoise.h" #include "program.hpp" +#include "version.h" + +// description +#define XSTR(a) STR(a) +#define STR(a) #a +static const string _description{ + ATTR_BOLD "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF + "otation language\n\n" + "using " ATTR_BOLD "GMP" ATTR_OFF " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( + __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING + " under GNU LGPL\n" + "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION + " under BSD\n"}; + +// syntax +static const string _syntax{ATTR_BOLD "Syntax" ATTR_OFF + ": rpn [command]\n" + "with optional command = list of commands"}; + +static const map _mpfr_round{{"nearest (even)", MPFR_RNDN}, + {"toward zero", MPFR_RNDZ}, + {"toward +inf", MPFR_RNDU}, + {"toward -inf", MPFR_RNDD}, + {"away from zero", MPFR_RNDA}, + {"faithful rounding", MPFR_RNDF}, + {"nearest (away from zero)", MPFR_RNDNA}}; /// @brief nop keyword implementation /// @@ -8,33 +38,31 @@ void program::rpn_nop() { /// @brief quit keyword implementation /// -void program::rpn_good_bye() { ERR_CONTEXT(ret_good_bye); } +void program::rpn_good_bye() { setErrorContext(ret_good_bye); } /// @brief nop keyword implementation /// the result is written on stdout /// void program::rpn_help() { // software name - cout << endl << ATTR_BOLD << uname << ATTR_OFF << endl; + cout << endl << ATTR_BOLD << RPN_UNAME << ATTR_OFF << endl; - // description - cout << description << endl << endl; + // _description + cout << _description << endl << endl; - // syntax - cout << syntax << endl; + // _syntax + cout << _syntax << endl; // keywords unsigned int i = 0; - while (s_keywords[i].type != cmd_max) { - if (s_keywords[i].comment.size() != 0) { + for (auto& kw : _keywords) + if (!kw.comment.empty()) { // titles in bold - if (s_keywords[i].type == cmd_undef) cout << ATTR_BOLD; + if (kw.type == cmd_undef) cout << ATTR_BOLD; // show title or keyword + comment - cout << s_keywords[i].name << '\t' << s_keywords[i].comment << endl; - if (s_keywords[i].type == cmd_undef) cout << ATTR_OFF; + cout << kw.name << '\t' << kw.comment << endl; + if (kw.type == cmd_undef) cout << ATTR_OFF; } - i++; - } cout << endl; // show mode @@ -57,14 +85,9 @@ void program::rpn_help() { // bits precision, decimal digits and rounding mode cout << " with " << number::s_digits << " digits after the decimal point" << endl; cout << "Current floating point precision is " << (int)mpreal::get_default_prec() << " bits" << endl; - struct RndStrings { - string name; - mp_rnd_t rnd; - }; - vector rndStrings{MPFR_ROUND_STRINGS}; - for (RndStrings r : rndStrings) - if (r.rnd == mpreal::get_default_rnd()) { - cout << "Current rounding mode is " << r.name << endl; + for (auto& rn : _mpfr_round) + if (rn.second == mpreal::get_default_rnd()) { + cout << "Current rounding mode is '" << rn.first << '\'' << endl; break; } cout << endl << endl; @@ -103,7 +126,7 @@ void program::rpn_std() { number::s_digits = (int)digits; _stack.pop(); } else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); } /// @brief fix keyword implementation @@ -120,7 +143,7 @@ void program::rpn_fix() { number::s_digits = (int)digits; _stack.pop(); } else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); } /// @brief sci keyword implementation @@ -137,16 +160,16 @@ void program::rpn_sci() { number::s_digits = (int)digits; _stack.pop(); } else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); } -/// @brief version keyword implementation +/// @brief _version keyword implementation /// -void program::rpn_version() { _stack.push_front(new ostring(version)); } +void program::rpn_version() { _stack.push_front(new ostring(RPN_VERSION)); } -/// @brief uname keyword implementation +/// @brief _uname keyword implementation /// -void program::rpn_uname() { _stack.push_front(new ostring(uname)); } +void program::rpn_uname() { _stack.push_front(new ostring(RPN_UNAME)); } /// @brief history keyword implementation /// @@ -154,7 +177,7 @@ void program::rpn_history() { // see command history on stdout int index = 0; char* line = linenoiseHistoryLine(index); - while (line != NULL) { + while (line != nullptr) { cout << line << endl; free(line); line = linenoiseHistoryLine(++index); @@ -191,7 +214,7 @@ void program::rpn_precision() { } _stack.pop(); } else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); } /// @brief round keyword implementation @@ -200,12 +223,12 @@ void program::rpn_round() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - map matchRound{MPFR_ROUND_STRINGS}; + map matchRound{_mpfr_round}; auto found = matchRound.find(_stack.value(0)); if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); _stack.pop(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 4b6582e..0a45f92 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -13,7 +13,7 @@ void program::rpn_log10() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = log10(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief alog10 keyword implementation @@ -25,7 +25,7 @@ void program::rpn_alog10() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief log2 keyword implementation @@ -37,7 +37,7 @@ void program::rpn_log2() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = log(_stack.value(0)) / const_log2(); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief alog2 keyword implementation @@ -49,7 +49,7 @@ void program::rpn_alog2() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = exp(const_log2() * _stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief ln keyword implementation @@ -61,7 +61,7 @@ void program::rpn_ln() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = log(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief exp keyword implementation @@ -73,7 +73,7 @@ void program::rpn_exp() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = exp(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief expm keyword implementation @@ -85,7 +85,7 @@ void program::rpn_expm() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = exp(_stack.value(0)) - mpreal(1); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief lnp1 keyword implementation @@ -97,7 +97,7 @@ void program::rpn_lnp1() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = log(_stack.value(0) + mpreal(1)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief sinh keyword implementation @@ -109,7 +109,7 @@ void program::rpn_sinh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = sinh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief asinh keyword implementation @@ -121,7 +121,7 @@ void program::rpn_asinh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = asinh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief cosh keyword implementation @@ -133,7 +133,7 @@ void program::rpn_cosh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = cosh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief acosh keyword implementation @@ -145,7 +145,7 @@ void program::rpn_acosh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = acosh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief tanh keyword implementation @@ -157,7 +157,7 @@ void program::rpn_tanh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = tanh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief atanh keyword implementation @@ -169,5 +169,5 @@ void program::rpn_atanh() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = atanh(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 8dbf217..f3196a4 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -14,7 +14,7 @@ bool program::find_variable(string& variable, object*& obj) { if (_local_heap.get(variable, obj)) found = true; else { - while (parent != NULL) { + while (parent != nullptr) { if (parent->_local_heap.get(variable, obj)) { found = true; break; @@ -36,7 +36,7 @@ void program::rpn_eval(void) { string prog_text; MIN_ARGUMENTS(1); - if (IS_ARG_TYPE(0, cmd_symbol)) { + if (_stack.type(0) == cmd_symbol) { // recall a variable object* obj; string variable(_stack.value(0)); @@ -53,21 +53,21 @@ void program::rpn_eval(void) { _stack.push_front(obj); } } else - ERR_CONTEXT(ret_unknown_variable); - } else if (IS_ARG_TYPE(0, cmd_program)) { + setErrorContext(ret_unknown_variable); + } else if (_stack.type(0) == cmd_program) { // eval a program prog_text = _stack.value(0); _stack.pop(); run_prog = true; } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); // run prog if any if (run_prog) { program prog(_stack, _heap, this); // make program from entry - if (program::parse(prog_text, prog) == ret_ok) { + if (prog.parse(prog_text) == ret_ok) { // run it prog.run(); } @@ -82,7 +82,7 @@ int program::rpn_inprog(branch& myobj) { bool prog_found = false; if (myobj.arg1 == -1) { - ERR_CONTEXT(ret_unknown_err); + setErrorContext(ret_unknown_err); return -1; } @@ -92,15 +92,15 @@ int program::rpn_inprog(branch& myobj) { // find next oprogram object for (unsigned int i = myobj.arg1 + 1; i < size(); i++) { // count symbol - if ((*this)[i]->_type == cmd_symbol) count_symbols++; + if (at(i)->_type == cmd_symbol) count_symbols++; // stop if prog - else if ((*this)[i]->_type == cmd_program) { + else if (at(i)->_type == cmd_program) { prog_found = true; break; } // found something other than symbol else { - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); show_error(_err, context); return -1; } @@ -108,37 +108,37 @@ int program::rpn_inprog(branch& myobj) { // found 0 symbols if (count_symbols == 0) { - ERR_CONTEXT(ret_syntax); + setErrorContext(ret_syntax); show_error(_err, context); return -1; } // is missing if (!prog_found) { - ERR_CONTEXT(ret_syntax); + setErrorContext(ret_syntax); show_error(_err, context); return -1; } // check symbols number vs stack size if (stack_size() < count_symbols) { - ERR_CONTEXT(ret_missing_operand); + setErrorContext(ret_missing_operand); show_error(_err, context); return -1; } // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[string(((symbol*)(*this)[i])->value)] = _stack.at(0)->clone(); + _local_heap[string(((symbol*)at(i))->value)] = _stack.at(0)->clone(); _stack.pop_front(); } // run the program - string entry(((oprogram*)(*this)[myobj.arg1 + count_symbols + 1])->value); + string entry(((oprogram*)at(myobj.arg1 + count_symbols + 1))->value); program prog(_stack, _heap, this); // make the program from entry - if (program::parse(entry, prog) == ret_ok) { + if (prog.parse(entry) == ret_ok) { // run it prog.run(); } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index e1b6257..ad618a0 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -31,7 +31,7 @@ void program::rpn_plus() { _stack.value(1) += _stack.value(0); _stack.pop(); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief - keyword implementation @@ -60,7 +60,7 @@ void program::rpn_minus() { _stack.value(1) = _stack.value(0) - _stack.value(1); _stack.pop(); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief * keyword implementation @@ -89,7 +89,7 @@ void program::rpn_mul() { _stack.value(1) *= _stack.value(0); _stack.pop(); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief / keyword implementation @@ -118,7 +118,7 @@ void program::rpn_div() { _stack.value(1) = _stack.value(0) / _stack.value(1); _stack.pop(); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief neg keyword implementation @@ -131,7 +131,7 @@ void program::rpn_neg() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = -_stack.value(0); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief inv keyword implementation @@ -144,7 +144,7 @@ void program::rpn_inv() { else if (_stack.type(0) == cmd_complex) _stack.value(0) = mpreal{1} / _stack.value(0); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief power keyword implementation @@ -172,7 +172,7 @@ void program::rpn_power() { _stack.value(1) = pow(_stack.value(0), _stack.value(1)); _stack.pop(); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief sqrt keyword implementation @@ -192,7 +192,7 @@ void program::rpn_squareroot() { } else if (_stack.type(0) == cmd_complex) _stack.value(0) = sqrt(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief hex keyword implementation @@ -205,7 +205,7 @@ void program::rpn_hex() { _stack.obj(0).reBase = 16; _stack.obj(0).imBase = 16; } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief bin keyword implementation @@ -218,7 +218,7 @@ void program::rpn_bin() { _stack.obj(0).reBase = 2; _stack.obj(0).imBase = 2; } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief dec keyword implementation @@ -231,7 +231,7 @@ void program::rpn_dec() { _stack.obj(0).reBase = 10; _stack.obj(0).imBase = 10; } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief base keyword implementation @@ -249,9 +249,9 @@ void program::rpn_base() { _stack.obj(0).imBase = base; } } else - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief % (purcent) keyword implementation @@ -283,7 +283,7 @@ void program::rpn_square() { else if (_stack.at(0)->_type == cmd_complex) _stack.value(0) *= _stack.value(0); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief mod keyword implementation @@ -306,7 +306,7 @@ void program::rpn_abs() { _stack.push(new number(abs(_stack.value(0)))); _stack.erase(1); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief fact (factorial) keyword implementation @@ -327,7 +327,7 @@ void program::rpn_sign() { else if (_stack.at(0)->_type == cmd_complex) _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief mant keyword implementation @@ -336,7 +336,7 @@ void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); if (!isfinite(_stack.value(0))) { - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); return; } mp_exp_t exp; @@ -349,7 +349,7 @@ void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); if (!isfinite(_stack.value(0))) { - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); return; } mp_exp_t exp; diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 8b864bc..fc142a7 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -77,7 +77,7 @@ void program::rpn_pick(void) { // treat stack depth errors if ((to_pick == 0) || (to_pick > _stack.size())) { - ERR_CONTEXT(ret_out_of_range); + setErrorContext(ret_out_of_range); return; } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 4a424c8..fac153e 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -1,4 +1,5 @@ #include "program.hpp" +#include "input.hpp" /// @brief sto keyword implementation /// @@ -22,7 +23,7 @@ void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -39,7 +40,7 @@ void program::rpn_stosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -56,7 +57,7 @@ void program::rpn_stomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -73,7 +74,7 @@ void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -90,7 +91,7 @@ void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -106,7 +107,7 @@ void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); return; } rpn_dup(); @@ -131,7 +132,7 @@ void program::rpn_rcl(void) { (void)_stack.pop_front(); _stack.push_front(obj->clone()); } else - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); } /// @brief edit keyword implementation @@ -146,7 +147,7 @@ void program::rpn_edit(void) { _stack.pop(); // set it as the linenoise line entry - linenoisePreloadBuffer((const char*)st.str().c_str()); + Input::preload(st.str().c_str()); } /// @brief recall then eval a symbol variable if it is auto-evaluable @@ -179,7 +180,7 @@ void program::rpn_purge(void) { delete i->second; _heap.erase(i); } else - ERR_CONTEXT(ret_unknown_variable); + setErrorContext(ret_unknown_variable); _stack.pop(); } @@ -199,7 +200,7 @@ void program::rpn_vars(void) { } // parents local variables - while (parent != NULL) { + while (parent != nullptr) { for (int i = 0; i < (int)parent->_local_heap.size(); i++) { (void)parent->_local_heap.get_by_index(i, name, obj); cout<<"var "<name()<<", value "; diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index c4b4ad6..b78b3c4 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -27,7 +27,7 @@ void program::rpn_strout() { _stack.pop(); // make program from string in stack level 1 - if (program::parse(entry, prog) == ret_ok) + if (prog.parse(entry) == ret_ok) // run it prog.run(); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index a127bdb..1b4dd5b 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -1,5 +1,8 @@ #include +using namespace std; +#include "version.h" +#include "escape.h" #include "program.hpp" /// @brief write stack in a string, each entry separated between commas @@ -59,9 +62,9 @@ void program::rpn_test() { string test_filename = _stack.value(0); _stack.pop(); - cout << endl << "rpn version is " << version << endl; + cout << endl << "rpn version is " << RPN_VERSION << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); - test_show_result("Total", total_tests, total_tests_failed, total_steps, total_steps_failed); + test_show_result("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); } /// @brief load a test file and run its tests @@ -228,7 +231,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail entry = regex_replace(entry, regex("`"), ""); if (!entry.empty()) { program prog(stk, hp); - ret = program::parse(entry, prog); + ret = prog.parse(entry); if (ret == ret_ok) { // run it (void)prog.run(); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index feaefe9..09ec315 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -28,7 +28,7 @@ void program::rpn_sup(void) { _stack.push_front(new number(cmp_strings_on_stack_top() == 1)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief >= keyword implementation @@ -46,7 +46,7 @@ void program::rpn_sup_eq(void) { _stack.push_front(new number(cmp_strings_on_stack_top() != -1)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief < keyword implementation @@ -64,7 +64,7 @@ void program::rpn_inf(void) { _stack.push_front(new number(cmp_strings_on_stack_top() == -1)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief <= keyword implementation @@ -80,7 +80,7 @@ void program::rpn_inf_eq(void) { _stack.push_front(new number(cmp_strings_on_stack_top() != 1)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief != keyword implementation @@ -103,7 +103,7 @@ void program::rpn_diff(void) { _stack.push_front(new number(cmp_strings_on_stack_top() != 0)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief == keyword implementation @@ -126,7 +126,7 @@ void program::rpn_eq(void) { _stack.push_front(new number(cmp_strings_on_stack_top() == 0)); _stack.erase(1, 2); } else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief and keyword implementation diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index cb75cec..4a75a1c 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -13,7 +13,7 @@ void program::rpn_time() { clock_gettime(CLOCK_REALTIME, &ts); time_t time = (time_t)ts.tv_sec; tm = localtime(&time); - if (tm != NULL) { + if (tm != nullptr) { // date format = HH.MMSSssssss date = ((double)tm->tm_hour) * 10000000000.0 + ((double)tm->tm_min) * 100000000.0 + ((double)tm->tm_sec) * 1000000.0 + (double)(ts.tv_nsec / 1000); @@ -23,7 +23,7 @@ void program::rpn_time() { _stack.push(new number(date)); _stack.value(0) /= 10000000000.0; } else - ERR_CONTEXT(ret_internal); + setErrorContext(ret_internal); } /// @brief date keyword implementation @@ -37,7 +37,7 @@ void program::rpn_date() { clock_gettime(CLOCK_REALTIME, &ts); time_t time = (time_t)ts.tv_sec; tm = localtime(&time); - if (tm != NULL) { + if (tm != nullptr) { // date format = (M)M.DDYYYY date = (double)(tm->tm_mon + 1) * 1000000.0 + (double)(tm->tm_mday) * 10000.0 + (double)(tm->tm_year + 1900); @@ -47,7 +47,7 @@ void program::rpn_date() { _stack.push(new number(date)); _stack.value(0) /= 1000000.0; } else - ERR_CONTEXT(ret_internal); + setErrorContext(ret_internal); } /// @brief ticks keyword implementation @@ -61,10 +61,10 @@ void program::rpn_ticks() { clock_gettime(CLOCK_REALTIME, &ts); time_t time = (time_t)ts.tv_sec; tm = localtime(&time); - if (tm != NULL) { + if (tm != nullptr) { // date in µs date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); _stack.push(new number(date)); } else - ERR_CONTEXT(ret_internal); + setErrorContext(ret_internal); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 3bec3d6..7eeca55 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -34,7 +34,7 @@ void program::rpn_sin(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = sin(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief asin keyword implementation @@ -47,7 +47,7 @@ void program::rpn_asin(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = asin(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief cos keyword implementation @@ -60,7 +60,7 @@ void program::rpn_cos(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = cos(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief acos keyword implementation @@ -73,7 +73,7 @@ void program::rpn_acos(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = acos(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief tan keyword implementation @@ -86,7 +86,7 @@ void program::rpn_tan(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = tan(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } /// @brief atan keyword implementation @@ -99,5 +99,5 @@ void program::rpn_atan(void) { else if (_stack.type(0) == cmd_complex) _stack.value(0) = atan(_stack.value(0)); else - ERR_CONTEXT(ret_bad_operand_type); + setErrorContext(ret_bad_operand_type); } diff --git a/src/version.h b/src/version.h index f84606b..52d5a96 100644 --- a/src/version.h +++ b/src/version.h @@ -1,23 +1,2 @@ -// version and soft name #define RPN_VERSION "2.4" -static const string version{RPN_VERSION}; -static const string uname{"rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3"}; - -#define XSTR(a) STR(a) -#define STR(a) #a - -// description -static const string description{ - ATTR_BOLD "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF - "otation language\n\n" - "using " ATTR_BOLD "GMP" ATTR_OFF - " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( - __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING - " under GNU LGPL\n" - "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION - " under BSD\n"}; - -// syntax -static const string syntax{ATTR_BOLD "Syntax" ATTR_OFF - ": rpn [command]\n" - "with optional command = list of commands"}; +#define RPN_UNAME "rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3" From 56298f6b8a71e52a2a7afa780bb401913308752e Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 14:28:09 +0100 Subject: [PATCH 28/57] allocate mpreal obj in lexer only when needed --- CMakeLists.txt | 3 ++- src/lexer.cpp | 20 ++++++++++++-------- src/lexer.hpp | 6 +++--- src/main.cpp | 2 +- src/program.cpp | 4 ++-- src/rpn-general.cpp | 4 ++-- src/rpn-time.cpp | 2 +- 7 files changed, 23 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2eca5a6..422a184 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,7 @@ if(CMAKE_COMPILER_IS_GNUCXX) set(BASE_COMPILER_OPTIONS "-std=c++14 -Wl,--no-as-needed") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g") - set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -fomit-frame-pointer -s") + set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s") endif() # custom linenoise-ng @@ -75,6 +75,7 @@ add_executable( ${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp ) target_link_libraries(rpn mpfr) +target_link_libraries(rpn gmp) # man add_custom_target(man ALL) diff --git a/src/lexer.cpp b/src/lexer.cpp index bde5fa1..ac501a2 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -107,6 +107,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& nextIdx, vector= 5) { @@ -123,10 +124,11 @@ int Lexer::getBaseAt(string& entry, int idxStart, bool& positive) { return b; } } + #endif return 10; } -bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal& r, char delim) { +bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal** r, char delim) { stringstream ss; int idxNumber = 0; string token; @@ -138,8 +140,9 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m base = getBaseAt(token, idx, positive); if (base < BASE_MIN || base > BASE_MAX) return false; trim(token); - if (mpfr_set_str(r.mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { - if (!positive) r = -r; + *r = new mpreal; + if (mpfr_set_str((*r)->mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { + if (!positive) *(*r) = -*(*r); return true; } else return false; @@ -150,9 +153,9 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - mpreal r; + mpreal* r; int base = 10; - if (getNumberAt(entry, idx, nextIdx, base, r)) { + if (getNumberAt(entry, idx, nextIdx, base, &r)) { elements.push_back({cmd_number, .re = r, .reBase = base}); return true; } else { @@ -163,14 +166,15 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - mpreal re, im; + mpreal* re; + mpreal* im; int reBase, imBase = 10; if (idx + 1 == entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol } - if (!getNumberAt(entry, idx + 1, nextIdx, reBase, re, ',')) { + if (!getNumberAt(entry, idx + 1, nextIdx, reBase, &re, ',')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); return true; // complex format error, return a symbol @@ -184,7 +188,7 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& nextIdx, vector -#include +#include #include #include diff --git a/src/program.cpp b/src/program.cpp index 8ec91b0..aea896c 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -590,10 +590,10 @@ ret_value program::parse(string& entry) { for (Lexer::SynElement& element : elements) { switch (element.type) { case cmd_number: - push_back(new number(element.re, element.reBase)); + push_back(new number(*element.re, element.reBase)); break; case cmd_complex: - push_back(new ocomplex(element.re, element.im, element.reBase, element.imBase)); + push_back(new ocomplex(*element.re, *element.im, element.reBase, element.imBase)); break; case cmd_string: push_back(new ostring(element.value)); diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index c19a934..962b91d 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -1,7 +1,7 @@ -#include +#include +#include "linenoise.h" #include "escape.h" -#include "linenoise.h" #include "program.hpp" #include "version.h" diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index 4a75a1c..8ca0a02 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -1,4 +1,4 @@ -#include +#include #include "program.hpp" From 683c4702d1d2a31800622aa9f04c11ec80bd9aee Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 16:26:59 +0100 Subject: [PATCH 29/57] Remove regex from lexer, allocate mpreal only if needed --- src/lexer.cpp | 75 ++++++++++++++++++++++++++-------------- src/lexer.hpp | 2 +- test/023-parse-number.md | 32 +++++++++++++++++ 3 files changed, 83 insertions(+), 26 deletions(-) diff --git a/src/lexer.cpp b/src/lexer.cpp index ac501a2..afe433f 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -1,6 +1,3 @@ -#include -using namespace std; - #include "lexer.hpp" bool Lexer::lexer(string& entry, map& keywords, vector& elements, @@ -38,6 +35,8 @@ bool Lexer::lexer(string& entry, map& keywords, vector= 5) { - string sign = match[1].str(); - string base = match[2].str(); - // sign out, permits expressions like -0xAB3F - positive = sign.size() > 0 && sign[0] == '-' ? false : true; - // base - entry = entry.substr(base.size() + sign.size()); - if (base[1] == 'X' || base[1] == 'x') return 16; - if (base.size() > 0) { - int b = stoi(base.substr(0, base.size() - 1)); - if (b == 0) b = 2; // admit "0b" as binary suffix - return b; +int Lexer::getBaseAt(string& entry, size_t& nextIdx, bool& positive) { + // a regex could be "([+-])?((0[xX])|([0-9][0-9]?[bB]))" + // regex is not use because dramatically slow + // entry is scanned from idxStart, searching for [s]abc (sign and 3 first chars) + size_t scan = 0; + nextIdx = 0; + positive = true; + if (scan >= entry.size()) return 10; + if (entry[scan] == '+') { + scan++; + nextIdx = scan; + } + else if (entry[scan] == '-') { + scan++; + nextIdx = scan; + positive = false; + } + if (scan + 2 >= entry.size()) return 10; + char a = entry[scan]; + char b = entry[scan + 1]; + char c = 0; + if (scan + 2 < entry.size()) c = entry[scan + 2]; + if (a == '0') { + if (b == 'x' || b == 'X') { + nextIdx = scan + 2; + return 16; + } + if (b == 'b' || b == 'B') { + nextIdx = scan + 2; + return 2; + } + } else if (isdigit(a)) { + if (b == 'b' || b == 'B') { + nextIdx = scan + 2; + return int(a - '0'); + } + if (isdigit(b) && (c == 'b' || c == 'B')) { + nextIdx = scan + 3; + return 10 * int(a - '0') + int(b - '0'); } } - #endif return 10; } @@ -134,12 +155,16 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m string token; bool positive = true; + nextIdx = idx; + ss.str(entry.substr(idx)); if (getline(ss, token, delim)) { + size_t numberIdx; nextIdx = token.size() + idx + 1; - base = getBaseAt(token, idx, positive); - if (base < BASE_MIN || base > BASE_MAX) return false; trim(token); + base = getBaseAt(token, numberIdx, positive); + if (base < BASE_MIN || base > BASE_MAX) return false; + if (numberIdx != 0) token = token.substr(numberIdx); *r = new mpreal; if (mpfr_set_str((*r)->mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { if (!positive) *(*r) = -*(*r); @@ -153,7 +178,7 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - mpreal* r; + mpreal* r = nullptr; int base = 10; if (getNumberAt(entry, idx, nextIdx, base, &r)) { elements.push_back({cmd_number, .re = r, .reBase = base}); @@ -166,8 +191,8 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements) { - mpreal* re; - mpreal* im; + mpreal* re = nullptr; + mpreal* im = nullptr; int reBase, imBase = 10; if (idx + 1 == entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); diff --git a/src/lexer.hpp b/src/lexer.hpp index 6495093..34c4964 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -66,7 +66,7 @@ class Lexer { bool parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements); void trim(string& s); - int getBaseAt(string& entry, int idxStart, bool& positive); + int getBaseAt(string& entry, size_t& nextIdx, bool& positive); bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal** r, char delim = ' '); }; diff --git a/test/023-parse-number.md b/test/023-parse-number.md index df2178d..b7f34b8 100644 --- a/test/023-parse-number.md +++ b/test/023-parse-number.md @@ -10,6 +10,38 @@ `del` +## 1-shot entries + +``` +0 +0. +.0 +0.0 +-0 ++0 ++.0 ++0. +0.1 ++0.1 +-0.1 +-.1 ++.1 +``` + +-> stack should be 0, 0, 0, 0, -0, 0, 0, 0, 0.1, 0.1, -0.1, -0.1, 0.1 + +`del` + +## n-shot entries + +``` +0 0. .0 0.0 -0 +0 +.0 +0. 0.1 +0.1 -0.1 -.1 +.1 +``` + +-> stack should be 0, 0, 0, 0, -0, 0, 0, 0, 0.1, 0.1, -0.1, -0.1, 0.1 + +`del` + ## numb 1 `3.14 +3.14 -3.14` From 50351b19176c210a1c8be05f983abbb43aea6ea2 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 16:34:17 +0100 Subject: [PATCH 30/57] Add missing input.cpp and input.hpp --- src/input.cpp | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/input.hpp | 23 +++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100644 src/input.cpp create mode 100644 src/input.hpp diff --git a/src/input.cpp b/src/input.cpp new file mode 100644 index 0000000..f93c46d --- /dev/null +++ b/src/input.cpp @@ -0,0 +1,71 @@ +#include "string.h" +#include "input.hpp" + +vector* Input::_acWords = nullptr; + +Input::Input(string& entry, vector& autocompletionWords, string prompt, string mlPrompt) : status(cont) { + char* c_entry; + bool multiline = false; + int entry_len; + + _acWords = &autocompletionWords; + + // linenoise for entry + linenoiseSetCompletionCallback(entry_completion_generator); + while (status == cont) { + // get user entry + if (multiline) + c_entry = linenoise(mlPrompt.c_str(), &entry_len); + else + c_entry = linenoise(prompt.c_str(), &entry_len); + + // Ctrl-C + if (linenoiseKeyType() == 1) { + if (entry_len > 0 || multiline) + status = abort; + else + status = ctrlc; + } else if (linenoiseKeyType() == 3) { + multiline = true; + if (c_entry != nullptr) entry += c_entry; + entry += " "; + } else { + if (c_entry != nullptr) { + entry += c_entry; + // keep history + if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str()); + status = ok; + } else + status = error; + } + } +} + +/// @brief completion callback as asked by linenoise-ng +/// this is called by linenoise-ng whenever the user enters TAB +/// +/// @param text the text after wich the user entered TAB +/// @param lc the completion object to add strings with linenoiseAddCompletion() +/// +void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) { + if (Input::_acWords == nullptr || text == nullptr) + return; + + int text_len = strnlen(text, 6); + + // propose all keywords + if (text_len == 0) + for (string& ac : *Input::_acWords) + // add all keywords + linenoiseAddCompletion(lc, ac.c_str()); + // propose keywords matching to text begining + else + for (string& ac : *Input::_acWords) + // compare list entry with text, return if match + if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str()); +} + +void Input::preload(const char* preloadText) { + if (preloadText != nullptr) + linenoisePreloadBuffer(preloadText); +} diff --git a/src/input.hpp b/src/input.hpp new file mode 100644 index 0000000..55a7b23 --- /dev/null +++ b/src/input.hpp @@ -0,0 +1,23 @@ +#ifndef _ENTRY_HPP_ +#define _ENTRY_HPP_ + +#include +#include +using namespace std; + +#include +#include "linenoise.h" + +class Input { + public: + Input(string& entry, vector& autocompletionWords, string prompt = "rpn> ", string mlPrompt = ">"); + enum {ok, cont, abort, ctrlc, error} status; + + static void preload(const char* preloadText); + + private: + static void entry_completion_generator(const char* text, linenoiseCompletions* lc); + static vector* _acWords; +}; + +#endif From 5c976eb9223c4d3e37d09d86a7033187d8df9ba6 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 16:35:05 +0100 Subject: [PATCH 31/57] Add debug and release dirs in .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 426d7bf..d3d7230 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,5 @@ *bw-output*/* .vscode/* build/* +debug/* +release/* From 8f5a334fe0732f63e678803860d494c7bf14c10e Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 17:18:07 +0100 Subject: [PATCH 32/57] Correct mpreal mem leaks due to perf issue correction --- src/lexer.cpp | 16 ++++++++++------ src/program.cpp | 3 +++ test/mem_test.sh | 2 +- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/lexer.cpp b/src/lexer.cpp index afe433f..309a7eb 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -5,7 +5,7 @@ bool Lexer::lexer(string& entry, map& keywords, vectormpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { if (!positive) *(*r) = -*(*r); return true; - } else - return false; + } else { + delete *r; + return false; + } } nextIdx = token.size() + idx + 1; return false; @@ -206,16 +207,19 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& nextIdx, vector= entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); + if (re != nullptr) delete re; + if (im != nullptr) delete im; return true; // complex format error, return a symbol } if (!getNumberAt(entry, i, nextIdx, imBase, &im, ')')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); nextIdx = entry.size(); + if (re != nullptr) delete re; + if (im != nullptr) delete im; return true; // complex format error, return a symbol } elements.push_back({cmd_complex, .re = re, .im = im, .reBase = reBase, .imBase = imBase}); diff --git a/src/program.cpp b/src/program.cpp index aea896c..02ae9cf 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -612,7 +612,10 @@ ret_value program::parse(string& entry) { break; default: show_error(ret_unknown_err, "error creating program from entry"); + break; } + if (element.re != nullptr) delete element.re; + if (element.im != nullptr) delete element.im; } } else for (SynError& err : errors) show_syntax_error(err.err.c_str()); diff --git a/test/mem_test.sh b/test/mem_test.sh index 5c143f1..4fc101d 100755 --- a/test/mem_test.sh +++ b/test/mem_test.sh @@ -1,6 +1,6 @@ #!/bin/bash -rpn=../build/rpn +rpn=../debug/rpn FG_RED="\033[0;31m" FG_GREEN="\033[0;32m" From 4e51a21e0d7232e0c785d870de8371b82b60d057 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Tue, 22 Feb 2022 17:20:47 +0100 Subject: [PATCH 33/57] CMakeLists.txt strange warning (string vs STRING) tackled --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 422a184..c6bde2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ project(rpn) if((NOT CMAKE_BUILD_TYPE MATCHES Debug) AND (NOT CMAKE_BUILD_TYPE MATCHES Release)) - set(CMAKE_BUILD_TYPE Release CACHE string "Choose the type of build, options are: None Debug Release" FORCE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release" FORCE) endif() message(STATUS "Build mode: ${CMAKE_BUILD_TYPE}") From be1f0d54ac73f9e21fcf59d5c6ccba8292a14bab Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Wed, 23 Feb 2022 11:31:05 +0100 Subject: [PATCH 34/57] github action for tests --- .github/workflows/cmake.yml | 35 +++++++++++++++++++++++++++++++++++ .gitmodules | 5 +---- linenoise-ng | 2 +- src/constant.h | 2 +- src/main.cpp | 6 ++++-- src/program.cpp | 9 ++++++--- src/rpn-test-framework.cpp | 14 +++++++++----- test/100-complex.md | 4 ++-- test/mem_test.sh | 8 +++++++- 9 files changed, 66 insertions(+), 19 deletions(-) create mode 100644 .github/workflows/cmake.yml diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 0000000..5359907 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,35 @@ +name: CMake + +on: + pull_request: + branches: [ v2.4.0-devel ] + +env: + BUILD_TYPE: Release + +jobs: + functional_and_mem_tests: + # runs-on: ubuntu:21.10 + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + with: + submodules: 'true' + + - name: Install needed libs + run: sudo apt update && sudo apt install -y cmake build-essential libmpfr-dev valgrind + + - name: Configure CMake + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + run: make -C ${{github.workspace}}/build -j + + - name: Functional tests + working-directory: ${{github.workspace}}/test + run: ${{github.workspace}}/build/rpn \"all.md\" test + + - name: Memory tests + working-directory: ${{github.workspace}}/test + run: ./mem_test.sh ${{github.workspace}}/build/rpn diff --git a/.gitmodules b/.gitmodules index da98e6b..f283762 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,6 @@ -[submodule "build/linenoise-ng"] - path = build/linenoise-ng - url = git@github.com:louisrubet/linenoise-ng.git [submodule "linenoise-ng"] path = linenoise-ng - url = git@github.com:louisrubet/linenoise-ng.git + url = https://github.com/louisrubet/linenoise-ng.git [submodule "mpreal"] path = mpreal url = https://github.com/advanpix/mpreal diff --git a/linenoise-ng b/linenoise-ng index 6a37ee0..3d3d594 160000 --- a/linenoise-ng +++ b/linenoise-ng @@ -1 +1 @@ -Subproject commit 6a37ee0e9f117bb9950159545ecdbdbba41799bf +Subproject commit 3d3d594caf15b75517d9baea1f1860978cad771a diff --git a/src/constant.h b/src/constant.h index 8ee2408..084c96f 100644 --- a/src/constant.h +++ b/src/constant.h @@ -41,7 +41,7 @@ typedef enum { ret_abort_current_entry, ret_out_of_memory, ret_bad_value, - ret_max + ret_test_failed } ret_value; // base min and max diff --git a/src/main.cpp b/src/main.cpp index 72ed68d..3db8aeb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include -#include +#include +#include #include #include using namespace std; @@ -162,5 +163,6 @@ int main(int argc, char* argv[]) { mpfr_free_cache(); - return ret; + if (ret != ret_ok) return EXIT_FAILURE; + return EXIT_SUCCESS; } diff --git a/src/program.cpp b/src/program.cpp index 02ae9cf..01e176f 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -263,11 +263,14 @@ ret_value program::run() { // error: abort prog go_out = true; + // test error: make rpn return EXIT_FAILURE + if (_err == ret_test_failed) + ret = ret_test_failed; + // error: show it - if (show_error(_err, _err_context) == ret_deadly) { + if (show_error(_err, _err_context) == ret_deadly) // pb showing error -> go out software ret = ret_good_bye; - } break; } i++; @@ -633,7 +636,7 @@ ret_value program::show_error() { vector errorStrings {"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", "aborted current entry", "out of memory", - "bad value"}; + "bad value", "test failed"}; // clang-format on // show last recorded error if ((size_t)_err < errorStrings.size()) diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 1b4dd5b..fecaf7a 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -1,9 +1,9 @@ #include using namespace std; -#include "version.h" #include "escape.h" #include "program.hpp" +#include "version.h" /// @brief write stack in a string, each entry separated between commas /// @@ -34,10 +34,8 @@ void program::test_get_stack(string& stack_is, rpnstack& stk) { /// @param steps_failed failed steps nb /// void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) { - //cout << title << ": run " << tests << " tests: " << tests - tests_failed << " passed, "; - if (!title.empty()) - cout << title << ": "; - cout <<"run " << tests << " tests: " << tests - tests_failed << " passed, "; + if (!title.empty()) cout << title << ": "; + cout << "run " << tests << " tests: " << tests - tests_failed << " passed, "; if (tests_failed > 0) cout << FG_RED; cout << tests_failed << " failed"; if (tests_failed > 0) cout << COLOR_OFF; @@ -65,6 +63,12 @@ void program::rpn_test() { cout << endl << "rpn version is " << RPN_VERSION << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); test_show_result("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); + + // notify to caller that test succeeded or not + if (total_tests_failed > 0) { + _err = ret_test_failed; + _err_context = string("rpn version ") + RPN_VERSION + ", test file " + test_filename; + } } /// @brief load a test file and run its tests diff --git a/test/100-complex.md b/test/100-complex.md index 5a92b22..f1b07d6 100644 --- a/test/100-complex.md +++ b/test/100-complex.md @@ -36,9 +36,9 @@ ## entry (5) -`(0x1234,0x10.10)` +`(0x1234,0x1010)` --> stack should be (0x1.234p+12,0x1.01p+4) +-> stack should be (0x1234,0x1010) `del` diff --git a/test/mem_test.sh b/test/mem_test.sh index 4fc101d..bde629f 100755 --- a/test/mem_test.sh +++ b/test/mem_test.sh @@ -1,6 +1,12 @@ #!/bin/bash -rpn=../debug/rpn +if [ -z "${1}" ] + then + echo "Syntax: ${0} " + exit 1 +fi + +rpn=${1} FG_RED="\033[0;31m" FG_GREEN="\033[0;32m" From e034a7834c981a104c9785d1bed51f0a90436308 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 24 Feb 2022 11:31:27 +0100 Subject: [PATCH 35/57] Harden branch checks on command flow indexes --- TODO.md | 2 +- src/object.hpp | 10 +-- src/program.cpp | 15 ++-- src/program.hpp | 29 +++---- src/rpn-branch.cpp | 204 ++++++++++++++++++++++++++++----------------- src/rpn-test.cpp | 6 +- 6 files changed, 155 insertions(+), 111 deletions(-) diff --git a/TODO.md b/TODO.md index ba08ba0..0412908 100644 --- a/TODO.md +++ b/TODO.md @@ -3,4 +3,4 @@ TODO missing tests / problems - les arguments d'une fonction en erreur doivent ils être consommés ? ex embettant : sto+ -- `1 'i' sto while i <= 2 repeat 0 'j' sto while j <= 1 repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante +- `1 'i' sto while i 2 <= repeat 0 'j' sto while 1 <= j repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante diff --git a/src/object.hpp b/src/object.hpp index 6b83186..994e1ab 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -31,7 +31,7 @@ class program; class branch; typedef void (program::*program_fn_t)(void); -typedef int (program::*branch_fn_t)(branch&); +typedef size_t (program::*branch_fn_t)(branch&); /// @brief object - a generic stack object /// @@ -174,9 +174,9 @@ struct branch : object { branch() : object(cmd_branch) {} branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { fn = fn_; - arg1 = -1; - arg2 = -1; - arg3 = -1; + arg1 = (size_t)-1; + arg2 = (size_t)-1; + arg3 = (size_t)-1; arg_bool = 0; value = value_; } @@ -191,7 +191,7 @@ struct branch : object { virtual object* clone() { return new branch(*this); } virtual string name() { return string("branch"); } branch_fn_t fn; - int arg1, arg2, arg3; + size_t arg1, arg2, arg3; mpreal firstIndex, lastIndex; bool arg_bool; string value; diff --git a/src/program.cpp b/src/program.cpp index 01e176f..5ae1757 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -236,8 +236,8 @@ ret_value program::run() { } // iterate commands - for (int i = 0; (go_out == false) && (interrupt_now == false) && (i < (int)size());) { - object* o = (*this)[i]; + for (size_t i = 0; (go_out == false) && (interrupt_now == false) && (i < size());) { + object* o = at(i); switch (o->_type) { // could be an auto-evaluated symbol case cmd_symbol: @@ -281,18 +281,17 @@ ret_value program::run() { case cmd_branch: { // call matching function branch* b = (branch*)o; - int next_cmd = (this->*(b->fn))(*b); + size_t next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { - case -1: + case step_out: // step out i++; // meaning 'next command' break; - case -(int)ret_runtime_error: - // error: show it + case runtime_error: // runtime error (void)show_error(_err, _err_context); - go_out = true; // end of run + go_out = true; break; default: - i = next_cmd; // new direction + i = next_cmd; break; } break; diff --git a/src/program.hpp b/src/program.hpp index 1c98f09..02b5eb9 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -13,9 +13,9 @@ using namespace mpfr; // internal includes #include "constant.h" +#include "lexer.hpp" #include "object.hpp" #include "stack.hpp" -#include "lexer.hpp" //< convinient structure to preprocess a program struct if_layout_t { @@ -32,7 +32,7 @@ struct if_layout_t { //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque, public Lexer { public: - program(rpnstack& stk, heap& hp, program* parent = nullptr):_stack(stk),_heap(hp),_parent(parent) { + program(rpnstack& stk, heap& hp, program* parent = nullptr) : _stack(stk), _heap(hp), _parent(parent) { interrupt_now = false; } virtual ~program() { @@ -99,20 +99,21 @@ class program : public deque, public Lexer { //// // branch - int rpn_if(branch& myobj); - int rpn_then(branch& myobj); - int rpn_else(branch& myobj); - int rpn_end(branch& myobj); - int rpn_do(branch& myobj); - int rpn_until(branch& myobj); + size_t rpn_if(branch& myobj); + size_t rpn_then(branch& myobj); + size_t rpn_else(branch& myobj); + size_t rpn_end(branch& myobj); + size_t rpn_do(branch& myobj); + size_t rpn_until(branch& myobj); void rpn_ift(void); void rpn_ifte(void); - int rpn_while(branch& myobj); - int rpn_repeat(branch& myobj); - int rpn_start(branch& myobj); - int rpn_for(branch& myobj); - int rpn_next(branch& myobj); - int rpn_step(branch& myobj); + size_t rpn_while(branch& myobj); + size_t rpn_repeat(branch& myobj); + size_t rpn_start(branch& myobj); + size_t rpn_for(branch& myobj); + size_t rpn_next(branch& myobj); + size_t rpn_step(branch& myobj); + enum { step_out = (size_t)-1, runtime_error = (size_t)-2 }; // complex void rpn_re(); diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index 167758b..d9c42e0 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -3,34 +3,42 @@ /// @brief if keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_if(branch& myobj) { +size_t program::rpn_if(branch& myobj) { // myobj.arg1 = 'if' condition evaluation value - MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); + MIN_ARGUMENTS_RET(1, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); if (_stack.value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; _stack.pop(); - return -1; + return step_out; } /// @brief then keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_then(branch& myobj) { +size_t program::rpn_then(branch& myobj) { // myobj.arg1 = index of then + 1 // myobj.arg2 = index of else + 1 or end + 1 // myobj.arg3 = index of if // if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1) - branch* if_cmd = (branch*)at(myobj.arg3); + branch* if_cmd; + if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + if_cmd = (branch*)at(myobj.arg3); if (if_cmd->arg1 == 1) return myobj.arg1; else @@ -40,16 +48,22 @@ int program::rpn_then(branch& myobj) { /// @brief else keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_else(branch& myobj) { +size_t program::rpn_else(branch& myobj) { // myobj.arg1 = index of else + 1 // myobj.arg2 = index of end + 1 // myobj.arg3 = index of if // if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1) - branch* if_cmd = (branch*)at(myobj.arg3); + branch* if_cmd; + if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + if_cmd = (branch*)at(myobj.arg3); if (if_cmd->arg1 == 1) return myobj.arg2; else @@ -59,24 +73,25 @@ int program::rpn_else(branch& myobj) { /// @brief end keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_end(branch& myobj) { - int ret = -1; +size_t program::rpn_end(branch& myobj) { + size_t ret = step_out; // arg1 = index of do+1 in case of do..unti..end if (myobj.arg1 != -1) { - // in a template do..unti..end - MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); + // in a template do..until..end + MIN_ARGUMENTS_RET(1, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); // check arg if (_stack.value(0) == 0) ret = myobj.arg1; _stack.pop(); } // arg2 = index of while+1 in case of while..repeat..end - else if (myobj.arg2 != -1) + else if (myobj.arg2 != step_out) ret = myobj.arg2; return ret; @@ -85,30 +100,33 @@ int program::rpn_end(branch& myobj) { /// @brief do keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_do(branch& myobj) { +size_t program::rpn_do(branch& myobj) { // nothing - return -1; + return step_out; } /// @brief until keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_until(branch& myobj) { +size_t program::rpn_until(branch& myobj) { // nothing - return -1; + return step_out; } /// @brief ift keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// void program::rpn_ift(void) { MIN_ARGUMENTS(2); @@ -126,8 +144,9 @@ void program::rpn_ift(void) { /// @brief ifte keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// void program::rpn_ifte(void) { MIN_ARGUMENTS(3); @@ -146,25 +165,27 @@ void program::rpn_ifte(void) { /// @brief while keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_while(branch& myobj) { +size_t program::rpn_while(branch& myobj) { // nothing - return -1; + return step_out; } /// @brief repeat keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_repeat(branch& myobj) { - int ret = -1; +size_t program::rpn_repeat(branch& myobj) { + size_t ret = step_out; - MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); + MIN_ARGUMENTS_RET(1, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); // check arg // myobj.arg1 is end+1 @@ -177,15 +198,16 @@ int program::rpn_repeat(branch& myobj) { /// @brief start keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_start(branch& myobj) { - int ret = -1; +size_t program::rpn_start(branch& myobj) { + size_t ret = step_out; - MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); + MIN_ARGUMENTS_RET(2, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); // loop boundaries myobj.firstIndex = _stack.value(1); @@ -205,17 +227,23 @@ int program::rpn_start(branch& myobj) { /// @brief for keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_for(branch& myobj) { - int ret; +size_t program::rpn_for(branch& myobj) { + size_t ret; - MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); + MIN_ARGUMENTS_RET(2, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); - symbol* sym = (symbol*)at(myobj.arg1); // arg1 = loop variable index + symbol* sym; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_symbol) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + sym = (symbol*)at(myobj.arg1); // arg1 = loop variable index // loop boundaries myobj.firstIndex = _stack.value(1); @@ -246,13 +274,19 @@ int program::rpn_for(branch& myobj) { /// @brief next keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_next(branch& myobj) { +size_t program::rpn_next(branch& myobj) { // arg1 = loop variable index // firstIndex = current point in the loop - branch* start_or_for = (branch*)at(myobj.arg1); + branch* start_or_for; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + start_or_for = (branch*)at(myobj.arg1); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -265,8 +299,12 @@ int program::rpn_next(branch& myobj) { // for command: increment symbol too if (start_or_for->arg1 != -1) { object* obj; - unsigned int size; - symbol* var = (symbol*)at(start_or_for->arg1); + symbol* var; + if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + var = (symbol*)at(start_or_for->arg1); // store symbol variable (asserted existing in the local heap) ((number*)_local_heap[var->value])->value = myobj.firstIndex; @@ -276,7 +314,7 @@ int program::rpn_next(branch& myobj) { if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - return -1; + return step_out; } else { // for command: next instruction will be after symbol variable if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1; @@ -289,24 +327,30 @@ int program::rpn_next(branch& myobj) { /// @brief step keyword (branch) implementation /// /// @param myobj the current branch object -/// @return int index of the next object to run in the current program -/// @return -1 the next object index to run in the current program is the current+1 +/// @return size_t index of the next object to run in the current program +/// @return step_out next object to run in the current program is current + 1 +/// @return runtime_error something went wrong with preprocess, abort branch /// -int program::rpn_step(branch& myobj) { - int ret; - MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); +size_t program::rpn_step(branch& myobj) { + size_t ret; + MIN_ARGUMENTS_RET(1, runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); mpreal step = _stack.value(0); _stack.pop(); // end of loop if step is negative or zero if (step <= 0) - ret = -1; + ret = step_out; else { // arg1 = loop variable index // firstIndex = current count - branch* start_or_for = (branch*)at(myobj.arg1); + branch* start_or_for; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + start_or_for = (branch*)at(myobj.arg1); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -316,21 +360,25 @@ int program::rpn_step(branch& myobj) { // carefull: round toward minus infinity to avoid missing last boundary (because growing step) mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD); - // for command: increment symbol too if (start_or_for->arg1 != -1) { object* obj; - unsigned int size; - symbol* var = (symbol*)at(start_or_for->arg1); + symbol* var; + // for command: increment symbol too + if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { + setErrorContext(ret_missing_operand); + return runtime_error; + } + var = (symbol*)at(start_or_for->arg1); // increase symbol variable ((number*)_local_heap[var->value])->value = myobj.firstIndex; - } + } // test loop value is out of range if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - ret = -1; + ret = step_out; } else { // for command: next instruction will be after symbol variable if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1; diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 09ec315..351e890 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -17,7 +17,6 @@ long program::cmp_strings_on_stack_top() { /// void program::rpn_sup(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) > _stack.value(0))); @@ -35,7 +34,6 @@ void program::rpn_sup(void) { /// void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) >= _stack.value(0))); @@ -53,7 +51,6 @@ void program::rpn_sup_eq(void) { /// void program::rpn_inf(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) < _stack.value(0))); @@ -70,6 +67,7 @@ void program::rpn_inf(void) { /// @brief <= keyword implementation /// void program::rpn_inf_eq(void) { + MIN_ARGUMENTS(2); // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) <= _stack.value(0))); @@ -87,7 +85,6 @@ void program::rpn_inf_eq(void) { /// void program::rpn_diff(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) != _stack.value(0))); @@ -110,7 +107,6 @@ void program::rpn_diff(void) { /// void program::rpn_eq(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) == _stack.value(0))); From 3fcc74715544782170fdfe1de2bd25c3822bbb27 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 24 Feb 2022 12:09:43 +0100 Subject: [PATCH 36/57] Remove regex from test framework --- linenoise-ng | 2 +- src/rpn-test-framework.cpp | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/linenoise-ng b/linenoise-ng index 3d3d594..6a37ee0 160000 --- a/linenoise-ng +++ b/linenoise-ng @@ -1 +1 @@ -Subproject commit 3d3d594caf15b75517d9baea1f1860978cad771a +Subproject commit 6a37ee0e9f117bb9950159545ecdbdbba41799bf diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index fecaf7a..47f3cc4 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -1,10 +1,21 @@ -#include -using namespace std; - #include "escape.h" #include "program.hpp" #include "version.h" +static void _findAndReplaceAll(std::string & data, std::string toSearch, std::string replaceStr) +{ + // Get the first occurrence + size_t pos = data.find(toSearch); + // Repeat till end is reached + while( pos != std::string::npos) + { + // Replace this occurrence of Sub String + data.replace(pos, toSearch.size(), replaceStr); + // Get the next occurrence from the current position + pos =data.find(toSearch, pos + replaceStr.size()); + } +} + /// @brief write stack in a string, each entry separated between commas /// /// @param stack_is the output string @@ -232,7 +243,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail failed = true; } else { // parse entry and run line - entry = regex_replace(entry, regex("`"), ""); + _findAndReplaceAll(entry, "`", ""); if (!entry.empty()) { program prog(stk, hp); ret = prog.parse(entry); From fa936000ba0014ea62235071d0ee3721341bd7d8 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 24 Feb 2022 12:23:26 +0100 Subject: [PATCH 37/57] define guard --- Changelog.md | 2 ++ src/constant.h | 4 ++-- src/escape.h | 4 ++-- src/input.hpp | 4 ++-- src/lexer.hpp | 4 ++-- src/mpreal-out.hpp | 5 +++++ src/object.hpp | 4 ++-- src/program.hpp | 4 ++-- src/stack.hpp | 4 ++-- src/version.h | 5 +++++ 10 files changed, 26 insertions(+), 14 deletions(-) diff --git a/Changelog.md b/Changelog.md index 6f2cf35..91f5bf7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,8 @@ Changelog - SonarCloud integration, Sonar way profile - clang-format now based on google style - [google c++ style guide](https://google.github.io/styleguide/cppguide.html) applied + - define guard + - name and order of inclusions - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap - it seems cosh was giving sinh (!) diff --git a/src/constant.h b/src/constant.h index 084c96f..b1e1362 100644 --- a/src/constant.h +++ b/src/constant.h @@ -1,5 +1,5 @@ -#ifndef CONSTANT_H -#define CONSTANT_H +#ifndef CONSTANT_H_ +#define CONSTANT_H_ #define MPFR_USE_NO_MACRO #include diff --git a/src/escape.h b/src/escape.h index ba20c2c..f279cb9 100644 --- a/src/escape.h +++ b/src/escape.h @@ -1,5 +1,5 @@ -#ifndef ESCAPE_H -#define ESCAPE_H +#ifndef ESCAPE_H_ +#define ESCAPE_H_ // ANSI escape sequences diff --git a/src/input.hpp b/src/input.hpp index 55a7b23..5328a9c 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -1,5 +1,5 @@ -#ifndef _ENTRY_HPP_ -#define _ENTRY_HPP_ +#ifndef INPUT_HPP_ +#define INPUT_HPP_ #include #include diff --git a/src/lexer.hpp b/src/lexer.hpp index 34c4964..0b428ea 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -1,5 +1,5 @@ -#ifndef _PARSER_HPP_ -#define _PARSER_HPP_ +#ifndef LEXER_HPP_ +#define LEXER_HPP_ #include #include diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index f2e8e65..d007422 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -1,3 +1,6 @@ +#ifndef MPREAL_OUT_HPP_ +#define MPREAL_OUT_HPP_ + #include #include using namespace std; @@ -9,3 +12,5 @@ using namespace mpfr; ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); + +#endif diff --git a/src/object.hpp b/src/object.hpp index 994e1ab..723c5f0 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,5 +1,5 @@ -#ifndef OBJECT_HPP -#define OBJECT_HPP +#ifndef OBJECT_HPP_ +#define OBJECT_HPP_ #define MPFR_USE_NO_MACRO #include diff --git a/src/program.hpp b/src/program.hpp index 02b5eb9..9a1cef4 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -1,5 +1,5 @@ -#ifndef PROGRAM_HPP -#define PROGRAM_HPP +#ifndef PROGRAM_HPP_ +#define PROGRAM_HPP_ // std c++ #include diff --git a/src/stack.hpp b/src/stack.hpp index 8e30ebb..237e808 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -1,5 +1,5 @@ -#ifndef __stack_h__ -#define __stack_h__ +#ifndef STACK_HPP_ +#define STACK_HPP_ #include diff --git a/src/version.h b/src/version.h index 52d5a96..7af9ae7 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,7 @@ +#ifndef VERSION_H_ +#define VERSION_H_ + #define RPN_VERSION "2.4" #define RPN_UNAME "rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3" + +#endif From 524f8c73164f233ee974f9c591a584766b3129b5 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 24 Feb 2022 14:16:44 +0100 Subject: [PATCH 38/57] name and order of inclusions --- src/input.cpp | 3 ++- src/input.hpp | 3 ++- src/lexer.hpp | 8 ++++---- src/mpreal-out.hpp | 8 ++++---- src/object.hpp | 4 ++-- src/stack.hpp | 3 +-- 6 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/input.cpp b/src/input.cpp index f93c46d..8891684 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1,6 +1,7 @@ -#include "string.h" #include "input.hpp" +#include + vector* Input::_acWords = nullptr; Input::Input(string& entry, vector& autocompletionWords, string prompt, string mlPrompt) : status(cont) { diff --git a/src/input.hpp b/src/input.hpp index 5328a9c..d481221 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -1,11 +1,12 @@ #ifndef INPUT_HPP_ #define INPUT_HPP_ +#include + #include #include using namespace std; -#include #include "linenoise.h" class Input { diff --git a/src/lexer.hpp b/src/lexer.hpp index 0b428ea..93b0699 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -1,15 +1,15 @@ #ifndef LEXER_HPP_ #define LEXER_HPP_ -#include -#include -using namespace std; - #define MPFR_USE_NO_MACRO #include #include using namespace mpfr; +#include +#include +using namespace std; + #include "constant.h" #include "object.hpp" diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index d007422..98abe7e 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -1,15 +1,15 @@ #ifndef MPREAL_OUT_HPP_ #define MPREAL_OUT_HPP_ -#include -#include -using namespace std; - #define MPFR_USE_NO_MACRO #include #include using namespace mpfr; +#include +#include +using namespace std; + ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); diff --git a/src/object.hpp b/src/object.hpp index 723c5f0..ef6fc1b 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,6 +1,8 @@ #ifndef OBJECT_HPP_ #define OBJECT_HPP_ +#include "mpreal-out.hpp" + #define MPFR_USE_NO_MACRO #include #include @@ -11,8 +13,6 @@ using namespace mpfr; #include using namespace std; -#include "mpreal-out.hpp" - // definitions for objects /// typedef enum { diff --git a/src/stack.hpp b/src/stack.hpp index 237e808..787be32 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -1,8 +1,7 @@ #ifndef STACK_HPP_ #define STACK_HPP_ -#include - +#include #include #include #include From 9eb46998fda396c640465fca4b6bbd4cff1be9e8 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 24 Feb 2022 19:10:02 +0100 Subject: [PATCH 39/57] c++ google style, including cpplint --- CMakeLists.txt | 4 +- Changelog.md | 6 ++ TODO.md | 3 +- src/.clang-format | 1 + src/CPPLINT.cfg | 7 ++ src/constant.h | 51 ----------- src/escape.h | 18 ---- src/input.cpp | 24 ++--- src/input.hpp | 15 ++-- src/lexer.cpp | 17 ++-- src/lexer.hpp | 16 ++-- src/main.cpp | 54 +++-------- src/mpreal-out.cpp | 31 ++++--- src/mpreal-out.hpp | 10 +-- src/object.cpp | 5 +- src/object.hpp | 83 +++++++++++------ src/program.cpp | 178 +++++++++++++++++-------------------- src/program.hpp | 90 +++++++++---------- src/rpn-branch.cpp | 45 +++++----- src/rpn-complex.cpp | 2 + src/rpn-general.cpp | 92 +++++++++---------- src/rpn-logs.cpp | 2 + src/rpn-program.cpp | 32 ++++--- src/rpn-real.cpp | 131 ++++++++++++--------------- src/rpn-stack.cpp | 28 +++--- src/rpn-store.cpp | 53 +++++------ src/rpn-string.cpp | 10 ++- src/rpn-test-framework.cpp | 60 ++++++------- src/rpn-test.cpp | 82 +++++++---------- src/rpn-time.cpp | 20 +++-- src/rpn-trig.cpp | 8 +- src/stack.hpp | 75 +++------------- src/version.h | 8 +- test/090-program.md | 1 + 34 files changed, 569 insertions(+), 693 deletions(-) create mode 100644 src/CPPLINT.cfg delete mode 100644 src/constant.h delete mode 100644 src/escape.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c6bde2f..801a9d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,7 +12,7 @@ endif() message(STATUS "Build mode: ${CMAKE_BUILD_TYPE}") # INFO -set(RPN_VERSION "2.3.2") +set(RPN_VERSION "2.4") set(RPN_DISPLAY_NAME "rpn") set(RPN_URL_INFO_ABOUT "https://github.com/louisrubet/rpn") set(RPN_CONTACT "Louis Rubet ") @@ -25,7 +25,7 @@ set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md") if(CMAKE_COMPILER_IS_GNUCXX) message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}") # TODO still up to date? - set(BASE_COMPILER_OPTIONS "-std=c++14 -Wl,--no-as-needed") + set(BASE_COMPILER_OPTIONS "-std=c++17 -Wl,--no-as-needed") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s") diff --git a/Changelog.md b/Changelog.md index 91f5bf7..9b89648 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,8 +9,13 @@ Changelog - SonarCloud integration, Sonar way profile - clang-format now based on google style - [google c++ style guide](https://google.github.io/styleguide/cppguide.html) applied + - c++17 - define guard - name and order of inclusions + - static and global variables + - common patterns (ex: no static maps or vectors) + - classes (explicit) + - cpplint used with a CPPLINT.cfg removing some warnings - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap - it seems cosh was giving sinh (!) @@ -40,6 +45,7 @@ Compatibility is broken on these points - `sto+` `sto-` `sto*` `sto/` don't accept anymore the syntax `'varname' value stoX`, but only `value 'varname' stoX`, ex: `3 'a' sto*` - incomplete entry `(1,` is not available anymore - signed zero is the sign of zero is subject to change compared to previous version, for example `-3 sqrt` now equals `(0.000000,1.732051)` instead of `(-0.000000,1.732051)` +- removed CtrlC for interrupting a program (considered useless) Debug - `sub` now only accepts boundaries between 1 and the string length diff --git a/TODO.md b/TODO.md index 0412908..ffb181b 100644 --- a/TODO.md +++ b/TODO.md @@ -3,4 +3,5 @@ TODO missing tests / problems - les arguments d'une fonction en erreur doivent ils être consommés ? ex embettant : sto+ -- `1 'i' sto while i 2 <= repeat 0 'j' sto while 1 <= j repeat i (1,0) * j (0,1) * + 1 'j' sto+ end 1 'i' sto+ end` plante +- supprimer les vector et map static (il y en a 3 dans program) +- cpplint to install and run automatically diff --git a/src/.clang-format b/src/.clang-format index becb115..b5a7d96 100644 --- a/src/.clang-format +++ b/src/.clang-format @@ -7,3 +7,4 @@ Language: Cpp DerivePointerAlignment: false PointerAlignment: Left ColumnLimit: 120 +AccessModifierOffset: -3 \ No newline at end of file diff --git a/src/CPPLINT.cfg b/src/CPPLINT.cfg new file mode 100644 index 0000000..d771828 --- /dev/null +++ b/src/CPPLINT.cfg @@ -0,0 +1,7 @@ +set noparent + +filter=-whitespace/line_length + +// avoid "Is this a non-const reference? If so, make const or use a pointer" +// as it seems to be allowed by google now , cf https://github.com/cpplint/cpplint/issues/148 +filter=-runtime/references diff --git a/src/constant.h b/src/constant.h deleted file mode 100644 index b1e1362..0000000 --- a/src/constant.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef CONSTANT_H_ -#define CONSTANT_H_ - -#define MPFR_USE_NO_MACRO -#include - -// default values -// - -// default mode and number of printed digits -// -#define DEFAULT_MODE number::std - -/* directly calculated from 128 bits precision - ceil(128 * log10(2)) - 1 = 38 */ -#define DEFAULT_DECIMAL_DIGITS 38 - -// MPFR related defaults -// - -// 128 bits significand precision -#define MPFR_DEFAULT_PREC_BITS 128 - -// 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_abort_current_entry, - ret_out_of_memory, - ret_bad_value, - ret_test_failed -} ret_value; - -// base min and max -#define BASE_MIN 2 -#define BASE_MAX 62 - -#endif diff --git a/src/escape.h b/src/escape.h deleted file mode 100644 index f279cb9..0000000 --- a/src/escape.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef ESCAPE_H_ -#define ESCAPE_H_ - -// ANSI escape sequences - -// foreground colors -#define FG_BLACK "\33[30m" -#define FG_RED "\33[31m" -#define FG_GREEN "\33[32m" - -// background colors -#define COLOR_OFF "\33[m" - -// attributes -#define ATTR_BOLD "\33[1m" -#define ATTR_OFF "\33[0m" - -#endif diff --git a/src/input.cpp b/src/input.cpp index 8891684..c41f1bf 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "input.hpp" #include @@ -5,7 +7,7 @@ vector* Input::_acWords = nullptr; Input::Input(string& entry, vector& autocompletionWords, string prompt, string mlPrompt) : status(cont) { - char* c_entry; + char* c_entry = nullptr; bool multiline = false; int entry_len; @@ -36,10 +38,12 @@ Input::Input(string& entry, vector& autocompletionWords, string prompt, // keep history if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str()); status = ok; - } else + } else { status = error; + } } } + free(c_entry); } /// @brief completion callback as asked by linenoise-ng @@ -49,24 +53,20 @@ Input::Input(string& entry, vector& autocompletionWords, string prompt, /// @param lc the completion object to add strings with linenoiseAddCompletion() /// void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) { - if (Input::_acWords == nullptr || text == nullptr) - return; - + if (Input::_acWords == nullptr || text == nullptr) return; + int text_len = strnlen(text, 6); - // propose all keywords if (text_len == 0) - for (string& ac : *Input::_acWords) - // add all keywords - linenoiseAddCompletion(lc, ac.c_str()); - // propose keywords matching to text begining + // propose all keywords + for (string& ac : *Input::_acWords) linenoiseAddCompletion(lc, ac.c_str()); else + // propose only keywords matching to text begining for (string& ac : *Input::_acWords) // compare list entry with text, return if match if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str()); } void Input::preload(const char* preloadText) { - if (preloadText != nullptr) - linenoisePreloadBuffer(preloadText); + if (preloadText != nullptr) linenoisePreloadBuffer(preloadText); } diff --git a/src/input.hpp b/src/input.hpp index d481221..cec0079 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -1,8 +1,9 @@ -#ifndef INPUT_HPP_ -#define INPUT_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_INPUT_HPP_ +#define SRC_INPUT_HPP_ #include - #include #include using namespace std; @@ -10,15 +11,15 @@ using namespace std; #include "linenoise.h" class Input { - public: + public: Input(string& entry, vector& autocompletionWords, string prompt = "rpn> ", string mlPrompt = ">"); - enum {ok, cont, abort, ctrlc, error} status; + enum { ok, cont, abort, ctrlc, error } status; static void preload(const char* preloadText); - private: + private: static void entry_completion_generator(const char* text, linenoiseCompletions* lc); static vector* _acWords; }; -#endif +#endif // SRC_INPUT_HPP_ diff --git a/src/lexer.cpp b/src/lexer.cpp index 309a7eb..e4428f3 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "lexer.hpp" bool Lexer::lexer(string& entry, map& keywords, vector& elements, @@ -85,17 +87,18 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& nextIdx, vector>" or "»" int countNested = 0; for (size_t i = idx + 2; i < entry.size() - 1; i++) { - if ((entry[i] == '<' && entry[i + 1] == '<') || (entry.substr(i, 2) == "«")) + if ((entry[i] == '<' && entry[i + 1] == '<') || (entry.substr(i, 2) == "«")) { countNested++; - else if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { + } else if ((entry[i] == '>' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { if (countNested == 0) { string prg = entry.substr(idx + 2, i - idx - 2); trim(prg); elements.push_back({cmd_program, .value = prg}); nextIdx = i + 2; return true; - } else + } else { countNested--; + } } } string prg = entry.substr(idx + 2, entry.size() - idx - 2); @@ -138,11 +141,11 @@ int Lexer::getBaseAt(string& entry, size_t& nextIdx, bool& positive) { } else if (isdigit(a)) { if (b == 'b' || b == 'B') { nextIdx = scan + 2; - return int(a - '0'); + return static_cast(a - '0'); } if (isdigit(b) && (c == 'b' || c == 'B')) { nextIdx = scan + 3; - return 10 * int(a - '0') + int(b - '0'); + return 10 * static_cast(a - '0') + static_cast(b - '0'); } } return 10; @@ -162,7 +165,7 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m nextIdx = token.size() + idx + 1; trim(token); base = getBaseAt(token, numberIdx, positive); - if (base < BASE_MIN || base > BASE_MAX) return false; + if (base < 2 || base > 62) return false; if (numberIdx != 0) token = token.substr(numberIdx); *r = new mpreal; if (mpfr_set_str((*r)->mpfr_ptr(), token.c_str(), base, mpreal::get_default_rnd()) == 0) { @@ -170,7 +173,7 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m return true; } else { delete *r; - return false; + return false; } } nextIdx = token.size() + idx + 1; diff --git a/src/lexer.hpp b/src/lexer.hpp index 93b0699..08fc468 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -1,20 +1,20 @@ -#ifndef LEXER_HPP_ -#define LEXER_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_LEXER_HPP_ +#define SRC_LEXER_HPP_ -#define MPFR_USE_NO_MACRO -#include #include using namespace mpfr; #include #include +#include using namespace std; -#include "constant.h" #include "object.hpp" class Lexer { - public: + public: // a structure to describe a syntaxical element and its value struct SynElement { cmd_type_t type; @@ -50,7 +50,7 @@ class Lexer { bool lexer(string& entry, map& keywords, vector& elements, vector& errors); - private: + private: bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, vector& elements); bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, @@ -70,4 +70,4 @@ class Lexer { bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal** r, char delim = ' '); }; -#endif +#endif // SRC_LEXER_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 3db8aeb..a88ee26 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,10 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include #include -#include #include +#include #include using namespace std; @@ -10,10 +12,6 @@ using namespace std; #include "input.hpp" #include "program.hpp" -static heap _global_heap; -static rpnstack _global_stack; -static program* _prog_to_interrupt = nullptr; - /// @brief actions to be done at rpn exit /// static void exit_interactive_rpn() { @@ -54,26 +52,7 @@ static void init_interactive_rpn() { /// @param siginfo signal info, see POSIX sigaction /// @param context see POSIX sigaction /// -static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { - if (_prog_to_interrupt != nullptr) { - _prog_to_interrupt->stop(); - _prog_to_interrupt = nullptr; - } - - exit_interactive_rpn(); -} - -/// @brief handle SIGSEGV signal (sigaction handler): stop and exit rpn -/// -/// @param sig signal, see POSIX sigaction -/// @param siginfo signal info, see POSIX sigaction -/// @param context see POSIX sigaction -/// -static void segv_handler(int sig, siginfo_t* siginfo, void* context) { - cerr << "Internal error" << endl; - _prog_to_interrupt->stop(); - _prog_to_interrupt = nullptr; -} +static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { exit_interactive_rpn(); } /// @brief setup signals handlers to stop with honours /// @@ -82,17 +61,10 @@ static void segv_handler(int sig, siginfo_t* siginfo, void* context) { static void catch_signals(program* prog) { struct sigaction act = {0}; - _prog_to_interrupt = prog; - act.sa_sigaction = &ctrlc_handler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, nullptr) < 0) cerr << "Warning, Ctrl-C cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; - - act.sa_sigaction = &segv_handler; - act.sa_flags = SA_SIGINFO; - if (sigaction(SIGSEGV, &act, nullptr) < 0) - cerr << "Warning, SIGSEGV cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; } /// @brief rpn entry point @@ -114,9 +86,12 @@ int main(int argc, char* argv[]) { init_interactive_rpn(); // entry loop + heap heap; + rpnstack stack; while (go_on) { + // // make program from interactive entry - program prog(_global_stack, _global_heap); + program prog(stack, heap); string entry; switch (Input(entry, program::getAutocompletionWords()).status) { case Input::ok: @@ -126,7 +101,7 @@ int main(int argc, char* argv[]) { if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye) go_on = false; else - program::show_stack(_global_stack); + prog.show_stack(); break; case Input::ctrlc: go_on = false; @@ -139,15 +114,14 @@ int main(int argc, char* argv[]) { // manage history and exit exit_interactive_rpn(); } else { // run with cmd line arguments - program prog(_global_stack, _global_heap); + heap heap; + rpnstack stack; + program prog(stack, heap); string entry; int i; // make one string from entry - for (i = 1; i < argc; i++) { - entry += argv[i]; - entry += ' '; - } + for (i = 1; i < argc; i++) entry += string(argv[i]) + ' '; // make program ret = prog.parse(entry); @@ -157,7 +131,7 @@ int main(int argc, char* argv[]) { // run it ret = prog.run(); - program::show_stack(_global_stack, false); + prog.show_stack(false); } } diff --git a/src/mpreal-out.cpp b/src/mpreal-out.cpp index 0c58a3e..276852d 100644 --- a/src/mpreal-out.cpp +++ b/src/mpreal-out.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "mpreal-out.hpp" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) @@ -43,7 +45,7 @@ ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& valu static bool is_min(const mpreal& p, mpfr_prec_t prec) { // see mpfr_vasprintf code - // TODO here use mpreal functions like <=0, isinf etc + // TODO(louis): here use mpreal functions like <=0, isinf etc bool ret; int round_away; switch (mpreal::get_default_rnd()) { @@ -98,9 +100,9 @@ static void _out_base(ostream& out, int base) { ostream& _out_singular(ostream& out, int base, const mpreal& value) { const char* write_after_sign = NULL; // unused for now int digits = 0; // forced 0 digits after separator - if (MPFR_IS_NAN(value.mpfr_srcptr())) + if (MPFR_IS_NAN(value.mpfr_srcptr())) { out << "nan"; - else if (MPFR_IS_INF(value.mpfr_srcptr())) { + } else if (MPFR_IS_INF(value.mpfr_srcptr())) { if (MPFR_IS_NEG(value.mpfr_srcptr())) out << '-'; out << "inf"; } else { @@ -142,7 +144,9 @@ ostream& _out_number(ostream& out, int base, const mpreal& value) { int digits = 0; // forced 0 digits after separator mpfr_exp_t exp = mpfr_get_exp(value.mpfr_srcptr()); - char* str = mpfr_get_str(NULL, &exp, base, digits + exp + 1, value.mpfr_srcptr(), mpreal::get_default_rnd()); + char* str = mpfr_get_str(NULL, &exp, base, digits + static_cast(exp) + 1, value.mpfr_srcptr(), + mpreal::get_default_rnd()); + int nexp = static_cast(exp); char* print_from; if (str != NULL) { int len = strlen(str); @@ -163,25 +167,26 @@ ostream& _out_number(ostream& out, int base, const mpreal& value) { out << "0b"; else out << base << "b"; - if (exp < 0) { + if (nexp < 0) { out << '0'; if (digits > 0) { out << '.'; - for (int i = 0; i < -(int)exp; i++) out << '0'; + for (int i = 0; i < -nexp; i++) out << '0'; out << str; - for (int i = 0; i < (int)(digits - len + exp); i++) out << '0'; + for (int i = 0; i < digits - len + nexp; i++) out << '0'; } } else { - if (exp == 0) + if (nexp == 0) { out << '0'; - else - for (int i = 0; i < (int)exp; i++) out << print_from[i]; + } else { + for (int i = 0; i < nexp; i++) out << print_from[i]; + } if (digits > 0) { out << '.'; - int remaining = (int)MIN(strlen(print_from) - exp - 1, digits) + 1; - for (int i = (int)exp; i < remaining + (int)exp; i++) out << print_from[i]; - for (int i = 0; i < (int)(exp + digits - len); i++) out << '0'; + int remaining = MIN(strlen(print_from) - nexp - 1, digits) + 1; + for (int i = nexp; i < remaining + nexp; i++) out << print_from[i]; + for (int i = 0; i < nexp + digits - len; i++) out << '0'; } } } diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index 98abe7e..cac8f10 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -1,8 +1,8 @@ -#ifndef MPREAL_OUT_HPP_ -#define MPREAL_OUT_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_MPREAL_OUT_HPP_ +#define SRC_MPREAL_OUT_HPP_ -#define MPFR_USE_NO_MACRO -#include #include using namespace mpfr; @@ -13,4 +13,4 @@ using namespace std; ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); -#endif +#endif // SRC_MPREAL_OUT_HPP_ diff --git a/src/object.cpp b/src/object.cpp index e9af391..43b8d49 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -1,6 +1,7 @@ -#include "constant.h" +// Copyright (c) 2014-2022 Louis Rubet + #include "object.hpp" // number statics -number::mode_enum number::s_mode = DEFAULT_MODE; +number::mode_enum number::s_mode = number::DEFAULT_MODE; int number::s_digits = DEFAULT_DECIMAL_DIGITS; diff --git a/src/object.hpp b/src/object.hpp index ef6fc1b..0c52665 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -1,20 +1,41 @@ -#ifndef OBJECT_HPP_ -#define OBJECT_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_OBJECT_HPP_ +#define SRC_OBJECT_HPP_ + +#include #include "mpreal-out.hpp" - -#define MPFR_USE_NO_MACRO -#include -#include using namespace mpfr; #include -#include #include +#include using namespace std; // definitions for objects /// +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_abort_current_entry, + ret_out_of_memory, + ret_bad_value, + ret_test_failed +} ret_value; + typedef enum { cmd_undef, cmd_number, // floating point number @@ -36,7 +57,7 @@ typedef size_t (program::*branch_fn_t)(branch&); /// @brief object - a generic stack object /// struct object { - object(cmd_type_t type = cmd_undef) : _type(type) {} + explicit object(cmd_type_t type = cmd_undef) : _type(type) {} virtual ~object() {} cmd_type_t _type; virtual object* clone() { @@ -59,8 +80,8 @@ struct object { /// struct number : object { number() : object(cmd_number), base(10) {} - number(const mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} - number(long value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} + explicit number(const mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} + explicit number(int value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} int base; mpreal value; @@ -72,18 +93,21 @@ struct number : object { // representation mode typedef enum { std, fix, sci } mode_enum; static mode_enum s_mode; + static constexpr mode_enum DEFAULT_MODE = number::std; // precision + static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128; + static constexpr int DEFAULT_DECIMAL_DIGITS = 38; static int s_digits; // clang-format off static string _makeNumberFormat(mode_enum mode, int digits) { stringstream format; - format<<"%."<& value_, int reb = 10, int imb = 10) : object(cmd_complex), reBase(reb), imBase(imb) { + explicit ocomplex(complex& value_, int reb = 10, int imb = 10) + : object(cmd_complex), reBase(reb), imBase(imb) { value = value_; } - ocomplex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) : object(cmd_complex), reBase(reb), imBase(imb) { + explicit ocomplex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) + : object(cmd_complex), reBase(reb), imBase(imb) { value.real(re_); value.imag(im_); } @@ -127,7 +153,7 @@ struct ocomplex : object { /// struct ostring : object { ostring() : object(cmd_string) {} - ostring(const string& value_) : object(cmd_string), value(value_) {} + explicit ostring(const string& value_) : object(cmd_string), value(value_) {} virtual object* clone() { return new ostring(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } @@ -138,7 +164,7 @@ struct ostring : object { /// struct oprogram : object { oprogram() : object(cmd_program) {} - oprogram(const string& value_) : object(cmd_program), value(value_) {} + explicit oprogram(const string& value_) : object(cmd_program), value(value_) {} virtual object* clone() { return new oprogram(value); } virtual string name() { return string("program"); } virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } @@ -148,8 +174,9 @@ struct oprogram : object { /// @brief object symbol /// struct symbol : object { - symbol(bool autoEval_ = true) : object(cmd_symbol), autoEval(autoEval_) {} - symbol(const string& value_, bool autoEval_ = true) : object(cmd_symbol), value(value_), autoEval(autoEval_) {} + explicit symbol(bool autoEval_ = true) : object(cmd_symbol), autoEval(autoEval_) {} + explicit symbol(const string& value_, bool autoEval_ = true) + : object(cmd_symbol), value(value_), autoEval(autoEval_) {} virtual object* clone() { return new symbol(value, autoEval); } virtual string name() { return string("symbol"); } virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } @@ -161,7 +188,7 @@ struct symbol : object { /// struct keyword : object { keyword() : object(cmd_keyword) {} - keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword), fn(fn_), value(value_) {} + explicit keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword), fn(fn_), value(value_) {} virtual object* clone() { return new keyword(fn, value); } virtual string name() { return string("keyword"); } program_fn_t fn; @@ -172,15 +199,15 @@ struct keyword : object { /// struct branch : object { branch() : object(cmd_branch) {} - branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { + explicit branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { fn = fn_; - arg1 = (size_t)-1; - arg2 = (size_t)-1; - arg3 = (size_t)-1; + arg1 = static_cast(-1); + arg2 = static_cast(-1); + arg3 = static_cast(-1); arg_bool = 0; value = value_; } - branch(branch& other) : object(cmd_branch) { + explicit branch(branch& other) : object(cmd_branch) { fn = other.fn; arg1 = other.arg1; arg2 = other.arg2; @@ -197,4 +224,4 @@ struct branch : object { string value; }; -#endif +#endif // SRC_OBJECT_HPP_ diff --git a/src/program.cpp b/src/program.cpp index 5ae1757..918b2ab 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" //< language reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef) @@ -201,17 +203,13 @@ vector program::_keywords{ {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, }; -/// keywords map for lexer -map program::_keywordsMap; - /// autocompletion vector for linenoise autocompletion -vector program::_autocompletionWords; - vector& program::getAutocompletionWords() { - if (_autocompletionWords.empty()) + static vector autocompletionWords; + if (autocompletionWords.empty()) for (auto& kw : _keywords) - if (!kw.name.empty()) _autocompletionWords.push_back(kw.name); - return _autocompletionWords; + if (!kw.name.empty()) autocompletionWords.push_back(kw.name); + return autocompletionWords; } /// @brief run a program on a stack and a heap @@ -236,18 +234,18 @@ ret_value program::run() { } // iterate commands - for (size_t i = 0; (go_out == false) && (interrupt_now == false) && (i < size());) { + for (size_t i = 0; (go_out == false) && (i < size());) { object* o = at(i); switch (o->_type) { // could be an auto-evaluated symbol case cmd_symbol: - auto_rcl((symbol*)o); + auto_rcl(reinterpret_cast(o)); i++; break; // a keyword case cmd_keyword: { - keyword* k = (keyword*)o; + keyword* k = reinterpret_cast(o); // call the matching function (this->*(k->fn))(); switch (_err) { @@ -264,8 +262,7 @@ ret_value program::run() { go_out = true; // test error: make rpn return EXIT_FAILURE - if (_err == ret_test_failed) - ret = ret_test_failed; + if (_err == ret_test_failed) ret = ret_test_failed; // error: show it if (show_error(_err, _err_context) == ret_deadly) @@ -280,13 +277,13 @@ ret_value program::run() { // a branch keyword case cmd_branch: { // call matching function - branch* b = (branch*)o; + branch* b = reinterpret_cast(o); size_t next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { - case step_out: // step out - i++; // meaning 'next command' + case step_out: // step out + i++; // meaning 'next command' break; - case runtime_error: // runtime error + case runtime_error: // runtime error (void)show_error(_err, _err_context); go_out = true; break; @@ -310,34 +307,9 @@ ret_value program::run() { for (object* o : *this) delete o; _local_heap.clear(); - if (interrupt_now) { - cerr << endl << "Interrupted" << endl; - interrupt_now = false; - } - return ret; } -/// @brief stop a program -/// -/// -void program::stop() { interrupt_now = true; } - -/// @brief return whether a branch object has a given name -/// -/// @param b the branch object -/// @param str_to_compare the name -/// @param len the name length -/// @return true the branch name is str_to_compare -/// @return false the branch name is NOT str_to_compare -/// -bool program::compare_branch(branch* b, const char* str_to_compare, int len) { - if (str_to_compare != nullptr) - return b->value == str_to_compare; - else - return false; -} - /// @brief prepare a program for execution /// this is needed before a program can be run /// inner members of branch or keyword objects are filled by this function @@ -346,6 +318,20 @@ bool program::compare_branch(branch* b, const char* str_to_compare, int len) { /// @return ret_value see this type /// ret_value program::preprocess(void) { + struct if_layout_t { + if_layout_t() + : index_then_or_unti_or_repeat(-1), + index_else(-1), + index_end(-1), + is_do_unti(false), + is_while_repeat(false) {} + int index_if_or_do_or_while; + int index_then_or_unti_or_repeat; + int index_else; + int index_end; + bool is_do_unti; + bool is_while_repeat; + }; // for if-then-else-end vector vlayout; int layout_index = -1; @@ -354,20 +340,20 @@ ret_value program::preprocess(void) { // analyse if-then-else-end branches // analyse start-{next, step} branches - for (int i = 0; i < (int)size(); i++) { - if ((*this)[i]->_type == cmd_branch) { - branch* k = (branch*)(*this)[i]; - if (compare_branch(k, "if", 2)) { + for (size_t i = 0; i < size(); i++) { + if (at(i)->_type == cmd_branch) { + branch* k = reinterpret_cast(at(i)); + if (k->value == "if") { if_layout_t layout; layout.index_if_or_do_or_while = i; vlayout.push_back(layout); layout_index++; - } else if (compare_branch(k, "then", 4)) { - int next = i + 1; - if (next >= (int)size()) next = -1; + } else if (k->value == "then") { + size_t next = i + 1; + if (next >= size()) next = step_out; // nothing after 'then' -> error - if (next == -1) { + if (next == step_out) { // error: show it show_syntax_error("missing end after then"); return ret_syntax; @@ -385,12 +371,12 @@ ret_value program::preprocess(void) { vlayout[layout_index].index_then_or_unti_or_repeat = i; k->arg1 = next; k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - } else if (compare_branch(k, "else", 4)) { - int next = i + 1; - if (next >= (int)size()) next = -1; + } else if (k->value == "else") { + size_t next = i + 1; + if (next >= size()) next = step_out; // nothing after 'else' -> error - if (next == -1) { + if (next == step_out) { // error: show it show_syntax_error("missing end after else"); return ret_syntax; @@ -413,47 +399,47 @@ ret_value program::preprocess(void) { vlayout[layout_index].index_else = i; k->arg1 = next; // fill branch1 (if was false) of 'else' k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg2 = + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = next; // fill branch2 (if was false) of 'then' - } else if (compare_branch(k, "start", 5)) + } else if (k->value == "start") { vstartindex.push_back(i); - else if (compare_branch(k, "for", 3)) { + } else if (k->value == "for") { vstartindex.push_back(i); k->arg1 = i + 1; // arg1 points on symbol variable - } else if (compare_branch(k, "next", 4)) { + } else if (k->value == "next") { 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*)(*this)[vstartindex[vstartindex.size() - 1]])->arg2 = + reinterpret_cast(at(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); - } else if (compare_branch(k, "step", 4)) { + } else if (k->value == "step") { 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*)(*this)[vstartindex[vstartindex.size() - 1]])->arg2 = + reinterpret_cast(at(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); - } else if (compare_branch(k, "->", 2)) { + } else if (k->value == "->") { k->arg1 = i; // arg1 is '->' command index in program - } else if (compare_branch(k, "do", 2)) { + } else if (k->value == "do") { if_layout_t layout; layout.index_if_or_do_or_while = i; layout.is_do_unti = true; vlayout.push_back(layout); layout_index++; - } else if (compare_branch(k, "until", 4)) { - int next = i + 1; - if (next >= (int)size()) next = -1; + } else if (k->value == "until") { + size_t next = i + 1; + if (next >= size()) next = step_out; // nothing after 'unti' -> error - if (next == -1) { + if (next == step_out) { // error: show it show_syntax_error("missing end"); return ret_syntax; @@ -469,13 +455,13 @@ ret_value program::preprocess(void) { return ret_syntax; } vlayout[layout_index].index_then_or_unti_or_repeat = i; - } else if (compare_branch(k, "while", 4)) { + } else if (k->value == "while") { if_layout_t layout; layout.index_if_or_do_or_while = i; layout.is_while_repeat = true; vlayout.push_back(layout); layout_index++; - } else if (compare_branch(k, "repeat", 5)) { + } else if (k->value == "repeat") { if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) { // error: show it show_syntax_error("missing while"); @@ -487,9 +473,9 @@ ret_value program::preprocess(void) { return ret_syntax; } vlayout[layout_index].index_then_or_unti_or_repeat = i; - } else if (compare_branch(k, "end", 3)) { - int next = i + 1; - if (next >= (int)size()) next = -1; + } else if (k->value == "end") { + size_t next = i + 1; + if (next >= size()) next = step_out; if (layout_index < 0) { // error: show it @@ -529,7 +515,8 @@ ret_value program::preprocess(void) { } // fill 'repeat' arg1 with 'end+1' - ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg1 = i + 1; + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg1 = + i + 1; layout_index--; } else { // this end closes an if..then..(else) @@ -538,14 +525,15 @@ ret_value program::preprocess(void) { show_syntax_error("duplicate end"); return ret_syntax; } - if (vlayout[layout_index].index_else != -1) + if (vlayout[layout_index].index_else != -1) { // fill 'end' branch of 'else' - ((branch*)(*this)[vlayout[layout_index].index_else])->arg2 = i; - else { + reinterpret_cast(at(vlayout[layout_index].index_else))->arg2 = i; + } else { // fill 'end' branch of 'then' - if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) - ((branch*)(*this)[vlayout[layout_index].index_then_or_unti_or_repeat])->arg2 = i; - else { + if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat)) + ->arg2 = i; + } else { // error: show it show_syntax_error("missing then"); return ret_syntax; @@ -577,17 +565,18 @@ ret_value program::preprocess(void) { /// @return ret_value see this type /// ret_value program::parse(string& entry) { + static map keywordsMap; vector elements; vector errors; ret_value ret = ret_ok; // prepare map for finding reserved keywords - if (_keywordsMap.empty()) + if (keywordsMap.empty()) for (auto& kw : _keywords) - if (!kw.name.empty()) _keywordsMap[kw.name] = {kw.type, kw.fn}; + if (!kw.name.empty()) keywordsMap[kw.name] = {kw.type, kw.fn}; // separate the entry string - if (lexer(entry, _keywordsMap, elements, errors)) { + if (lexer(entry, keywordsMap, elements, errors)) { // make objects from parsed elements for (Lexer::SynElement& element : elements) { switch (element.type) { @@ -619,8 +608,9 @@ ret_value program::parse(string& entry) { if (element.re != nullptr) delete element.re; if (element.im != nullptr) delete element.im; } - } else + } else { for (SynError& err : errors) show_syntax_error(err.err.c_str()); + } return ret; } @@ -638,7 +628,7 @@ ret_value program::show_error() { "bad value", "test failed"}; // clang-format on // show last recorded error - if ((size_t)_err < errorStrings.size()) + if (static_cast(_err) < errorStrings.size()) cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl; else cerr << _err_context << " (unknown error code)" << endl; @@ -701,26 +691,26 @@ ret_value program::get_err(void) { return _err; } /// @brief show a stack (show its different objects) /// generally a stack is associated to a running program /// -/// @param st the stack to show /// @param show_separator whether to show a stack level prefix or not /// -void program::show_stack(rpnstack& st, bool show_separator) { - if (st.size() == 1) - cout << st[0] << endl; - else - for (int i = st.size() - 1; i >= 0; i--) { +void program::show_stack(bool show_separator) { + if (_stack.size() == 1) { + cout << _stack[0] << endl; + } else { + for (int i = _stack.size() - 1; i >= 0; i--) { if (show_separator) cout << i + 1 << "> "; - cout << st[i] << endl; + cout << _stack[i] << endl; } + } } /// @brief apply default precision mode and digits /// void program::apply_default() { // default float precision, float mode - number::s_mode = DEFAULT_MODE; - number::s_digits = DEFAULT_DECIMAL_DIGITS; - mpreal::set_default_prec(MPFR_DEFAULT_PREC_BITS); + number::s_mode = number::DEFAULT_MODE; + number::s_digits = number::DEFAULT_DECIMAL_DIGITS; + mpreal::set_default_prec(number::MPFR_DEFAULT_PREC_BITS); static mp_rnd_t def_rnd = mpreal::get_default_rnd(); mpreal::set_default_rnd(def_rnd); diff --git a/src/program.hpp b/src/program.hpp index 9a1cef4..3571bbf 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -1,40 +1,27 @@ -#ifndef PROGRAM_HPP_ -#define PROGRAM_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_PROGRAM_HPP_ +#define SRC_PROGRAM_HPP_ // std c++ +#include #include +#include #include using namespace std; -#define MPFR_USE_NO_MACRO -#include #include using namespace mpfr; // internal includes -#include "constant.h" #include "lexer.hpp" #include "object.hpp" #include "stack.hpp" -//< convinient structure to preprocess a program -struct if_layout_t { - if_layout_t() - : index_then_or_unti_or_repeat(-1), index_else(-1), index_end(-1), is_do_unti(false), is_while_repeat(false) {} - int index_if_or_do_or_while; - int index_then_or_unti_or_repeat; - int index_else; - int index_end; - bool is_do_unti; - bool is_while_repeat; -}; - //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque, public Lexer { - public: - program(rpnstack& stk, heap& hp, program* parent = nullptr) : _stack(stk), _heap(hp), _parent(parent) { - interrupt_now = false; - } + public: + program(rpnstack& stk, heap& hp, program* parent = nullptr) : _stack(stk), _heap(hp), _parent(parent) {} virtual ~program() { _local_heap.clear(); clear(); @@ -47,7 +34,6 @@ class program : public deque, public Lexer { // running ret_value run(); void stop(); - bool compare_branch(branch* b, const char* str_to_compare, int len); ret_value preprocess(void); ret_value show_error(); @@ -56,15 +42,13 @@ class program : public deque, public Lexer { void show_syntax_error(const char* context); ret_value get_err(void); - static void show_stack(rpnstack& st, bool show_separator = true); + void show_stack(bool show_separator = true); static void apply_default(); static vector& getAutocompletionWords(); - private: - bool interrupt_now; - + private: // current error and its context ret_value _err; string _err_context; @@ -81,9 +65,7 @@ class program : public deque, public Lexer { // parent prog for inheriting heaps program* _parent; - int stack_size() { return _stack.size(); } - - private: + private: // keywords struct keyword_t { cmd_type_t type; @@ -92,8 +74,6 @@ class program : public deque, public Lexer { string comment; }; static vector _keywords; - static map _keywordsMap; - static vector _autocompletionWords; // keywords implementation //// @@ -113,7 +93,7 @@ class program : public deque, public Lexer { size_t rpn_for(branch& myobj); size_t rpn_next(branch& myobj); size_t rpn_step(branch& myobj); - enum { step_out = (size_t)-1, runtime_error = (size_t)-2 }; + enum { step_out = static_cast(-1), runtime_error = static_cast(-2) }; // complex void rpn_re(); @@ -233,14 +213,11 @@ class program : public deque, public Lexer { void rpn_strsub(); // test-core - void test_get_stack(string& stack_is, rpnstack& stk); - void test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed); void rpn_test(); void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed); // test - long cmp_strings_on_stack_top(); void rpn_sup(void); void rpn_sup_eq(void); void rpn_inf(void); @@ -270,26 +247,45 @@ class program : public deque, public Lexer { void rpn_ticks(); }; -// clang-format off - // convenience macros for rpn_xx function // carefull : some of these macros modify program flow -#define setErrorContext(err) do { _err = (err); _err_context = __FUNCTION__; } while (0) -#define MIN_ARGUMENTS(num) do { \ - if (stack_size() < (num)) { setErrorContext(ret_missing_operand); return; } \ +#define setErrorContext(err) \ + do { \ + _err = (err); \ + _err_context = __FUNCTION__; \ } while (0) -#define MIN_ARGUMENTS_RET(num, ret) do { \ - if (stack_size() < (num)) { setErrorContext(ret_missing_operand); return (ret); } \ +#define MIN_ARGUMENTS(num) \ + do { \ + if ((num) >= 0 && _stack.size() < (num)) { \ + setErrorContext(ret_missing_operand); \ + return; \ + } \ } while (0) -#define ARG_MUST_BE_OF_TYPE(num, type) do { \ - if (_stack.at(num)->_type != (type)) { setErrorContext(ret_bad_operand_type); return; } \ +#define MIN_ARGUMENTS_RET(num, ret) \ + do { \ + if ((num) >= 0 && _stack.size() < (num)) { \ + setErrorContext(ret_missing_operand); \ + return (ret); \ + } \ } while (0) -#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) do { \ - if (_stack.at(num)->_type != (type)) { setErrorContext(ret_bad_operand_type); return (ret); } \ +#define ARG_MUST_BE_OF_TYPE(num, type) \ + do { \ + if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ + setErrorContext(ret_bad_operand_type); \ + return; \ + } \ } while (0) -#endif +#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ + do { \ + if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ + setErrorContext(ret_bad_operand_type); \ + return (ret); \ + } \ + } while (0) + +#endif // SRC_PROGRAM_HPP_ diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index d9c42e0..182cc03 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief if keyword (branch) implementation @@ -38,7 +40,7 @@ size_t program::rpn_then(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - if_cmd = (branch*)at(myobj.arg3); + if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) return myobj.arg1; else @@ -63,7 +65,7 @@ size_t program::rpn_else(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - if_cmd = (branch*)at(myobj.arg3); + if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) return myobj.arg2; else @@ -89,10 +91,10 @@ size_t program::rpn_end(branch& myobj) { // check arg if (_stack.value(0) == 0) ret = myobj.arg1; _stack.pop(); - } - // arg2 = index of while+1 in case of while..repeat..end - else if (myobj.arg2 != step_out) + } else if (myobj.arg2 != step_out) { + // arg2 = index of while+1 in case of while..repeat..end ret = myobj.arg2; + } return ret; } @@ -134,11 +136,10 @@ void program::rpn_ift(void) { // check ift arg // arg is true if number != 0 or if is nan or +/-inf - if (_stack.value(1) != 0) { + if (_stack.value(1) != 0) _stack.erase(1); - } else { - _stack.pop_front(2); - } + else + _stack.erase(0, 2); } /// @brief ifte keyword (branch) implementation @@ -212,7 +213,7 @@ size_t program::rpn_start(branch& myobj) { // loop boundaries myobj.firstIndex = _stack.value(1); myobj.lastIndex = _stack.value(0); - _stack.pop_front(2); + _stack.erase(0, 2); // test value if (myobj.firstIndex > myobj.lastIndex) @@ -243,19 +244,19 @@ size_t program::rpn_for(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - sym = (symbol*)at(myobj.arg1); // arg1 = loop variable index + sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index // loop boundaries myobj.firstIndex = _stack.value(1); myobj.lastIndex = _stack.value(0); // test value - if (myobj.firstIndex > myobj.lastIndex) + if (myobj.firstIndex > myobj.lastIndex) { // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' ret = myobj.arg2 + 1; - else { + } else { // store symbol with first value auto it = _local_heap.find(sym->value); if (it != _local_heap.end()) { @@ -266,7 +267,7 @@ size_t program::rpn_for(branch& myobj) { ret = myobj.arg1 + 1; } - _stack.pop_front(2); + _stack.erase(0, 2); return ret; } @@ -286,7 +287,7 @@ size_t program::rpn_next(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - start_or_for = (branch*)at(myobj.arg1); + start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -304,10 +305,10 @@ size_t program::rpn_next(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - var = (symbol*)at(start_or_for->arg1); + var = reinterpret_cast(at(start_or_for->arg1)); // store symbol variable (asserted existing in the local heap) - ((number*)_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; } // test value @@ -340,9 +341,9 @@ size_t program::rpn_step(branch& myobj) { _stack.pop(); // end of loop if step is negative or zero - if (step <= 0) + if (step <= 0) { ret = step_out; - else { + } else { // arg1 = loop variable index // firstIndex = current count branch* start_or_for; @@ -350,7 +351,7 @@ size_t program::rpn_step(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - start_or_for = (branch*)at(myobj.arg1); + start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -369,9 +370,9 @@ size_t program::rpn_step(branch& myobj) { setErrorContext(ret_missing_operand); return runtime_error; } - var = (symbol*)at(start_or_for->arg1); + var = reinterpret_cast(at(start_or_for->arg1)); // increase symbol variable - ((number*)_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; } // test loop value is out of range diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index 3444fbc..ca94145 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief re keyword implementation diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 962b91d..cd04390 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -1,34 +1,39 @@ -#include -#include "linenoise.h" +// Copyright (c) 2014-2022 Louis Rubet + +#include +#include + +#include "linenoise.h" +using namespace std; -#include "escape.h" #include "program.hpp" #include "version.h" // description +static const string ATTR_BOLD = "\33[1m"; +static const string ATTR_OFF = "\33[0m"; + #define XSTR(a) STR(a) #define STR(a) #a -static const string _description{ - ATTR_BOLD "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF - "otation language\n\n" - "using " ATTR_BOLD "GMP" ATTR_OFF " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( - __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING - " under GNU LGPL\n" - "and " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION - " under BSD\n"}; +static const string _description{ATTR_BOLD + "R" + ATTR_OFF + "everse " + ATTR_BOLD + "P" + ATTR_OFF + "olish " + + ATTR_BOLD + "N" + ATTR_OFF + "otation language\n\nusing " + ATTR_BOLD + "GMP" + + ATTR_OFF + + " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( + __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" + + ATTR_BOLD + "MPFR" + ATTR_OFF + " v" MPFR_VERSION_STRING " under GNU LGPL\nand " + + ATTR_BOLD + "linenoise-ng" + ATTR_OFF + " v" LINENOISE_VERSION " under BSD\n"}; // syntax -static const string _syntax{ATTR_BOLD "Syntax" ATTR_OFF - ": rpn [command]\n" - "with optional command = list of commands"}; +static const string _syntax{ATTR_BOLD + "Syntax" + ATTR_OFF + + ": rpn [command]\nwith optional command = list of commands"}; static const map _mpfr_round{{"nearest (even)", MPFR_RNDN}, - {"toward zero", MPFR_RNDZ}, - {"toward +inf", MPFR_RNDU}, - {"toward -inf", MPFR_RNDD}, - {"away from zero", MPFR_RNDA}, - {"faithful rounding", MPFR_RNDF}, - {"nearest (away from zero)", MPFR_RNDNA}}; + {"toward zero", MPFR_RNDZ}, + {"toward +inf", MPFR_RNDU}, + {"toward -inf", MPFR_RNDD}, + {"away from zero", MPFR_RNDA}, + {"faithful rounding", MPFR_RNDF}, + {"nearest (away from zero)", MPFR_RNDNA}}; /// @brief nop keyword implementation /// @@ -84,7 +89,7 @@ void program::rpn_help() { // bits precision, decimal digits and rounding mode cout << " with " << number::s_digits << " digits after the decimal point" << endl; - cout << "Current floating point precision is " << (int)mpreal::get_default_prec() << " bits" << endl; + cout << "Current floating point precision is " << static_cast(mpreal::get_default_prec()) << " bits" << endl; for (auto& rn : _mpfr_round) if (rn.second == mpreal::get_default_rnd()) { cout << "Current rounding mode is '" << rn.first << '\'' << endl; @@ -93,23 +98,14 @@ void program::rpn_help() { cout << endl << endl; } -/// @brief whether a precision is in the precision min/max +/// @brief whether a printed precision is in the precision min/max /// -/// @param precision the precision in bits +/// @param precision the precision in digits /// @return true the precision is good /// @return false the precision is not good /// -static bool check_decimal_digits(double precision) { - bool ret = true; - - // MPFR_PREC_MAX mpfr_prec_t depends on _MPFR_PREC_FORMAT macro (see mpfr.h) - // this could not exceed 63 bits max (0x7FFFFFFFFFFFFFFF) - double prec_max = (double)MPFR_PREC_MAX; - double prec_min = 0.0; - - if (precision < prec_min || precision > prec_max) ret = false; - - return ret; +static bool check_decimal_digits(int precision) { + return precision >= 0; } /// @brief std keyword implementation @@ -118,15 +114,16 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack.value(0)); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::std; - number::s_digits = (int)digits; + number::s_digits = digits; _stack.pop(); - } else + } else { setErrorContext(ret_out_of_range); + } } /// @brief fix keyword implementation @@ -135,15 +132,16 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack.value(0)); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::fix; - number::s_digits = (int)digits; + number::s_digits = digits; _stack.pop(); - } else + } else { setErrorContext(ret_out_of_range); + } } /// @brief sci keyword implementation @@ -152,15 +150,16 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - double digits = double(_stack.value(0)); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format number::s_mode = number::sci; - number::s_digits = (int)digits; + number::s_digits = digits; _stack.pop(); - } else + } else { setErrorContext(ret_out_of_range); + } } /// @brief _version keyword implementation @@ -203,8 +202,8 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - unsigned long prec = _stack.value(0).toULong(); - if (prec >= (unsigned long)MPFR_PREC_MIN && prec <= (unsigned long)MPFR_PREC_MAX) { + int prec = static_cast(_stack.value(0).toLong()); + if (prec >= MPFR_PREC_MIN && prec <= MPFR_PREC_MAX) { mpreal::set_default_prec(prec); // modify digits seen by user if std mode @@ -213,8 +212,9 @@ void program::rpn_precision() { number::s_digits = bits2digits(mpreal::get_default_prec()); } _stack.pop(); - } else + } else { setErrorContext(ret_out_of_range); + } } /// @brief round keyword implementation diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 0a45f92..0ee199b 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief e keyword implementation diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index f3196a4..d6ea074 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief find variable by its name in local heap, successive parents heaps, global heap @@ -11,9 +13,9 @@ bool program::find_variable(string& variable, object*& obj) { bool found = false; program* parent = _parent; - if (_local_heap.get(variable, obj)) + if (_local_heap.get(variable, obj)) { found = true; - else { + } else { while (parent != nullptr) { if (parent->_local_heap.get(variable, obj)) { found = true; @@ -52,15 +54,17 @@ void program::rpn_eval(void) { // else recall this variable (i.e. stack its content) _stack.push_front(obj); } - } else + } else { setErrorContext(ret_unknown_variable); + } } else if (_stack.type(0) == cmd_program) { // eval a program prog_text = _stack.value(0); _stack.pop(); run_prog = true; - } else + } else { setErrorContext(ret_bad_operand_type); + } // run prog if any if (run_prog) { @@ -92,14 +96,14 @@ int program::rpn_inprog(branch& myobj) { // find next oprogram object for (unsigned int i = myobj.arg1 + 1; i < size(); i++) { // count symbol - if (at(i)->_type == cmd_symbol) count_symbols++; - // stop if prog - else if (at(i)->_type == cmd_program) { + if (at(i)->_type == cmd_symbol) { + count_symbols++; + } else if (at(i)->_type == cmd_program) { + // stop if prog prog_found = true; break; - } - // found something other than symbol - else { + } else { + // found something other than symbol setErrorContext(ret_bad_operand_type); show_error(_err, context); return -1; @@ -121,7 +125,7 @@ int program::rpn_inprog(branch& myobj) { } // check symbols number vs stack size - if (stack_size() < count_symbols) { + if (_stack.size() < count_symbols) { setErrorContext(ret_missing_operand); show_error(_err, context); return -1; @@ -129,12 +133,12 @@ int program::rpn_inprog(branch& myobj) { // load variables for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[string(((symbol*)at(i))->value)] = _stack.at(0)->clone(); - _stack.pop_front(); + _local_heap[reinterpret_cast(at(i))->value] = _stack.at(0)->clone(); + _stack.pop(); } // run the program - string entry(((oprogram*)at(myobj.arg1 + count_symbols + 1))->value); + string& entry = reinterpret_cast(at(myobj.arg1 + count_symbols + 1))->value; program prog(_stack, _heap, this); // make the program from entry diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index ad618a0..471046e 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -1,131 +1,102 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief + keyword implementation /// void program::rpn_plus() { MIN_ARGUMENTS(2); - - // strings if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { _stack.value(1) += _stack.value(0); _stack.pop(); - } - // numbers - else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.value(1) += _stack.value(0); _stack.pop(); - } - // complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.value(1) += _stack.value(0); _stack.pop(); - } - // complex+number - else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { _stack.value(1) += _stack.value(0); _stack.pop(); - } - // number+complex - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); _stack.value(1) += _stack.value(0); _stack.pop(); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief - keyword implementation /// void program::rpn_minus() { MIN_ARGUMENTS(2); - - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } - // complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } - // subbing complex-number - else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } - // number-complex - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); _stack.value(1) = _stack.value(0) - _stack.value(1); _stack.pop(); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief * keyword implementation /// void program::rpn_mul() { MIN_ARGUMENTS(2); - - // mutiplying numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } - // mutiplying complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } - // mutiplying complex*number - else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } - // mutiplying number*complex - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); _stack.value(1) *= _stack.value(0); _stack.pop(); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief / keyword implementation /// void program::rpn_div() { MIN_ARGUMENTS(2); - - // dividing numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } - // dividing complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } - // dividing complex/number - else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } - // dividing number/complex - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); _stack.value(1) = _stack.value(0) / _stack.value(1); _stack.pop(); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief neg keyword implementation /// void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = -_stack.value(0); else if (_stack.type(0) == cmd_complex) @@ -138,11 +109,10 @@ void program::rpn_neg() { /// void program::rpn_inv() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = 1 / _stack.value(0); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = mpreal{1} / _stack.value(0); + _stack.value(0) = mpreal(1) / _stack.value(0); else setErrorContext(ret_bad_operand_type); } @@ -171,8 +141,9 @@ void program::rpn_power() { rpn_swap(); _stack.value(1) = pow(_stack.value(0), _stack.value(1)); _stack.pop(); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief sqrt keyword implementation @@ -185,53 +156,58 @@ void program::rpn_squareroot() { } else { // negative number -> square root is complex mpreal zero; - _stack.push(new ocomplex(_stack.value(0), zero, _stack.obj(0).base)); // TODO manage new errors + _stack.push(new ocomplex(_stack.value(0), zero, + _stack.obj(0).base)); // TODO(louis) manage new errors _stack.value(0) = sqrt(_stack.value(0)); _stack.erase(1); } - } else if (_stack.type(0) == cmd_complex) + } else if (_stack.type(0) == cmd_complex) { _stack.value(0) = sqrt(_stack.value(0)); - else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief hex keyword implementation /// void program::rpn_hex() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == cmd_number) { _stack.obj(0).base = 16; - else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex) { _stack.obj(0).reBase = 16; _stack.obj(0).imBase = 16; - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief bin keyword implementation /// void program::rpn_bin() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == cmd_number) { _stack.obj(0).base = 2; - else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex) { _stack.obj(0).reBase = 2; _stack.obj(0).imBase = 2; - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief dec keyword implementation /// void program::rpn_dec() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == cmd_number) { _stack.obj(0).base = 10; - else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex) { _stack.obj(0).reBase = 10; _stack.obj(0).imBase = 10; - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief base keyword implementation @@ -239,19 +215,21 @@ void program::rpn_dec() { void program::rpn_base() { MIN_ARGUMENTS(2); if (_stack.type(1) == cmd_number || _stack.type(1) == cmd_complex) { - int base = (int)_stack.value(0).toLong(); + int base = static_cast(_stack.value(0).toLong()); _stack.pop(); - if (base >= BASE_MIN && base <= BASE_MAX) { - if (_stack.type(0) == cmd_number) + if (base >= 2 && base <= 62) { + if (_stack.type(0) == cmd_number) { _stack.obj(0).base = base; - else { + } else { _stack.obj(0).reBase = base; _stack.obj(0).imBase = base; } - } else + } else { setErrorContext(ret_out_of_range); - } else + } + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief % (purcent) keyword implementation @@ -300,13 +278,14 @@ void program::rpn_modulo() { /// void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == cmd_number) { _stack.value(0) = abs(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex) { _stack.push(new number(abs(_stack.value(0)))); _stack.erase(1); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief fact (factorial) keyword implementation diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index fc142a7..646a845 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief swap keyword implementation @@ -20,7 +22,7 @@ void program::rpn_drop(void) { /// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); - _stack.pop_front(2); + _stack.erase(0, 2); } /// @brief dropn keyword implementation @@ -29,7 +31,7 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)_stack.value(0).toLong(); + int args = static_cast(_stack.value(0).toLong()); MIN_ARGUMENTS(args + 1); _stack.erase(0, args + 1); } @@ -42,7 +44,7 @@ void program::rpn_erase(void) { _stack.erase(0, _stack.size()); } /// void program::rpn_dup(void) { MIN_ARGUMENTS(1); - rpnstack::copy_and_push_front(_stack, 0, _stack); + _stack.push_front(_stack.at(0)->clone()); } /// @brief dupn keyword implementation @@ -51,19 +53,19 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack.front())->value.toLong(); + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) rpnstack::copy_and_push_front(_stack, args - 1, _stack); + for (int i = 0; i < args; i++) _stack.push_front(_stack.at(args - 1)->clone()); } /// @brief dup2 keyword implementation /// void program::rpn_dup2(void) { MIN_ARGUMENTS(2); - rpnstack::copy_and_push_front(_stack, 1, _stack); - rpnstack::copy_and_push_front(_stack, 1, _stack); + _stack.push_front(_stack.at(1)->clone()); + _stack.push_front(_stack.at(1)->clone()); } /// @brief pick keyword implementation @@ -72,7 +74,7 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - unsigned int to_pick = (unsigned int)_stack.value(0); + int to_pick = static_cast(_stack.value(0).toLong()); _stack.pop(); // treat stack depth errors @@ -81,7 +83,7 @@ void program::rpn_pick(void) { return; } - rpnstack::copy_and_push_front(_stack, to_pick - 1, _stack); + _stack.push_front(_stack.at(to_pick - 1)->clone()); } /// @brief rot keyword implementation @@ -103,7 +105,7 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - size_t args = (int)((number*)_stack.front())->value; + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); @@ -118,7 +120,7 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = (int)((number*)_stack.front())->value.toLong(); + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); @@ -131,7 +133,5 @@ void program::rpn_rolld(void) { /// void program::rpn_over(void) { MIN_ARGUMENTS(2); - - rpnstack::copy_and_push_front(_stack, 1, _stack); + _stack.push_front(_stack.at(1)->clone()); } - diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index fac153e..4e9f195 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -1,5 +1,7 @@ -#include "program.hpp" +// Copyright (c) 2014-2022 Louis Rubet + #include "input.hpp" +#include "program.hpp" /// @brief sto keyword implementation /// @@ -14,7 +16,7 @@ void program::rpn_sto(void) { _heap.erase(it); } _heap[_stack.value(0)] = _stack.at(1)->clone(); - _stack.pop_front(2); + _stack.erase(0, 2); } /// @brief sto+ keyword implementation @@ -27,7 +29,7 @@ void program::rpn_stoadd(void) { return; } rpn_dup(); - rpn_rcl(); // TODO is rcl the good one? it will recall local variables too + rpn_rcl(); // TODO(louis) is rcl the good one? it will recall local variables too rpn_rot(); rpn_plus(); rpn_swap(); @@ -129,10 +131,11 @@ void program::rpn_rcl(void) { // mind the order of heaps if (find_variable(variable, obj)) { - (void)_stack.pop_front(); + (void)_stack.pop(); _stack.push_front(obj->clone()); - } else + } else { setErrorContext(ret_unknown_variable); + } } /// @brief edit keyword implementation @@ -163,10 +166,12 @@ void program::auto_rcl(symbol* symb) { if (find_variable(variable, obj)) { _stack.push_front(obj->clone()); if (obj->_type == cmd_program) rpn_eval(); - } else + } else { _stack.push_front(symb->clone()); - } else + } + } else { _stack.push_front(symb->clone()); + } } /// @brief purge keyword implementation @@ -179,8 +184,9 @@ void program::rpn_purge(void) { if (i != _heap.end()) { delete i->second; _heap.erase(i); - } else + } else { setErrorContext(ret_unknown_variable); + } _stack.pop(); } @@ -190,33 +196,28 @@ void program::rpn_vars(void) { object* obj; program* parent = _parent; string name; + int index = 1; // heap variables - for (int i = 0; i < (int)_heap.size(); i++) { - (void)_heap.get_by_index(i, name, obj); - cout<<"var "<name()<<", value "; - obj->show(cout); - cout<name() << ", value "; + i.second->show(cout) << endl; + } + + // local variables + for (auto i : _local_heap) { + cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; + i.second->show(cout) << endl; } // parents local variables while (parent != nullptr) { - for (int i = 0; i < (int)parent->_local_heap.size(); i++) { - (void)parent->_local_heap.get_by_index(i, name, obj); - cout<<"var "<name()<<", value "; - obj->show(cout); - cout<_local_heap) { + cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; + obj->show(cout) << endl; } parent = parent->_parent; } - - // local variables - for (int i = 0; i < (int)_local_heap.size(); i++) { - (void)_local_heap.get_by_index(i, name, obj); - cout<<"var "<name()<<", value "; - obj->show(cout); - cout< #include "program.hpp" @@ -37,7 +39,7 @@ void program::rpn_strout() { void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - char the_chr = (char)(int)_stack.value(0); + char the_chr = static_cast(_stack.value(0).toLong()); _stack.pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; _stack.push_front(new ostring(string(1, the_chr))); @@ -72,7 +74,7 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(1, cmd_string); size_t pos = _stack.value(1).find(_stack.value(0)) + 1; - _stack.pop_front(2); + _stack.erase(0, 2); _stack.push_front(new number(pos)); } @@ -84,8 +86,8 @@ void program::rpn_strsub() { ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_string); - size_t first = (size_t)_stack.value(1); - size_t len = (size_t)_stack.value(0) - first + 1; + size_t first = _stack.value(1).toULong(); + size_t len = _stack.value(0).toULong() - first + 1; first--; if (first > _stack.value(2).size()) first = len = 0; diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 47f3cc4..60d26b1 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -1,18 +1,25 @@ -#include "escape.h" +// Copyright (c) 2014-2022 Louis Rubet + +#include +using namespace std; + #include "program.hpp" #include "version.h" -static void _findAndReplaceAll(std::string & data, std::string toSearch, std::string replaceStr) -{ +// foreground colors +static const string FG_RED = "\33[31m"; +static const string FG_GREEN = "\33[32m"; +static const string COLOR_OFF = "\33[m"; + +static void _findAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr) { // Get the first occurrence size_t pos = data.find(toSearch); // Repeat till end is reached - while( pos != std::string::npos) - { + while (pos != std::string::npos) { // Replace this occurrence of Sub String data.replace(pos, toSearch.size(), replaceStr); // Get the next occurrence from the current position - pos =data.find(toSearch, pos + replaceStr.size()); + pos = data.find(toSearch, pos + replaceStr.size()); } } @@ -21,7 +28,7 @@ static void _findAndReplaceAll(std::string & data, std::string toSearch, std::st /// @param stack_is the output string /// @param stk the stack /// -void program::test_get_stack(string& stack_is, rpnstack& stk) { +static void getStackAsString(string& stack_is, rpnstack& stk) { ostringstream st; if (stk.empty()) { stack_is.clear(); @@ -29,7 +36,7 @@ void program::test_get_stack(string& stack_is, rpnstack& stk) { } stk[stk.size() - 1]->show(st); stack_is += st.str(); - for (int i = (int)stk.size() - 2; i >= 0; i--) { + for (int i = static_cast(stk.size()) - 2; i >= 0; i--) { ostringstream st; stk[i]->show(st); stack_is += ", " + st.str(); @@ -44,7 +51,7 @@ void program::test_get_stack(string& stack_is, rpnstack& stk) { /// @param steps steps nb /// @param steps_failed failed steps nb /// -void program::test_show_result(string title, int tests, int tests_failed, int steps, int steps_failed) { +static void testShowResult(string title, int tests, int tests_failed, int steps, int steps_failed) { if (!title.empty()) cout << title << ": "; cout << "run " << tests << " tests: " << tests - tests_failed << " passed, "; if (tests_failed > 0) cout << FG_RED; @@ -73,7 +80,7 @@ void program::rpn_test() { _stack.pop(); cout << endl << "rpn version is " << RPN_VERSION << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); - test_show_result("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); + testShowResult("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); // notify to caller that test succeeded or not if (total_tests_failed > 0) { @@ -123,11 +130,11 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail getline(test_file, entry); if (entry.empty()) continue; - if (entry.substr(0, 8) == "@include") + if (entry.substr(0, 8) == "@include") { test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed); - else if (entry.substr(0, 2) == "# ") + } else if (entry.substr(0, 2) == "# ") { cout << endl << test_filename << ": " << entry.substr(2) << endl; - else if (entry.substr(0, 3) == "## ") { + } else if (entry.substr(0, 3) == "## ") { // indicates the status of previous test if (failed == false && tests > 0) cout << FG_GREEN << " PASSED" << COLOR_OFF << endl; failed = false; @@ -137,9 +144,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail is_first_step = true; is_test_error_shown = false; cout << test_title; - } - // treat "-> stack size should be " - else if (entry.find(stack_size, 0) == 0) { + } else if (entry.find(stack_size, 0) == 0) { // treat "-> stack size should be " // count test and step if (is_first_step) tests++; steps++; @@ -150,7 +155,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail isub.str(entry.substr(stack_size.size())); isub >> size; - if (size != (int)stk.size()) { + if (size != static_cast(stk.size())) { // count fail test and step if (!is_test_error_shown) { cout << FG_RED << " FAIL" << COLOR_OFF << endl; @@ -165,9 +170,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail failed = true; } is_first_step = false; - } - // treat "-> stack should be " - else if (entry.find(stack_value, 0) == 0) { + } else if (entry.find(stack_value, 0) == 0) { // treat "-> stack should be " // count test if (is_first_step) tests++; steps++; @@ -176,7 +179,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail string stack_should_be = entry.substr(stack_value.size()); string stack_is; - test_get_stack(stack_is, stk); + getStackAsString(stack_is, stk); if (stack_is != stack_should_be) { // count fail test and step @@ -193,9 +196,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail failed = true; } is_first_step = false; - } - // treat "-> error should be " - else if (entry.find(cmd_error, 0) == 0) { + } else if (entry.find(cmd_error, 0) == 0) { // treat "-> error should be " // count test if (is_first_step) tests++; steps++; @@ -223,9 +224,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail } else if (entry.find(cmd_exit, 0) == 0) { // forced test end break; - } - // treat unknown "->" - else if (entry.find("->", 0) == 0) { + } else if (entry.find("->", 0) == 0) { // treat unknown "->" // count test if (is_first_step) tests++; steps++; @@ -250,7 +249,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (ret == ret_ok) { // run it (void)prog.run(); - last_err = (int)prog.get_err(); + last_err = static_cast(prog.get_err()); } } } @@ -265,13 +264,14 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // conclusion: show and keep for total if (tests != 0) { - test_show_result("", tests, tests_failed, steps, steps_failed); + testShowResult("", tests, tests_failed, steps, steps_failed); total_tests += tests; total_tests_failed += tests_failed; total_steps += steps; total_steps_failed += steps_failed; } - } else + } else { cerr << "test file '" << test_filename << "' not found" << endl; + } } diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 351e890..8b80d52 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief compared 2 strings on top of the stack @@ -5,11 +7,11 @@ /// @return 0 strings are equal /// @return !0 strings are not equal (see strcmp output) /// -long program::cmp_strings_on_stack_top() { +static int cmpStringsOnStackTop(rpnstack& stk) { // _stack should have 2 strings at level 1 and 2 // this function removes these 2 entries - long res = (long)_stack.value(1).compare(_stack.value(0)); - (void)_stack.pop_front(2); + int res = stk.value(1).compare(stk.value(0)); + stk.erase(0, 2); return res; } @@ -17,112 +19,97 @@ long program::cmp_strings_on_stack_top() { /// void program::rpn_sup(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) > _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() == 1)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) == 1)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief >= keyword implementation /// void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) >= _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() != -1)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) != -1)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief < keyword implementation /// void program::rpn_inf(void) { MIN_ARGUMENTS(2); - // numbers + if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) < _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() == -1)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) == -1)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief <= keyword implementation /// void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) <= _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() != 1)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) != 1)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief != keyword implementation /// void program::rpn_diff(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); - } - // complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.push_front(new number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() != 0)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) != 0)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief == keyword implementation /// void program::rpn_eq(void) { MIN_ARGUMENTS(2); - // numbers if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { _stack.push_front(new number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); - } - // complexes - else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { _stack.push_front(new number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); - } - // strings - else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmp_strings_on_stack_top() == 0)); + } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + _stack.push_front(new number(cmpStringsOnStackTop(_stack) == 0)); _stack.erase(1, 2); - } else + } else { setErrorContext(ret_bad_operand_type); + } } /// @brief and keyword implementation @@ -131,7 +118,6 @@ void program::rpn_test_and(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 && _stack.value(1) != 0) _stack.push(new number(1)); else @@ -145,7 +131,6 @@ void program::rpn_test_or(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 || _stack.value(1) != 0) _stack.push(new number(1)); else @@ -159,7 +144,6 @@ void program::rpn_test_xor(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 ^ _stack.value(1) != 0) _stack.push(new number(1)); else @@ -173,7 +157,7 @@ void program::rpn_test_not(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.push(new number(_stack.value(0) == 0?1:0)); + _stack.push(new number(_stack.value(0) == 0 ? 1 : 0)); _stack.erase(1, 1); } diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index 8ca0a02..ad37b3f 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include #include "program.hpp" @@ -15,15 +17,16 @@ void program::rpn_time() { tm = localtime(&time); if (tm != nullptr) { // date format = HH.MMSSssssss - date = ((double)tm->tm_hour) * 10000000000.0 + ((double)tm->tm_min) * 100000000.0 + - ((double)tm->tm_sec) * 1000000.0 + (double)(ts.tv_nsec / 1000); + date = (static_cast(tm->tm_hour) * 10000000000.0 + static_cast(tm->tm_min) * 100000000.0 + + static_cast(tm->tm_sec) * 1000000.0 + static_cast(ts.tv_nsec / 1000)); // push it // division after push for real precision _stack.push(new number(date)); _stack.value(0) /= 10000000000.0; - } else + } else { setErrorContext(ret_internal); + } } /// @brief date keyword implementation @@ -39,15 +42,17 @@ void program::rpn_date() { tm = localtime(&time); if (tm != nullptr) { // date format = (M)M.DDYYYY - date = (double)(tm->tm_mon + 1) * 1000000.0 + (double)(tm->tm_mday) * 10000.0 + (double)(tm->tm_year + 1900); + date = static_cast(tm->tm_mon + 1) * 1000000.0 + static_cast(tm->tm_mday) * 10000.0 + + static_cast(tm->tm_year + 1900); // push it number* num; // division after push for real precision _stack.push(new number(date)); _stack.value(0) /= 1000000.0; - } else + } else { setErrorContext(ret_internal); + } } /// @brief ticks keyword implementation @@ -63,8 +68,9 @@ void program::rpn_ticks() { tm = localtime(&time); if (tm != nullptr) { // date in µs - date = 1000000.0 * (double)ts.tv_sec + (double)(ts.tv_nsec / 1000); + date = 1000000.0 * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec / 1000); _stack.push(new number(date)); - } else + } else { setErrorContext(ret_internal); + } } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 7eeca55..678c42d 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -1,3 +1,5 @@ +// Copyright (c) 2014-2022 Louis Rubet + #include "program.hpp" /// @brief pi keyword implementation @@ -28,7 +30,6 @@ void program::rpn_r2d(void) { /// void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = sin(_stack.value(0)); else if (_stack.type(0) == cmd_complex) @@ -41,7 +42,6 @@ void program::rpn_sin(void) { /// void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = asin(_stack.value(0)); else if (_stack.type(0) == cmd_complex) @@ -54,7 +54,6 @@ void program::rpn_asin(void) { /// void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = cos(_stack.value(0)); else if (_stack.type(0) == cmd_complex) @@ -67,7 +66,6 @@ void program::rpn_cos(void) { /// void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = acos(_stack.value(0)); else if (_stack.type(0) == cmd_complex) @@ -80,7 +78,6 @@ void program::rpn_acos(void) { /// void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = tan(_stack.value(0)); else if (_stack.type(0) == cmd_complex) @@ -93,7 +90,6 @@ void program::rpn_tan(void) { /// void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) _stack.value(0) = atan(_stack.value(0)); else if (_stack.type(0) == cmd_complex) diff --git a/src/stack.hpp b/src/stack.hpp index 787be32..1e55024 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -1,55 +1,37 @@ -#ifndef STACK_HPP_ -#define STACK_HPP_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_STACK_HPP_ +#define SRC_STACK_HPP_ -#include #include #include #include +#include +using namespace std; #include "object.hpp" -using namespace std; /// @brief stack object, parens of program, storing execution stack values or programs /// class rpnstack : public deque { - public: + public: rpnstack() {} virtual ~rpnstack() { for_each(begin(), end(), [](object* o) { delete o; }); deque::erase(begin(), end()); } - /// @brief copy a whole stack entry and push it back to another stack - /// - /// @param from copy from - /// @param index_from index t ocopy from - /// @param to copy to - /// - static void copy_and_push_front(rpnstack& from, unsigned int index_from, rpnstack& to) { - // carefull: caller must ensure that index_from is correct - to.push_front(from[index_from]->clone()); - } - - /// @brief erase a stack entry from it index - /// - /// @param first index to start - /// @param last index to stop - /// + // stack manipulation void erase(size_t first = 0, size_t nb = 1, bool del = true) { size_t last = std::min(first + nb, size()); - if (del) - for_each(begin() + first, begin() + last, [](object* o) { delete o; }); + if (del) for_each(begin() + first, begin() + last, [](object* o) { delete o; }); deque::erase(begin() + first, begin() + last); } - /// @brief pop front several entries - /// - /// @param levels nb of entries - /// - void pop_front(size_t levels = 1) { erase(0, levels); } void pop() { erase(); } // access helpers + // cmd_type_t type(int level) { // carefull: caller must ensure that level is correct return at(level)->_type; @@ -73,7 +55,7 @@ class rpnstack : public deque { /// @brief heap object, storing variables (=named object) /// class heap : public map { - public: + public: heap() {} virtual ~heap() { clear(); } @@ -82,43 +64,14 @@ class heap : public map { map::erase(begin(), end()); } - /// @brief get a variable - /// - /// @param name the variable name - /// @param obj the variable content - /// @return true the variable was found - /// @return false the variable was not found - /// bool get(const string name, object*& obj) { - bool ret = false; auto i = find(name); if (i != end()) { obj = i->second; - ret = true; - } - return ret; - } - - /// @brief get a variable by its index in heap - /// - /// @param num the variable index - /// @param name the variable name - /// @param obj the variable content - /// @return true the variable was found - /// @return false the variable was not found - /// - bool get_by_index(int num, string& name, object*& obj) { - if (num >= 0 && num < (int)size()) { - object* local; - auto i = begin(); - for (; num > 0; num--, i++) - ; - obj = i->second; - name = i->first; return true; - } else - return false; + } + return false; } }; -#endif // __stack_h__ +#endif // SRC_STACK_HPP_ diff --git a/src/version.h b/src/version.h index 7af9ae7..c05594a 100644 --- a/src/version.h +++ b/src/version.h @@ -1,7 +1,9 @@ -#ifndef VERSION_H_ -#define VERSION_H_ +// Copyright (c) 2014-2022 Louis Rubet + +#ifndef SRC_VERSION_H_ +#define SRC_VERSION_H_ #define RPN_VERSION "2.4" #define RPN_UNAME "rpn v" RPN_VERSION ", (c) 2017 , GNU LGPL v3" -#endif +#endif // SRC_VERSION_H_ diff --git a/test/090-program.md b/test/090-program.md index 119d833..8042afc 100644 --- a/test/090-program.md +++ b/test/090-program.md @@ -96,6 +96,7 @@ ``` «dup 1 > if then dup 1 - fibo swap 2 - fibo + else 1 == if then 1 else 0 end end» 'fibo' sto +«dup 1 > if then dup 1 - fibo swap 2 - fibo + else 1 == 1 0 ifte end» 'fibo' sto 7 fibo 13 == if then 'ok!' end ``` From e0665fc94ff6add2054618d5cf155630f815bd5e Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 11:15:15 +0100 Subject: [PATCH 40/57] Removed some cpplint warnings --- Changelog.md | 1 + src/CPPLINT.cfg | 8 ++++-- src/input.hpp | 3 ++- src/lexer.hpp | 6 +++-- src/main.cpp | 2 +- src/mpreal-out.hpp | 5 ++-- src/object.hpp | 14 ++++++---- src/program.hpp | 2 +- src/rpn-general.cpp | 52 ++++++++++++++++++-------------------- src/rpn-logs.cpp | 10 ++++---- src/rpn-test-framework.cpp | 14 +++++----- src/rpn-trig.cpp | 6 ++--- 12 files changed, 66 insertions(+), 57 deletions(-) diff --git a/Changelog.md b/Changelog.md index 9b89648..db3e782 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,6 +15,7 @@ Changelog - static and global variables - common patterns (ex: no static maps or vectors) - classes (explicit) + - naming: file names (.cc .h), types (PascalCase), variables (snake_case), members (trailing _), static const (camelCase begining with k), enum (enum class, values like static const) - cpplint used with a CPPLINT.cfg removing some warnings - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap diff --git a/src/CPPLINT.cfg b/src/CPPLINT.cfg index d771828..1910e8d 100644 --- a/src/CPPLINT.cfg +++ b/src/CPPLINT.cfg @@ -2,6 +2,10 @@ set noparent filter=-whitespace/line_length -// avoid "Is this a non-const reference? If so, make const or use a pointer" -// as it seems to be allowed by google now , cf https://github.com/cpplint/cpplint/issues/148 +# avoid "Is this a non-const reference? If so, make const or use a pointer" +# as it seems to be allowed by google now , cf https://github.com/cpplint/cpplint/issues/148 filter=-runtime/references + +# avoid "Include the directory when naming header files" +# for files not being in a subdirectory +filter=-build/include_subdir diff --git a/src/input.hpp b/src/input.hpp index cec0079..bd56db0 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -6,7 +6,8 @@ #include #include #include -using namespace std; +using std::vector; +using std::string; #include "linenoise.h" diff --git a/src/lexer.hpp b/src/lexer.hpp index 08fc468..18455f2 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -4,12 +4,14 @@ #define SRC_LEXER_HPP_ #include -using namespace mpfr; +using mpfr::mpreal; #include #include #include -using namespace std; +using std::map; +using std::string; +using std::vector; #include "object.hpp" diff --git a/src/main.cpp b/src/main.cpp index a88ee26..10a6722 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ #include #include #include -using namespace std; +using std::cerr; // internal includes #include "input.hpp" diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index cac8f10..c5f5e89 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -4,11 +4,12 @@ #define SRC_MPREAL_OUT_HPP_ #include -using namespace mpfr; +using mpfr::mpreal; #include #include -using namespace std; +using std::string; +using std::ostream; ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); diff --git a/src/object.hpp b/src/object.hpp index 0c52665..77a7af8 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -4,14 +4,18 @@ #define SRC_OBJECT_HPP_ #include - -#include "mpreal-out.hpp" -using namespace mpfr; +using mpfr::mpreal; #include -#include #include -using namespace std; +#include +#include +using std::ostream; +using std::string; +using std::stringstream; +using std::complex; + +#include "mpreal-out.hpp" // definitions for objects /// diff --git a/src/program.hpp b/src/program.hpp index 3571bbf..a5d6d84 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -11,7 +11,7 @@ using namespace std; #include -using namespace mpfr; +using mpfr::mpreal; // internal includes #include "lexer.hpp" diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index cd04390..a493550 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -1,39 +1,36 @@ // Copyright (c) 2014-2022 Louis Rubet -#include +#include #include +#include +using std::cout; +using std::string; +using std::pair; #include "linenoise.h" -using namespace std; - #include "program.hpp" #include "version.h" // description -static const string ATTR_BOLD = "\33[1m"; -static const string ATTR_OFF = "\33[0m"; +#define ATTR_BOLD "\33[1m" +#define ATTR_OFF "\33[0m" #define XSTR(a) STR(a) #define STR(a) #a -static const string _description{ATTR_BOLD + "R" + ATTR_OFF + "everse " + ATTR_BOLD + "P" + ATTR_OFF + "olish " + - ATTR_BOLD + "N" + ATTR_OFF + "otation language\n\nusing " + ATTR_BOLD + "GMP" + - ATTR_OFF + - " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( - __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" + - ATTR_BOLD + "MPFR" + ATTR_OFF + " v" MPFR_VERSION_STRING " under GNU LGPL\nand " + - ATTR_BOLD + "linenoise-ng" + ATTR_OFF + " v" LINENOISE_VERSION " under BSD\n"}; +static const char _description[] = ATTR_BOLD + "R" ATTR_OFF "everse " ATTR_BOLD "P" ATTR_OFF "olish " ATTR_BOLD "N" ATTR_OFF "otation language\n\nusing " ATTR_BOLD + "GMP" ATTR_OFF " v" XSTR(__GNU_MP_VERSION) "." XSTR(__GNU_MP_VERSION_MINOR) "." XSTR( + __GNU_MP_VERSION_PATCHLEVEL) " under GNU LGPL\n" ATTR_BOLD "MPFR" ATTR_OFF " v" MPFR_VERSION_STRING + " under GNU LGPL\nand " ATTR_BOLD "linenoise-ng" ATTR_OFF " v" LINENOISE_VERSION + " under BSD\n"; -// syntax -static const string _syntax{ATTR_BOLD + "Syntax" + ATTR_OFF + - ": rpn [command]\nwith optional command = list of commands"}; +static const char _syntax[] = ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\nwith optional command = list of commands"; -static const map _mpfr_round{{"nearest (even)", MPFR_RNDN}, - {"toward zero", MPFR_RNDZ}, - {"toward +inf", MPFR_RNDU}, - {"toward -inf", MPFR_RNDD}, - {"away from zero", MPFR_RNDA}, - {"faithful rounding", MPFR_RNDF}, - {"nearest (away from zero)", MPFR_RNDNA}}; +#define MPFR_ROUND \ + {"nearest (even)", MPFR_RNDN}, {"toward zero", MPFR_RNDZ}, {"toward +inf", MPFR_RNDU}, {"toward -inf", MPFR_RNDD}, \ + {"away from zero", MPFR_RNDA}, {"faithful rounding", MPFR_RNDF}, { \ + "nearest (away from zero)", MPFR_RNDNA \ + } /// @brief nop keyword implementation /// @@ -90,7 +87,8 @@ void program::rpn_help() { // bits precision, decimal digits and rounding mode cout << " with " << number::s_digits << " digits after the decimal point" << endl; cout << "Current floating point precision is " << static_cast(mpreal::get_default_prec()) << " bits" << endl; - for (auto& rn : _mpfr_round) + vector> rnd{MPFR_ROUND}; + for (auto& rn : rnd) if (rn.second == mpreal::get_default_rnd()) { cout << "Current rounding mode is '" << rn.first << '\'' << endl; break; @@ -104,9 +102,7 @@ void program::rpn_help() { /// @return true the precision is good /// @return false the precision is not good /// -static bool check_decimal_digits(int precision) { - return precision >= 0; -} +static bool check_decimal_digits(int precision) { return precision >= 0; } /// @brief std keyword implementation /// @@ -209,7 +205,7 @@ void program::rpn_precision() { // modify digits seen by user if std mode if (number::s_mode == number::std) { // calc max nb of digits user can see with the current bit precision - number::s_digits = bits2digits(mpreal::get_default_prec()); + number::s_digits = mpfr::bits2digits(mpreal::get_default_prec()); } _stack.pop(); } else { @@ -223,7 +219,7 @@ void program::rpn_round() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - map matchRound{_mpfr_round}; + map matchRound{MPFR_ROUND}; auto found = matchRound.find(_stack.value(0)); if (found != matchRound.end()) diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 0ee199b..ffbad53 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -4,7 +4,7 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { _stack.push(new number(const_euler())); } +void program::rpn_e(void) { _stack.push(new number(mpfr::const_euler())); } /// @brief log10 keyword implementation /// @@ -35,9 +35,9 @@ void program::rpn_alog10() { void program::rpn_log2() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = log(_stack.value(0)) / const_log2(); + _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = log(_stack.value(0)) / const_log2(); + _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); else setErrorContext(ret_bad_operand_type); } @@ -47,9 +47,9 @@ void program::rpn_log2() { void program::rpn_alog2() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = exp(const_log2() * _stack.value(0)); + _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = exp(const_log2() * _stack.value(0)); + _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); else setErrorContext(ret_bad_operand_type); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 60d26b1..0685e8b 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -1,21 +1,21 @@ // Copyright (c) 2014-2022 Louis Rubet #include -using namespace std; +using std::string; #include "program.hpp" #include "version.h" // foreground colors -static const string FG_RED = "\33[31m"; -static const string FG_GREEN = "\33[32m"; -static const string COLOR_OFF = "\33[m"; +static const char FG_RED[] = "\33[31m"; +static const char FG_GREEN[] = "\33[32m"; +static const char COLOR_OFF[] = "\33[m"; -static void _findAndReplaceAll(std::string& data, std::string toSearch, std::string replaceStr) { +static void findAndReplaceAll(string& data, string toSearch, string replaceStr) { // Get the first occurrence size_t pos = data.find(toSearch); // Repeat till end is reached - while (pos != std::string::npos) { + while (pos != string::npos) { // Replace this occurrence of Sub String data.replace(pos, toSearch.size(), replaceStr); // Get the next occurrence from the current position @@ -242,7 +242,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail failed = true; } else { // parse entry and run line - _findAndReplaceAll(entry, "`", ""); + findAndReplaceAll(entry, "`", ""); if (!entry.empty()) { program prog(stk, hp); ret = prog.parse(entry); diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 678c42d..ebce9d6 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -5,7 +5,7 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - _stack.push_front(new number(const_pi())); + _stack.push_front(new number(mpfr::const_pi())); } /// @brief d->r keyword implementation @@ -13,7 +13,7 @@ void program::rpn_pi(void) { void program::rpn_d2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) *= const_pi(); + _stack.value(0) *= mpfr::const_pi(); _stack.value(0) /= 180; } @@ -22,7 +22,7 @@ void program::rpn_d2r(void) { void program::rpn_r2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) /= const_pi(); + _stack.value(0) /= mpfr::const_pi(); _stack.value(0) *= 180; } From d0c7304ffdf3e5dd8c7e41c1c67ae41f5a68044e Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 12:19:25 +0100 Subject: [PATCH 41/57] PascalCase classes, snake_case variables, (some) PAscalCase functions --- Changelog.md | 4 +- src/input.cpp | 15 ++-- src/input.hpp | 6 +- src/lexer.cpp | 72 ++++++++++---------- src/lexer.hpp | 18 ++--- src/main.cpp | 18 ++--- src/mpreal-out.cpp | 4 +- src/mpreal-out.hpp | 4 +- src/object.cpp | 4 +- src/object.hpp | 122 +++++++++++++++------------------ src/program.cpp | 83 +++++++++++----------- src/program.hpp | 32 ++++----- src/rpn-branch.cpp | 88 ++++++++++++------------ src/rpn-complex.cpp | 24 +++---- src/rpn-general.cpp | 42 ++++++------ src/rpn-logs.cpp | 58 ++++++++-------- src/rpn-program.cpp | 34 +++++----- src/rpn-real.cpp | 136 ++++++++++++++++++------------------- src/rpn-stack.cpp | 20 +++--- src/rpn-store.cpp | 28 ++++---- src/rpn-string.cpp | 28 ++++---- src/rpn-test-framework.cpp | 2 +- src/rpn-test.cpp | 52 +++++++------- src/rpn-time.cpp | 12 ++-- src/rpn-trig.cpp | 34 +++++----- src/stack.hpp | 12 ++-- 26 files changed, 472 insertions(+), 480 deletions(-) diff --git a/Changelog.md b/Changelog.md index db3e782..30360a0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -15,7 +15,9 @@ Changelog - static and global variables - common patterns (ex: no static maps or vectors) - classes (explicit) - - naming: file names (.cc .h), types (PascalCase), variables (snake_case), members (trailing _), static const (camelCase begining with k), enum (enum class, values like static const) + - naming: + - file names (.cc .h), types (PascalCase), variables (snake_case), members (trailing _), static const (camelCase begining with k), enum (enum class, values like static const + - consistent comments (//), class comments, functions comments - cpplint used with a CPPLINT.cfg removing some warnings - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap diff --git a/src/input.cpp b/src/input.cpp index c41f1bf..6a0fa67 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -4,21 +4,22 @@ #include -vector* Input::_acWords = nullptr; +vector* Input::_ac_list = nullptr; -Input::Input(string& entry, vector& autocompletionWords, string prompt, string mlPrompt) : status(cont) { +Input::Input(string& entry, vector& autocompletion_list, string prompt, string multiline_prompt) + : status(cont) { char* c_entry = nullptr; bool multiline = false; int entry_len; - _acWords = &autocompletionWords; + _ac_list = &autocompletion_list; // linenoise for entry linenoiseSetCompletionCallback(entry_completion_generator); while (status == cont) { // get user entry if (multiline) - c_entry = linenoise(mlPrompt.c_str(), &entry_len); + c_entry = linenoise(multiline_prompt.c_str(), &entry_len); else c_entry = linenoise(prompt.c_str(), &entry_len); @@ -53,16 +54,16 @@ Input::Input(string& entry, vector& autocompletionWords, string prompt, /// @param lc the completion object to add strings with linenoiseAddCompletion() /// void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) { - if (Input::_acWords == nullptr || text == nullptr) return; + if (Input::_ac_list == nullptr || text == nullptr) return; int text_len = strnlen(text, 6); if (text_len == 0) // propose all keywords - for (string& ac : *Input::_acWords) linenoiseAddCompletion(lc, ac.c_str()); + for (string& ac : *Input::_ac_list) linenoiseAddCompletion(lc, ac.c_str()); else // propose only keywords matching to text begining - for (string& ac : *Input::_acWords) + for (string& ac : *Input::_ac_list) // compare list entry with text, return if match if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str()); } diff --git a/src/input.hpp b/src/input.hpp index bd56db0..f1d9e19 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -6,21 +6,21 @@ #include #include #include -using std::vector; using std::string; +using std::vector; #include "linenoise.h" class Input { public: - Input(string& entry, vector& autocompletionWords, string prompt = "rpn> ", string mlPrompt = ">"); + Input(string& entry, vector& autocompletion_list, string prompt = "rpn> ", string multiline_prompt = ">"); enum { ok, cont, abort, ctrlc, error } status; static void preload(const char* preloadText); private: static void entry_completion_generator(const char* text, linenoiseCompletions* lc); - static vector* _acWords; + static vector* _ac_list; }; #endif // SRC_INPUT_HPP_ diff --git a/src/lexer.cpp b/src/lexer.cpp index e4428f3..747a5e2 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -49,39 +49,39 @@ void Lexer::trim(string& s) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end()); } -bool Lexer::parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, +bool Lexer::parseString(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry[0] is at least '"' for (size_t i = idx + 1; i < entry.size(); i++) { if (entry[i] == '"') { if (entry[i] - 1 != '\\') { elements.push_back({cmd_string, .value = entry.substr(idx + 1, i - idx - 1)}); - nextIdx = i + 1; + next_idx = i + 1; return true; } } } elements.push_back({cmd_string, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); - nextIdx = entry.size(); + next_idx = entry.size(); return true; } -bool Lexer::parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, +bool Lexer::parseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry[0] is at least '\'' for (size_t i = idx + 1; i < entry.size(); i++) { if (entry[i] == '\'') { elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, i - idx - 1), .autoEval = false}); - nextIdx = i + 1; + next_idx = i + 1; return true; } } elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, entry.size() - idx - 1)}); - nextIdx = entry.size(); + next_idx = entry.size(); return true; } -bool Lexer::parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, +bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry is at least "<<" // find last ">>" or "»" @@ -94,7 +94,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& nextIdx, vector= entry.size()) return 10; if (entry[scan] == '+') { scan++; - nextIdx = scan; + next_idx = scan; } else if (entry[scan] == '-') { scan++; - nextIdx = scan; + next_idx = scan; positive = false; } if (scan + 2 >= entry.size()) return 10; @@ -131,38 +131,38 @@ int Lexer::getBaseAt(string& entry, size_t& nextIdx, bool& positive) { if (scan + 2 < entry.size()) c = entry[scan + 2]; if (a == '0') { if (b == 'x' || b == 'X') { - nextIdx = scan + 2; + next_idx = scan + 2; return 16; } if (b == 'b' || b == 'B') { - nextIdx = scan + 2; + next_idx = scan + 2; return 2; } } else if (isdigit(a)) { if (b == 'b' || b == 'B') { - nextIdx = scan + 2; + next_idx = scan + 2; return static_cast(a - '0'); } if (isdigit(b) && (c == 'b' || c == 'B')) { - nextIdx = scan + 3; + next_idx = scan + 3; return 10 * static_cast(a - '0') + static_cast(b - '0'); } } return 10; } -bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal** r, char delim) { +bool Lexer::getNumberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim) { stringstream ss; int idxNumber = 0; string token; bool positive = true; - nextIdx = idx; + next_idx = idx; ss.str(entry.substr(idx)); if (getline(ss, token, delim)) { size_t numberIdx; - nextIdx = token.size() + idx + 1; + next_idx = token.size() + idx + 1; trim(token); base = getBaseAt(token, numberIdx, positive); if (base < 2 || base > 62) return false; @@ -176,15 +176,15 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, m return false; } } - nextIdx = token.size() + idx + 1; + next_idx = token.size() + idx + 1; return false; } -bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, +bool Lexer::parseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { mpreal* r = nullptr; int base = 10; - if (getNumberAt(entry, idx, nextIdx, base, &r)) { + if (getNumberAt(entry, idx, next_idx, base, &r)) { elements.push_back({cmd_number, .re = r, .reBase = base}); return true; } else { @@ -193,44 +193,44 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, +bool Lexer::parseComplex(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { mpreal* re = nullptr; mpreal* im = nullptr; int reBase, imBase = 10; if (idx + 1 == entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); + next_idx = entry.size(); return true; // complex format error, return a symbol } - if (!getNumberAt(entry, idx + 1, nextIdx, reBase, &re, ',')) { + if (!getNumberAt(entry, idx + 1, next_idx, reBase, &re, ',')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); + next_idx = entry.size(); return true; // complex format error, return a symbol } - size_t i = nextIdx; + size_t i = next_idx; if (i >= entry.size()) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); + next_idx = entry.size(); if (re != nullptr) delete re; if (im != nullptr) delete im; return true; // complex format error, return a symbol } - if (!getNumberAt(entry, i, nextIdx, imBase, &im, ')')) { + if (!getNumberAt(entry, i, next_idx, imBase, &im, ')')) { elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); - nextIdx = entry.size(); + next_idx = entry.size(); if (re != nullptr) delete re; if (im != nullptr) delete im; return true; // complex format error, return a symbol } elements.push_back({cmd_complex, .re = re, .im = im, .reBase = reBase, .imBase = imBase}); - nextIdx++; + next_idx++; return true; } -bool Lexer::parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, +bool Lexer::parseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements, map& keywords) { stringstream ss(entry.substr(idx)); string token; @@ -239,17 +239,17 @@ bool Lexer::parseReserved(string& entry, size_t idx, size_t& nextIdx, vectorsecond.type, .value = token, .fn = resa->second.fn}); - nextIdx = token.size() + idx; + next_idx = token.size() + idx; return true; } return false; } -bool Lexer::parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements) { +bool Lexer::parseUnknown(string& entry, size_t idx, size_t& next_idx, vector& elements) { stringstream ss(entry.substr(idx)); string token; ss >> token; elements.push_back({cmd_symbol, .value = token, .autoEval = true}); - nextIdx = token.size() + idx; + next_idx = token.size() + idx; return true; } diff --git a/src/lexer.hpp b/src/lexer.hpp index 18455f2..217ded8 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -53,23 +53,23 @@ class Lexer { vector& errors); private: - bool parseString(string& entry, size_t idx, size_t& nextIdx, vector& errors, + bool parseString(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseSymbol(string& entry, size_t idx, size_t& nextIdx, vector& errors, + bool parseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseProgram(string& entry, size_t idx, size_t& nextIdx, vector& errors, + bool parseProgram(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseNumber(string& entry, size_t idx, size_t& nextIdx, vector& errors, + bool parseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseComplex(string& entry, size_t idx, size_t& nextIdx, vector& errors, + bool parseComplex(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseReserved(string& entry, size_t idx, size_t& nextIdx, vector& elements, + bool parseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements, map& keywords); - bool parseUnknown(string& entry, size_t idx, size_t& nextIdx, vector& elements); + bool parseUnknown(string& entry, size_t idx, size_t& next_idx, vector& elements); void trim(string& s); - int getBaseAt(string& entry, size_t& nextIdx, bool& positive); - bool getNumberAt(string& entry, size_t idx, size_t& nextIdx, int& base, mpreal** r, char delim = ' '); + int getBaseAt(string& entry, size_t& next_idx, bool& positive); + bool getNumberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim = ' '); }; #endif // SRC_LEXER_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 10a6722..bed85d1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,7 +14,7 @@ using std::cerr; /// @brief actions to be done at rpn exit /// -static void exit_interactive_rpn() { +static void ExitInteractive() { struct passwd* pw = getpwuid(getuid()); if (pw != nullptr) { stringstream history_path; @@ -34,7 +34,7 @@ static void exit_interactive_rpn() { /// @brief actions to be done at rpn exit /// -static void init_interactive_rpn() { +static void EnterInteractive() { struct passwd* pw = getpwuid(getuid()); if (pw != nullptr) { stringstream history_path; @@ -52,16 +52,16 @@ static void init_interactive_rpn() { /// @param siginfo signal info, see POSIX sigaction /// @param context see POSIX sigaction /// -static void ctrlc_handler(int sig, siginfo_t* siginfo, void* context) { exit_interactive_rpn(); } +static void CtrlHandler(int sig, siginfo_t* siginfo, void* context) { ExitInteractive(); } /// @brief setup signals handlers to stop with honours /// /// @param prog the prog to catch the signals to, must be checked not nullptr by user /// -static void catch_signals(program* prog) { +static void CatchSignals(program* prog) { struct sigaction act = {0}; - act.sa_sigaction = &ctrlc_handler; + act.sa_sigaction = &CtrlHandler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, nullptr) < 0) cerr << "Warning, Ctrl-C cannot be caught [errno=" << errno << ' ' << strerror(errno) << "']" << endl; @@ -83,7 +83,7 @@ int main(int argc, char* argv[]) { // run with interactive prompt if (argc == 1) { // init history - init_interactive_rpn(); + EnterInteractive(); // entry loop heap heap; @@ -96,7 +96,7 @@ int main(int argc, char* argv[]) { switch (Input(entry, program::getAutocompletionWords()).status) { case Input::ok: // user could stop prog with CtrlC - catch_signals(&prog); + CatchSignals(&prog); // run it if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye) go_on = false; @@ -112,7 +112,7 @@ int main(int argc, char* argv[]) { } // manage history and exit - exit_interactive_rpn(); + ExitInteractive(); } else { // run with cmd line arguments heap heap; rpnstack stack; @@ -127,7 +127,7 @@ int main(int argc, char* argv[]) { ret = prog.parse(entry); if (ret == ret_ok) { // user could stop prog with CtrlC - catch_signals(&prog); + CatchSignals(&prog); // run it ret = prog.run(); diff --git a/src/mpreal-out.cpp b/src/mpreal-out.cpp index 276852d..6b71028 100644 --- a/src/mpreal-out.cpp +++ b/src/mpreal-out.cpp @@ -33,7 +33,7 @@ #define MPFR_IS_POS(x) (MPFR_SIGN(x) > 0) #define MPFR_PREC(x) ((x)->_mpfr_prec) -ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value) { +ostream& MprealOutput10Base(ostream& out, const string& fmt, const mpreal& value) { // cf std::ostream& mpreal::output(std::ostream& os) const char* s = NULL; if (!(mpfr_asprintf(&s, fmt.c_str(), mpreal::get_default_rnd(), value.mpfr_srcptr()) < 0)) { @@ -195,7 +195,7 @@ ostream& _out_number(ostream& out, int base, const mpreal& value) { return out; } -ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value) { +ostream& MprealOutputNBase(ostream& out, int base, const mpreal& value) { // see mpfr_vasprintf code int digits = 0; // forced 0 digits after separator diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index c5f5e89..ddab132 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -11,7 +11,7 @@ using mpfr::mpreal; using std::string; using std::ostream; -ostream& mpreal_output10base(ostream& out, const string& fmt, const mpreal& value); -ostream& mpreal_outputNbase(ostream& out, int base, const mpreal& value); +ostream& MprealOutput10Base(ostream& out, const string& fmt, const mpreal& value); +ostream& MprealOutputNBase(ostream& out, int base, const mpreal& value); #endif // SRC_MPREAL_OUT_HPP_ diff --git a/src/object.cpp b/src/object.cpp index 43b8d49..3ab1baa 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -3,5 +3,5 @@ #include "object.hpp" // number statics -number::mode_enum number::s_mode = number::DEFAULT_MODE; -int number::s_digits = DEFAULT_DECIMAL_DIGITS; +Number::mode_enum Number::s_mode = Number::DEFAULT_MODE; +int Number::s_digits = DEFAULT_DECIMAL_DIGITS; diff --git a/src/object.hpp b/src/object.hpp index 77a7af8..c491dd7 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -44,60 +44,60 @@ typedef enum { cmd_undef, cmd_number, // floating point number cmd_complex, // complex, couple of floating point numbers - cmd_string, // string like "string" - cmd_symbol, // symbol like 'symbol' - cmd_program, // program like << instructions >> - cmd_keyword, // langage keyword - cmd_branch, // langage branch keyword + cmd_string, // "string" + cmd_symbol, // 'symbol' + cmd_program, // << instructions >> «instructions» + cmd_keyword, // langage (reserved) keyword + cmd_branch, // langage (reserved) branch keyword cmd_max } cmd_type_t; class program; -class branch; +class Branch; typedef void (program::*program_fn_t)(void); -typedef size_t (program::*branch_fn_t)(branch&); +typedef size_t (program::*branch_fn_t)(Branch&); -/// @brief object - a generic stack object +/// @brief Object - a generic stack object /// -struct object { - explicit object(cmd_type_t type = cmd_undef) : _type(type) {} - virtual ~object() {} +struct Object { + explicit Object(cmd_type_t type = cmd_undef) : _type(type) {} + virtual ~Object() {} cmd_type_t _type; - virtual object* clone() { - object* o = new object(); + virtual Object* clone() { + Object* o = new Object(); if (o != nullptr) *o = *this; return o; } - virtual string name() { return string("object"); } + virtual string name() { return string("Object"); } virtual ostream& show(ostream& out) { out << "(" << name() << " - unknown representation)"; return out; } - friend ostream& operator<<(ostream& os, object* o) { return o->show(os); } + friend ostream& operator<<(ostream& os, Object* o) { return o->show(os); } unsigned int size() { return sizeof(*this); } }; -/// @brief stack objects derived from object +/// @brief stack objects derived from Object /// -struct number : object { - number() : object(cmd_number), base(10) {} - explicit number(const mpreal& value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} - explicit number(int value_, int base_ = 10) : object(cmd_number), base(base_), value(value_) {} +struct Number : Object { + Number() : Object(cmd_number), base(10) {} + explicit Number(const mpreal& value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {} + explicit Number(int value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {} int base; mpreal value; - virtual object* clone() { return new number(value, base); } + virtual Object* clone() { return new Number(value, base); } virtual string name() { return string("number"); } virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); } // representation mode typedef enum { std, fix, sci } mode_enum; static mode_enum s_mode; - static constexpr mode_enum DEFAULT_MODE = number::std; + static constexpr mode_enum DEFAULT_MODE = Number::std; // precision static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128; @@ -119,22 +119,22 @@ struct number : object { static ostream& showValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base) { if (base == 10) - return mpreal_output10base(out, _makeNumberFormat(s_mode, s_digits), value); + return MprealOutput10Base(out, _makeNumberFormat(s_mode, s_digits), value); else - return mpreal_outputNbase(out, base, value); + return MprealOutputNBase(out, base, value); } }; -/// @brief stack objects derived from object +/// @brief stack objects inheriting Object /// -struct ocomplex : object { - ocomplex() : object(cmd_complex), reBase(10), imBase(10) {} - explicit ocomplex(complex& value_, int reb = 10, int imb = 10) - : object(cmd_complex), reBase(reb), imBase(imb) { +struct Complex : Object { + Complex() : Object(cmd_complex), reBase(10), imBase(10) {} + explicit Complex(complex& value_, int reb = 10, int imb = 10) + : Object(cmd_complex), reBase(reb), imBase(imb) { value = value_; } - explicit ocomplex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) - : object(cmd_complex), reBase(reb), imBase(imb) { + explicit Complex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) + : Object(cmd_complex), reBase(reb), imBase(imb) { value.real(re_); value.imag(im_); } @@ -142,68 +142,58 @@ struct ocomplex : object { int reBase, imBase; complex value; - virtual object* clone() { return new ocomplex(value, reBase, imBase); } + virtual Object* clone() { return new Complex(value, reBase, imBase); } virtual string name() { return string("complex"); } virtual ostream& show(ostream& out) { out << '('; - number::showValue(out, value.real(), number::s_mode, number::s_digits, reBase); + Number::showValue(out, value.real(), Number::s_mode, Number::s_digits, reBase); out << ','; - number::showValue(out, value.imag(), number::s_mode, number::s_digits, imBase); + Number::showValue(out, value.imag(), Number::s_mode, Number::s_digits, imBase); return out << ')'; } }; -/// @brief object string -/// -struct ostring : object { - ostring() : object(cmd_string) {} - explicit ostring(const string& value_) : object(cmd_string), value(value_) {} - virtual object* clone() { return new ostring(value); } +struct String : Object { + String() : Object(cmd_string) {} + explicit String(const string& value_) : Object(cmd_string), value(value_) {} + virtual Object* clone() { return new String(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } string value; }; -/// @brief object program -/// -struct oprogram : object { - oprogram() : object(cmd_program) {} - explicit oprogram(const string& value_) : object(cmd_program), value(value_) {} - virtual object* clone() { return new oprogram(value); } +struct Program : Object { + Program() : Object(cmd_program) {} + explicit Program(const string& value_) : Object(cmd_program), value(value_) {} + virtual Object* clone() { return new Program(value); } virtual string name() { return string("program"); } virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } string value; }; -/// @brief object symbol -/// -struct symbol : object { - explicit symbol(bool autoEval_ = true) : object(cmd_symbol), autoEval(autoEval_) {} - explicit symbol(const string& value_, bool autoEval_ = true) - : object(cmd_symbol), value(value_), autoEval(autoEval_) {} - virtual object* clone() { return new symbol(value, autoEval); } +struct Symbol : Object { + explicit Symbol(bool autoEval_ = true) : Object(cmd_symbol), autoEval(autoEval_) {} + explicit Symbol(const string& value_, bool autoEval_ = true) + : Object(cmd_symbol), value(value_), autoEval(autoEval_) {} + virtual Object* clone() { return new Symbol(value, autoEval); } virtual string name() { return string("symbol"); } virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } bool autoEval; string value; }; -/// @brief object keyword -/// -struct keyword : object { - keyword() : object(cmd_keyword) {} - explicit keyword(program_fn_t fn_, const string& value_) : object(cmd_keyword), fn(fn_), value(value_) {} - virtual object* clone() { return new keyword(fn, value); } +struct Keyword : Object { + Keyword() : Object(cmd_keyword) {} + explicit Keyword(program_fn_t fn_, const string& value_) : Object(cmd_keyword), fn(fn_), value(value_) {} + virtual Object* clone() { return new Keyword(fn, value); } virtual string name() { return string("keyword"); } program_fn_t fn; string value; }; -/// @brief object branch -/// -struct branch : object { - branch() : object(cmd_branch) {} - explicit branch(branch_fn_t fn_, const string& value_) : object(cmd_branch) { +struct Branch : Object { + Branch() : Object(cmd_branch) {} + explicit Branch(branch_fn_t fn_, const string& value_) : Object(cmd_branch) { fn = fn_; arg1 = static_cast(-1); arg2 = static_cast(-1); @@ -211,7 +201,7 @@ struct branch : object { arg_bool = 0; value = value_; } - explicit branch(branch& other) : object(cmd_branch) { + explicit Branch(Branch& other) : Object(cmd_branch) { fn = other.fn; arg1 = other.arg1; arg2 = other.arg2; @@ -219,7 +209,7 @@ struct branch : object { arg_bool = other.arg_bool; value = other.value; } - virtual object* clone() { return new branch(*this); } + virtual Object* clone() { return new Branch(*this); } virtual string name() { return string("branch"); } branch_fn_t fn; size_t arg1, arg2, arg3; diff --git a/src/program.cpp b/src/program.cpp index 918b2ab..1a6b89f 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -205,11 +205,11 @@ vector program::_keywords{ /// autocompletion vector for linenoise autocompletion vector& program::getAutocompletionWords() { - static vector autocompletionWords; - if (autocompletionWords.empty()) + static vector autocompletion_words; + if (autocompletion_words.empty()) for (auto& kw : _keywords) - if (!kw.name.empty()) autocompletionWords.push_back(kw.name); - return autocompletionWords; + if (!kw.name.empty()) autocompletion_words.push_back(kw.name); + return autocompletion_words; } /// @brief run a program on a stack and a heap @@ -228,24 +228,24 @@ ret_value program::run() { ret = preprocess(); if (ret != ret_ok) { // free allocated - for (object* o : *this) delete o; + for (Object* o : *this) delete o; _local_heap.clear(); return ret; } // iterate commands for (size_t i = 0; (go_out == false) && (i < size());) { - object* o = at(i); + Object* o = at(i); switch (o->_type) { // could be an auto-evaluated symbol case cmd_symbol: - auto_rcl(reinterpret_cast(o)); + auto_rcl(reinterpret_cast(o)); i++; break; // a keyword case cmd_keyword: { - keyword* k = reinterpret_cast(o); + Keyword* k = reinterpret_cast(o); // call the matching function (this->*(k->fn))(); switch (_err) { @@ -277,7 +277,7 @@ ret_value program::run() { // a branch keyword case cmd_branch: { // call matching function - branch* b = reinterpret_cast(o); + Branch* b = reinterpret_cast(o); size_t next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { case step_out: // step out @@ -304,7 +304,7 @@ ret_value program::run() { } // free allocated - for (object* o : *this) delete o; + for (Object* o : *this) delete o; _local_heap.clear(); return ret; @@ -336,13 +336,13 @@ ret_value program::preprocess(void) { vector vlayout; int layout_index = -1; // for start-end-step - vector vstartindex; + vector vstart_index; // analyse if-then-else-end branches // analyse start-{next, step} branches for (size_t i = 0; i < size(); i++) { if (at(i)->_type == cmd_branch) { - branch* k = reinterpret_cast(at(i)); + Branch* k = reinterpret_cast(at(i)); if (k->value == "if") { if_layout_t layout; layout.index_if_or_do_or_while = i; @@ -399,33 +399,33 @@ ret_value program::preprocess(void) { vlayout[layout_index].index_else = i; k->arg1 = next; // fill branch1 (if was false) of 'else' k->arg3 = vlayout[layout_index].index_if_or_do_or_while; - reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg2 = next; // fill branch2 (if was false) of 'then' } else if (k->value == "start") { - vstartindex.push_back(i); + vstart_index.push_back(i); } else if (k->value == "for") { - vstartindex.push_back(i); + vstart_index.push_back(i); k->arg1 = i + 1; // arg1 points on symbol variable } else if (k->value == "next") { - if (vstartindex.size() == 0) { + if (vstart_index.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 - reinterpret_cast(at(vstartindex[vstartindex.size() - 1]))->arg2 = + k->arg1 = vstart_index[vstart_index.size() - 1]; // 'next' arg1 = 'start' index + reinterpret_cast(at(vstart_index[vstart_index.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index - vstartindex.pop_back(); + vstart_index.pop_back(); } else if (k->value == "step") { - if (vstartindex.size() == 0) { + if (vstart_index.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 - reinterpret_cast(at(vstartindex[vstartindex.size() - 1]))->arg2 = + k->arg1 = vstart_index[vstart_index.size() - 1]; // fill 'step' branch1 = 'start' index + reinterpret_cast(at(vstart_index[vstart_index.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index - vstartindex.pop_back(); + vstart_index.pop_back(); } else if (k->value == "->") { k->arg1 = i; // arg1 is '->' command index in program } else if (k->value == "do") { @@ -515,8 +515,7 @@ ret_value program::preprocess(void) { } // fill 'repeat' arg1 with 'end+1' - reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg1 = - i + 1; + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat))->arg1 = i + 1; layout_index--; } else { // this end closes an if..then..(else) @@ -527,11 +526,11 @@ ret_value program::preprocess(void) { } if (vlayout[layout_index].index_else != -1) { // fill 'end' branch of 'else' - reinterpret_cast(at(vlayout[layout_index].index_else))->arg2 = i; + reinterpret_cast(at(vlayout[layout_index].index_else))->arg2 = i; } else { // fill 'end' branch of 'then' if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { - reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat)) + reinterpret_cast(at(vlayout[layout_index].index_then_or_unti_or_repeat)) ->arg2 = i; } else { // error: show it @@ -550,7 +549,7 @@ ret_value program::preprocess(void) { show_syntax_error("missing end"); return ret_syntax; } - if (vstartindex.size() > 0) { + if (vstart_index.size() > 0) { // error: show it show_syntax_error("missing next or step after for or start"); return ret_syntax; @@ -565,41 +564,41 @@ ret_value program::preprocess(void) { /// @return ret_value see this type /// ret_value program::parse(string& entry) { - static map keywordsMap; + static map keywords_map; vector elements; vector errors; ret_value ret = ret_ok; // prepare map for finding reserved keywords - if (keywordsMap.empty()) + if (keywords_map.empty()) for (auto& kw : _keywords) - if (!kw.name.empty()) keywordsMap[kw.name] = {kw.type, kw.fn}; + if (!kw.name.empty()) keywords_map[kw.name] = {kw.type, kw.fn}; // separate the entry string - if (lexer(entry, keywordsMap, elements, errors)) { + if (lexer(entry, keywords_map, elements, errors)) { // make objects from parsed elements for (Lexer::SynElement& element : elements) { switch (element.type) { case cmd_number: - push_back(new number(*element.re, element.reBase)); + push_back(new Number(*element.re, element.reBase)); break; case cmd_complex: - push_back(new ocomplex(*element.re, *element.im, element.reBase, element.imBase)); + push_back(new Complex(*element.re, *element.im, element.reBase, element.imBase)); break; case cmd_string: - push_back(new ostring(element.value)); + push_back(new String(element.value)); break; case cmd_symbol: - push_back(new symbol(element.value, element.autoEval)); + push_back(new Symbol(element.value, element.autoEval)); break; case cmd_program: - push_back(new oprogram(element.value)); + push_back(new Program(element.value)); break; case cmd_keyword: - push_back(new keyword(element.fn, element.value)); + push_back(new Keyword(element.fn, element.value)); break; case cmd_branch: - push_back(new branch((branch_fn_t)element.fn, element.value)); + push_back(new Branch((branch_fn_t)element.fn, element.value)); break; default: show_error(ret_unknown_err, "error creating program from entry"); @@ -708,9 +707,9 @@ void program::show_stack(bool show_separator) { /// void program::apply_default() { // default float precision, float mode - number::s_mode = number::DEFAULT_MODE; - number::s_digits = number::DEFAULT_DECIMAL_DIGITS; - mpreal::set_default_prec(number::MPFR_DEFAULT_PREC_BITS); + Number::s_mode = Number::DEFAULT_MODE; + Number::s_digits = Number::DEFAULT_DECIMAL_DIGITS; + mpreal::set_default_prec(Number::MPFR_DEFAULT_PREC_BITS); static mp_rnd_t def_rnd = mpreal::get_default_rnd(); mpreal::set_default_rnd(def_rnd); diff --git a/src/program.hpp b/src/program.hpp index a5d6d84..05fb7dc 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -19,7 +19,7 @@ using mpfr::mpreal; #include "stack.hpp" //< program class: the class containing a string parser, all the programs keywords, a stack for running the program -class program : public deque, public Lexer { +class program : public deque, public Lexer { public: program(rpnstack& stk, heap& hp, program* parent = nullptr) : _stack(stk), _heap(hp), _parent(parent) {} virtual ~program() { @@ -79,20 +79,20 @@ class program : public deque, public Lexer { //// // branch - size_t rpn_if(branch& myobj); - size_t rpn_then(branch& myobj); - size_t rpn_else(branch& myobj); - size_t rpn_end(branch& myobj); - size_t rpn_do(branch& myobj); - size_t rpn_until(branch& myobj); + size_t rpn_if(Branch& myobj); + size_t rpn_then(Branch& myobj); + size_t rpn_else(Branch& myobj); + size_t rpn_end(Branch& myobj); + size_t rpn_do(Branch& myobj); + size_t rpn_until(Branch& myobj); void rpn_ift(void); void rpn_ifte(void); - size_t rpn_while(branch& myobj); - size_t rpn_repeat(branch& myobj); - size_t rpn_start(branch& myobj); - size_t rpn_for(branch& myobj); - size_t rpn_next(branch& myobj); - size_t rpn_step(branch& myobj); + size_t rpn_while(Branch& myobj); + size_t rpn_repeat(Branch& myobj); + size_t rpn_start(Branch& myobj); + size_t rpn_for(Branch& myobj); + size_t rpn_next(Branch& myobj); + size_t rpn_step(Branch& myobj); enum { step_out = static_cast(-1), runtime_error = static_cast(-2) }; // complex @@ -138,9 +138,9 @@ class program : public deque, public Lexer { void rpn_atanh(); // program - bool find_variable(string& variable, object*& obj); + bool find_variable(string& variable, Object*& obj); void rpn_eval(void); - int rpn_inprog(branch& myobj); + int rpn_inprog(Branch& inprog_obj); // real void rpn_plus(); @@ -198,7 +198,7 @@ class program : public deque, public Lexer { void rpn_stoinv(void); void rpn_rcl(void); void rpn_edit(void); - void auto_rcl(symbol* symb); + void auto_rcl(Symbol* symb); void rpn_purge(void); void rpn_vars(void); void rpn_clusr(void); diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index 182cc03..d39ca10 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -9,12 +9,12 @@ /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_if(branch& myobj) { +size_t program::rpn_if(Branch& myobj) { // myobj.arg1 = 'if' condition evaluation value MIN_ARGUMENTS_RET(1, runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); - if (_stack.value(0) != 0) + if (_stack.value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; @@ -27,20 +27,20 @@ size_t program::rpn_if(branch& myobj) { /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program /// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return runtime_error something went wrong with preprocess, abort Branch /// -size_t program::rpn_then(branch& myobj) { +size_t program::rpn_then(Branch& myobj) { // myobj.arg1 = index of then + 1 // myobj.arg2 = index of else + 1 or end + 1 // myobj.arg3 = index of if // if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1) - branch* if_cmd; + Branch* if_cmd; if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { setErrorContext(ret_missing_operand); return runtime_error; } - if_cmd = reinterpret_cast(at(myobj.arg3)); + if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) return myobj.arg1; else @@ -54,18 +54,18 @@ size_t program::rpn_then(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_else(branch& myobj) { +size_t program::rpn_else(Branch& myobj) { // myobj.arg1 = index of else + 1 // myobj.arg2 = index of end + 1 // myobj.arg3 = index of if // if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1) - branch* if_cmd; + Branch* if_cmd; if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { setErrorContext(ret_missing_operand); return runtime_error; } - if_cmd = reinterpret_cast(at(myobj.arg3)); + if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) return myobj.arg2; else @@ -79,7 +79,7 @@ size_t program::rpn_else(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_end(branch& myobj) { +size_t program::rpn_end(Branch& myobj) { size_t ret = step_out; // arg1 = index of do+1 in case of do..unti..end @@ -89,7 +89,7 @@ size_t program::rpn_end(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); // check arg - if (_stack.value(0) == 0) ret = myobj.arg1; + if (_stack.value(0) == 0) ret = myobj.arg1; _stack.pop(); } else if (myobj.arg2 != step_out) { // arg2 = index of while+1 in case of while..repeat..end @@ -106,7 +106,7 @@ size_t program::rpn_end(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_do(branch& myobj) { +size_t program::rpn_do(Branch& myobj) { // nothing return step_out; } @@ -116,9 +116,9 @@ size_t program::rpn_do(branch& myobj) { /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program /// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return runtime_error something went wrong with preprocess, abort Branch /// -size_t program::rpn_until(branch& myobj) { +size_t program::rpn_until(Branch& myobj) { // nothing return step_out; } @@ -135,8 +135,8 @@ void program::rpn_ift(void) { ARG_MUST_BE_OF_TYPE(1, cmd_number); // check ift arg - // arg is true if number != 0 or if is nan or +/-inf - if (_stack.value(1) != 0) + // arg is true if Number != 0 or if is nan or +/-inf + if (_stack.value(1) != 0) _stack.erase(1); else _stack.erase(0, 2); @@ -154,7 +154,7 @@ void program::rpn_ifte(void) { ARG_MUST_BE_OF_TYPE(2, cmd_number); // check ifte arg - if (_stack.value(2) != 0) { + if (_stack.value(2) != 0) { _stack.erase(2); _stack.pop(); } else { @@ -170,7 +170,7 @@ void program::rpn_ifte(void) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_while(branch& myobj) { +size_t program::rpn_while(Branch& myobj) { // nothing return step_out; } @@ -182,7 +182,7 @@ size_t program::rpn_while(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_repeat(branch& myobj) { +size_t program::rpn_repeat(Branch& myobj) { size_t ret = step_out; MIN_ARGUMENTS_RET(1, runtime_error); @@ -190,7 +190,7 @@ size_t program::rpn_repeat(branch& myobj) { // check arg // myobj.arg1 is end+1 - if (_stack.value(0) == 0) ret = myobj.arg1; + if (_stack.value(0) == 0) ret = myobj.arg1; _stack.pop(); return ret; @@ -203,7 +203,7 @@ size_t program::rpn_repeat(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_start(branch& myobj) { +size_t program::rpn_start(Branch& myobj) { size_t ret = step_out; MIN_ARGUMENTS_RET(2, runtime_error); @@ -211,8 +211,8 @@ size_t program::rpn_start(branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); // loop boundaries - myobj.firstIndex = _stack.value(1); - myobj.lastIndex = _stack.value(0); + myobj.firstIndex = _stack.value(1); + myobj.lastIndex = _stack.value(0); _stack.erase(0, 2); // test value @@ -232,23 +232,23 @@ size_t program::rpn_start(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_for(branch& myobj) { +size_t program::rpn_for(Branch& myobj) { size_t ret; MIN_ARGUMENTS_RET(2, runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); - symbol* sym; + Symbol* sym; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_symbol) { setErrorContext(ret_missing_operand); return runtime_error; } - sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index + sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index // loop boundaries - myobj.firstIndex = _stack.value(1); - myobj.lastIndex = _stack.value(0); + myobj.firstIndex = _stack.value(1); + myobj.lastIndex = _stack.value(0); // test value if (myobj.firstIndex > myobj.lastIndex) { @@ -263,7 +263,7 @@ size_t program::rpn_for(branch& myobj) { delete it->second; _local_heap.erase(it); } - _local_heap[sym->value] = _stack.obj(1).clone(); + _local_heap[sym->value] = _stack.obj(1).clone(); ret = myobj.arg1 + 1; } @@ -279,15 +279,15 @@ size_t program::rpn_for(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_next(branch& myobj) { +size_t program::rpn_next(Branch& myobj) { // arg1 = loop variable index // firstIndex = current point in the loop - branch* start_or_for; + Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { setErrorContext(ret_missing_operand); return runtime_error; } - start_or_for = reinterpret_cast(at(myobj.arg1)); + start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -299,16 +299,16 @@ size_t program::rpn_next(branch& myobj) { // for command: increment symbol too if (start_or_for->arg1 != -1) { - object* obj; - symbol* var; + Object* obj; + Symbol* var; if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { setErrorContext(ret_missing_operand); return runtime_error; } - var = reinterpret_cast(at(start_or_for->arg1)); + var = reinterpret_cast(at(start_or_for->arg1)); // store symbol variable (asserted existing in the local heap) - reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; } // test value @@ -332,12 +332,12 @@ size_t program::rpn_next(branch& myobj) { /// @return step_out next object to run in the current program is current + 1 /// @return runtime_error something went wrong with preprocess, abort branch /// -size_t program::rpn_step(branch& myobj) { +size_t program::rpn_step(Branch& myobj) { size_t ret; MIN_ARGUMENTS_RET(1, runtime_error); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); - mpreal step = _stack.value(0); + mpreal step = _stack.value(0); _stack.pop(); // end of loop if step is negative or zero @@ -346,12 +346,12 @@ size_t program::rpn_step(branch& myobj) { } else { // arg1 = loop variable index // firstIndex = current count - branch* start_or_for; + Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { setErrorContext(ret_missing_operand); return runtime_error; } - start_or_for = reinterpret_cast(at(myobj.arg1)); + start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; myobj.firstIndex = start_or_for->firstIndex; @@ -362,17 +362,17 @@ size_t program::rpn_step(branch& myobj) { mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD); if (start_or_for->arg1 != -1) { - object* obj; - symbol* var; + Object* obj; + Symbol* var; // for command: increment symbol too if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { setErrorContext(ret_missing_operand); return runtime_error; } - var = reinterpret_cast(at(start_or_for->arg1)); + var = reinterpret_cast(at(start_or_for->arg1)); // increase symbol variable - reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; } // test loop value is out of range diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index ca94145..d90ca2d 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -8,7 +8,7 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.push_front(new number(real(_stack.value(0)))); + _stack.push_front(new Number(real(_stack.value(0)))); _stack.erase(1); } @@ -18,7 +18,7 @@ void program::rpn_re() { void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.push_front(new number(imag(_stack.value(0)))); + _stack.push_front(new Number(imag(_stack.value(0)))); _stack.erase(1); } @@ -28,7 +28,7 @@ void program::rpn_im() { void program::rpn_arg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.push_front(new number(arg(_stack.value(0)))); + _stack.push_front(new Number(arg(_stack.value(0)))); _stack.erase(1); } @@ -38,7 +38,7 @@ void program::rpn_arg() { void program::rpn_conj() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.value(0) = conj(_stack.value(0)); + _stack.value(0) = conj(_stack.value(0)); } /// @brief r2c keyword implementation @@ -48,7 +48,7 @@ void program::rpn_r2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.push(new ocomplex(_stack.value(1), _stack.value(0), _stack.obj(1).reBase, _stack.obj(0).reBase)); + _stack.push(new Complex(_stack.value(1), _stack.value(0), _stack.obj(1).reBase, _stack.obj(0).reBase)); _stack.erase(1, 2); } @@ -58,8 +58,8 @@ void program::rpn_r2c() { void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.push(new number(real(_stack.value(0)), _stack.obj(0).reBase)); - _stack.push(new number(imag(_stack.value(1)), _stack.obj(1).imBase)); + _stack.push(new Number(real(_stack.value(0)), _stack.obj(0).reBase)); + _stack.push(new Number(imag(_stack.value(1)), _stack.obj(1).imBase)); _stack.erase(2); } @@ -69,10 +69,10 @@ void program::rpn_c2r() { void program::rpn_r2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - mpreal rho = abs(_stack.value(0)); - mpreal theta = arg(_stack.value(0)); - _stack.value(0).real(rho); - _stack.value(0).imag(theta); + mpreal rho = abs(_stack.value(0)); + mpreal theta = arg(_stack.value(0)); + _stack.value(0).real(rho); + _stack.value(0).imag(theta); } /// @brief p2r keyword implementation @@ -81,5 +81,5 @@ void program::rpn_r2p() { void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_complex); - _stack.value(0) = polar(abs(_stack.value(0)), arg(_stack.value(0))); + _stack.value(0) = polar(abs(_stack.value(0)), arg(_stack.value(0))); } diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index a493550..7443805 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -69,14 +69,14 @@ void program::rpn_help() { // show mode cout << "Current float mode is "; - switch (number::s_mode) { - case number::std: + switch (Number::s_mode) { + case Number::std: cout << "'std'"; break; - case number::fix: + case Number::fix: cout << "'fix'"; break; - case number::sci: + case Number::sci: cout << "'sci'"; break; default: @@ -85,7 +85,7 @@ void program::rpn_help() { } // bits precision, decimal digits and rounding mode - cout << " with " << number::s_digits << " digits after the decimal point" << endl; + cout << " with " << Number::s_digits << " digits after the decimal point" << endl; cout << "Current floating point precision is " << static_cast(mpreal::get_default_prec()) << " bits" << endl; vector> rnd{MPFR_ROUND}; for (auto& rn : rnd) @@ -110,12 +110,12 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - number::s_mode = number::std; - number::s_digits = digits; + Number::s_mode = Number::std; + Number::s_digits = digits; _stack.pop(); } else { setErrorContext(ret_out_of_range); @@ -128,12 +128,12 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - number::s_mode = number::fix; - number::s_digits = digits; + Number::s_mode = Number::fix; + Number::s_digits = digits; _stack.pop(); } else { setErrorContext(ret_out_of_range); @@ -146,12 +146,12 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - number::s_mode = number::sci; - number::s_digits = digits; + Number::s_mode = Number::sci; + Number::s_digits = digits; _stack.pop(); } else { setErrorContext(ret_out_of_range); @@ -160,11 +160,11 @@ void program::rpn_sci() { /// @brief _version keyword implementation /// -void program::rpn_version() { _stack.push_front(new ostring(RPN_VERSION)); } +void program::rpn_version() { _stack.push_front(new String(RPN_VERSION)); } /// @brief _uname keyword implementation /// -void program::rpn_uname() { _stack.push_front(new ostring(RPN_UNAME)); } +void program::rpn_uname() { _stack.push_front(new String(RPN_UNAME)); } /// @brief history keyword implementation /// @@ -183,7 +183,7 @@ void program::rpn_history() { /// void program::rpn_type() { MIN_ARGUMENTS(1); - _stack.push(new ostring(_stack.at(0)->name())); + _stack.push(new String(_stack.at(0)->name())); _stack.erase(1); } @@ -198,14 +198,14 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, cmd_number); // set precision - int prec = static_cast(_stack.value(0).toLong()); + int prec = static_cast(_stack.value(0).toLong()); if (prec >= MPFR_PREC_MIN && prec <= MPFR_PREC_MAX) { mpreal::set_default_prec(prec); // modify digits seen by user if std mode - if (number::s_mode == number::std) { + if (Number::s_mode == Number::std) { // calc max nb of digits user can see with the current bit precision - number::s_digits = mpfr::bits2digits(mpreal::get_default_prec()); + Number::s_digits = mpfr::bits2digits(mpreal::get_default_prec()); } _stack.pop(); } else { @@ -221,7 +221,7 @@ void program::rpn_round() { map matchRound{MPFR_ROUND}; - auto found = matchRound.find(_stack.value(0)); + auto found = matchRound.find(_stack.value(0)); if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index ffbad53..c0f06c5 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -4,16 +4,16 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { _stack.push(new number(mpfr::const_euler())); } +void program::rpn_e(void) { _stack.push(new Number(mpfr::const_euler())); } /// @brief log10 keyword implementation /// void program::rpn_log10() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = log10(_stack.value(0)); + _stack.value(0) = log10(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = log10(_stack.value(0)); + _stack.value(0) = log10(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -23,9 +23,9 @@ void program::rpn_log10() { void program::rpn_alog10() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); + _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); + _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -35,9 +35,9 @@ void program::rpn_alog10() { void program::rpn_log2() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); + _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); + _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); else setErrorContext(ret_bad_operand_type); } @@ -47,9 +47,9 @@ void program::rpn_log2() { void program::rpn_alog2() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); + _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); + _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -59,9 +59,9 @@ void program::rpn_alog2() { void program::rpn_ln() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = log(_stack.value(0)); + _stack.value(0) = log(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = log(_stack.value(0)); + _stack.value(0) = log(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -71,9 +71,9 @@ void program::rpn_ln() { void program::rpn_exp() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = exp(_stack.value(0)); + _stack.value(0) = exp(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = exp(_stack.value(0)); + _stack.value(0) = exp(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -83,9 +83,9 @@ void program::rpn_exp() { void program::rpn_expm() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = exp(_stack.value(0)) - mpreal(1); + _stack.value(0) = exp(_stack.value(0)) - mpreal(1); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = exp(_stack.value(0)) - mpreal(1); + _stack.value(0) = exp(_stack.value(0)) - mpreal(1); else setErrorContext(ret_bad_operand_type); } @@ -95,9 +95,9 @@ void program::rpn_expm() { void program::rpn_lnp1() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = log(_stack.value(0) + 1); + _stack.value(0) = log(_stack.value(0) + 1); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = log(_stack.value(0) + mpreal(1)); + _stack.value(0) = log(_stack.value(0) + mpreal(1)); else setErrorContext(ret_bad_operand_type); } @@ -107,9 +107,9 @@ void program::rpn_lnp1() { void program::rpn_sinh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = sinh(_stack.value(0)); + _stack.value(0) = sinh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = sinh(_stack.value(0)); + _stack.value(0) = sinh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -119,9 +119,9 @@ void program::rpn_sinh() { void program::rpn_asinh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = asinh(_stack.value(0)); + _stack.value(0) = asinh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = asinh(_stack.value(0)); + _stack.value(0) = asinh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -131,9 +131,9 @@ void program::rpn_asinh() { void program::rpn_cosh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = cosh(_stack.value(0)); + _stack.value(0) = cosh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = cosh(_stack.value(0)); + _stack.value(0) = cosh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -143,9 +143,9 @@ void program::rpn_cosh() { void program::rpn_acosh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = acosh(_stack.value(0)); + _stack.value(0) = acosh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = acosh(_stack.value(0)); + _stack.value(0) = acosh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -155,9 +155,9 @@ void program::rpn_acosh() { void program::rpn_tanh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = tanh(_stack.value(0)); + _stack.value(0) = tanh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = tanh(_stack.value(0)); + _stack.value(0) = tanh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -167,9 +167,9 @@ void program::rpn_tanh() { void program::rpn_atanh() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = atanh(_stack.value(0)); + _stack.value(0) = atanh(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = atanh(_stack.value(0)); + _stack.value(0) = atanh(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index d6ea074..4e83558 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -9,7 +9,7 @@ /// @return true variable was found /// @return false variable was not found /// -bool program::find_variable(string& variable, object*& obj) { +bool program::find_variable(string& variable, Object*& obj) { bool found = false; program* parent = _parent; @@ -40,14 +40,14 @@ void program::rpn_eval(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_symbol) { // recall a variable - object* obj; - string variable(_stack.value(0)); + Object* obj; + string variable(_stack.value(0)); _stack.pop(); // if variable holds a program, run this program if (find_variable(variable, obj)) { if (obj->_type == cmd_program) { - prog_text = _stack.value(0); + prog_text = _stack.value(0); _stack.pop(); run_prog = true; } else { @@ -59,7 +59,7 @@ void program::rpn_eval(void) { } } else if (_stack.type(0) == cmd_program) { // eval a program - prog_text = _stack.value(0); + prog_text = _stack.value(0); _stack.pop(); run_prog = true; } else { @@ -78,23 +78,23 @@ void program::rpn_eval(void) { } } -/// @brief -> keyword (branch) implementation +/// @brief -> keyword (Branch) implementation /// -int program::rpn_inprog(branch& myobj) { +int program::rpn_inprog(Branch& inprog_obj) { string context("->"); // for showing errors int count_symbols = 0; bool prog_found = false; - if (myobj.arg1 == -1) { + if (inprog_obj.arg1 == -1) { setErrorContext(ret_unknown_err); return -1; } // syntax must be - // -> ... + // -> ... - // find next oprogram object - for (unsigned int i = myobj.arg1 + 1; i < size(); i++) { + // find next Program object + for (unsigned int i = inprog_obj.arg1 + 1; i < size(); i++) { // count symbol if (at(i)->_type == cmd_symbol) { count_symbols++; @@ -117,14 +117,14 @@ int program::rpn_inprog(branch& myobj) { return -1; } - // is missing + // is missing if (!prog_found) { setErrorContext(ret_syntax); show_error(_err, context); return -1; } - // check symbols number vs stack size + // check symbols Number vs stack size if (_stack.size() < count_symbols) { setErrorContext(ret_missing_operand); show_error(_err, context); @@ -132,13 +132,13 @@ int program::rpn_inprog(branch& myobj) { } // load variables - for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--) { - _local_heap[reinterpret_cast(at(i))->value] = _stack.at(0)->clone(); + for (unsigned int i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) { + _local_heap[reinterpret_cast(at(i))->value] = _stack.at(0)->clone(); _stack.pop(); } // run the program - string& entry = reinterpret_cast(at(myobj.arg1 + count_symbols + 1))->value; + string& entry = reinterpret_cast(at(inprog_obj.arg1 + count_symbols + 1))->value; program prog(_stack, _heap, this); // make the program from entry @@ -148,5 +148,5 @@ int program::rpn_inprog(branch& myobj) { } // point on next command - return myobj.arg1 + count_symbols + 2; + return inprog_obj.arg1 + count_symbols + 2; } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 471046e..d9d00a5 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -7,20 +7,20 @@ void program::rpn_plus() { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.value(1) += _stack.value(0); + _stack.value(1) += _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.value(1) += _stack.value(0); + _stack.value(1) += _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.value(1) += _stack.value(0); + _stack.value(1) += _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { - _stack.value(1) += _stack.value(0); + _stack.value(1) += _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack.value(1) += _stack.value(0); + _stack.value(1) += _stack.value(0); _stack.pop(); } else { setErrorContext(ret_bad_operand_type); @@ -32,17 +32,17 @@ void program::rpn_plus() { void program::rpn_minus() { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.value(1) -= _stack.value(0); + _stack.value(1) -= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.value(1) -= _stack.value(0); + _stack.value(1) -= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { - _stack.value(1) -= _stack.value(0); + _stack.value(1) -= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack.value(1) = _stack.value(0) - _stack.value(1); + _stack.value(1) = _stack.value(0) - _stack.value(1); _stack.pop(); } else { setErrorContext(ret_bad_operand_type); @@ -54,17 +54,17 @@ void program::rpn_minus() { void program::rpn_mul() { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.value(1) *= _stack.value(0); + _stack.value(1) *= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.value(1) *= _stack.value(0); + _stack.value(1) *= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { - _stack.value(1) *= _stack.value(0); + _stack.value(1) *= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack.value(1) *= _stack.value(0); + _stack.value(1) *= _stack.value(0); _stack.pop(); } else { setErrorContext(ret_bad_operand_type); @@ -76,17 +76,17 @@ void program::rpn_mul() { void program::rpn_div() { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.value(1) /= _stack.value(0); + _stack.value(1) /= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.value(1) /= _stack.value(0); + _stack.value(1) /= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { - _stack.value(1) /= _stack.value(0); + _stack.value(1) /= _stack.value(0); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack.value(1) = _stack.value(0) / _stack.value(1); + _stack.value(1) = _stack.value(0) / _stack.value(1); _stack.pop(); } else { setErrorContext(ret_bad_operand_type); @@ -98,9 +98,9 @@ void program::rpn_div() { void program::rpn_neg() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = -_stack.value(0); + _stack.value(0) = -_stack.value(0); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = -_stack.value(0); + _stack.value(0) = -_stack.value(0); else setErrorContext(ret_bad_operand_type); } @@ -110,9 +110,9 @@ void program::rpn_neg() { void program::rpn_inv() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = 1 / _stack.value(0); + _stack.value(0) = 1 / _stack.value(0); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = mpreal(1) / _stack.value(0); + _stack.value(0) = mpreal(1) / _stack.value(0); else setErrorContext(ret_bad_operand_type); } @@ -122,24 +122,24 @@ void program::rpn_inv() { void program::rpn_power() { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - if (_stack.value(1) >= 0) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + if (_stack.value(1) >= 0) { + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); } else { mpreal zero; - _stack.push(new ocomplex(_stack.value(1), zero, _stack.obj(1).base)); - _stack.value(0) = pow(_stack.value(0), _stack.value(1)); + _stack.push(new Complex(_stack.value(1), zero, _stack.obj(1).base)); + _stack.value(0) = pow(_stack.value(0), _stack.value(1)); _stack.erase(1, 2); } } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); + _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { rpn_swap(); - _stack.value(1) = pow(_stack.value(0), _stack.value(1)); + _stack.value(1) = pow(_stack.value(0), _stack.value(1)); _stack.pop(); } else { setErrorContext(ret_bad_operand_type); @@ -151,18 +151,18 @@ void program::rpn_power() { void program::rpn_squareroot() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) { - if (_stack.value(0) >= 0) { - _stack.value(0) = sqrt(_stack.value(0)); + if (_stack.value(0) >= 0) { + _stack.value(0) = sqrt(_stack.value(0)); } else { // negative number -> square root is complex mpreal zero; - _stack.push(new ocomplex(_stack.value(0), zero, - _stack.obj(0).base)); // TODO(louis) manage new errors - _stack.value(0) = sqrt(_stack.value(0)); + _stack.push(new Complex(_stack.value(0), zero, + _stack.obj(0).base)); // TODO(louis) manage new errors + _stack.value(0) = sqrt(_stack.value(0)); _stack.erase(1); } } else if (_stack.type(0) == cmd_complex) { - _stack.value(0) = sqrt(_stack.value(0)); + _stack.value(0) = sqrt(_stack.value(0)); } else { setErrorContext(ret_bad_operand_type); } @@ -173,10 +173,10 @@ void program::rpn_squareroot() { void program::rpn_hex() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) { - _stack.obj(0).base = 16; + _stack.obj(0).base = 16; } else if (_stack.type(0) == cmd_complex) { - _stack.obj(0).reBase = 16; - _stack.obj(0).imBase = 16; + _stack.obj(0).reBase = 16; + _stack.obj(0).imBase = 16; } else { setErrorContext(ret_bad_operand_type); } @@ -187,10 +187,10 @@ void program::rpn_hex() { void program::rpn_bin() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) { - _stack.obj(0).base = 2; + _stack.obj(0).base = 2; } else if (_stack.type(0) == cmd_complex) { - _stack.obj(0).reBase = 2; - _stack.obj(0).imBase = 2; + _stack.obj(0).reBase = 2; + _stack.obj(0).imBase = 2; } else { setErrorContext(ret_bad_operand_type); } @@ -201,10 +201,10 @@ void program::rpn_bin() { void program::rpn_dec() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) { - _stack.obj(0).base = 10; + _stack.obj(0).base = 10; } else if (_stack.type(0) == cmd_complex) { - _stack.obj(0).reBase = 10; - _stack.obj(0).imBase = 10; + _stack.obj(0).reBase = 10; + _stack.obj(0).imBase = 10; } else { setErrorContext(ret_bad_operand_type); } @@ -215,14 +215,14 @@ void program::rpn_dec() { void program::rpn_base() { MIN_ARGUMENTS(2); if (_stack.type(1) == cmd_number || _stack.type(1) == cmd_complex) { - int base = static_cast(_stack.value(0).toLong()); + int base = static_cast(_stack.value(0).toLong()); _stack.pop(); if (base >= 2 && base <= 62) { if (_stack.type(0) == cmd_number) { - _stack.obj(0).base = base; + _stack.obj(0).base = base; } else { - _stack.obj(0).reBase = base; - _stack.obj(0).imBase = base; + _stack.obj(0).reBase = base; + _stack.obj(0).imBase = base; } } else { setErrorContext(ret_out_of_range); @@ -238,7 +238,7 @@ void program::rpn_purcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.value(1) *= _stack.value(0) / 100; + _stack.value(1) *= _stack.value(0) / 100; _stack.pop(); } @@ -248,7 +248,7 @@ void program::rpn_purcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.value(1) = (_stack.value(0) * 100) / _stack.value(1); + _stack.value(1) = (_stack.value(0) * 100) / _stack.value(1); _stack.pop(); } @@ -257,9 +257,9 @@ void program::rpn_purcentCH() { void program::rpn_square() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) *= _stack.value(0); + _stack.value(0) *= _stack.value(0); else if (_stack.at(0)->_type == cmd_complex) - _stack.value(0) *= _stack.value(0); + _stack.value(0) *= _stack.value(0); else setErrorContext(ret_bad_operand_type); } @@ -270,7 +270,7 @@ void program::rpn_modulo() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.value(1) = fmod(_stack.value(1), _stack.value(0)); + _stack.value(1) = fmod(_stack.value(1), _stack.value(0)); _stack.pop(); } @@ -279,9 +279,9 @@ void program::rpn_modulo() { void program::rpn_abs() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) { - _stack.value(0) = abs(_stack.value(0)); + _stack.value(0) = abs(_stack.value(0)); } else if (_stack.type(0) == cmd_complex) { - _stack.push(new number(abs(_stack.value(0)))); + _stack.push(new Number(abs(_stack.value(0)))); _stack.erase(1); } else { setErrorContext(ret_bad_operand_type); @@ -294,7 +294,7 @@ void program::rpn_fact() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); // fact(n) = gamma(n+1) - _stack.value(0) = gamma(_stack.value(0) + 1); + _stack.value(0) = gamma(_stack.value(0) + 1); } /// @brief sign keyword implementation @@ -302,9 +302,9 @@ void program::rpn_fact() { void program::rpn_sign() { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = sgn(_stack.value(0)); + _stack.value(0) = sgn(_stack.value(0)); else if (_stack.at(0)->_type == cmd_complex) - _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); + _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -314,12 +314,12 @@ void program::rpn_sign() { void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - if (!isfinite(_stack.value(0))) { + if (!isfinite(_stack.value(0))) { setErrorContext(ret_out_of_range); return; } mp_exp_t exp; - _stack.value(0) = frexp(_stack.value(0), &exp); + _stack.value(0) = frexp(_stack.value(0), &exp); } /// @brief xpon keyword implementation @@ -327,13 +327,13 @@ void program::rpn_mant() { void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - if (!isfinite(_stack.value(0))) { + if (!isfinite(_stack.value(0))) { setErrorContext(ret_out_of_range); return; } mp_exp_t exp; - (void)frexp(_stack.value(0), &exp); - _stack.value(0) = exp; + (void)frexp(_stack.value(0), &exp); + _stack.value(0) = exp; } /// @brief floor keyword implementation @@ -341,7 +341,7 @@ void program::rpn_xpon() { void program::rpn_floor() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) = floor(_stack.value(0)); + _stack.value(0) = floor(_stack.value(0)); } /// @brief ceil keyword implementation @@ -349,7 +349,7 @@ void program::rpn_floor() { void program::rpn_ceil() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) = ceil(_stack.value(0)); + _stack.value(0) = ceil(_stack.value(0)); } /// @brief fp keyword implementation @@ -357,7 +357,7 @@ void program::rpn_ceil() { void program::rpn_fp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) = frac(_stack.value(0)); + _stack.value(0) = frac(_stack.value(0)); } /// @brief ip keyword implementation @@ -365,7 +365,7 @@ void program::rpn_fp() { void program::rpn_ip() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) = trunc(_stack.value(0)); + _stack.value(0) = trunc(_stack.value(0)); } /// @brief min keyword implementation @@ -374,7 +374,7 @@ void program::rpn_min() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.value(0) = min(_stack.value(0), _stack.value(1)); + _stack.value(0) = min(_stack.value(0), _stack.value(1)); _stack.erase(1); } @@ -384,6 +384,6 @@ void program::rpn_max() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - _stack.value(0) = max(_stack.value(0), _stack.value(1)); + _stack.value(0) = max(_stack.value(0), _stack.value(1)); _stack.erase(1); } diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 646a845..fa98451 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -6,7 +6,7 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - object* tmp = _stack.front(); + Object* tmp = _stack.front(); _stack.erase(0, 1, false); _stack.insert(_stack.begin() + 1, tmp); } @@ -31,7 +31,7 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = static_cast(_stack.value(0).toLong()); + int args = static_cast(_stack.value(0).toLong()); MIN_ARGUMENTS(args + 1); _stack.erase(0, args + 1); } @@ -53,7 +53,7 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = static_cast(_stack.value(0).toLong()); + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); @@ -74,7 +74,7 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int to_pick = static_cast(_stack.value(0).toLong()); + int to_pick = static_cast(_stack.value(0).toLong()); _stack.pop(); // treat stack depth errors @@ -90,14 +90,14 @@ void program::rpn_pick(void) { /// void program::rpn_rot(void) { MIN_ARGUMENTS(3); - object* tmp = _stack.at(2); + Object* tmp = _stack.at(2); _stack.erase(2, 1, false); _stack.insert(_stack.begin(), tmp); } /// @brief depth keyword implementation /// -void program::rpn_depth(void) { _stack.push_front(new number(_stack.size())); } +void program::rpn_depth(void) { _stack.push_front(new Number(_stack.size())); } /// @brief roll keyword implementation /// @@ -105,11 +105,11 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = static_cast(_stack.value(0).toLong()); + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); - object* tmp = _stack.at(args - 1); + Object* tmp = _stack.at(args - 1); _stack.erase(args - 1, 1, false); _stack.insert(_stack.begin(), tmp); } @@ -120,11 +120,11 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); - int args = static_cast(_stack.value(0).toLong()); + int args = static_cast(_stack.value(0).toLong()); _stack.pop(); MIN_ARGUMENTS(args); - object* tmp = _stack.at(0); + Object* tmp = _stack.at(0); _stack.erase(0, 1, false); _stack.insert(_stack.begin() + args - 1, tmp); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 4e9f195..b8a1135 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -10,12 +10,12 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); // store symbol with first value - const auto it = _heap.find(_stack.value(0)); + const auto it = _heap.find(_stack.value(0)); if (it != _heap.end()) { delete it->second; _heap.erase(it); } - _heap[_stack.value(0)] = _stack.at(1)->clone(); + _heap[_stack.value(0)] = _stack.at(1)->clone(); _stack.erase(0, 2); } @@ -24,7 +24,7 @@ void program::rpn_sto(void) { void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -41,7 +41,7 @@ void program::rpn_stoadd(void) { void program::rpn_stosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -58,7 +58,7 @@ void program::rpn_stosub(void) { void program::rpn_stomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -75,7 +75,7 @@ void program::rpn_stomul(void) { void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -92,7 +92,7 @@ void program::rpn_stodiv(void) { void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -108,7 +108,7 @@ void program::rpn_stoneg(void) { void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (_heap.find(_stack.value(0)) == _heap.end()) { setErrorContext(ret_unknown_variable); return; } @@ -126,8 +126,8 @@ void program::rpn_rcl(void) { ARG_MUST_BE_OF_TYPE(0, cmd_symbol); // recall a variable - object* obj; - string variable(_stack.value(0)); + Object* obj; + string variable(_stack.value(0)); // mind the order of heaps if (find_variable(variable, obj)) { @@ -157,9 +157,9 @@ void program::rpn_edit(void) { /// /// @param symb the smlbol to recall and autoeval /// -void program::auto_rcl(symbol* symb) { +void program::auto_rcl(Symbol* symb) { if (symb->autoEval) { - object* obj; + Object* obj; string variable(symb->value); // mind the order of heaps @@ -180,7 +180,7 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_symbol); - const auto i = _heap.find(_stack.value(0)); + const auto i = _heap.find(_stack.value(0)); if (i != _heap.end()) { delete i->second; _heap.erase(i); @@ -193,7 +193,7 @@ void program::rpn_purge(void) { /// @brief vars keyword implementation /// void program::rpn_vars(void) { - object* obj; + Object* obj; program* parent = _parent; string name; int index = 1; diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 18b5b1d..dc8e38d 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -14,7 +14,7 @@ void program::rpn_instr() { stringstream ss; ss << _stack.at(0); _stack.pop(); - _stack.push(new ostring(ss.str())); + _stack.push(new String(ss.str())); } } @@ -24,7 +24,7 @@ void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - string entry(_stack.value(0)); + string entry(_stack.value(0)); program prog(_stack, _heap); _stack.pop(); @@ -39,10 +39,10 @@ void program::rpn_strout() { void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - char the_chr = static_cast(_stack.value(0).toLong()); + char the_chr = static_cast(_stack.value(0).toLong()); _stack.pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; - _stack.push_front(new ostring(string(1, the_chr))); + _stack.push_front(new String(string(1, the_chr))); } /// @brief num keyword implementation @@ -50,10 +50,10 @@ void program::rpn_chr() { void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - if (_stack.value(0).size() > 0) - _stack.push_front(new number(_stack.value(0)[0])); + if (_stack.value(0).size() > 0) + _stack.push_front(new Number(_stack.value(0)[0])); else - _stack.push_front(new number(0)); + _stack.push_front(new Number(0)); _stack.erase(1); } @@ -62,7 +62,7 @@ void program::rpn_num() { void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_string); - _stack.push_front(new number(_stack.value(0).size())); + _stack.push_front(new Number(_stack.value(0).size())); _stack.erase(1); } @@ -73,9 +73,9 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(0, cmd_string); ARG_MUST_BE_OF_TYPE(1, cmd_string); - size_t pos = _stack.value(1).find(_stack.value(0)) + 1; + size_t pos = _stack.value(1).find(_stack.value(0)) + 1; _stack.erase(0, 2); - _stack.push_front(new number(pos)); + _stack.push_front(new Number(pos)); } /// @brief sub keyword implementation @@ -86,11 +86,11 @@ void program::rpn_strsub() { ARG_MUST_BE_OF_TYPE(1, cmd_number); ARG_MUST_BE_OF_TYPE(2, cmd_string); - size_t first = _stack.value(1).toULong(); - size_t len = _stack.value(0).toULong() - first + 1; + size_t first = _stack.value(1).toULong(); + size_t len = _stack.value(0).toULong() - first + 1; first--; - if (first > _stack.value(2).size()) first = len = 0; - _stack.push(new ostring(_stack.value(2).substr(first, len))); + if (first > _stack.value(2).size()) first = len = 0; + _stack.push(new String(_stack.value(2).substr(first, len))); _stack.erase(1, 3); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index 0685e8b..d838779 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -76,7 +76,7 @@ void program::rpn_test() { int total_steps = 0; int total_steps_failed = 0; - string test_filename = _stack.value(0); + string test_filename = _stack.value(0); _stack.pop(); cout << endl << "rpn version is " << RPN_VERSION << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 8b80d52..defe403 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -7,10 +7,10 @@ /// @return 0 strings are equal /// @return !0 strings are not equal (see strcmp output) /// -static int cmpStringsOnStackTop(rpnstack& stk) { +static int CmpStringOnStackTop(rpnstack& stk) { // _stack should have 2 strings at level 1 and 2 // this function removes these 2 entries - int res = stk.value(1).compare(stk.value(0)); + int res = stk.value(1).compare(stk.value(0)); stk.erase(0, 2); return res; } @@ -20,10 +20,10 @@ static int cmpStringsOnStackTop(rpnstack& stk) { void program::rpn_sup(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) > _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) > _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) == 1)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 1)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -35,10 +35,10 @@ void program::rpn_sup(void) { void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) >= _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) >= _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) != -1)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) != -1)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -51,10 +51,10 @@ void program::rpn_inf(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) < _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) < _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) == -1)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) == -1)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -66,10 +66,10 @@ void program::rpn_inf(void) { void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) <= _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) <= _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) != 1)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 1)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -81,13 +81,13 @@ void program::rpn_inf_eq(void) { void program::rpn_diff(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) != _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.push_front(new number(_stack.value(1) != _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) != 0)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 0)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -99,13 +99,13 @@ void program::rpn_diff(void) { void program::rpn_eq(void) { MIN_ARGUMENTS(2); if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { - _stack.push_front(new number(_stack.value(1) == _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { - _stack.push_front(new number(_stack.value(1) == _stack.value(0))); + _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { - _stack.push_front(new number(cmpStringsOnStackTop(_stack) == 0)); + _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 0)); _stack.erase(1, 2); } else { setErrorContext(ret_bad_operand_type); @@ -118,10 +118,10 @@ void program::rpn_test_and(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 && _stack.value(1) != 0) - _stack.push(new number(1)); + if (_stack.value(0) != 0 && _stack.value(1) != 0) + _stack.push(new Number(1)); else - _stack.push(new number(0)); + _stack.push(new Number(0)); _stack.erase(1, 2); } @@ -131,10 +131,10 @@ void program::rpn_test_or(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 || _stack.value(1) != 0) - _stack.push(new number(1)); + if (_stack.value(0) != 0 || _stack.value(1) != 0) + _stack.push(new Number(1)); else - _stack.push(new number(0)); + _stack.push(new Number(0)); _stack.erase(1, 2); } @@ -144,10 +144,10 @@ void program::rpn_test_xor(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(1, cmd_number); - if (_stack.value(0) != 0 ^ _stack.value(1) != 0) - _stack.push(new number(1)); + if (_stack.value(0) != 0 ^ _stack.value(1) != 0) + _stack.push(new Number(1)); else - _stack.push(new number(0)); + _stack.push(new Number(0)); _stack.erase(1, 2); } @@ -157,7 +157,7 @@ void program::rpn_test_not(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.push(new number(_stack.value(0) == 0 ? 1 : 0)); + _stack.push(new Number(_stack.value(0) == 0 ? 1 : 0)); _stack.erase(1, 1); } diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index ad37b3f..08f8bae 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -22,8 +22,8 @@ void program::rpn_time() { // push it // division after push for real precision - _stack.push(new number(date)); - _stack.value(0) /= 10000000000.0; + _stack.push(new Number(date)); + _stack.value(0) /= 10000000000.0; } else { setErrorContext(ret_internal); } @@ -46,10 +46,10 @@ void program::rpn_date() { static_cast(tm->tm_year + 1900); // push it - number* num; + Number* num; // division after push for real precision - _stack.push(new number(date)); - _stack.value(0) /= 1000000.0; + _stack.push(new Number(date)); + _stack.value(0) /= 1000000.0; } else { setErrorContext(ret_internal); } @@ -69,7 +69,7 @@ void program::rpn_ticks() { if (tm != nullptr) { // date in µs date = 1000000.0 * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec / 1000); - _stack.push(new number(date)); + _stack.push(new Number(date)); } else { setErrorContext(ret_internal); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index ebce9d6..de01e50 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -5,7 +5,7 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - _stack.push_front(new number(mpfr::const_pi())); + _stack.push_front(new Number(mpfr::const_pi())); } /// @brief d->r keyword implementation @@ -13,8 +13,8 @@ void program::rpn_pi(void) { void program::rpn_d2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) *= mpfr::const_pi(); - _stack.value(0) /= 180; + _stack.value(0) *= mpfr::const_pi(); + _stack.value(0) /= 180; } /// @brief r->d keyword implementation @@ -22,8 +22,8 @@ void program::rpn_d2r(void) { void program::rpn_r2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, cmd_number); - _stack.value(0) /= mpfr::const_pi(); - _stack.value(0) *= 180; + _stack.value(0) /= mpfr::const_pi(); + _stack.value(0) *= 180; } /// @brief sin keyword implementation @@ -31,9 +31,9 @@ void program::rpn_r2d(void) { void program::rpn_sin(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = sin(_stack.value(0)); + _stack.value(0) = sin(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = sin(_stack.value(0)); + _stack.value(0) = sin(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -43,9 +43,9 @@ void program::rpn_sin(void) { void program::rpn_asin(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = asin(_stack.value(0)); + _stack.value(0) = asin(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = asin(_stack.value(0)); + _stack.value(0) = asin(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -55,9 +55,9 @@ void program::rpn_asin(void) { void program::rpn_cos(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = cos(_stack.value(0)); + _stack.value(0) = cos(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = cos(_stack.value(0)); + _stack.value(0) = cos(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -67,9 +67,9 @@ void program::rpn_cos(void) { void program::rpn_acos(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = acos(_stack.value(0)); + _stack.value(0) = acos(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = acos(_stack.value(0)); + _stack.value(0) = acos(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -79,9 +79,9 @@ void program::rpn_acos(void) { void program::rpn_tan(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = tan(_stack.value(0)); + _stack.value(0) = tan(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = tan(_stack.value(0)); + _stack.value(0) = tan(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } @@ -91,9 +91,9 @@ void program::rpn_tan(void) { void program::rpn_atan(void) { MIN_ARGUMENTS(1); if (_stack.type(0) == cmd_number) - _stack.value(0) = atan(_stack.value(0)); + _stack.value(0) = atan(_stack.value(0)); else if (_stack.type(0) == cmd_complex) - _stack.value(0) = atan(_stack.value(0)); + _stack.value(0) = atan(_stack.value(0)); else setErrorContext(ret_bad_operand_type); } diff --git a/src/stack.hpp b/src/stack.hpp index 1e55024..21e43bc 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -13,18 +13,18 @@ using namespace std; /// @brief stack object, parens of program, storing execution stack values or programs /// -class rpnstack : public deque { +class rpnstack : public deque { public: rpnstack() {} virtual ~rpnstack() { - for_each(begin(), end(), [](object* o) { delete o; }); + for_each(begin(), end(), [](Object* o) { delete o; }); deque::erase(begin(), end()); } // stack manipulation void erase(size_t first = 0, size_t nb = 1, bool del = true) { size_t last = std::min(first + nb, size()); - if (del) for_each(begin() + first, begin() + last, [](object* o) { delete o; }); + if (del) for_each(begin() + first, begin() + last, [](Object* o) { delete o; }); deque::erase(begin() + first, begin() + last); } @@ -49,12 +49,12 @@ class rpnstack : public deque { return static_cast(at(level))->value; } - void push(object* o) { deque::push_front(o); } + void push(Object* o) { deque::push_front(o); } }; /// @brief heap object, storing variables (=named object) /// -class heap : public map { +class heap : public map { public: heap() {} virtual ~heap() { clear(); } @@ -64,7 +64,7 @@ class heap : public map { map::erase(begin(), end()); } - bool get(const string name, object*& obj) { + bool get(const string name, Object*& obj) { auto i = find(name); if (i != end()) { obj = i->second; From 2a980eb74dd1185a2e3ccc6759d092614aba3dc3 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 14:16:55 +0100 Subject: [PATCH 42/57] enum names and values --- src/input.cpp | 22 +- src/input.hpp | 4 +- src/lexer.cpp | 26 +- src/lexer.hpp | 4 +- src/main.cpp | 10 +- src/object.hpp | 105 ++++---- src/program.cpp | 496 +++++++++++++++++++------------------ src/program.hpp | 30 +-- src/rpn-branch.cpp | 152 ++++++------ src/rpn-complex.cpp | 18 +- src/rpn-general.cpp | 40 +-- src/rpn-logs.cpp | 84 +++---- src/rpn-program.cpp | 28 +-- src/rpn-real.cpp | 152 ++++++------ src/rpn-stack.cpp | 12 +- src/rpn-store.cpp | 36 +-- src/rpn-string.cpp | 22 +- src/rpn-test-framework.cpp | 8 +- src/rpn-test.cpp | 54 ++-- src/rpn-time.cpp | 6 +- src/rpn-trig.cpp | 40 +-- src/stack.hpp | 2 +- 22 files changed, 676 insertions(+), 675 deletions(-) diff --git a/src/input.cpp b/src/input.cpp index 6a0fa67..a272f16 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -4,19 +4,19 @@ #include -vector* Input::_ac_list = nullptr; +vector* Input::ac_list_ = nullptr; Input::Input(string& entry, vector& autocompletion_list, string prompt, string multiline_prompt) - : status(cont) { + : status(InputStatus::kContinue) { char* c_entry = nullptr; bool multiline = false; int entry_len; - _ac_list = &autocompletion_list; + ac_list_ = &autocompletion_list; // linenoise for entry linenoiseSetCompletionCallback(entry_completion_generator); - while (status == cont) { + while (status == InputStatus::kContinue) { // get user entry if (multiline) c_entry = linenoise(multiline_prompt.c_str(), &entry_len); @@ -26,9 +26,9 @@ Input::Input(string& entry, vector& autocompletion_list, string prompt, // Ctrl-C if (linenoiseKeyType() == 1) { if (entry_len > 0 || multiline) - status = abort; + status = InputStatus::kAbort; else - status = ctrlc; + status = InputStatus::kCtrlc; } else if (linenoiseKeyType() == 3) { multiline = true; if (c_entry != nullptr) entry += c_entry; @@ -38,9 +38,9 @@ Input::Input(string& entry, vector& autocompletion_list, string prompt, entry += c_entry; // keep history if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str()); - status = ok; + status = InputStatus::kOk; } else { - status = error; + status = InputStatus::kError; } } } @@ -54,16 +54,16 @@ Input::Input(string& entry, vector& autocompletion_list, string prompt, /// @param lc the completion object to add strings with linenoiseAddCompletion() /// void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) { - if (Input::_ac_list == nullptr || text == nullptr) return; + if (Input::ac_list_ == nullptr || text == nullptr) return; int text_len = strnlen(text, 6); if (text_len == 0) // propose all keywords - for (string& ac : *Input::_ac_list) linenoiseAddCompletion(lc, ac.c_str()); + for (string& ac : *Input::ac_list_) linenoiseAddCompletion(lc, ac.c_str()); else // propose only keywords matching to text begining - for (string& ac : *Input::_ac_list) + for (string& ac : *Input::ac_list_) // compare list entry with text, return if match if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str()); } diff --git a/src/input.hpp b/src/input.hpp index f1d9e19..896749c 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -14,13 +14,13 @@ using std::vector; class Input { public: Input(string& entry, vector& autocompletion_list, string prompt = "rpn> ", string multiline_prompt = ">"); - enum { ok, cont, abort, ctrlc, error } status; + enum class InputStatus { kOk, kContinue, kAbort, kCtrlc, kError } status; static void preload(const char* preloadText); private: static void entry_completion_generator(const char* text, linenoiseCompletions* lc); - static vector* _ac_list; + static vector* ac_list_; }; #endif // SRC_INPUT_HPP_ diff --git a/src/lexer.cpp b/src/lexer.cpp index 747a5e2..e8169f7 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -55,13 +55,13 @@ bool Lexer::parseString(string& entry, size_t idx, size_t& next_idx, vector= entry.size()) { - elements.push_back({cmd_symbol, .value = entry.substr(idx, entry.size() - idx)}); + elements.push_back({kSymbol, .value = entry.substr(idx, entry.size() - idx)}); next_idx = entry.size(); if (re != nullptr) delete re; if (im != nullptr) delete im; @@ -219,13 +219,13 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& next_idx, vector> token; - elements.push_back({cmd_symbol, .value = token, .autoEval = true}); + elements.push_back({kSymbol, .value = token, .autoEval = true}); next_idx = token.size() + idx; return true; } diff --git a/src/lexer.hpp b/src/lexer.hpp index 217ded8..509124c 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -19,7 +19,7 @@ class Lexer { public: // a structure to describe a syntaxical element and its value struct SynElement { - cmd_type_t type; + ObjectType type; string value; mpreal* re; mpreal* im; @@ -35,7 +35,7 @@ class Lexer { }; struct ReservedWord { - cmd_type_t type; + ObjectType type; program_fn_t fn; }; diff --git a/src/main.cpp b/src/main.cpp index bed85d1..8179141 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -94,16 +94,16 @@ int main(int argc, char* argv[]) { program prog(stack, heap); string entry; switch (Input(entry, program::getAutocompletionWords()).status) { - case Input::ok: + case Input::InputStatus::kOk: // user could stop prog with CtrlC CatchSignals(&prog); // run it - if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye) + if (prog.parse(entry) == kOk && prog.run() == kGoodbye) go_on = false; else prog.show_stack(); break; - case Input::ctrlc: + case Input::InputStatus::kCtrlc: go_on = false; break; default: @@ -125,7 +125,7 @@ int main(int argc, char* argv[]) { // make program ret = prog.parse(entry); - if (ret == ret_ok) { + if (ret == kOk) { // user could stop prog with CtrlC CatchSignals(&prog); @@ -137,6 +137,6 @@ int main(int argc, char* argv[]) { mpfr_free_cache(); - if (ret != ret_ok) return EXIT_FAILURE; + if (ret != kOk) return EXIT_FAILURE; return EXIT_SUCCESS; } diff --git a/src/object.hpp b/src/object.hpp index c491dd7..67e2727 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -20,37 +20,36 @@ using std::complex; // definitions for objects /// 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_abort_current_entry, - ret_out_of_memory, - ret_bad_value, - ret_test_failed -} ret_value; + kOk, + kUnknownError, + kMissingOperand, + kBadOperandType, + kOutOfRange, + kUnknownVariable, + kInternalError, + kDeadlyError, + kGoodbye, + kNotImplemented, + kNop, + kSyntaxError, + kDivByZero, + kRuntimeError, + kAbortCurrentEntry, + kOutOfMemory, + kBadValue, + kTestFailed +} RetValue; typedef enum { - cmd_undef, - cmd_number, // floating point number - cmd_complex, // complex, couple of floating point numbers - cmd_string, // "string" - cmd_symbol, // 'symbol' - cmd_program, // << instructions >> «instructions» - cmd_keyword, // langage (reserved) keyword - cmd_branch, // langage (reserved) branch keyword - cmd_max -} cmd_type_t; + kUndef, + kNumber, // 3.1416, 1e-1234, 0x12ab, 2b110, 50ba12 + kComplex, // (1,2) + kString, // "string" + kSymbol, // 'symbol' + kProgram, // << instructions >> «instructions» + kKeyword, // langage (reserved) keyword (rot, dup, swap ..) + kBranch // langage (reserved) branch keyword (for, if, then ..) +} ObjectType; class program; class Branch; @@ -61,9 +60,9 @@ typedef size_t (program::*branch_fn_t)(Branch&); /// @brief Object - a generic stack object /// struct Object { - explicit Object(cmd_type_t type = cmd_undef) : _type(type) {} + explicit Object(ObjectType type = kUndef) : _type(type) {} virtual ~Object() {} - cmd_type_t _type; + ObjectType _type; virtual Object* clone() { Object* o = new Object(); if (o != nullptr) *o = *this; @@ -83,9 +82,9 @@ struct Object { /// @brief stack objects derived from Object /// struct Number : Object { - Number() : Object(cmd_number), base(10) {} - explicit Number(const mpreal& value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {} - explicit Number(int value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {} + Number() : Object(kNumber), base(10) {} + explicit Number(const mpreal& value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {} + explicit Number(int value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {} int base; mpreal value; @@ -95,9 +94,9 @@ struct Number : Object { virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); } // representation mode - typedef enum { std, fix, sci } mode_enum; + typedef enum { kStd, kFix, kSci } mode_enum; static mode_enum s_mode; - static constexpr mode_enum DEFAULT_MODE = Number::std; + static constexpr mode_enum DEFAULT_MODE = Number::kStd; // precision static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128; @@ -109,9 +108,9 @@ struct Number : Object { stringstream format; format << "%." << digits; switch ( mode ) { - case std: format << "R*g"; break; - case fix: format << "R*f"; break; - case sci: format << "R*e"; break; + case kStd: format << "R*g"; break; + case kFix: format << "R*f"; break; + case kSci: format << "R*e"; break; } return format.str(); } @@ -128,13 +127,13 @@ struct Number : Object { /// @brief stack objects inheriting Object /// struct Complex : Object { - Complex() : Object(cmd_complex), reBase(10), imBase(10) {} + Complex() : Object(kComplex), reBase(10), imBase(10) {} explicit Complex(complex& value_, int reb = 10, int imb = 10) - : Object(cmd_complex), reBase(reb), imBase(imb) { + : Object(kComplex), reBase(reb), imBase(imb) { value = value_; } explicit Complex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) - : Object(cmd_complex), reBase(reb), imBase(imb) { + : Object(kComplex), reBase(reb), imBase(imb) { value.real(re_); value.imag(im_); } @@ -154,8 +153,8 @@ struct Complex : Object { }; struct String : Object { - String() : Object(cmd_string) {} - explicit String(const string& value_) : Object(cmd_string), value(value_) {} + String() : Object(kString) {} + explicit String(const string& value_) : Object(kString), value(value_) {} virtual Object* clone() { return new String(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } @@ -163,8 +162,8 @@ struct String : Object { }; struct Program : Object { - Program() : Object(cmd_program) {} - explicit Program(const string& value_) : Object(cmd_program), value(value_) {} + Program() : Object(kProgram) {} + explicit Program(const string& value_) : Object(kProgram), value(value_) {} virtual Object* clone() { return new Program(value); } virtual string name() { return string("program"); } virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } @@ -172,9 +171,9 @@ struct Program : Object { }; struct Symbol : Object { - explicit Symbol(bool autoEval_ = true) : Object(cmd_symbol), autoEval(autoEval_) {} + explicit Symbol(bool autoEval_ = true) : Object(kSymbol), autoEval(autoEval_) {} explicit Symbol(const string& value_, bool autoEval_ = true) - : Object(cmd_symbol), value(value_), autoEval(autoEval_) {} + : Object(kSymbol), value(value_), autoEval(autoEval_) {} virtual Object* clone() { return new Symbol(value, autoEval); } virtual string name() { return string("symbol"); } virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } @@ -183,8 +182,8 @@ struct Symbol : Object { }; struct Keyword : Object { - Keyword() : Object(cmd_keyword) {} - explicit Keyword(program_fn_t fn_, const string& value_) : Object(cmd_keyword), fn(fn_), value(value_) {} + Keyword() : Object(kKeyword) {} + explicit Keyword(program_fn_t fn_, const string& value_) : Object(kKeyword), fn(fn_), value(value_) {} virtual Object* clone() { return new Keyword(fn, value); } virtual string name() { return string("keyword"); } program_fn_t fn; @@ -192,8 +191,8 @@ struct Keyword : Object { }; struct Branch : Object { - Branch() : Object(cmd_branch) {} - explicit Branch(branch_fn_t fn_, const string& value_) : Object(cmd_branch) { + Branch() : Object(kBranch) {} + explicit Branch(branch_fn_t fn_, const string& value_) : Object(kBranch) { fn = fn_; arg1 = static_cast(-1); arg2 = static_cast(-1); @@ -201,7 +200,7 @@ struct Branch : Object { arg_bool = 0; value = value_; } - explicit Branch(Branch& other) : Object(cmd_branch) { + explicit Branch(Branch& other) : Object(kBranch) { fn = other.fn; arg1 = other.arg1; arg2 = other.arg2; diff --git a/src/program.cpp b/src/program.cpp index 1a6b89f..722da4f 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -2,205 +2,205 @@ #include "program.hpp" -//< language reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef) +//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef) vector program::_keywords{ // GENERAL - {cmd_undef, "", nullptr, "\nGENERAL"}, - {cmd_keyword, "nop", &program::rpn_nop, "no operation"}, - {cmd_keyword, "help", &program::rpn_help, "this help message"}, - {cmd_keyword, "h", &program::rpn_help, ""}, - {cmd_keyword, "?", &program::rpn_help, ""}, - {cmd_keyword, "quit", &program::rpn_good_bye, "quit software"}, - {cmd_keyword, "q", &program::rpn_good_bye, ""}, - {cmd_keyword, "exit", &program::rpn_good_bye, ""}, - {cmd_keyword, "test", &program::rpn_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, "history", &program::rpn_history, "see commands history"}, + {kUndef, "", nullptr, "\nGENERAL"}, + {kKeyword, "nop", &program::rpn_nop, "no operation"}, + {kKeyword, "help", &program::rpn_help, "this help message"}, + {kKeyword, "h", &program::rpn_help, ""}, + {kKeyword, "?", &program::rpn_help, ""}, + {kKeyword, "quit", &program::rpn_good_bye, "quit software"}, + {kKeyword, "q", &program::rpn_good_bye, ""}, + {kKeyword, "exit", &program::rpn_good_bye, ""}, + {kKeyword, "test", &program::rpn_test, ""}, // not seen by user + {kKeyword, "version", &program::rpn_version, "show rpn version"}, + {kKeyword, "uname", &program::rpn_uname, "show rpn complete identification string"}, + {kKeyword, "history", &program::rpn_history, "see commands history"}, // USUAL OPERATIONS ON REALS AND COMPLEXES - {cmd_undef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, - {cmd_keyword, "+", &program::rpn_plus, "addition"}, - {cmd_keyword, "-", &program::rpn_minus, "substraction"}, - {cmd_keyword, "*", &program::rpn_mul, "multiplication"}, - {cmd_keyword, "/", &program::rpn_div, "division"}, - {cmd_keyword, "inv", &program::rpn_inv, "inverse"}, - {cmd_keyword, "chs", &program::rpn_neg, "negation"}, - {cmd_keyword, "neg", &program::rpn_neg, ""}, - {cmd_keyword, "^", &program::rpn_power, "power"}, - {cmd_keyword, "pow", &program::rpn_power, ""}, - {cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, - {cmd_keyword, "sq", &program::rpn_square, "rpn_square"}, - {cmd_keyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, - {cmd_keyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, + {kUndef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, + {kKeyword, "+", &program::rpn_plus, "addition"}, + {kKeyword, "-", &program::rpn_minus, "substraction"}, + {kKeyword, "*", &program::rpn_mul, "multiplication"}, + {kKeyword, "/", &program::rpn_div, "division"}, + {kKeyword, "inv", &program::rpn_inv, "inverse"}, + {kKeyword, "chs", &program::rpn_neg, "negation"}, + {kKeyword, "neg", &program::rpn_neg, ""}, + {kKeyword, "^", &program::rpn_power, "power"}, + {kKeyword, "pow", &program::rpn_power, ""}, + {kKeyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, + {kKeyword, "sq", &program::rpn_square, "rpn_square"}, + {kKeyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, + {kKeyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, // OPERATIONS ON REALS - {cmd_undef, "", nullptr, "\nOPERATIONS ON REALS"}, - {cmd_keyword, "%", &program::rpn_purcent, "purcent"}, - {cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, - {cmd_keyword, "mod", &program::rpn_modulo, "modulo"}, - {cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, - {cmd_keyword, "mant", &program::rpn_mant, "mantissa of a real number"}, - {cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, - {cmd_keyword, "floor", &program::rpn_floor, "largest number <="}, - {cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="}, - {cmd_keyword, "ip", &program::rpn_ip, "integer part"}, - {cmd_keyword, "fp", &program::rpn_fp, "fractional part"}, - {cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"}, - {cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"}, + {kUndef, "", nullptr, "\nOPERATIONS ON REALS"}, + {kKeyword, "%", &program::rpn_purcent, "purcent"}, + {kKeyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, + {kKeyword, "mod", &program::rpn_modulo, "modulo"}, + {kKeyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, + {kKeyword, "mant", &program::rpn_mant, "mantissa of a real number"}, + {kKeyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, + {kKeyword, "floor", &program::rpn_floor, "largest number <="}, + {kKeyword, "ceil", &program::rpn_ceil, "smallest number >="}, + {kKeyword, "ip", &program::rpn_ip, "integer part"}, + {kKeyword, "fp", &program::rpn_fp, "fractional part"}, + {kKeyword, "min", &program::rpn_min, "min of 2 real numbers"}, + {kKeyword, "max", &program::rpn_max, "max of 2 real numbers"}, // OPERATIONS ON COMPLEXES - {cmd_undef, "", nullptr, "\nOPERATIONS ON COMPLEXES"}, - {cmd_keyword, "re", &program::rpn_re, "complex real part"}, - {cmd_keyword, "im", &program::rpn_im, "complex imaginary part"}, - {cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"}, - {cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"}, - {cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, - {cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, - {cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, - {cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, + {kUndef, "", nullptr, "\nOPERATIONS ON COMPLEXES"}, + {kKeyword, "re", &program::rpn_re, "complex real part"}, + {kKeyword, "im", &program::rpn_im, "complex imaginary part"}, + {kKeyword, "conj", &program::rpn_conj, "complex conjugate"}, + {kKeyword, "arg", &program::rpn_arg, "complex argument in radians"}, + {kKeyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, + {kKeyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, + {kKeyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, + {kKeyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, // MODE - {cmd_undef, "", nullptr, "\nMODE"}, - {cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"}, - {cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"}, - {cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"}, - {cmd_keyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec"}, - {cmd_keyword, "round", &program::rpn_round, + {kUndef, "", nullptr, "\nMODE"}, + {kKeyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"}, + {kKeyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"}, + {kKeyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"}, + {kKeyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec"}, + {kKeyword, "round", &program::rpn_round, "set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward " "+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"] round"}, - {cmd_keyword, "default", &program::rpn_default, "set float representation and precision to default"}, - {cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"}, - {cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"}, - {cmd_keyword, "dec", &program::rpn_dec, "decimal representation, applies on stack level 0 only"}, - {cmd_keyword, "bin", &program::rpn_bin, "binary representation, applies on stack level 0 only"}, - {cmd_keyword, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"}, + {kKeyword, "default", &program::rpn_default, "set float representation and precision to default"}, + {kKeyword, "type", &program::rpn_type, "show type of stack first entry"}, + {kKeyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"}, + {kKeyword, "dec", &program::rpn_dec, "decimal representation, applies on stack level 0 only"}, + {kKeyword, "bin", &program::rpn_bin, "binary representation, applies on stack level 0 only"}, + {kKeyword, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"}, // TESTS - {cmd_undef, "", nullptr, "\nTEST"}, - {cmd_keyword, ">", &program::rpn_sup, "binary operator >"}, - {cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="}, - {cmd_keyword, "<", &program::rpn_inf, "binary operator <"}, - {cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="}, - {cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"}, - {cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"}, - {cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"}, - {cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"}, - {cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"}, - {cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"}, - {cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"}, + {kUndef, "", nullptr, "\nTEST"}, + {kKeyword, ">", &program::rpn_sup, "binary operator >"}, + {kKeyword, ">=", &program::rpn_sup_eq, "binary operator >="}, + {kKeyword, "<", &program::rpn_inf, "binary operator <"}, + {kKeyword, "<=", &program::rpn_inf_eq, "binary operator <="}, + {kKeyword, "!=", &program::rpn_diff, "binary operator != (different)"}, + {kKeyword, "==", &program::rpn_eq, "binary operator == (equal)"}, + {kKeyword, "and", &program::rpn_test_and, "boolean operator and"}, + {kKeyword, "or", &program::rpn_test_or, "boolean operator or"}, + {kKeyword, "xor", &program::rpn_test_xor, "boolean operator xor"}, + {kKeyword, "not", &program::rpn_test_not, "boolean operator not"}, + {kKeyword, "same", &program::rpn_same, "boolean operator same (equal)"}, // STACK - {cmd_undef, "", nullptr, "\nSTACK"}, - {cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"}, - {cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"}, - {cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"}, - {cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries"}, - {cmd_keyword, "del", &program::rpn_erase, "drop all stack entries"}, - {cmd_keyword, "erase", &program::rpn_erase, ""}, - {cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"}, - {cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"}, - {cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries"}, - {cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries"}, - {cmd_keyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack"}, - {cmd_keyword, "depth", &program::rpn_depth, "give stack depth"}, - {cmd_keyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack"}, - {cmd_keyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position"}, - {cmd_keyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, + {kUndef, "", nullptr, "\nSTACK"}, + {kKeyword, "swap", &program::rpn_swap, "swap 2 first stack entries"}, + {kKeyword, "drop", &program::rpn_drop, "drop first stack entry"}, + {kKeyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"}, + {kKeyword, "dropn", &program::rpn_dropn, "drop n first stack entries"}, + {kKeyword, "del", &program::rpn_erase, "drop all stack entries"}, + {kKeyword, "erase", &program::rpn_erase, ""}, + {kKeyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"}, + {kKeyword, "dup", &program::rpn_dup, "duplicate first stack entry"}, + {kKeyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries"}, + {kKeyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries"}, + {kKeyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack"}, + {kKeyword, "depth", &program::rpn_depth, "give stack depth"}, + {kKeyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack"}, + {kKeyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position"}, + {kKeyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, // STRING - {cmd_undef, "", nullptr, "\nSTRING"}, - {cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"}, - {cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"}, - {cmd_keyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, - {cmd_keyword, "num", &program::rpn_num, + {kUndef, "", nullptr, "\nSTRING"}, + {kKeyword, "->str", &program::rpn_instr, "convert an object into a string"}, + {kKeyword, "str->", &program::rpn_strout, "convert a string into an object"}, + {kKeyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, + {kKeyword, "num", &program::rpn_num, "return ASCII code of the first character of the string in stack level 1 as a real number"}, - {cmd_keyword, "size", &program::rpn_strsize, "return the length of the string"}, - {cmd_keyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, - {cmd_keyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, + {kKeyword, "size", &program::rpn_strsize, "return the length of the string"}, + {kKeyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, + {kKeyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, // BRANCH - {cmd_undef, "", nullptr, "\nBRANCH"}, - {cmd_branch, "if", (program_fn_t)&program::rpn_if, + {kUndef, "", nullptr, "\nBRANCH"}, + {kBranch, "if", (program_fn_t)&program::rpn_if, "if then else " "end"}, - {cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"}, - {cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"}, - {cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, - {cmd_branch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, - {cmd_branch, "for", (program_fn_t)&program::rpn_for, + {kBranch, "then", (program_fn_t)&program::rpn_then, "used with if"}, + {kBranch, "else", (program_fn_t)&program::rpn_else, "used with if"}, + {kBranch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, + {kBranch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, + {kBranch, "for", (program_fn_t)&program::rpn_for, " for next| step"}, - {cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, - {cmd_branch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, - {cmd_keyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, - {cmd_keyword, "ifte", &program::rpn_ifte, + {kBranch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, + {kBranch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, + {kKeyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, + {kKeyword, "ifte", &program::rpn_ifte, "similar to if-then-else-end, " " ifte"}, - {cmd_branch, "do", (program_fn_t)&program::rpn_do, "do until end"}, - {cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"}, - {cmd_branch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, - {cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, + {kBranch, "do", (program_fn_t)&program::rpn_do, "do until end"}, + {kBranch, "until", (program_fn_t)&program::rpn_until, "used with do"}, + {kBranch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, + {kBranch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, // STORE - {cmd_undef, "", nullptr, "\nSTORE"}, - {cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"}, - {cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"}, - {cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"}, - {cmd_keyword, "vars", &program::rpn_vars, "list all variables"}, - {cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"}, - {cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"}, - {cmd_keyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, - {cmd_keyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, - {cmd_keyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, - {cmd_keyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, - {cmd_keyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, - {cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, + {kUndef, "", nullptr, "\nSTORE"}, + {kKeyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"}, + {kKeyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"}, + {kKeyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"}, + {kKeyword, "vars", &program::rpn_vars, "list all variables"}, + {kKeyword, "clusr", &program::rpn_clusr, "erase all variables"}, + {kKeyword, "edit", &program::rpn_edit, "edit a variable content"}, + {kKeyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, + {kKeyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, + {kKeyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, + {kKeyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, + {kKeyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, + {kKeyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, // PROGRAM - {cmd_undef, "", nullptr, "\nPROGRAM"}, - {cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, - {cmd_branch, "->", (program_fn_t)&program::rpn_inprog, + {kUndef, "", nullptr, "\nPROGRAM"}, + {kKeyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, + {kBranch, "->", (program_fn_t)&program::rpn_inprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> " ">>"}, // TRIG ON REALS AND COMPLEXES - {cmd_undef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"}, - {cmd_keyword, "pi", &program::rpn_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::rpn_d2r, "convert degrees to radians"}, - {cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, + {kUndef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"}, + {kKeyword, "pi", &program::rpn_pi, "pi constant"}, + {kKeyword, "sin", &program::rpn_sin, "sinus"}, + {kKeyword, "asin", &program::rpn_asin, "arg sinus"}, + {kKeyword, "cos", &program::rpn_cos, "cosinus"}, + {kKeyword, "acos", &program::rpn_acos, "arg cosinus"}, + {kKeyword, "tan", &program::rpn_tan, "tangent"}, + {kKeyword, "atan", &program::rpn_atan, "arg tangent"}, + {kKeyword, "d->r", &program::rpn_d2r, "convert degrees to radians"}, + {kKeyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES - {cmd_undef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"}, - {cmd_keyword, "e", &program::rpn_e, "Euler constant"}, - {cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"}, - {cmd_keyword, "log", &program::rpn_ln, ""}, - {cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, - {cmd_keyword, "exp", &program::rpn_exp, "exponential"}, - {cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, - {cmd_keyword, "log10", &program::rpn_log10, "logarithm base 10"}, - {cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"}, - {cmd_keyword, "exp10", &program::rpn_alog10, ""}, - {cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"}, - {cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"}, - {cmd_keyword, "exp2", &program::rpn_alog2, ""}, - {cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"}, - {cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"}, - {cmd_keyword, "cosh", &program::rpn_cosh, "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"}, + {kUndef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"}, + {kKeyword, "e", &program::rpn_e, "Euler constant"}, + {kKeyword, "ln", &program::rpn_ln, "logarithm base e"}, + {kKeyword, "log", &program::rpn_ln, ""}, + {kKeyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, + {kKeyword, "exp", &program::rpn_exp, "exponential"}, + {kKeyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, + {kKeyword, "log10", &program::rpn_log10, "logarithm base 10"}, + {kKeyword, "alog10", &program::rpn_alog10, "exponential base 10"}, + {kKeyword, "exp10", &program::rpn_alog10, ""}, + {kKeyword, "log2", &program::rpn_log2, "logarithm base 2"}, + {kKeyword, "alog2", &program::rpn_alog2, "exponential base 2"}, + {kKeyword, "exp2", &program::rpn_alog2, ""}, + {kKeyword, "sinh", &program::rpn_sinh, "hyperbolic sine"}, + {kKeyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"}, + {kKeyword, "cosh", &program::rpn_cosh, "hyperbolic cosine"}, + {kKeyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"}, + {kKeyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"}, + {kKeyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"}, // TIME AND DATE - {cmd_undef, "", nullptr, "\nTIME AND DATE"}, - {cmd_keyword, "time", &program::rpn_time, "time in local format"}, - {cmd_keyword, "date", &program::rpn_date, "date in local format"}, - {cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"}, + {kUndef, "", nullptr, "\nTIME AND DATE"}, + {kKeyword, "time", &program::rpn_time, "time in local format"}, + {kKeyword, "date", &program::rpn_date, "date in local format"}, + {kKeyword, "ticks", &program::rpn_ticks, "system tick in µs"}, }; /// autocompletion vector for linenoise autocompletion @@ -214,19 +214,19 @@ vector& program::getAutocompletionWords() { /// @brief run a program on a stack and a heap /// -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::run() { +RetValue program::run() { bool go_out = false; - ret_value ret = ret_ok; - cmd_type_t type; + RetValue ret = kOk; + ObjectType type; - _err = ret_ok; + _err = kOk; _err_context = ""; // branches for 'if' ret = preprocess(); - if (ret != ret_ok) { + if (ret != kOk) { // free allocated for (Object* o : *this) delete o; _local_heap.clear(); @@ -238,36 +238,36 @@ ret_value program::run() { Object* o = at(i); switch (o->_type) { // could be an auto-evaluated symbol - case cmd_symbol: + case kSymbol: auto_rcl(reinterpret_cast(o)); i++; break; // a keyword - case cmd_keyword: { + case kKeyword: { Keyword* k = reinterpret_cast(o); // call the matching function (this->*(k->fn))(); switch (_err) { // no pb -> go on - case ret_ok: + case kOk: break; // explicit go out software - case ret_good_bye: + case kGoodbye: go_out = true; - ret = ret_good_bye; + ret = kGoodbye; break; default: // error: abort prog go_out = true; // test error: make rpn return EXIT_FAILURE - if (_err == ret_test_failed) ret = ret_test_failed; + if (_err == kTestFailed) ret = kTestFailed; // error: show it - if (show_error(_err, _err_context) == ret_deadly) + if (show_error(_err, _err_context) == kDeadlyError) // pb showing error -> go out software - ret = ret_good_bye; + ret = kGoodbye; break; } i++; @@ -275,15 +275,15 @@ ret_value program::run() { } // a branch keyword - case cmd_branch: { + case kBranch: { // call matching function Branch* b = reinterpret_cast(o); size_t next_cmd = (this->*(b->fn))(*b); switch (next_cmd) { - case step_out: // step out + case kStepOut: // step out i++; // meaning 'next command' break; - case runtime_error: // runtime error + case kRtError: // runtime error (void)show_error(_err, _err_context); go_out = true; break; @@ -315,9 +315,9 @@ ret_value program::run() { /// inner members of branch or keyword objects are filled by this function /// these inner members store for example the index of the next keyword to execute etc. /// -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::preprocess(void) { +RetValue program::preprocess(void) { struct if_layout_t { if_layout_t() : index_then_or_unti_or_repeat(-1), @@ -341,7 +341,7 @@ ret_value program::preprocess(void) { // analyse if-then-else-end branches // analyse start-{next, step} branches for (size_t i = 0; i < size(); i++) { - if (at(i)->_type == cmd_branch) { + if (at(i)->_type == kBranch) { Branch* k = reinterpret_cast(at(i)); if (k->value == "if") { if_layout_t layout; @@ -350,51 +350,51 @@ ret_value program::preprocess(void) { layout_index++; } else if (k->value == "then") { size_t next = i + 1; - if (next >= size()) next = step_out; + if (next >= size()) next = kStepOut; // nothing after 'then' -> error - if (next == step_out) { + if (next == kStepOut) { // error: show it show_syntax_error("missing end after then"); - return ret_syntax; + return kSyntaxError; } if (layout_index < 0) { // error: show it show_syntax_error("missing if before then"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it show_syntax_error("duplicate then"); - return ret_syntax; + return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; k->arg1 = next; k->arg3 = vlayout[layout_index].index_if_or_do_or_while; } else if (k->value == "else") { size_t next = i + 1; - if (next >= size()) next = step_out; + if (next >= size()) next = kStepOut; // nothing after 'else' -> error - if (next == step_out) { + if (next == kStepOut) { // error: show it show_syntax_error("missing end after else"); - return ret_syntax; + return kSyntaxError; } if (layout_index < 0) { // error: show it show_syntax_error("missing if before else"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it show_syntax_error("missing then before else"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_else != -1) { // error: show it show_syntax_error("duplicate else"); - return ret_syntax; + return kSyntaxError; } vlayout[layout_index].index_else = i; k->arg1 = next; // fill branch1 (if was false) of 'else' @@ -410,7 +410,7 @@ ret_value program::preprocess(void) { if (vstart_index.size() == 0) { // error: show it show_syntax_error("missing start or for before next"); - return ret_syntax; + return kSyntaxError; } k->arg1 = vstart_index[vstart_index.size() - 1]; // 'next' arg1 = 'start' index reinterpret_cast(at(vstart_index[vstart_index.size() - 1]))->arg2 = @@ -420,7 +420,7 @@ ret_value program::preprocess(void) { if (vstart_index.size() == 0) { // error: show it show_syntax_error("missing start or for before step"); - return ret_syntax; + return kSyntaxError; } k->arg1 = vstart_index[vstart_index.size() - 1]; // fill 'step' branch1 = 'start' index reinterpret_cast(at(vstart_index[vstart_index.size() - 1]))->arg2 = @@ -436,23 +436,23 @@ ret_value program::preprocess(void) { layout_index++; } else if (k->value == "until") { size_t next = i + 1; - if (next >= size()) next = step_out; + if (next >= size()) next = kStepOut; // nothing after 'unti' -> error - if (next == step_out) { + if (next == kStepOut) { // error: show it show_syntax_error("missing end"); - return ret_syntax; + return kSyntaxError; } if (layout_index < 0 || !vlayout[layout_index].is_do_unti) { // error: show it show_syntax_error("missing do"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it show_syntax_error("duplicate until"); - return ret_syntax; + return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; } else if (k->value == "while") { @@ -465,35 +465,35 @@ ret_value program::preprocess(void) { if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) { // error: show it show_syntax_error("missing while"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it show_syntax_error("duplicate repeat"); - return ret_syntax; + return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; } else if (k->value == "end") { size_t next = i + 1; - if (next >= size()) next = step_out; + if (next >= size()) next = kStepOut; if (layout_index < 0) { // error: show it show_syntax_error("missing branch instruction before end"); - return ret_syntax; + return kSyntaxError; } else { if (vlayout[layout_index].is_do_unti) { // this end closes a do..unti if (vlayout[layout_index].index_end != -1) { // error: show it show_syntax_error("duplicate end"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it show_syntax_error("missing until"); - return ret_syntax; + return kSyntaxError; } k->arg1 = vlayout[layout_index].index_if_or_do_or_while + 1; @@ -503,7 +503,7 @@ ret_value program::preprocess(void) { if (vlayout[layout_index].index_end != -1) { // error: show it show_syntax_error("duplicate end"); - return ret_syntax; + return kSyntaxError; } k->arg2 = vlayout[layout_index].index_if_or_do_or_while + 1; @@ -511,7 +511,7 @@ ret_value program::preprocess(void) { if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it show_syntax_error("missing repeat"); - return ret_syntax; + return kSyntaxError; } // fill 'repeat' arg1 with 'end+1' @@ -522,7 +522,7 @@ ret_value program::preprocess(void) { if (vlayout[layout_index].index_end != -1) { // error: show it show_syntax_error("duplicate end"); - return ret_syntax; + return kSyntaxError; } if (vlayout[layout_index].index_else != -1) { // fill 'end' branch of 'else' @@ -535,7 +535,7 @@ ret_value program::preprocess(void) { } else { // error: show it show_syntax_error("missing then"); - return ret_syntax; + return kSyntaxError; } } layout_index--; @@ -547,27 +547,27 @@ ret_value program::preprocess(void) { if (layout_index >= 0) { // error: show it show_syntax_error("missing end"); - return ret_syntax; + return kSyntaxError; } if (vstart_index.size() > 0) { // error: show it show_syntax_error("missing next or step after for or start"); - return ret_syntax; + return kSyntaxError; } - return ret_ok; + return kOk; } /// @brief parse an entry string: cut it into objects chunks and add them to a program /// /// @param entry the entry string /// @param prog the program to be filled -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::parse(string& entry) { +RetValue program::parse(string& entry) { static map keywords_map; vector elements; vector errors; - ret_value ret = ret_ok; + RetValue ret = kOk; // prepare map for finding reserved keywords if (keywords_map.empty()) @@ -579,29 +579,29 @@ ret_value program::parse(string& entry) { // make objects from parsed elements for (Lexer::SynElement& element : elements) { switch (element.type) { - case cmd_number: + case kNumber: push_back(new Number(*element.re, element.reBase)); break; - case cmd_complex: + case kComplex: push_back(new Complex(*element.re, *element.im, element.reBase, element.imBase)); break; - case cmd_string: + case kString: push_back(new String(element.value)); break; - case cmd_symbol: + case kSymbol: push_back(new Symbol(element.value, element.autoEval)); break; - case cmd_program: + case kProgram: push_back(new Program(element.value)); break; - case cmd_keyword: + case kKeyword: push_back(new Keyword(element.fn, element.value)); break; - case cmd_branch: + case kBranch: push_back(new Branch((branch_fn_t)element.fn, element.value)); break; default: - show_error(ret_unknown_err, "error creating program from entry"); + show_error(kUnknownError, "error creating program from entry"); break; } if (element.re != nullptr) delete element.re; @@ -616,27 +616,29 @@ ret_value program::parse(string& entry) { /// @brief show the last error set /// -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::show_error() { - ret_value ret; +RetValue program::show_error() { + RetValue ret; // clang-format off - vector errorStrings {"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", "aborted current entry", "out of memory", - "bad value", "test failed"}; + map errorStrings{{kOk, "ok"}, {kUnknownError, "unknown command"}, + {kMissingOperand, "missing operand"}, {kBadOperandType, "bad operand type"}, + {kOutOfRange, "out of range"}, {kUnknownVariable, "unknown variable"}, + {kInternalError, "internal error, aborting"}, {kDeadlyError, "deadly"}, + {kGoodbye, "goodbye"}, {kNotImplemented, "not implemented"}, + {kNop, "no operation"}, {kSyntaxError, "syntax error"}, + {kDivByZero, "division by zero"}, {kRuntimeError, "runtime error"}, + {kAbortCurrentEntry, "aborted current entry"}, {kOutOfMemory, "out of memory"}, + {kBadValue, "bad value"}, {kTestFailed, "test failed"} + }; // clang-format on - // show last recorded error - if (static_cast(_err) < errorStrings.size()) - cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl; - else - cerr << _err_context << " (unknown error code)" << endl; + cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl; switch (_err) { - case ret_internal: - case ret_deadly: - ret = ret_deadly; + case kInternalError: + case kDeadlyError: + ret = kDeadlyError; default: - ret = ret_ok; + ret = kOk; } return ret; @@ -646,9 +648,9 @@ ret_value program::show_error() { /// /// @param err the error to record /// @param context a context string -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::show_error(ret_value err, string& context) { +RetValue program::show_error(RetValue err, string& context) { // record error _err = err; _err_context = context; @@ -659,9 +661,9 @@ ret_value program::show_error(ret_value err, string& context) { /// /// @param err the error to record /// @param context a context string -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::show_error(ret_value err, const char* context) { +RetValue program::show_error(RetValue err, const char* context) { // record error _err = err; _err_context = context; @@ -672,20 +674,20 @@ ret_value program::show_error(ret_value err, const char* context) { /// /// @param err the error to record /// @param context a context string -/// @return ret_value see this type +/// @return RetValue see this type /// void program::show_syntax_error(const char* context) { // record error - _err = ret_syntax; + _err = kSyntaxError; _err_context = context; (void)show_error(); } /// @brief return the last error set /// -/// @return ret_value see this type +/// @return RetValue see this type /// -ret_value program::get_err(void) { return _err; } +RetValue program::get_err(void) { return _err; } /// @brief show a stack (show its different objects) /// generally a stack is associated to a running program diff --git a/src/program.hpp b/src/program.hpp index 05fb7dc..6a7b3da 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -28,19 +28,19 @@ class program : public deque, public Lexer { } // parser - ret_value parse(string& entry); - static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type); + RetValue parse(string& entry); + static RetValue get_fn(const char* fn_name, program_fn_t& fn, ObjectType& type); // running - ret_value run(); + RetValue run(); void stop(); - ret_value preprocess(void); + RetValue preprocess(void); - ret_value show_error(); - ret_value show_error(ret_value err, string& context); - ret_value show_error(ret_value err, const char* context); + RetValue show_error(); + RetValue show_error(RetValue err, string& context); + RetValue show_error(RetValue err, const char* context); void show_syntax_error(const char* context); - ret_value get_err(void); + RetValue get_err(void); void show_stack(bool show_separator = true); @@ -50,7 +50,7 @@ class program : public deque, public Lexer { private: // current error and its context - ret_value _err; + RetValue _err; string _err_context; // global stack holding results for user @@ -68,7 +68,7 @@ class program : public deque, public Lexer { private: // keywords struct keyword_t { - cmd_type_t type; + ObjectType type; string name; program_fn_t fn; string comment; @@ -93,7 +93,7 @@ class program : public deque, public Lexer { size_t rpn_for(Branch& myobj); size_t rpn_next(Branch& myobj); size_t rpn_step(Branch& myobj); - enum { step_out = static_cast(-1), runtime_error = static_cast(-2) }; + enum { kStepOut = static_cast(-1), kRtError = static_cast(-2) }; // complex void rpn_re(); @@ -259,7 +259,7 @@ class program : public deque, public Lexer { #define MIN_ARGUMENTS(num) \ do { \ if ((num) >= 0 && _stack.size() < (num)) { \ - setErrorContext(ret_missing_operand); \ + setErrorContext(kMissingOperand); \ return; \ } \ } while (0) @@ -267,7 +267,7 @@ class program : public deque, public Lexer { #define MIN_ARGUMENTS_RET(num, ret) \ do { \ if ((num) >= 0 && _stack.size() < (num)) { \ - setErrorContext(ret_missing_operand); \ + setErrorContext(kMissingOperand); \ return (ret); \ } \ } while (0) @@ -275,7 +275,7 @@ class program : public deque, public Lexer { #define ARG_MUST_BE_OF_TYPE(num, type) \ do { \ if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ - setErrorContext(ret_bad_operand_type); \ + setErrorContext(kBadOperandType); \ return; \ } \ } while (0) @@ -283,7 +283,7 @@ class program : public deque, public Lexer { #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ do { \ if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ - setErrorContext(ret_bad_operand_type); \ + setErrorContext(kBadOperandType); \ return (ret); \ } \ } while (0) diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index d39ca10..7d12d9b 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -6,28 +6,28 @@ /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_if(Branch& myobj) { // myobj.arg1 = 'if' condition evaluation value - MIN_ARGUMENTS_RET(1, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(1, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); if (_stack.value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; _stack.pop(); - return step_out; + return kStepOut; } /// @brief then keyword (branch) implementation /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort Branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort Branch /// size_t program::rpn_then(Branch& myobj) { // myobj.arg1 = index of then + 1 @@ -36,9 +36,9 @@ size_t program::rpn_then(Branch& myobj) { // if condition is true -> arg1 (= jump to then + 1) // else -> arg2 (= jump to else + 1 or end + 1) Branch* if_cmd; - if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) { + setErrorContext(kMissingOperand); + return kRtError; } if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) @@ -51,8 +51,8 @@ size_t program::rpn_then(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_else(Branch& myobj) { // myobj.arg1 = index of else + 1 @@ -61,9 +61,9 @@ size_t program::rpn_else(Branch& myobj) { // if condition was false -> arg1 (= jump to else + 1) // if condition was true -> arg2 (= jump to end + 1) Branch* if_cmd; - if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) { + setErrorContext(kMissingOperand); + return kRtError; } if_cmd = reinterpret_cast(at(myobj.arg3)); if (if_cmd->arg1 == 1) @@ -76,22 +76,22 @@ size_t program::rpn_else(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_end(Branch& myobj) { - size_t ret = step_out; + size_t ret = kStepOut; // arg1 = index of do+1 in case of do..unti..end if (myobj.arg1 != -1) { // in a template do..until..end - MIN_ARGUMENTS_RET(1, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(1, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); // check arg if (_stack.value(0) == 0) ret = myobj.arg1; _stack.pop(); - } else if (myobj.arg2 != step_out) { + } else if (myobj.arg2 != kStepOut) { // arg2 = index of while+1 in case of while..repeat..end ret = myobj.arg2; } @@ -103,36 +103,36 @@ size_t program::rpn_end(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_do(Branch& myobj) { // nothing - return step_out; + return kStepOut; } /// @brief until keyword (branch) implementation /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort Branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort Branch /// size_t program::rpn_until(Branch& myobj) { // nothing - return step_out; + return kStepOut; } /// @brief ift keyword (branch) implementation /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// void program::rpn_ift(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(1, kNumber); // check ift arg // arg is true if Number != 0 or if is nan or +/-inf @@ -146,12 +146,12 @@ void program::rpn_ift(void) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// void program::rpn_ifte(void) { MIN_ARGUMENTS(3); - ARG_MUST_BE_OF_TYPE(2, cmd_number); + ARG_MUST_BE_OF_TYPE(2, kNumber); // check ifte arg if (_stack.value(2) != 0) { @@ -167,26 +167,26 @@ void program::rpn_ifte(void) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_while(Branch& myobj) { // nothing - return step_out; + return kStepOut; } /// @brief repeat keyword (branch) implementation /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_repeat(Branch& myobj) { - size_t ret = step_out; + size_t ret = kStepOut; - MIN_ARGUMENTS_RET(1, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(1, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); // check arg // myobj.arg1 is end+1 @@ -200,15 +200,15 @@ size_t program::rpn_repeat(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_start(Branch& myobj) { - size_t ret = step_out; + size_t ret = kStepOut; - MIN_ARGUMENTS_RET(2, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(2, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); + ARG_MUST_BE_OF_TYPE_RET(1, kNumber, kRtError); // loop boundaries myobj.firstIndex = _stack.value(1); @@ -229,20 +229,20 @@ size_t program::rpn_start(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_for(Branch& myobj) { size_t ret; - MIN_ARGUMENTS_RET(2, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(2, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); + ARG_MUST_BE_OF_TYPE_RET(1, kNumber, kRtError); Symbol* sym; - if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_symbol) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kSymbol) { + setErrorContext(kMissingOperand); + return kRtError; } sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index @@ -276,16 +276,16 @@ size_t program::rpn_for(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_next(Branch& myobj) { // arg1 = loop variable index // firstIndex = current point in the loop Branch* start_or_for; - if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { + setErrorContext(kMissingOperand); + return kRtError; } start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { @@ -301,9 +301,9 @@ size_t program::rpn_next(Branch& myobj) { if (start_or_for->arg1 != -1) { Object* obj; Symbol* var; - if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) { + setErrorContext(kMissingOperand); + return kRtError; } var = reinterpret_cast(at(start_or_for->arg1)); @@ -315,7 +315,7 @@ size_t program::rpn_next(Branch& myobj) { if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - return step_out; + return kStepOut; } else { // for command: next instruction will be after symbol variable if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1; @@ -329,27 +329,27 @@ size_t program::rpn_next(Branch& myobj) { /// /// @param myobj the current branch object /// @return size_t index of the next object to run in the current program -/// @return step_out next object to run in the current program is current + 1 -/// @return runtime_error something went wrong with preprocess, abort branch +/// @return kStepOut next object to run in the current program is current + 1 +/// @return kRtError something went wrong with preprocess, abort branch /// size_t program::rpn_step(Branch& myobj) { size_t ret; - MIN_ARGUMENTS_RET(1, runtime_error); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error); + MIN_ARGUMENTS_RET(1, kRtError); + ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); mpreal step = _stack.value(0); _stack.pop(); // end of loop if step is negative or zero if (step <= 0) { - ret = step_out; + ret = kStepOut; } else { // arg1 = loop variable index // firstIndex = current count Branch* start_or_for; - if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { + setErrorContext(kMissingOperand); + return kRtError; } start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { @@ -366,9 +366,9 @@ size_t program::rpn_step(Branch& myobj) { Symbol* var; // for command: increment symbol too - if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) { - setErrorContext(ret_missing_operand); - return runtime_error; + if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) { + setErrorContext(kMissingOperand); + return kRtError; } var = reinterpret_cast(at(start_or_for->arg1)); // increase symbol variable @@ -379,7 +379,7 @@ size_t program::rpn_step(Branch& myobj) { if (myobj.firstIndex > start_or_for->lastIndex) { // end of loop myobj.arg_bool = false; // init again next time - ret = step_out; + ret = kStepOut; } else { // for command: next instruction will be after symbol variable if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1; diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index d90ca2d..b46716f 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -7,7 +7,7 @@ /// void program::rpn_re() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.push_front(new Number(real(_stack.value(0)))); _stack.erase(1); } @@ -17,7 +17,7 @@ void program::rpn_re() { /// void program::rpn_im() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.push_front(new Number(imag(_stack.value(0)))); _stack.erase(1); } @@ -27,7 +27,7 @@ void program::rpn_im() { /// void program::rpn_arg() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.push_front(new Number(arg(_stack.value(0)))); _stack.erase(1); } @@ -37,7 +37,7 @@ void program::rpn_arg() { /// void program::rpn_conj() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.value(0) = conj(_stack.value(0)); } @@ -46,8 +46,8 @@ void program::rpn_conj() { /// void program::rpn_r2c() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.push(new Complex(_stack.value(1), _stack.value(0), _stack.obj(1).reBase, _stack.obj(0).reBase)); _stack.erase(1, 2); } @@ -57,7 +57,7 @@ void program::rpn_r2c() { /// void program::rpn_c2r() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.push(new Number(real(_stack.value(0)), _stack.obj(0).reBase)); _stack.push(new Number(imag(_stack.value(1)), _stack.obj(1).imBase)); _stack.erase(2); @@ -68,7 +68,7 @@ void program::rpn_c2r() { /// void program::rpn_r2p() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); mpreal rho = abs(_stack.value(0)); mpreal theta = arg(_stack.value(0)); _stack.value(0).real(rho); @@ -80,6 +80,6 @@ void program::rpn_r2p() { /// void program::rpn_p2r() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_complex); + ARG_MUST_BE_OF_TYPE(0, kComplex); _stack.value(0) = polar(abs(_stack.value(0)), arg(_stack.value(0))); } diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 7443805..f7d51b5 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -40,7 +40,7 @@ void program::rpn_nop() { /// @brief quit keyword implementation /// -void program::rpn_good_bye() { setErrorContext(ret_good_bye); } +void program::rpn_good_bye() { setErrorContext(kGoodbye); } /// @brief nop keyword implementation /// the result is written on stdout @@ -60,23 +60,23 @@ void program::rpn_help() { for (auto& kw : _keywords) if (!kw.comment.empty()) { // titles in bold - if (kw.type == cmd_undef) cout << ATTR_BOLD; + if (kw.type == kUndef) cout << ATTR_BOLD; // show title or keyword + comment cout << kw.name << '\t' << kw.comment << endl; - if (kw.type == cmd_undef) cout << ATTR_OFF; + if (kw.type == kUndef) cout << ATTR_OFF; } cout << endl; // show mode cout << "Current float mode is "; switch (Number::s_mode) { - case Number::std: + case Number::kStd: cout << "'std'"; break; - case Number::fix: + case Number::kFix: cout << "'fix'"; break; - case Number::sci: + case Number::kSci: cout << "'sci'"; break; default: @@ -108,17 +108,17 @@ static bool check_decimal_digits(int precision) { return precision >= 0; } /// void program::rpn_std() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::std; + Number::s_mode = Number::kStd; Number::s_digits = digits; _stack.pop(); } else { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); } } @@ -126,17 +126,17 @@ void program::rpn_std() { /// void program::rpn_fix() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::fix; + Number::s_mode = Number::kFix; Number::s_digits = digits; _stack.pop(); } else { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); } } @@ -144,17 +144,17 @@ void program::rpn_fix() { /// void program::rpn_sci() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int digits = static_cast(_stack.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::sci; + Number::s_mode = Number::kSci; Number::s_digits = digits; _stack.pop(); } else { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); } } @@ -195,7 +195,7 @@ void program::rpn_default() { program::apply_default(); } /// void program::rpn_precision() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); // set precision int prec = static_cast(_stack.value(0).toLong()); @@ -203,13 +203,13 @@ void program::rpn_precision() { mpreal::set_default_prec(prec); // modify digits seen by user if std mode - if (Number::s_mode == Number::std) { + if (Number::s_mode == Number::kStd) { // calc max nb of digits user can see with the current bit precision Number::s_digits = mpfr::bits2digits(mpreal::get_default_prec()); } _stack.pop(); } else { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); } } @@ -217,7 +217,7 @@ void program::rpn_precision() { /// void program::rpn_round() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); map matchRound{MPFR_ROUND}; @@ -225,6 +225,6 @@ void program::rpn_round() { if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); _stack.pop(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index c0f06c5..2c5796a 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -10,166 +10,166 @@ void program::rpn_e(void) { _stack.push(new Number(mpfr::const_euler())); } /// void program::rpn_log10() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = log10(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = log10(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief alog10 keyword implementation /// void program::rpn_alog10() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief log2 keyword implementation /// void program::rpn_log2() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief alog2 keyword implementation /// void program::rpn_alog2() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief ln keyword implementation /// void program::rpn_ln() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = log(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = log(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief exp keyword implementation /// void program::rpn_exp() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = exp(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = exp(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief expm keyword implementation /// void program::rpn_expm() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = exp(_stack.value(0)) - mpreal(1); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = exp(_stack.value(0)) - mpreal(1); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief lnp1 keyword implementation /// void program::rpn_lnp1() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = log(_stack.value(0) + 1); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = log(_stack.value(0) + mpreal(1)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief sinh keyword implementation /// void program::rpn_sinh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = sinh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = sinh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief asinh keyword implementation /// void program::rpn_asinh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = asinh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = asinh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief cosh keyword implementation /// void program::rpn_cosh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = cosh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = cosh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief acosh keyword implementation /// void program::rpn_acosh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = acosh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = acosh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief tanh keyword implementation /// void program::rpn_tanh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = tanh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = tanh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief atanh keyword implementation /// void program::rpn_atanh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = atanh(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = atanh(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 4e83558..b7afa8e 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -38,7 +38,7 @@ void program::rpn_eval(void) { string prog_text; MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_symbol) { + if (_stack.type(0) == kSymbol) { // recall a variable Object* obj; string variable(_stack.value(0)); @@ -46,7 +46,7 @@ void program::rpn_eval(void) { // if variable holds a program, run this program if (find_variable(variable, obj)) { - if (obj->_type == cmd_program) { + if (obj->_type == kProgram) { prog_text = _stack.value(0); _stack.pop(); run_prog = true; @@ -55,15 +55,15 @@ void program::rpn_eval(void) { _stack.push_front(obj); } } else { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); } - } else if (_stack.type(0) == cmd_program) { + } else if (_stack.type(0) == kProgram) { // eval a program prog_text = _stack.value(0); _stack.pop(); run_prog = true; } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } // run prog if any @@ -71,7 +71,7 @@ void program::rpn_eval(void) { program prog(_stack, _heap, this); // make program from entry - if (prog.parse(prog_text) == ret_ok) { + if (prog.parse(prog_text) == kOk) { // run it prog.run(); } @@ -86,7 +86,7 @@ int program::rpn_inprog(Branch& inprog_obj) { bool prog_found = false; if (inprog_obj.arg1 == -1) { - setErrorContext(ret_unknown_err); + setErrorContext(kUnknownError); return -1; } @@ -96,15 +96,15 @@ int program::rpn_inprog(Branch& inprog_obj) { // find next Program object for (unsigned int i = inprog_obj.arg1 + 1; i < size(); i++) { // count symbol - if (at(i)->_type == cmd_symbol) { + if (at(i)->_type == kSymbol) { count_symbols++; - } else if (at(i)->_type == cmd_program) { + } else if (at(i)->_type == kProgram) { // stop if prog prog_found = true; break; } else { // found something other than symbol - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); show_error(_err, context); return -1; } @@ -112,21 +112,21 @@ int program::rpn_inprog(Branch& inprog_obj) { // found 0 symbols if (count_symbols == 0) { - setErrorContext(ret_syntax); + setErrorContext(kSyntaxError); show_error(_err, context); return -1; } // is missing if (!prog_found) { - setErrorContext(ret_syntax); + setErrorContext(kSyntaxError); show_error(_err, context); return -1; } // check symbols Number vs stack size if (_stack.size() < count_symbols) { - setErrorContext(ret_missing_operand); + setErrorContext(kMissingOperand); show_error(_err, context); return -1; } @@ -142,7 +142,7 @@ int program::rpn_inprog(Branch& inprog_obj) { program prog(_stack, _heap, this); // make the program from entry - if (prog.parse(entry) == ret_ok) { + if (prog.parse(entry) == kOk) { // run it prog.run(); } diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index d9d00a5..5f59bd3 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -6,24 +6,24 @@ /// void program::rpn_plus() { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.value(1) += _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.value(1) += _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.value(1) += _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { _stack.value(1) += _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { rpn_swap(); _stack.value(1) += _stack.value(0); _stack.pop(); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -31,21 +31,21 @@ void program::rpn_plus() { /// void program::rpn_minus() { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { _stack.value(1) -= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { rpn_swap(); _stack.value(1) = _stack.value(0) - _stack.value(1); _stack.pop(); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -53,21 +53,21 @@ void program::rpn_minus() { /// void program::rpn_mul() { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { _stack.value(1) *= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { rpn_swap(); _stack.value(1) *= _stack.value(0); _stack.pop(); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -75,21 +75,21 @@ void program::rpn_mul() { /// void program::rpn_div() { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { _stack.value(1) /= _stack.value(0); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { rpn_swap(); _stack.value(1) = _stack.value(0) / _stack.value(1); _stack.pop(); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -97,31 +97,31 @@ void program::rpn_div() { /// void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = -_stack.value(0); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = -_stack.value(0); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief inv keyword implementation /// void program::rpn_inv() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = 1 / _stack.value(0); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = mpreal(1) / _stack.value(0); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief power keyword implementation /// void program::rpn_power() { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { if (_stack.value(1) >= 0) { _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); @@ -131,18 +131,18 @@ void program::rpn_power() { _stack.value(0) = pow(_stack.value(0), _stack.value(1)); _stack.erase(1, 2); } - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); - } else if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { _stack.value(1) = pow(_stack.value(1), _stack.value(0)); _stack.pop(); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_number) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { rpn_swap(); _stack.value(1) = pow(_stack.value(0), _stack.value(1)); _stack.pop(); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -150,7 +150,7 @@ void program::rpn_power() { /// void program::rpn_squareroot() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { if (_stack.value(0) >= 0) { _stack.value(0) = sqrt(_stack.value(0)); } else { @@ -161,10 +161,10 @@ void program::rpn_squareroot() { _stack.value(0) = sqrt(_stack.value(0)); _stack.erase(1); } - } else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == kComplex) { _stack.value(0) = sqrt(_stack.value(0)); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -172,13 +172,13 @@ void program::rpn_squareroot() { /// void program::rpn_hex() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { _stack.obj(0).base = 16; - } else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == kComplex) { _stack.obj(0).reBase = 16; _stack.obj(0).imBase = 16; } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -186,13 +186,13 @@ void program::rpn_hex() { /// void program::rpn_bin() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { _stack.obj(0).base = 2; - } else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == kComplex) { _stack.obj(0).reBase = 2; _stack.obj(0).imBase = 2; } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -200,13 +200,13 @@ void program::rpn_bin() { /// void program::rpn_dec() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { _stack.obj(0).base = 10; - } else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == kComplex) { _stack.obj(0).reBase = 10; _stack.obj(0).imBase = 10; } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -214,21 +214,21 @@ void program::rpn_dec() { /// void program::rpn_base() { MIN_ARGUMENTS(2); - if (_stack.type(1) == cmd_number || _stack.type(1) == cmd_complex) { + if (_stack.type(1) == kNumber || _stack.type(1) == kComplex) { int base = static_cast(_stack.value(0).toLong()); _stack.pop(); if (base >= 2 && base <= 62) { - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { _stack.obj(0).base = base; } else { _stack.obj(0).reBase = base; _stack.obj(0).imBase = base; } } else { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); } } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -236,8 +236,8 @@ void program::rpn_base() { /// void program::rpn_purcent() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.value(1) *= _stack.value(0) / 100; _stack.pop(); } @@ -246,8 +246,8 @@ void program::rpn_purcent() { /// void program::rpn_purcentCH() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.value(1) = (_stack.value(0) * 100) / _stack.value(1); _stack.pop(); } @@ -256,20 +256,20 @@ void program::rpn_purcentCH() { /// void program::rpn_square() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) *= _stack.value(0); - else if (_stack.at(0)->_type == cmd_complex) + else if (_stack.at(0)->_type == kComplex) _stack.value(0) *= _stack.value(0); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief mod keyword implementation /// void program::rpn_modulo() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.value(1) = fmod(_stack.value(1), _stack.value(0)); _stack.pop(); } @@ -278,13 +278,13 @@ void program::rpn_modulo() { /// void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) { + if (_stack.type(0) == kNumber) { _stack.value(0) = abs(_stack.value(0)); - } else if (_stack.type(0) == cmd_complex) { + } else if (_stack.type(0) == kComplex) { _stack.push(new Number(abs(_stack.value(0)))); _stack.erase(1); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -292,7 +292,7 @@ void program::rpn_abs() { /// void program::rpn_fact() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); // fact(n) = gamma(n+1) _stack.value(0) = gamma(_stack.value(0) + 1); } @@ -301,21 +301,21 @@ void program::rpn_fact() { /// void program::rpn_sign() { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = sgn(_stack.value(0)); - else if (_stack.at(0)->_type == cmd_complex) + else if (_stack.at(0)->_type == kComplex) _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief mant keyword implementation /// void program::rpn_mant() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); if (!isfinite(_stack.value(0))) { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); return; } mp_exp_t exp; @@ -326,9 +326,9 @@ void program::rpn_mant() { /// void program::rpn_xpon() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); if (!isfinite(_stack.value(0))) { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); return; } mp_exp_t exp; @@ -340,7 +340,7 @@ void program::rpn_xpon() { /// void program::rpn_floor() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) = floor(_stack.value(0)); } @@ -348,7 +348,7 @@ void program::rpn_floor() { /// void program::rpn_ceil() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) = ceil(_stack.value(0)); } @@ -356,7 +356,7 @@ void program::rpn_ceil() { /// void program::rpn_fp() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) = frac(_stack.value(0)); } @@ -364,7 +364,7 @@ void program::rpn_fp() { /// void program::rpn_ip() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) = trunc(_stack.value(0)); } @@ -372,8 +372,8 @@ void program::rpn_ip() { /// void program::rpn_min() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.value(0) = min(_stack.value(0), _stack.value(1)); _stack.erase(1); } @@ -382,8 +382,8 @@ void program::rpn_min() { /// void program::rpn_max() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); _stack.value(0) = max(_stack.value(0), _stack.value(1)); _stack.erase(1); } diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index fa98451..63cedbf 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -29,7 +29,7 @@ void program::rpn_drop2(void) { /// void program::rpn_dropn(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int args = static_cast(_stack.value(0).toLong()); MIN_ARGUMENTS(args + 1); @@ -51,7 +51,7 @@ void program::rpn_dup(void) { /// void program::rpn_dupn(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int args = static_cast(_stack.value(0).toLong()); _stack.pop(); @@ -72,14 +72,14 @@ void program::rpn_dup2(void) { /// void program::rpn_pick(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int to_pick = static_cast(_stack.value(0).toLong()); _stack.pop(); // treat stack depth errors if ((to_pick == 0) || (to_pick > _stack.size())) { - setErrorContext(ret_out_of_range); + setErrorContext(kOutOfRange); return; } @@ -103,7 +103,7 @@ void program::rpn_depth(void) { _stack.push_front(new Number(_stack.size())); } /// void program::rpn_roll(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int args = static_cast(_stack.value(0).toLong()); _stack.pop(); @@ -118,7 +118,7 @@ void program::rpn_roll(void) { /// void program::rpn_rolld(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); int args = static_cast(_stack.value(0).toLong()); _stack.pop(); diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index b8a1135..6d3e6d7 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -7,7 +7,7 @@ /// void program::rpn_sto(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); // store symbol with first value const auto it = _heap.find(_stack.value(0)); @@ -23,9 +23,9 @@ void program::rpn_sto(void) { /// void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -40,9 +40,9 @@ void program::rpn_stoadd(void) { /// void program::rpn_stosub(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -57,9 +57,9 @@ void program::rpn_stosub(void) { /// void program::rpn_stomul(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -74,9 +74,9 @@ void program::rpn_stomul(void) { /// void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -91,9 +91,9 @@ void program::rpn_stodiv(void) { /// void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -107,9 +107,9 @@ void program::rpn_stoneg(void) { /// void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); if (_heap.find(_stack.value(0)) == _heap.end()) { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); return; } rpn_dup(); @@ -123,7 +123,7 @@ void program::rpn_stoinv(void) { /// void program::rpn_rcl(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); // recall a variable Object* obj; @@ -134,7 +134,7 @@ void program::rpn_rcl(void) { (void)_stack.pop(); _stack.push_front(obj->clone()); } else { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); } } @@ -165,7 +165,7 @@ void program::auto_rcl(Symbol* symb) { // mind the order of heaps if (find_variable(variable, obj)) { _stack.push_front(obj->clone()); - if (obj->_type == cmd_program) rpn_eval(); + if (obj->_type == kProgram) rpn_eval(); } else { _stack.push_front(symb->clone()); } @@ -178,14 +178,14 @@ void program::auto_rcl(Symbol* symb) { /// void program::rpn_purge(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_symbol); + ARG_MUST_BE_OF_TYPE(0, kSymbol); const auto i = _heap.find(_stack.value(0)); if (i != _heap.end()) { delete i->second; _heap.erase(i); } else { - setErrorContext(ret_unknown_variable); + setErrorContext(kUnknownVariable); } _stack.pop(); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index dc8e38d..6412c8a 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -10,7 +10,7 @@ void program::rpn_instr() { MIN_ARGUMENTS(1); // stringify only if not already a string - if (_stack.type(0) != cmd_string) { + if (_stack.type(0) != kString) { stringstream ss; ss << _stack.at(0); _stack.pop(); @@ -22,14 +22,14 @@ void program::rpn_instr() { /// void program::rpn_strout() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); string entry(_stack.value(0)); program prog(_stack, _heap); _stack.pop(); // make program from string in stack level 1 - if (prog.parse(entry) == ret_ok) + if (prog.parse(entry) == kOk) // run it prog.run(); } @@ -38,7 +38,7 @@ void program::rpn_strout() { /// void program::rpn_chr() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); char the_chr = static_cast(_stack.value(0).toLong()); _stack.pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; @@ -49,7 +49,7 @@ void program::rpn_chr() { /// void program::rpn_num() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); if (_stack.value(0).size() > 0) _stack.push_front(new Number(_stack.value(0)[0])); else @@ -61,7 +61,7 @@ void program::rpn_num() { /// void program::rpn_strsize() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); _stack.push_front(new Number(_stack.value(0).size())); _stack.erase(1); } @@ -70,8 +70,8 @@ void program::rpn_strsize() { /// void program::rpn_strpos() { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_string); - ARG_MUST_BE_OF_TYPE(1, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); + ARG_MUST_BE_OF_TYPE(1, kString); size_t pos = _stack.value(1).find(_stack.value(0)) + 1; _stack.erase(0, 2); @@ -82,9 +82,9 @@ void program::rpn_strpos() { /// void program::rpn_strsub() { MIN_ARGUMENTS(3); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); - ARG_MUST_BE_OF_TYPE(2, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); + ARG_MUST_BE_OF_TYPE(2, kString); size_t first = _stack.value(1).toULong(); size_t len = _stack.value(0).toULong() - first + 1; diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index d838779..eaad02c 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -69,7 +69,7 @@ static void testShowResult(string title, int tests, int tests_failed, int steps, /// void program::rpn_test() { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_string); + ARG_MUST_BE_OF_TYPE(0, kString); int total_tests = 0; int total_tests_failed = 0; @@ -84,7 +84,7 @@ void program::rpn_test() { // notify to caller that test succeeded or not if (total_tests_failed > 0) { - _err = ret_test_failed; + _err = kTestFailed; _err_context = string("rpn version ") + RPN_VERSION + ", test file " + test_filename; } } @@ -113,7 +113,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (test_file.is_open()) { string test_title; string entry; - ret_value ret; + RetValue ret; rpnstack stk; heap hp; bool failed = false; @@ -246,7 +246,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (!entry.empty()) { program prog(stk, hp); ret = prog.parse(entry); - if (ret == ret_ok) { + if (ret == kOk) { // run it (void)prog.run(); last_err = static_cast(prog.get_err()); diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index defe403..06dac2e 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -19,14 +19,14 @@ static int CmpStringOnStackTop(rpnstack& stk) { /// void program::rpn_sup(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) > _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 1)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -34,14 +34,14 @@ void program::rpn_sup(void) { /// void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) >= _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) != -1)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -50,14 +50,14 @@ void program::rpn_sup_eq(void) { void program::rpn_inf(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) < _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) == -1)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -65,14 +65,14 @@ void program::rpn_inf(void) { /// void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) <= _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 1)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -80,17 +80,17 @@ void program::rpn_inf_eq(void) { /// void program::rpn_diff(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 0)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -98,17 +98,17 @@ void program::rpn_diff(void) { /// void program::rpn_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == cmd_number && _stack.type(1) == cmd_number) { + if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_complex && _stack.type(1) == cmd_complex) { + } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); _stack.erase(1, 2); - } else if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) { + } else if (_stack.type(0) == kString && _stack.type(1) == kString) { _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 0)); _stack.erase(1, 2); } else { - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } } @@ -116,8 +116,8 @@ void program::rpn_eq(void) { /// void program::rpn_test_and(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); if (_stack.value(0) != 0 && _stack.value(1) != 0) _stack.push(new Number(1)); else @@ -129,8 +129,8 @@ void program::rpn_test_and(void) { /// void program::rpn_test_or(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); if (_stack.value(0) != 0 || _stack.value(1) != 0) _stack.push(new Number(1)); else @@ -142,8 +142,8 @@ void program::rpn_test_or(void) { /// void program::rpn_test_xor(void) { MIN_ARGUMENTS(2); - ARG_MUST_BE_OF_TYPE(0, cmd_number); - ARG_MUST_BE_OF_TYPE(1, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); + ARG_MUST_BE_OF_TYPE(1, kNumber); if (_stack.value(0) != 0 ^ _stack.value(1) != 0) _stack.push(new Number(1)); else @@ -155,7 +155,7 @@ void program::rpn_test_xor(void) { /// void program::rpn_test_not(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.push(new Number(_stack.value(0) == 0 ? 1 : 0)); _stack.erase(1, 1); diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index 08f8bae..d97956a 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -25,7 +25,7 @@ void program::rpn_time() { _stack.push(new Number(date)); _stack.value(0) /= 10000000000.0; } else { - setErrorContext(ret_internal); + setErrorContext(kInternalError); } } @@ -51,7 +51,7 @@ void program::rpn_date() { _stack.push(new Number(date)); _stack.value(0) /= 1000000.0; } else { - setErrorContext(ret_internal); + setErrorContext(kInternalError); } } @@ -71,6 +71,6 @@ void program::rpn_ticks() { date = 1000000.0 * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec / 1000); _stack.push(new Number(date)); } else { - setErrorContext(ret_internal); + setErrorContext(kInternalError); } } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index de01e50..8af66a1 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -12,7 +12,7 @@ void program::rpn_pi(void) { /// void program::rpn_d2r(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) *= mpfr::const_pi(); _stack.value(0) /= 180; } @@ -21,7 +21,7 @@ void program::rpn_d2r(void) { /// void program::rpn_r2d(void) { MIN_ARGUMENTS(1); - ARG_MUST_BE_OF_TYPE(0, cmd_number); + ARG_MUST_BE_OF_TYPE(0, kNumber); _stack.value(0) /= mpfr::const_pi(); _stack.value(0) *= 180; } @@ -30,70 +30,70 @@ void program::rpn_r2d(void) { /// void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = sin(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = sin(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief asin keyword implementation /// void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = asin(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = asin(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief cos keyword implementation /// void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = cos(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = cos(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief acos keyword implementation /// void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = acos(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = acos(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief tan keyword implementation /// void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = tan(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = tan(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } /// @brief atan keyword implementation /// void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == cmd_number) + if (_stack.type(0) == kNumber) _stack.value(0) = atan(_stack.value(0)); - else if (_stack.type(0) == cmd_complex) + else if (_stack.type(0) == kComplex) _stack.value(0) = atan(_stack.value(0)); else - setErrorContext(ret_bad_operand_type); + setErrorContext(kBadOperandType); } diff --git a/src/stack.hpp b/src/stack.hpp index 21e43bc..fc69912 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -32,7 +32,7 @@ class rpnstack : public deque { // access helpers // - cmd_type_t type(int level) { + ObjectType type(int level) { // carefull: caller must ensure that level is correct return at(level)->_type; } From 327229dda4249b82f824956ca178a3e17afdb621 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 14:52:48 +0100 Subject: [PATCH 43/57] struct and class names --- src/lexer.cpp | 14 +- src/lexer.hpp | 6 +- src/object.cpp | 4 +- src/object.hpp | 72 +++++----- src/program.cpp | 62 ++++----- src/program.hpp | 39 +++--- src/rpn-branch.cpp | 76 +++++----- src/rpn-complex.cpp | 34 ++--- src/rpn-general.cpp | 50 +++---- src/rpn-logs.cpp | 114 +++++++-------- src/rpn-program.cpp | 50 +++---- src/rpn-real.cpp | 278 ++++++++++++++++++------------------- src/rpn-stack.cpp | 68 ++++----- src/rpn-store.cpp | 62 ++++----- src/rpn-string.cpp | 50 +++---- src/rpn-test-framework.cpp | 8 +- src/rpn-test.cpp | 116 ++++++++-------- src/rpn-time.cpp | 10 +- src/rpn-trig.cpp | 58 ++++---- 19 files changed, 586 insertions(+), 585 deletions(-) diff --git a/src/lexer.cpp b/src/lexer.cpp index e8169f7..7479504 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -71,7 +71,7 @@ bool Lexer::parseSymbol(string& entry, size_t idx, size_t& next_idx, vector& elements) { mpreal* re = nullptr; mpreal* im = nullptr; - int reBase, imBase = 10; + int re_base, im_base = 10; if (idx + 1 == entry.size()) { elements.push_back({kSymbol, .value = entry.substr(idx, entry.size() - idx)}); next_idx = entry.size(); return true; // complex format error, return a symbol } - if (!getNumberAt(entry, idx + 1, next_idx, reBase, &re, ',')) { + if (!getNumberAt(entry, idx + 1, next_idx, re_base, &re, ',')) { elements.push_back({kSymbol, .value = entry.substr(idx, entry.size() - idx)}); next_idx = entry.size(); return true; // complex format error, return a symbol @@ -218,14 +218,14 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& next_idx, vector> token; - elements.push_back({kSymbol, .value = token, .autoEval = true}); + elements.push_back({kSymbol, .value = token, .auto_eval = true}); next_idx = token.size() + idx; return true; } diff --git a/src/lexer.hpp b/src/lexer.hpp index 509124c..c921537 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -23,10 +23,10 @@ class Lexer { string value; mpreal* re; mpreal* im; - int reBase; - int imBase; + int re_base; + int im_base; program_fn_t fn; - bool autoEval; + bool auto_eval; }; struct SynError { diff --git a/src/object.cpp b/src/object.cpp index 3ab1baa..43ba057 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -3,5 +3,5 @@ #include "object.hpp" // number statics -Number::mode_enum Number::s_mode = Number::DEFAULT_MODE; -int Number::s_digits = DEFAULT_DECIMAL_DIGITS; +Number::mode_enum Number::mode = Number::DEFAULT_MODE; +int Number::digits = kDefaultDecimalDigits; diff --git a/src/object.hpp b/src/object.hpp index 67e2727..760b9c0 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -6,14 +6,14 @@ #include using mpfr::mpreal; -#include -#include -#include #include +#include +#include +#include +using std::complex; using std::ostream; using std::string; using std::stringstream; -using std::complex; #include "mpreal-out.hpp" @@ -83,25 +83,25 @@ struct Object { /// struct Number : Object { Number() : Object(kNumber), base(10) {} - explicit Number(const mpreal& value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {} - explicit Number(int value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {} + explicit Number(const mpreal& value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {} + explicit Number(int value__, int base__ = 10) : Object(kNumber), base(base__), value(value__) {} int base; mpreal value; virtual Object* clone() { return new Number(value, base); } virtual string name() { return string("number"); } - virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); } + virtual ostream& show(ostream& out) { return showValue(out, value, mode, digits, base); } // representation mode typedef enum { kStd, kFix, kSci } mode_enum; - static mode_enum s_mode; + static mode_enum mode; static constexpr mode_enum DEFAULT_MODE = Number::kStd; // precision - static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128; - static constexpr int DEFAULT_DECIMAL_DIGITS = 38; - static int s_digits; + static constexpr mpfr_prec_t kMpfrDefaultPrecBits = 128; + static constexpr int kDefaultDecimalDigits = 38; + static int digits; // clang-format off static string _makeNumberFormat(mode_enum mode, int digits) { @@ -118,7 +118,7 @@ struct Number : Object { static ostream& showValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base) { if (base == 10) - return MprealOutput10Base(out, _makeNumberFormat(s_mode, s_digits), value); + return MprealOutput10Base(out, _makeNumberFormat(mode, digits), value); else return MprealOutputNBase(out, base, value); } @@ -127,34 +127,34 @@ struct Number : Object { /// @brief stack objects inheriting Object /// struct Complex : Object { - Complex() : Object(kComplex), reBase(10), imBase(10) {} - explicit Complex(complex& value_, int reb = 10, int imb = 10) - : Object(kComplex), reBase(reb), imBase(imb) { - value = value_; + Complex() : Object(kComplex), re_base(10), im_base(10) {} + explicit Complex(complex& value__, int re_base__ = 10, int im_base__ = 10) + : Object(kComplex), re_base(re_base__), im_base(im_base__) { + value = value__; } - explicit Complex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10) - : Object(kComplex), reBase(reb), imBase(imb) { - value.real(re_); - value.imag(im_); + explicit Complex(mpreal& re__, mpreal& im__, int re_base__ = 10, int im_base__ = 10) + : Object(kComplex), re_base(re_base__), im_base(im_base__) { + value.real(re__); + value.imag(im__); } - int reBase, imBase; + int re_base, im_base; complex value; - virtual Object* clone() { return new Complex(value, reBase, imBase); } + virtual Object* clone() { return new Complex(value, re_base, im_base); } virtual string name() { return string("complex"); } virtual ostream& show(ostream& out) { out << '('; - Number::showValue(out, value.real(), Number::s_mode, Number::s_digits, reBase); + Number::showValue(out, value.real(), Number::mode, Number::digits, re_base); out << ','; - Number::showValue(out, value.imag(), Number::s_mode, Number::s_digits, imBase); + Number::showValue(out, value.imag(), Number::mode, Number::digits, im_base); return out << ')'; } }; struct String : Object { String() : Object(kString) {} - explicit String(const string& value_) : Object(kString), value(value_) {} + explicit String(const string& value__) : Object(kString), value(value__) {} virtual Object* clone() { return new String(value); } virtual string name() { return string("string"); } virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } @@ -163,7 +163,7 @@ struct String : Object { struct Program : Object { Program() : Object(kProgram) {} - explicit Program(const string& value_) : Object(kProgram), value(value_) {} + explicit Program(const string& value__) : Object(kProgram), value(value__) {} virtual Object* clone() { return new Program(value); } virtual string name() { return string("program"); } virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } @@ -171,19 +171,19 @@ struct Program : Object { }; struct Symbol : Object { - explicit Symbol(bool autoEval_ = true) : Object(kSymbol), autoEval(autoEval_) {} - explicit Symbol(const string& value_, bool autoEval_ = true) - : Object(kSymbol), value(value_), autoEval(autoEval_) {} - virtual Object* clone() { return new Symbol(value, autoEval); } + explicit Symbol(bool auto_eval__ = true) : Object(kSymbol), auto_eval(auto_eval__) {} + explicit Symbol(const string& value__, bool auto_eval__ = true) + : Object(kSymbol), value(value__), auto_eval(auto_eval__) {} + virtual Object* clone() { return new Symbol(value, auto_eval); } virtual string name() { return string("symbol"); } virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } - bool autoEval; + bool auto_eval; string value; }; struct Keyword : Object { Keyword() : Object(kKeyword) {} - explicit Keyword(program_fn_t fn_, const string& value_) : Object(kKeyword), fn(fn_), value(value_) {} + explicit Keyword(program_fn_t fn__, const string& value__) : Object(kKeyword), fn(fn__), value(value__) {} virtual Object* clone() { return new Keyword(fn, value); } virtual string name() { return string("keyword"); } program_fn_t fn; @@ -192,13 +192,13 @@ struct Keyword : Object { struct Branch : Object { Branch() : Object(kBranch) {} - explicit Branch(branch_fn_t fn_, const string& value_) : Object(kBranch) { - fn = fn_; + explicit Branch(branch_fn_t fn__, const string& value__) : Object(kBranch) { + fn = fn__; arg1 = static_cast(-1); arg2 = static_cast(-1); arg3 = static_cast(-1); arg_bool = 0; - value = value_; + value = value__; } explicit Branch(Branch& other) : Object(kBranch) { fn = other.fn; @@ -212,7 +212,7 @@ struct Branch : Object { virtual string name() { return string("branch"); } branch_fn_t fn; size_t arg1, arg2, arg3; - mpreal firstIndex, lastIndex; + mpreal first_index, last_index; bool arg_bool; string value; }; diff --git a/src/program.cpp b/src/program.cpp index 722da4f..30c9550 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -3,7 +3,7 @@ #include "program.hpp" //< language reserved keywords (allowed types are kKeyword, kBranch or kUndef) -vector program::_keywords{ +vector program::keywords_{ // GENERAL {kUndef, "", nullptr, "\nGENERAL"}, {kKeyword, "nop", &program::rpn_nop, "no operation"}, @@ -207,7 +207,7 @@ vector program::_keywords{ vector& program::getAutocompletionWords() { static vector autocompletion_words; if (autocompletion_words.empty()) - for (auto& kw : _keywords) + for (auto& kw : keywords_) if (!kw.name.empty()) autocompletion_words.push_back(kw.name); return autocompletion_words; } @@ -221,15 +221,15 @@ RetValue program::run() { RetValue ret = kOk; ObjectType type; - _err = kOk; - _err_context = ""; + err_ = kOk; + err_context_ = ""; // branches for 'if' ret = preprocess(); if (ret != kOk) { // free allocated for (Object* o : *this) delete o; - _local_heap.clear(); + local_heap_.clear(); return ret; } @@ -248,7 +248,7 @@ RetValue program::run() { Keyword* k = reinterpret_cast(o); // call the matching function (this->*(k->fn))(); - switch (_err) { + switch (err_) { // no pb -> go on case kOk: break; @@ -262,10 +262,10 @@ RetValue program::run() { go_out = true; // test error: make rpn return EXIT_FAILURE - if (_err == kTestFailed) ret = kTestFailed; + if (err_ == kTestFailed) ret = kTestFailed; // error: show it - if (show_error(_err, _err_context) == kDeadlyError) + if (show_error(err_, err_context_) == kDeadlyError) // pb showing error -> go out software ret = kGoodbye; break; @@ -284,7 +284,7 @@ RetValue program::run() { i++; // meaning 'next command' break; case kRtError: // runtime error - (void)show_error(_err, _err_context); + (void)show_error(err_, err_context_); go_out = true; break; default: @@ -297,7 +297,7 @@ RetValue program::run() { default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - _stack.push_front(o->clone()); + stack_.push_front(o->clone()); i++; break; } @@ -305,7 +305,7 @@ RetValue program::run() { // free allocated for (Object* o : *this) delete o; - _local_heap.clear(); + local_heap_.clear(); return ret; } @@ -571,7 +571,7 @@ RetValue program::parse(string& entry) { // prepare map for finding reserved keywords if (keywords_map.empty()) - for (auto& kw : _keywords) + for (auto& kw : keywords_) if (!kw.name.empty()) keywords_map[kw.name] = {kw.type, kw.fn}; // separate the entry string @@ -580,16 +580,16 @@ RetValue program::parse(string& entry) { for (Lexer::SynElement& element : elements) { switch (element.type) { case kNumber: - push_back(new Number(*element.re, element.reBase)); + push_back(new Number(*element.re, element.re_base)); break; case kComplex: - push_back(new Complex(*element.re, *element.im, element.reBase, element.imBase)); + push_back(new Complex(*element.re, *element.im, element.re_base, element.im_base)); break; case kString: push_back(new String(element.value)); break; case kSymbol: - push_back(new Symbol(element.value, element.autoEval)); + push_back(new Symbol(element.value, element.auto_eval)); break; case kProgram: push_back(new Program(element.value)); @@ -632,8 +632,8 @@ RetValue program::show_error() { {kBadValue, "bad value"}, {kTestFailed, "test failed"} }; // clang-format on - cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl; - switch (_err) { + cerr << err_context_ << ": error " << err_ << ": " << errorStrings[err_] << endl; + switch (err_) { case kInternalError: case kDeadlyError: ret = kDeadlyError; @@ -652,8 +652,8 @@ RetValue program::show_error() { /// RetValue program::show_error(RetValue err, string& context) { // record error - _err = err; - _err_context = context; + err_ = err; + err_context_ = context; return show_error(); } @@ -665,8 +665,8 @@ RetValue program::show_error(RetValue err, string& context) { /// RetValue program::show_error(RetValue err, const char* context) { // record error - _err = err; - _err_context = context; + err_ = err; + err_context_ = context; return show_error(); } @@ -678,8 +678,8 @@ RetValue program::show_error(RetValue err, const char* context) { /// void program::show_syntax_error(const char* context) { // record error - _err = kSyntaxError; - _err_context = context; + err_ = kSyntaxError; + err_context_ = context; (void)show_error(); } @@ -687,7 +687,7 @@ void program::show_syntax_error(const char* context) { /// /// @return RetValue see this type /// -RetValue program::get_err(void) { return _err; } +RetValue program::get_err(void) { return err_; } /// @brief show a stack (show its different objects) /// generally a stack is associated to a running program @@ -695,12 +695,12 @@ RetValue program::get_err(void) { return _err; } /// @param show_separator whether to show a stack level prefix or not /// void program::show_stack(bool show_separator) { - if (_stack.size() == 1) { - cout << _stack[0] << endl; + if (stack_.size() == 1) { + cout << stack_[0] << endl; } else { - for (int i = _stack.size() - 1; i >= 0; i--) { + for (int i = stack_.size() - 1; i >= 0; i--) { if (show_separator) cout << i + 1 << "> "; - cout << _stack[i] << endl; + cout << stack_[i] << endl; } } } @@ -709,9 +709,9 @@ void program::show_stack(bool show_separator) { /// void program::apply_default() { // default float precision, float mode - Number::s_mode = Number::DEFAULT_MODE; - Number::s_digits = Number::DEFAULT_DECIMAL_DIGITS; - mpreal::set_default_prec(Number::MPFR_DEFAULT_PREC_BITS); + Number::mode = Number::DEFAULT_MODE; + Number::digits = Number::kDefaultDecimalDigits; + mpreal::set_default_prec(Number::kMpfrDefaultPrecBits); static mp_rnd_t def_rnd = mpreal::get_default_rnd(); mpreal::set_default_rnd(def_rnd); diff --git a/src/program.hpp b/src/program.hpp index 6a7b3da..b3dab55 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -21,9 +21,10 @@ using mpfr::mpreal; //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque, public Lexer { public: - program(rpnstack& stk, heap& hp, program* parent = nullptr) : _stack(stk), _heap(hp), _parent(parent) {} + program(rpnstack& stack__, heap& heap__, program* parent__ = nullptr) + : stack_(stack__), heap_(heap__), parent_(parent__) {} virtual ~program() { - _local_heap.clear(); + local_heap_.clear(); clear(); } @@ -50,20 +51,20 @@ class program : public deque, public Lexer { private: // current error and its context - RetValue _err; - string _err_context; + RetValue err_; + string err_context_; // global stack holding results for user - rpnstack& _stack; + rpnstack& stack_; // global heap (sto, rcl) - heap& _heap; + heap& heap_; // local heap for local loop variables (for..next) - heap _local_heap; + heap local_heap_; // parent prog for inheriting heaps - program* _parent; + program* parent_; private: // keywords @@ -73,7 +74,7 @@ class program : public deque, public Lexer { program_fn_t fn; string comment; }; - static vector _keywords; + static vector keywords_; // keywords implementation //// @@ -252,38 +253,38 @@ class program : public deque, public Lexer { #define setErrorContext(err) \ do { \ - _err = (err); \ - _err_context = __FUNCTION__; \ + err_ = (err); \ + err_context_ = __FUNCTION__; \ } while (0) #define MIN_ARGUMENTS(num) \ do { \ - if ((num) >= 0 && _stack.size() < (num)) { \ - setErrorContext(kMissingOperand); \ + if ((num) >= 0 && stack_.size() < (num)) { \ + setErrorContext(kMissingOperand); \ return; \ } \ } while (0) #define MIN_ARGUMENTS_RET(num, ret) \ do { \ - if ((num) >= 0 && _stack.size() < (num)) { \ - setErrorContext(kMissingOperand); \ + if ((num) >= 0 && stack_.size() < (num)) { \ + setErrorContext(kMissingOperand); \ return (ret); \ } \ } while (0) #define ARG_MUST_BE_OF_TYPE(num, type) \ do { \ - if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ - setErrorContext(kBadOperandType); \ + if ((num) >= 0 && stack_.at(num)->_type != (type)) { \ + setErrorContext(kBadOperandType); \ return; \ } \ } while (0) #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ do { \ - if ((num) >= 0 && _stack.at(num)->_type != (type)) { \ - setErrorContext(kBadOperandType); \ + if ((num) >= 0 && stack_.at(num)->_type != (type)) { \ + setErrorContext(kBadOperandType); \ return (ret); \ } \ } while (0) diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index 7d12d9b..efab5dc 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -14,11 +14,11 @@ size_t program::rpn_if(Branch& myobj) { MIN_ARGUMENTS_RET(1, kRtError); ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); - if (_stack.value(0) != 0) + if (stack_.value(0) != 0) myobj.arg1 = 1; else myobj.arg1 = 0; - _stack.pop(); + stack_.pop(); return kStepOut; } @@ -89,8 +89,8 @@ size_t program::rpn_end(Branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); // check arg - if (_stack.value(0) == 0) ret = myobj.arg1; - _stack.pop(); + if (stack_.value(0) == 0) ret = myobj.arg1; + stack_.pop(); } else if (myobj.arg2 != kStepOut) { // arg2 = index of while+1 in case of while..repeat..end ret = myobj.arg2; @@ -136,10 +136,10 @@ void program::rpn_ift(void) { // check ift arg // arg is true if Number != 0 or if is nan or +/-inf - if (_stack.value(1) != 0) - _stack.erase(1); + if (stack_.value(1) != 0) + stack_.erase(1); else - _stack.erase(0, 2); + stack_.erase(0, 2); } /// @brief ifte keyword (branch) implementation @@ -154,12 +154,12 @@ void program::rpn_ifte(void) { ARG_MUST_BE_OF_TYPE(2, kNumber); // check ifte arg - if (_stack.value(2) != 0) { - _stack.erase(2); - _stack.pop(); + if (stack_.value(2) != 0) { + stack_.erase(2); + stack_.pop(); } else { - _stack.erase(2); - _stack.erase(1); + stack_.erase(2); + stack_.erase(1); } } @@ -190,8 +190,8 @@ size_t program::rpn_repeat(Branch& myobj) { // check arg // myobj.arg1 is end+1 - if (_stack.value(0) == 0) ret = myobj.arg1; - _stack.pop(); + if (stack_.value(0) == 0) ret = myobj.arg1; + stack_.pop(); return ret; } @@ -211,12 +211,12 @@ size_t program::rpn_start(Branch& myobj) { ARG_MUST_BE_OF_TYPE_RET(1, kNumber, kRtError); // loop boundaries - myobj.firstIndex = _stack.value(1); - myobj.lastIndex = _stack.value(0); - _stack.erase(0, 2); + myobj.first_index = stack_.value(1); + myobj.last_index = stack_.value(0); + stack_.erase(0, 2); // test value - if (myobj.firstIndex > myobj.lastIndex) + if (myobj.first_index > myobj.last_index) // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' @@ -247,27 +247,27 @@ size_t program::rpn_for(Branch& myobj) { sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index // loop boundaries - myobj.firstIndex = _stack.value(1); - myobj.lastIndex = _stack.value(0); + myobj.first_index = stack_.value(1); + myobj.last_index = stack_.value(0); // test value - if (myobj.firstIndex > myobj.lastIndex) { + if (myobj.first_index > myobj.last_index) { // last boundary lower than first boundary // -> next command shall be after 'next' // arg2 holds index of 'next' ret = myobj.arg2 + 1; } else { // store symbol with first value - auto it = _local_heap.find(sym->value); - if (it != _local_heap.end()) { + auto it = local_heap_.find(sym->value); + if (it != local_heap_.end()) { delete it->second; - _local_heap.erase(it); + local_heap_.erase(it); } - _local_heap[sym->value] = _stack.obj(1).clone(); + local_heap_[sym->value] = stack_.obj(1).clone(); ret = myobj.arg1 + 1; } - _stack.erase(0, 2); + stack_.erase(0, 2); return ret; } @@ -281,7 +281,7 @@ size_t program::rpn_for(Branch& myobj) { /// size_t program::rpn_next(Branch& myobj) { // arg1 = loop variable index - // firstIndex = current point in the loop + // first_index = current point in the loop Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { setErrorContext(kMissingOperand); @@ -290,12 +290,12 @@ size_t program::rpn_next(Branch& myobj) { start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; - myobj.firstIndex = start_or_for->firstIndex; + myobj.first_index = start_or_for->first_index; } // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), mpreal(1).mpfr_srcptr(), MPFR_RNDD); + mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), mpreal(1).mpfr_srcptr(), MPFR_RNDD); // for command: increment symbol too if (start_or_for->arg1 != -1) { @@ -308,11 +308,11 @@ size_t program::rpn_next(Branch& myobj) { var = reinterpret_cast(at(start_or_for->arg1)); // store symbol variable (asserted existing in the local heap) - reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(local_heap_[var->value])->value = myobj.first_index; } // test value - if (myobj.firstIndex > start_or_for->lastIndex) { + if (myobj.first_index > start_or_for->last_index) { // end of loop myobj.arg_bool = false; // init again next time return kStepOut; @@ -337,15 +337,15 @@ size_t program::rpn_step(Branch& myobj) { MIN_ARGUMENTS_RET(1, kRtError); ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); - mpreal step = _stack.value(0); - _stack.pop(); + mpreal step = stack_.value(0); + stack_.pop(); // end of loop if step is negative or zero if (step <= 0) { ret = kStepOut; } else { // arg1 = loop variable index - // firstIndex = current count + // first_index = current count Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { setErrorContext(kMissingOperand); @@ -354,12 +354,12 @@ size_t program::rpn_step(Branch& myobj) { start_or_for = reinterpret_cast(at(myobj.arg1)); if (!myobj.arg_bool) { myobj.arg_bool = true; - myobj.firstIndex = start_or_for->firstIndex; + myobj.first_index = start_or_for->first_index; } // increment then test // carefull: round toward minus infinity to avoid missing last boundary (because growing step) - mpfr_add(myobj.firstIndex.mpfr_ptr(), myobj.firstIndex.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD); + mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD); if (start_or_for->arg1 != -1) { Object* obj; @@ -372,11 +372,11 @@ size_t program::rpn_step(Branch& myobj) { } var = reinterpret_cast(at(start_or_for->arg1)); // increase symbol variable - reinterpret_cast(_local_heap[var->value])->value = myobj.firstIndex; + reinterpret_cast(local_heap_[var->value])->value = myobj.first_index; } // test loop value is out of range - if (myobj.firstIndex > start_or_for->lastIndex) { + if (myobj.first_index > start_or_for->last_index) { // end of loop myobj.arg_bool = false; // init again next time ret = kStepOut; diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index b46716f..e3c24c2 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -8,8 +8,8 @@ void program::rpn_re() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.push_front(new Number(real(_stack.value(0)))); - _stack.erase(1); + stack_.push_front(new Number(real(stack_.value(0)))); + stack_.erase(1); } /// @brief im keyword implementation @@ -18,8 +18,8 @@ void program::rpn_re() { void program::rpn_im() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.push_front(new Number(imag(_stack.value(0)))); - _stack.erase(1); + stack_.push_front(new Number(imag(stack_.value(0)))); + stack_.erase(1); } /// @brief arg keyword implementation @@ -28,8 +28,8 @@ void program::rpn_im() { void program::rpn_arg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.push_front(new Number(arg(_stack.value(0)))); - _stack.erase(1); + stack_.push_front(new Number(arg(stack_.value(0)))); + stack_.erase(1); } /// @brief conj keyword implementation @@ -38,7 +38,7 @@ void program::rpn_arg() { void program::rpn_conj() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.value(0) = conj(_stack.value(0)); + stack_.value(0) = conj(stack_.value(0)); } /// @brief r2c keyword implementation @@ -48,8 +48,8 @@ void program::rpn_r2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.push(new Complex(_stack.value(1), _stack.value(0), _stack.obj(1).reBase, _stack.obj(0).reBase)); - _stack.erase(1, 2); + stack_.push(new Complex(stack_.value(1), stack_.value(0), stack_.obj(1).re_base, stack_.obj(0).re_base)); + stack_.erase(1, 2); } /// @brief c2r keyword implementation @@ -58,9 +58,9 @@ void program::rpn_r2c() { void program::rpn_c2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.push(new Number(real(_stack.value(0)), _stack.obj(0).reBase)); - _stack.push(new Number(imag(_stack.value(1)), _stack.obj(1).imBase)); - _stack.erase(2); + stack_.push(new Number(real(stack_.value(0)), stack_.obj(0).re_base)); + stack_.push(new Number(imag(stack_.value(1)), stack_.obj(1).im_base)); + stack_.erase(2); } /// @brief r2p keyword implementation @@ -69,10 +69,10 @@ void program::rpn_c2r() { void program::rpn_r2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - mpreal rho = abs(_stack.value(0)); - mpreal theta = arg(_stack.value(0)); - _stack.value(0).real(rho); - _stack.value(0).imag(theta); + mpreal rho = abs(stack_.value(0)); + mpreal theta = arg(stack_.value(0)); + stack_.value(0).real(rho); + stack_.value(0).imag(theta); } /// @brief p2r keyword implementation @@ -81,5 +81,5 @@ void program::rpn_r2p() { void program::rpn_p2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); - _stack.value(0) = polar(abs(_stack.value(0)), arg(_stack.value(0))); + stack_.value(0) = polar(abs(stack_.value(0)), arg(stack_.value(0))); } diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index f7d51b5..23e44d2 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -57,7 +57,7 @@ void program::rpn_help() { // keywords unsigned int i = 0; - for (auto& kw : _keywords) + for (auto& kw : keywords_) if (!kw.comment.empty()) { // titles in bold if (kw.type == kUndef) cout << ATTR_BOLD; @@ -69,7 +69,7 @@ void program::rpn_help() { // show mode cout << "Current float mode is "; - switch (Number::s_mode) { + switch (Number::mode) { case Number::kStd: cout << "'std'"; break; @@ -85,7 +85,7 @@ void program::rpn_help() { } // bits precision, decimal digits and rounding mode - cout << " with " << Number::s_digits << " digits after the decimal point" << endl; + cout << " with " << Number::digits << " digits after the decimal point" << endl; cout << "Current floating point precision is " << static_cast(mpreal::get_default_prec()) << " bits" << endl; vector> rnd{MPFR_ROUND}; for (auto& rn : rnd) @@ -110,13 +110,13 @@ void program::rpn_std() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(stack_.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::kStd; - Number::s_digits = digits; - _stack.pop(); + Number::mode = Number::kStd; + Number::digits = digits; + stack_.pop(); } else { setErrorContext(kOutOfRange); } @@ -128,13 +128,13 @@ void program::rpn_fix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(stack_.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::kFix; - Number::s_digits = digits; - _stack.pop(); + Number::mode = Number::kFix; + Number::digits = digits; + stack_.pop(); } else { setErrorContext(kOutOfRange); } @@ -146,13 +146,13 @@ void program::rpn_sci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int digits = static_cast(_stack.value(0).toLong()); + int digits = static_cast(stack_.value(0).toLong()); if (check_decimal_digits(digits)) { // set mode, decimal digits and print format - Number::s_mode = Number::kSci; - Number::s_digits = digits; - _stack.pop(); + Number::mode = Number::kSci; + Number::digits = digits; + stack_.pop(); } else { setErrorContext(kOutOfRange); } @@ -160,11 +160,11 @@ void program::rpn_sci() { /// @brief _version keyword implementation /// -void program::rpn_version() { _stack.push_front(new String(RPN_VERSION)); } +void program::rpn_version() { stack_.push_front(new String(RPN_VERSION)); } /// @brief _uname keyword implementation /// -void program::rpn_uname() { _stack.push_front(new String(RPN_UNAME)); } +void program::rpn_uname() { stack_.push_front(new String(RPN_UNAME)); } /// @brief history keyword implementation /// @@ -183,8 +183,8 @@ void program::rpn_history() { /// void program::rpn_type() { MIN_ARGUMENTS(1); - _stack.push(new String(_stack.at(0)->name())); - _stack.erase(1); + stack_.push(new String(stack_.at(0)->name())); + stack_.erase(1); } /// @brief default keyword implementation @@ -198,16 +198,16 @@ void program::rpn_precision() { ARG_MUST_BE_OF_TYPE(0, kNumber); // set precision - int prec = static_cast(_stack.value(0).toLong()); + int prec = static_cast(stack_.value(0).toLong()); if (prec >= MPFR_PREC_MIN && prec <= MPFR_PREC_MAX) { mpreal::set_default_prec(prec); // modify digits seen by user if std mode - if (Number::s_mode == Number::kStd) { + if (Number::mode == Number::kStd) { // calc max nb of digits user can see with the current bit precision - Number::s_digits = mpfr::bits2digits(mpreal::get_default_prec()); + Number::digits = mpfr::bits2digits(mpreal::get_default_prec()); } - _stack.pop(); + stack_.pop(); } else { setErrorContext(kOutOfRange); } @@ -221,10 +221,10 @@ void program::rpn_round() { map matchRound{MPFR_ROUND}; - auto found = matchRound.find(_stack.value(0)); + auto found = matchRound.find(stack_.value(0)); if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else setErrorContext(kOutOfRange); - _stack.pop(); + stack_.pop(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 2c5796a..224ec5b 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -4,16 +4,16 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { _stack.push(new Number(mpfr::const_euler())); } +void program::rpn_e(void) { stack_.push(new Number(mpfr::const_euler())); } /// @brief log10 keyword implementation /// void program::rpn_log10() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = log10(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = log10(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = log10(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = log10(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -22,10 +22,10 @@ void program::rpn_log10() { /// void program::rpn_alog10() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = exp(log(mpreal(10)) * _stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = exp(log(mpreal(10)) * stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = exp(log(mpreal(10)) * stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -34,10 +34,10 @@ void program::rpn_alog10() { /// void program::rpn_log2() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); - else if (_stack.type(0) == kComplex) - _stack.value(0) = log(_stack.value(0)) / mpfr::const_log2(); + if (stack_.type(0) == kNumber) + stack_.value(0) = log(stack_.value(0)) / mpfr::const_log2(); + else if (stack_.type(0) == kComplex) + stack_.value(0) = log(stack_.value(0)) / mpfr::const_log2(); else setErrorContext(kBadOperandType); } @@ -46,10 +46,10 @@ void program::rpn_log2() { /// void program::rpn_alog2() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = exp(mpfr::const_log2() * _stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = exp(mpfr::const_log2() * stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = exp(mpfr::const_log2() * stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -58,10 +58,10 @@ void program::rpn_alog2() { /// void program::rpn_ln() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = log(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = log(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = log(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = log(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -70,10 +70,10 @@ void program::rpn_ln() { /// void program::rpn_exp() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = exp(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = exp(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = exp(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = exp(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -82,10 +82,10 @@ void program::rpn_exp() { /// void program::rpn_expm() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = exp(_stack.value(0)) - mpreal(1); - else if (_stack.type(0) == kComplex) - _stack.value(0) = exp(_stack.value(0)) - mpreal(1); + if (stack_.type(0) == kNumber) + stack_.value(0) = exp(stack_.value(0)) - mpreal(1); + else if (stack_.type(0) == kComplex) + stack_.value(0) = exp(stack_.value(0)) - mpreal(1); else setErrorContext(kBadOperandType); } @@ -94,10 +94,10 @@ void program::rpn_expm() { /// void program::rpn_lnp1() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = log(_stack.value(0) + 1); - else if (_stack.type(0) == kComplex) - _stack.value(0) = log(_stack.value(0) + mpreal(1)); + if (stack_.type(0) == kNumber) + stack_.value(0) = log(stack_.value(0) + 1); + else if (stack_.type(0) == kComplex) + stack_.value(0) = log(stack_.value(0) + mpreal(1)); else setErrorContext(kBadOperandType); } @@ -106,10 +106,10 @@ void program::rpn_lnp1() { /// void program::rpn_sinh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = sinh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = sinh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = sinh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = sinh(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -118,10 +118,10 @@ void program::rpn_sinh() { /// void program::rpn_asinh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = asinh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = asinh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = asinh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = asinh(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -130,10 +130,10 @@ void program::rpn_asinh() { /// void program::rpn_cosh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = cosh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = cosh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = cosh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = cosh(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -142,10 +142,10 @@ void program::rpn_cosh() { /// void program::rpn_acosh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = acosh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = acosh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = acosh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = acosh(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -154,10 +154,10 @@ void program::rpn_acosh() { /// void program::rpn_tanh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = tanh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = tanh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = tanh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = tanh(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -166,10 +166,10 @@ void program::rpn_tanh() { /// void program::rpn_atanh() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = atanh(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = atanh(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = atanh(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = atanh(stack_.value(0)); else setErrorContext(kBadOperandType); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index b7afa8e..93e1ab0 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -11,20 +11,20 @@ /// bool program::find_variable(string& variable, Object*& obj) { bool found = false; - program* parent = _parent; + program* parent = parent_; - if (_local_heap.get(variable, obj)) { + if (local_heap_.get(variable, obj)) { found = true; } else { while (parent != nullptr) { - if (parent->_local_heap.get(variable, obj)) { + if (parent->local_heap_.get(variable, obj)) { found = true; break; } - parent = parent->_parent; + parent = parent->parent_; } if (!found) { - if (_heap.get(variable, obj)) found = true; + if (heap_.get(variable, obj)) found = true; } } @@ -38,29 +38,29 @@ void program::rpn_eval(void) { string prog_text; MIN_ARGUMENTS(1); - if (_stack.type(0) == kSymbol) { + if (stack_.type(0) == kSymbol) { // recall a variable Object* obj; - string variable(_stack.value(0)); - _stack.pop(); + string variable(stack_.value(0)); + stack_.pop(); // if variable holds a program, run this program if (find_variable(variable, obj)) { if (obj->_type == kProgram) { - prog_text = _stack.value(0); - _stack.pop(); + prog_text = stack_.value(0); + stack_.pop(); run_prog = true; } else { - // else recall this variable (i.e. stack its content) - _stack.push_front(obj); + // else recall this variable (i.e. stack_ its content) + stack_.push_front(obj); } } else { setErrorContext(kUnknownVariable); } - } else if (_stack.type(0) == kProgram) { + } else if (stack_.type(0) == kProgram) { // eval a program - prog_text = _stack.value(0); - _stack.pop(); + prog_text = stack_.value(0); + stack_.pop(); run_prog = true; } else { setErrorContext(kBadOperandType); @@ -68,7 +68,7 @@ void program::rpn_eval(void) { // run prog if any if (run_prog) { - program prog(_stack, _heap, this); + program prog(stack_, heap_, this); // make program from entry if (prog.parse(prog_text) == kOk) { @@ -105,7 +105,7 @@ int program::rpn_inprog(Branch& inprog_obj) { } else { // found something other than symbol setErrorContext(kBadOperandType); - show_error(_err, context); + show_error(err_, context); return -1; } } @@ -113,33 +113,33 @@ int program::rpn_inprog(Branch& inprog_obj) { // found 0 symbols if (count_symbols == 0) { setErrorContext(kSyntaxError); - show_error(_err, context); + show_error(err_, context); return -1; } // is missing if (!prog_found) { setErrorContext(kSyntaxError); - show_error(_err, context); + show_error(err_, context); return -1; } - // check symbols Number vs stack size - if (_stack.size() < count_symbols) { + // check symbols Number vs stack_ size + if (stack_.size() < count_symbols) { setErrorContext(kMissingOperand); - show_error(_err, context); + show_error(err_, context); return -1; } // load variables for (unsigned int i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) { - _local_heap[reinterpret_cast(at(i))->value] = _stack.at(0)->clone(); - _stack.pop(); + local_heap_[reinterpret_cast(at(i))->value] = stack_.at(0)->clone(); + stack_.pop(); } // run the program string& entry = reinterpret_cast(at(inprog_obj.arg1 + count_symbols + 1))->value; - program prog(_stack, _heap, this); + program prog(stack_, heap_, this); // make the program from entry if (prog.parse(entry) == kOk) { diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 5f59bd3..17b0eef 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -6,22 +6,22 @@ /// void program::rpn_plus() { MIN_ARGUMENTS(2); - if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.value(1) += _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.value(1) += _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.value(1) += _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { - _stack.value(1) += _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { + if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.value(1) += stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.value(1) += stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.value(1) += stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) { + stack_.value(1) += stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { rpn_swap(); - _stack.value(1) += _stack.value(0); - _stack.pop(); + stack_.value(1) += stack_.value(0); + stack_.pop(); } else { setErrorContext(kBadOperandType); } @@ -31,19 +31,19 @@ void program::rpn_plus() { /// void program::rpn_minus() { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.value(1) -= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.value(1) -= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { - _stack.value(1) -= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.value(1) -= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.value(1) -= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) { + stack_.value(1) -= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { rpn_swap(); - _stack.value(1) = _stack.value(0) - _stack.value(1); - _stack.pop(); + stack_.value(1) = stack_.value(0) - stack_.value(1); + stack_.pop(); } else { setErrorContext(kBadOperandType); } @@ -53,19 +53,19 @@ void program::rpn_minus() { /// void program::rpn_mul() { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.value(1) *= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.value(1) *= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { - _stack.value(1) *= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.value(1) *= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.value(1) *= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) { + stack_.value(1) *= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { rpn_swap(); - _stack.value(1) *= _stack.value(0); - _stack.pop(); + stack_.value(1) *= stack_.value(0); + stack_.pop(); } else { setErrorContext(kBadOperandType); } @@ -75,19 +75,19 @@ void program::rpn_mul() { /// void program::rpn_div() { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.value(1) /= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.value(1) /= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { - _stack.value(1) /= _stack.value(0); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.value(1) /= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.value(1) /= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) { + stack_.value(1) /= stack_.value(0); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { rpn_swap(); - _stack.value(1) = _stack.value(0) / _stack.value(1); - _stack.pop(); + stack_.value(1) = stack_.value(0) / stack_.value(1); + stack_.pop(); } else { setErrorContext(kBadOperandType); } @@ -97,10 +97,10 @@ void program::rpn_div() { /// void program::rpn_neg() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = -_stack.value(0); - else if (_stack.type(0) == kComplex) - _stack.value(0) = -_stack.value(0); + if (stack_.type(0) == kNumber) + stack_.value(0) = -stack_.value(0); + else if (stack_.type(0) == kComplex) + stack_.value(0) = -stack_.value(0); else setErrorContext(kBadOperandType); } @@ -109,10 +109,10 @@ void program::rpn_neg() { /// void program::rpn_inv() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = 1 / _stack.value(0); - else if (_stack.type(0) == kComplex) - _stack.value(0) = mpreal(1) / _stack.value(0); + if (stack_.type(0) == kNumber) + stack_.value(0) = 1 / stack_.value(0); + else if (stack_.type(0) == kComplex) + stack_.value(0) = mpreal(1) / stack_.value(0); else setErrorContext(kBadOperandType); } @@ -121,26 +121,26 @@ void program::rpn_inv() { /// void program::rpn_power() { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - if (_stack.value(1) >= 0) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); - _stack.pop(); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + if (stack_.value(1) >= 0) { + stack_.value(1) = pow(stack_.value(1), stack_.value(0)); + stack_.pop(); } else { mpreal zero; - _stack.push(new Complex(_stack.value(1), zero, _stack.obj(1).base)); - _stack.value(0) = pow(_stack.value(0), _stack.value(1)); - _stack.erase(1, 2); + stack_.push(new Complex(stack_.value(1), zero, stack_.obj(1).base)); + stack_.value(0) = pow(stack_.value(0), stack_.value(1)); + stack_.erase(1, 2); } - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); - _stack.pop(); - } else if (_stack.type(0) == kNumber && _stack.type(1) == kComplex) { - _stack.value(1) = pow(_stack.value(1), _stack.value(0)); - _stack.pop(); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kNumber) { + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.value(1) = pow(stack_.value(1), stack_.value(0)); + stack_.pop(); + } else if (stack_.type(0) == kNumber && stack_.type(1) == kComplex) { + stack_.value(1) = pow(stack_.value(1), stack_.value(0)); + stack_.pop(); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { rpn_swap(); - _stack.value(1) = pow(_stack.value(0), _stack.value(1)); - _stack.pop(); + stack_.value(1) = pow(stack_.value(0), stack_.value(1)); + stack_.pop(); } else { setErrorContext(kBadOperandType); } @@ -150,19 +150,19 @@ void program::rpn_power() { /// void program::rpn_squareroot() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) { - if (_stack.value(0) >= 0) { - _stack.value(0) = sqrt(_stack.value(0)); + if (stack_.type(0) == kNumber) { + if (stack_.value(0) >= 0) { + stack_.value(0) = sqrt(stack_.value(0)); } else { // negative number -> square root is complex mpreal zero; - _stack.push(new Complex(_stack.value(0), zero, - _stack.obj(0).base)); // TODO(louis) manage new errors - _stack.value(0) = sqrt(_stack.value(0)); - _stack.erase(1); + stack_.push(new Complex(stack_.value(0), zero, + stack_.obj(0).base)); // TODO(louis) manage new errors + stack_.value(0) = sqrt(stack_.value(0)); + stack_.erase(1); } - } else if (_stack.type(0) == kComplex) { - _stack.value(0) = sqrt(_stack.value(0)); + } else if (stack_.type(0) == kComplex) { + stack_.value(0) = sqrt(stack_.value(0)); } else { setErrorContext(kBadOperandType); } @@ -172,11 +172,11 @@ void program::rpn_squareroot() { /// void program::rpn_hex() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) { - _stack.obj(0).base = 16; - } else if (_stack.type(0) == kComplex) { - _stack.obj(0).reBase = 16; - _stack.obj(0).imBase = 16; + if (stack_.type(0) == kNumber) { + stack_.obj(0).base = 16; + } else if (stack_.type(0) == kComplex) { + stack_.obj(0).re_base = 16; + stack_.obj(0).im_base = 16; } else { setErrorContext(kBadOperandType); } @@ -186,11 +186,11 @@ void program::rpn_hex() { /// void program::rpn_bin() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) { - _stack.obj(0).base = 2; - } else if (_stack.type(0) == kComplex) { - _stack.obj(0).reBase = 2; - _stack.obj(0).imBase = 2; + if (stack_.type(0) == kNumber) { + stack_.obj(0).base = 2; + } else if (stack_.type(0) == kComplex) { + stack_.obj(0).re_base = 2; + stack_.obj(0).im_base = 2; } else { setErrorContext(kBadOperandType); } @@ -200,11 +200,11 @@ void program::rpn_bin() { /// void program::rpn_dec() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) { - _stack.obj(0).base = 10; - } else if (_stack.type(0) == kComplex) { - _stack.obj(0).reBase = 10; - _stack.obj(0).imBase = 10; + if (stack_.type(0) == kNumber) { + stack_.obj(0).base = 10; + } else if (stack_.type(0) == kComplex) { + stack_.obj(0).re_base = 10; + stack_.obj(0).im_base = 10; } else { setErrorContext(kBadOperandType); } @@ -214,15 +214,15 @@ void program::rpn_dec() { /// void program::rpn_base() { MIN_ARGUMENTS(2); - if (_stack.type(1) == kNumber || _stack.type(1) == kComplex) { - int base = static_cast(_stack.value(0).toLong()); - _stack.pop(); + if (stack_.type(1) == kNumber || stack_.type(1) == kComplex) { + int base = static_cast(stack_.value(0).toLong()); + stack_.pop(); if (base >= 2 && base <= 62) { - if (_stack.type(0) == kNumber) { - _stack.obj(0).base = base; + if (stack_.type(0) == kNumber) { + stack_.obj(0).base = base; } else { - _stack.obj(0).reBase = base; - _stack.obj(0).imBase = base; + stack_.obj(0).re_base = base; + stack_.obj(0).im_base = base; } } else { setErrorContext(kOutOfRange); @@ -238,8 +238,8 @@ void program::rpn_purcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.value(1) *= _stack.value(0) / 100; - _stack.pop(); + stack_.value(1) *= stack_.value(0) / 100; + stack_.pop(); } /// @brief %CH keyword implementation @@ -248,18 +248,18 @@ void program::rpn_purcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.value(1) = (_stack.value(0) * 100) / _stack.value(1); - _stack.pop(); + stack_.value(1) = (stack_.value(0) * 100) / stack_.value(1); + stack_.pop(); } /// @brief sq keyword implementation /// void program::rpn_square() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) *= _stack.value(0); - else if (_stack.at(0)->_type == kComplex) - _stack.value(0) *= _stack.value(0); + if (stack_.type(0) == kNumber) + stack_.value(0) *= stack_.value(0); + else if (stack_.at(0)->_type == kComplex) + stack_.value(0) *= stack_.value(0); else setErrorContext(kBadOperandType); } @@ -270,19 +270,19 @@ void program::rpn_modulo() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.value(1) = fmod(_stack.value(1), _stack.value(0)); - _stack.pop(); + stack_.value(1) = fmod(stack_.value(1), stack_.value(0)); + stack_.pop(); } /// @brief abs keyword implementation /// void program::rpn_abs() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) { - _stack.value(0) = abs(_stack.value(0)); - } else if (_stack.type(0) == kComplex) { - _stack.push(new Number(abs(_stack.value(0)))); - _stack.erase(1); + if (stack_.type(0) == kNumber) { + stack_.value(0) = abs(stack_.value(0)); + } else if (stack_.type(0) == kComplex) { + stack_.push(new Number(abs(stack_.value(0)))); + stack_.erase(1); } else { setErrorContext(kBadOperandType); } @@ -294,17 +294,17 @@ void program::rpn_fact() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); // fact(n) = gamma(n+1) - _stack.value(0) = gamma(_stack.value(0) + 1); + stack_.value(0) = gamma(stack_.value(0) + 1); } /// @brief sign keyword implementation /// void program::rpn_sign() { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = sgn(_stack.value(0)); - else if (_stack.at(0)->_type == kComplex) - _stack.value(0) = _stack.value(0) / abs(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = sgn(stack_.value(0)); + else if (stack_.at(0)->_type == kComplex) + stack_.value(0) = stack_.value(0) / abs(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -314,12 +314,12 @@ void program::rpn_sign() { void program::rpn_mant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - if (!isfinite(_stack.value(0))) { + if (!isfinite(stack_.value(0))) { setErrorContext(kOutOfRange); return; } mp_exp_t exp; - _stack.value(0) = frexp(_stack.value(0), &exp); + stack_.value(0) = frexp(stack_.value(0), &exp); } /// @brief xpon keyword implementation @@ -327,13 +327,13 @@ void program::rpn_mant() { void program::rpn_xpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - if (!isfinite(_stack.value(0))) { + if (!isfinite(stack_.value(0))) { setErrorContext(kOutOfRange); return; } mp_exp_t exp; - (void)frexp(_stack.value(0), &exp); - _stack.value(0) = exp; + (void)frexp(stack_.value(0), &exp); + stack_.value(0) = exp; } /// @brief floor keyword implementation @@ -341,7 +341,7 @@ void program::rpn_xpon() { void program::rpn_floor() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) = floor(_stack.value(0)); + stack_.value(0) = floor(stack_.value(0)); } /// @brief ceil keyword implementation @@ -349,7 +349,7 @@ void program::rpn_floor() { void program::rpn_ceil() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) = ceil(_stack.value(0)); + stack_.value(0) = ceil(stack_.value(0)); } /// @brief fp keyword implementation @@ -357,7 +357,7 @@ void program::rpn_ceil() { void program::rpn_fp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) = frac(_stack.value(0)); + stack_.value(0) = frac(stack_.value(0)); } /// @brief ip keyword implementation @@ -365,7 +365,7 @@ void program::rpn_fp() { void program::rpn_ip() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) = trunc(_stack.value(0)); + stack_.value(0) = trunc(stack_.value(0)); } /// @brief min keyword implementation @@ -374,8 +374,8 @@ void program::rpn_min() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.value(0) = min(_stack.value(0), _stack.value(1)); - _stack.erase(1); + stack_.value(0) = min(stack_.value(0), stack_.value(1)); + stack_.erase(1); } /// @brief max keyword implementation @@ -384,6 +384,6 @@ void program::rpn_max() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - _stack.value(0) = max(_stack.value(0), _stack.value(1)); - _stack.erase(1); + stack_.value(0) = max(stack_.value(0), stack_.value(1)); + stack_.erase(1); } diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 63cedbf..66e2247 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -6,23 +6,23 @@ /// void program::rpn_swap(void) { MIN_ARGUMENTS(2); - Object* tmp = _stack.front(); - _stack.erase(0, 1, false); - _stack.insert(_stack.begin() + 1, tmp); + Object* tmp = stack_.front(); + stack_.erase(0, 1, false); + stack_.insert(stack_.begin() + 1, tmp); } /// @brief drop keyword implementation /// void program::rpn_drop(void) { MIN_ARGUMENTS(1); - _stack.pop(); + stack_.pop(); } /// @brief drop2 keyword implementation /// void program::rpn_drop2(void) { MIN_ARGUMENTS(2); - _stack.erase(0, 2); + stack_.erase(0, 2); } /// @brief dropn keyword implementation @@ -31,20 +31,20 @@ void program::rpn_dropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int args = static_cast(_stack.value(0).toLong()); + int args = static_cast(stack_.value(0).toLong()); MIN_ARGUMENTS(args + 1); - _stack.erase(0, args + 1); + stack_.erase(0, args + 1); } /// @brief erase / del keyword implementation /// -void program::rpn_erase(void) { _stack.erase(0, _stack.size()); } +void program::rpn_erase(void) { stack_.erase(0, stack_.size()); } /// @brief dup keyword implementation /// void program::rpn_dup(void) { MIN_ARGUMENTS(1); - _stack.push_front(_stack.at(0)->clone()); + stack_.push_front(stack_.at(0)->clone()); } /// @brief dupn keyword implementation @@ -53,19 +53,19 @@ void program::rpn_dupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int args = static_cast(_stack.value(0).toLong()); - _stack.pop(); + int args = static_cast(stack_.value(0).toLong()); + stack_.pop(); MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) _stack.push_front(_stack.at(args - 1)->clone()); + for (int i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->clone()); } /// @brief dup2 keyword implementation /// void program::rpn_dup2(void) { MIN_ARGUMENTS(2); - _stack.push_front(_stack.at(1)->clone()); - _stack.push_front(_stack.at(1)->clone()); + stack_.push_front(stack_.at(1)->clone()); + stack_.push_front(stack_.at(1)->clone()); } /// @brief pick keyword implementation @@ -74,30 +74,30 @@ void program::rpn_pick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int to_pick = static_cast(_stack.value(0).toLong()); - _stack.pop(); + int to_pick = static_cast(stack_.value(0).toLong()); + stack_.pop(); - // treat stack depth errors - if ((to_pick == 0) || (to_pick > _stack.size())) { + // treat stack_ depth errors + if ((to_pick == 0) || (to_pick > stack_.size())) { setErrorContext(kOutOfRange); return; } - _stack.push_front(_stack.at(to_pick - 1)->clone()); + stack_.push_front(stack_.at(to_pick - 1)->clone()); } /// @brief rot keyword implementation /// void program::rpn_rot(void) { MIN_ARGUMENTS(3); - Object* tmp = _stack.at(2); - _stack.erase(2, 1, false); - _stack.insert(_stack.begin(), tmp); + Object* tmp = stack_.at(2); + stack_.erase(2, 1, false); + stack_.insert(stack_.begin(), tmp); } /// @brief depth keyword implementation /// -void program::rpn_depth(void) { _stack.push_front(new Number(_stack.size())); } +void program::rpn_depth(void) { stack_.push_front(new Number(stack_.size())); } /// @brief roll keyword implementation /// @@ -105,13 +105,13 @@ void program::rpn_roll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - int args = static_cast(_stack.value(0).toLong()); - _stack.pop(); + int args = static_cast(stack_.value(0).toLong()); + stack_.pop(); MIN_ARGUMENTS(args); - Object* tmp = _stack.at(args - 1); - _stack.erase(args - 1, 1, false); - _stack.insert(_stack.begin(), tmp); + Object* tmp = stack_.at(args - 1); + stack_.erase(args - 1, 1, false); + stack_.insert(stack_.begin(), tmp); } /// @brief rolld keyword implementation @@ -120,18 +120,18 @@ void program::rpn_rolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); - int args = static_cast(_stack.value(0).toLong()); - _stack.pop(); + int args = static_cast(stack_.value(0).toLong()); + stack_.pop(); MIN_ARGUMENTS(args); - Object* tmp = _stack.at(0); - _stack.erase(0, 1, false); - _stack.insert(_stack.begin() + args - 1, tmp); + Object* tmp = stack_.at(0); + stack_.erase(0, 1, false); + stack_.insert(stack_.begin() + args - 1, tmp); } /// @brief over keyword implementation /// void program::rpn_over(void) { MIN_ARGUMENTS(2); - _stack.push_front(_stack.at(1)->clone()); + stack_.push_front(stack_.at(1)->clone()); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index 6d3e6d7..c9ea63d 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -10,13 +10,13 @@ void program::rpn_sto(void) { ARG_MUST_BE_OF_TYPE(0, kSymbol); // store symbol with first value - const auto it = _heap.find(_stack.value(0)); - if (it != _heap.end()) { + const auto it = heap_.find(stack_.value(0)); + if (it != heap_.end()) { delete it->second; - _heap.erase(it); + heap_.erase(it); } - _heap[_stack.value(0)] = _stack.at(1)->clone(); - _stack.erase(0, 2); + heap_[stack_.value(0)] = stack_.at(1)->clone(); + stack_.erase(0, 2); } /// @brief sto+ keyword implementation @@ -24,7 +24,7 @@ void program::rpn_sto(void) { void program::rpn_stoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -41,7 +41,7 @@ void program::rpn_stoadd(void) { void program::rpn_stosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -58,7 +58,7 @@ void program::rpn_stosub(void) { void program::rpn_stomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -75,7 +75,7 @@ void program::rpn_stomul(void) { void program::rpn_stodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -92,7 +92,7 @@ void program::rpn_stodiv(void) { void program::rpn_stoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -108,7 +108,7 @@ void program::rpn_stoneg(void) { void program::rpn_stoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); - if (_heap.find(_stack.value(0)) == _heap.end()) { + if (heap_.find(stack_.value(0)) == heap_.end()) { setErrorContext(kUnknownVariable); return; } @@ -127,12 +127,12 @@ void program::rpn_rcl(void) { // recall a variable Object* obj; - string variable(_stack.value(0)); + string variable(stack_.value(0)); // mind the order of heaps if (find_variable(variable, obj)) { - (void)_stack.pop(); - _stack.push_front(obj->clone()); + (void)stack_.pop(); + stack_.push_front(obj->clone()); } else { setErrorContext(kUnknownVariable); } @@ -145,9 +145,9 @@ void program::rpn_edit(void) { ostringstream st; - // re-write stack objet in a stream - _stack.at(0)->show(st); - _stack.pop(); + // re-write stack_ objet in a stream + stack_.at(0)->show(st); + stack_.pop(); // set it as the linenoise line entry Input::preload(st.str().c_str()); @@ -158,19 +158,19 @@ void program::rpn_edit(void) { /// @param symb the smlbol to recall and autoeval /// void program::auto_rcl(Symbol* symb) { - if (symb->autoEval) { + if (symb->auto_eval) { Object* obj; string variable(symb->value); // mind the order of heaps if (find_variable(variable, obj)) { - _stack.push_front(obj->clone()); + stack_.push_front(obj->clone()); if (obj->_type == kProgram) rpn_eval(); } else { - _stack.push_front(symb->clone()); + stack_.push_front(symb->clone()); } } else { - _stack.push_front(symb->clone()); + stack_.push_front(symb->clone()); } } @@ -180,46 +180,46 @@ void program::rpn_purge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); - const auto i = _heap.find(_stack.value(0)); - if (i != _heap.end()) { + const auto i = heap_.find(stack_.value(0)); + if (i != heap_.end()) { delete i->second; - _heap.erase(i); + heap_.erase(i); } else { setErrorContext(kUnknownVariable); } - _stack.pop(); + stack_.pop(); } /// @brief vars keyword implementation /// void program::rpn_vars(void) { Object* obj; - program* parent = _parent; + program* parent = parent_; string name; int index = 1; // heap variables - for (auto i : _heap) { + for (auto i : heap_) { cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; i.second->show(cout) << endl; } // local variables - for (auto i : _local_heap) { + for (auto i : local_heap_) { cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; i.second->show(cout) << endl; } // parents local variables while (parent != nullptr) { - for (auto i : parent->_local_heap) { + for (auto i : parent->local_heap_) { cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; obj->show(cout) << endl; } - parent = parent->_parent; + parent = parent->parent_; } } /// @brief clusr keyword implementation /// -void program::rpn_clusr(void) { _heap.clear(); } +void program::rpn_clusr(void) { heap_.clear(); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 6412c8a..4908265 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -10,11 +10,11 @@ void program::rpn_instr() { MIN_ARGUMENTS(1); // stringify only if not already a string - if (_stack.type(0) != kString) { + if (stack_.type(0) != kString) { stringstream ss; - ss << _stack.at(0); - _stack.pop(); - _stack.push(new String(ss.str())); + ss << stack_.at(0); + stack_.pop(); + stack_.push(new String(ss.str())); } } @@ -24,11 +24,11 @@ void program::rpn_strout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); - string entry(_stack.value(0)); - program prog(_stack, _heap); - _stack.pop(); + string entry(stack_.value(0)); + program prog(stack_, heap_); + stack_.pop(); - // make program from string in stack level 1 + // make program from string in stack_ level 1 if (prog.parse(entry) == kOk) // run it prog.run(); @@ -39,10 +39,10 @@ void program::rpn_strout() { void program::rpn_chr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - char the_chr = static_cast(_stack.value(0).toLong()); - _stack.pop(); + char the_chr = static_cast(stack_.value(0).toLong()); + stack_.pop(); if (the_chr < 32 || the_chr > 126) the_chr = '.'; - _stack.push_front(new String(string(1, the_chr))); + stack_.push_front(new String(string(1, the_chr))); } /// @brief num keyword implementation @@ -50,11 +50,11 @@ void program::rpn_chr() { void program::rpn_num() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); - if (_stack.value(0).size() > 0) - _stack.push_front(new Number(_stack.value(0)[0])); + if (stack_.value(0).size() > 0) + stack_.push_front(new Number(stack_.value(0)[0])); else - _stack.push_front(new Number(0)); - _stack.erase(1); + stack_.push_front(new Number(0)); + stack_.erase(1); } /// @brief size keyword implementation @@ -62,8 +62,8 @@ void program::rpn_num() { void program::rpn_strsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); - _stack.push_front(new Number(_stack.value(0).size())); - _stack.erase(1); + stack_.push_front(new Number(stack_.value(0).size())); + stack_.erase(1); } /// @brief pos keyword implementation @@ -73,9 +73,9 @@ void program::rpn_strpos() { ARG_MUST_BE_OF_TYPE(0, kString); ARG_MUST_BE_OF_TYPE(1, kString); - size_t pos = _stack.value(1).find(_stack.value(0)) + 1; - _stack.erase(0, 2); - _stack.push_front(new Number(pos)); + size_t pos = stack_.value(1).find(stack_.value(0)) + 1; + stack_.erase(0, 2); + stack_.push_front(new Number(pos)); } /// @brief sub keyword implementation @@ -86,11 +86,11 @@ void program::rpn_strsub() { ARG_MUST_BE_OF_TYPE(1, kNumber); ARG_MUST_BE_OF_TYPE(2, kString); - size_t first = _stack.value(1).toULong(); - size_t len = _stack.value(0).toULong() - first + 1; + size_t first = stack_.value(1).toULong(); + size_t len = stack_.value(0).toULong() - first + 1; first--; - if (first > _stack.value(2).size()) first = len = 0; - _stack.push(new String(_stack.value(2).substr(first, len))); - _stack.erase(1, 3); + if (first > stack_.value(2).size()) first = len = 0; + stack_.push(new String(stack_.value(2).substr(first, len))); + stack_.erase(1, 3); } diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index eaad02c..d2a91bb 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -76,16 +76,16 @@ void program::rpn_test() { int total_steps = 0; int total_steps_failed = 0; - string test_filename = _stack.value(0); - _stack.pop(); + string test_filename = stack_.value(0); + stack_.pop(); cout << endl << "rpn version is " << RPN_VERSION << endl; test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); testShowResult("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); // notify to caller that test succeeded or not if (total_tests_failed > 0) { - _err = kTestFailed; - _err_context = string("rpn version ") + RPN_VERSION + ", test file " + test_filename; + err_ = kTestFailed; + err_context_ = string("rpn version ") + RPN_VERSION + ", test file " + test_filename; } } diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 06dac2e..57df584 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -2,13 +2,13 @@ #include "program.hpp" -/// @brief compared 2 strings on top of the stack +/// @brief compared 2 strings on top of the stack_ /// /// @return 0 strings are equal /// @return !0 strings are not equal (see strcmp output) /// static int CmpStringOnStackTop(rpnstack& stk) { - // _stack should have 2 strings at level 1 and 2 + // stack_ should have 2 strings at level 1 and 2 // this function removes these 2 entries int res = stk.value(1).compare(stk.value(0)); stk.erase(0, 2); @@ -19,12 +19,12 @@ static int CmpStringOnStackTop(rpnstack& stk) { /// void program::rpn_sup(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) > _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 1)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) > stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) == 1)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -34,12 +34,12 @@ void program::rpn_sup(void) { /// void program::rpn_sup_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) >= _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) != -1)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) >= stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) != -1)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -50,12 +50,12 @@ void program::rpn_sup_eq(void) { void program::rpn_inf(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) < _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) == -1)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) < stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) == -1)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -65,12 +65,12 @@ void program::rpn_inf(void) { /// void program::rpn_inf_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) <= _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 1)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) <= stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) != 1)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -80,15 +80,15 @@ void program::rpn_inf_eq(void) { /// void program::rpn_diff(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.push_front(new Number(_stack.value(1) != _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) != 0)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) != stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.push_front(new Number(stack_.value(1) != stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) != 0)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -98,15 +98,15 @@ void program::rpn_diff(void) { /// void program::rpn_eq(void) { MIN_ARGUMENTS(2); - if (_stack.type(0) == kNumber && _stack.type(1) == kNumber) { - _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kComplex && _stack.type(1) == kComplex) { - _stack.push_front(new Number(_stack.value(1) == _stack.value(0))); - _stack.erase(1, 2); - } else if (_stack.type(0) == kString && _stack.type(1) == kString) { - _stack.push_front(new Number(CmpStringOnStackTop(_stack) == 0)); - _stack.erase(1, 2); + if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { + stack_.push_front(new Number(stack_.value(1) == stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kComplex && stack_.type(1) == kComplex) { + stack_.push_front(new Number(stack_.value(1) == stack_.value(0))); + stack_.erase(1, 2); + } else if (stack_.type(0) == kString && stack_.type(1) == kString) { + stack_.push_front(new Number(CmpStringOnStackTop(stack_) == 0)); + stack_.erase(1, 2); } else { setErrorContext(kBadOperandType); } @@ -118,11 +118,11 @@ void program::rpn_test_and(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - if (_stack.value(0) != 0 && _stack.value(1) != 0) - _stack.push(new Number(1)); + if (stack_.value(0) != 0 && stack_.value(1) != 0) + stack_.push(new Number(1)); else - _stack.push(new Number(0)); - _stack.erase(1, 2); + stack_.push(new Number(0)); + stack_.erase(1, 2); } /// @brief or keyword implementation @@ -131,11 +131,11 @@ void program::rpn_test_or(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - if (_stack.value(0) != 0 || _stack.value(1) != 0) - _stack.push(new Number(1)); + if (stack_.value(0) != 0 || stack_.value(1) != 0) + stack_.push(new Number(1)); else - _stack.push(new Number(0)); - _stack.erase(1, 2); + stack_.push(new Number(0)); + stack_.erase(1, 2); } /// @brief xor keyword implementation @@ -144,11 +144,11 @@ void program::rpn_test_xor(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); - if (_stack.value(0) != 0 ^ _stack.value(1) != 0) - _stack.push(new Number(1)); + if (stack_.value(0) != 0 ^ stack_.value(1) != 0) + stack_.push(new Number(1)); else - _stack.push(new Number(0)); - _stack.erase(1, 2); + stack_.push(new Number(0)); + stack_.erase(1, 2); } /// @brief not keyword implementation @@ -157,8 +157,8 @@ void program::rpn_test_not(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.push(new Number(_stack.value(0) == 0 ? 1 : 0)); - _stack.erase(1, 1); + stack_.push(new Number(stack_.value(0) == 0 ? 1 : 0)); + stack_.erase(1, 1); } /// @brief test same implementation diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index d97956a..3a8cb1f 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -22,8 +22,8 @@ void program::rpn_time() { // push it // division after push for real precision - _stack.push(new Number(date)); - _stack.value(0) /= 10000000000.0; + stack_.push(new Number(date)); + stack_.value(0) /= 10000000000.0; } else { setErrorContext(kInternalError); } @@ -48,8 +48,8 @@ void program::rpn_date() { // push it Number* num; // division after push for real precision - _stack.push(new Number(date)); - _stack.value(0) /= 1000000.0; + stack_.push(new Number(date)); + stack_.value(0) /= 1000000.0; } else { setErrorContext(kInternalError); } @@ -69,7 +69,7 @@ void program::rpn_ticks() { if (tm != nullptr) { // date in µs date = 1000000.0 * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec / 1000); - _stack.push(new Number(date)); + stack_.push(new Number(date)); } else { setErrorContext(kInternalError); } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 8af66a1..61c7da8 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -5,7 +5,7 @@ /// @brief pi keyword implementation /// void program::rpn_pi(void) { - _stack.push_front(new Number(mpfr::const_pi())); + stack_.push_front(new Number(mpfr::const_pi())); } /// @brief d->r keyword implementation @@ -13,8 +13,8 @@ void program::rpn_pi(void) { void program::rpn_d2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) *= mpfr::const_pi(); - _stack.value(0) /= 180; + stack_.value(0) *= mpfr::const_pi(); + stack_.value(0) /= 180; } /// @brief r->d keyword implementation @@ -22,18 +22,18 @@ void program::rpn_d2r(void) { void program::rpn_r2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); - _stack.value(0) /= mpfr::const_pi(); - _stack.value(0) *= 180; + stack_.value(0) /= mpfr::const_pi(); + stack_.value(0) *= 180; } /// @brief sin keyword implementation /// void program::rpn_sin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = sin(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = sin(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = sin(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = sin(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -42,10 +42,10 @@ void program::rpn_sin(void) { /// void program::rpn_asin(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = asin(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = asin(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = asin(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = asin(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -54,10 +54,10 @@ void program::rpn_asin(void) { /// void program::rpn_cos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = cos(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = cos(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = cos(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = cos(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -66,10 +66,10 @@ void program::rpn_cos(void) { /// void program::rpn_acos(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = acos(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = acos(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = acos(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = acos(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -78,10 +78,10 @@ void program::rpn_acos(void) { /// void program::rpn_tan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = tan(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = tan(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = tan(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = tan(stack_.value(0)); else setErrorContext(kBadOperandType); } @@ -90,10 +90,10 @@ void program::rpn_tan(void) { /// void program::rpn_atan(void) { MIN_ARGUMENTS(1); - if (_stack.type(0) == kNumber) - _stack.value(0) = atan(_stack.value(0)); - else if (_stack.type(0) == kComplex) - _stack.value(0) = atan(_stack.value(0)); + if (stack_.type(0) == kNumber) + stack_.value(0) = atan(stack_.value(0)); + else if (stack_.type(0) == kComplex) + stack_.value(0) = atan(stack_.value(0)); else setErrorContext(kBadOperandType); } From b7774f20d979c2c42e6f7484074375a2fa62c789 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 15:32:36 +0100 Subject: [PATCH 44/57] method names --- Changelog.md | 9 +- src/input.cpp | 6 +- src/input.hpp | 7 +- src/lexer.cpp | 50 ++--- src/lexer.hpp | 30 ++- src/main.cpp | 18 +- src/mpreal-out.hpp | 3 +- src/object.cpp | 2 +- src/object.hpp | 67 +++---- src/program.cpp | 384 ++++++++++++++++++------------------- src/program.hpp | 313 +++++++++++++++--------------- src/rpn-branch.cpp | 44 ++--- src/rpn-complex.cpp | 16 +- src/rpn-general.cpp | 42 ++-- src/rpn-logs.cpp | 58 +++--- src/rpn-program.cpp | 40 ++-- src/rpn-real.cpp | 100 +++++----- src/rpn-stack.cpp | 42 ++-- src/rpn-store.cpp | 142 +++++++------- src/rpn-string.cpp | 18 +- src/rpn-test-framework.cpp | 32 ++-- src/rpn-test.cpp | 34 ++-- src/rpn-time.cpp | 12 +- src/rpn-trig.cpp | 30 +-- src/stack.hpp | 4 +- 25 files changed, 741 insertions(+), 762 deletions(-) diff --git a/Changelog.md b/Changelog.md index 30360a0..18bc9a7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -21,14 +21,7 @@ Changelog - cpplint used with a CPPLINT.cfg removing some warnings - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap -- it seems cosh was giving sinh (!) - -grosse perte en performances (!) -- v2.3.2 fibo: 0,01s user 0,01s system 97% cpu 0,017 total -- v3.0.0 fibo: 2,60s user 0,00s system 99% cpu 2,611 total -- facteur 150 environ -cf https://gmplib.org/manual/Custom-Allocation -cf https://www.geeksforgeeks.org/overloading-new-delete-operator-c/ +- error string are slightly different, althought error codes are still the same New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid diff --git a/src/input.cpp b/src/input.cpp index a272f16..7c84f5b 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -15,7 +15,7 @@ Input::Input(string& entry, vector& autocompletion_list, string prompt, ac_list_ = &autocompletion_list; // linenoise for entry - linenoiseSetCompletionCallback(entry_completion_generator); + linenoiseSetCompletionCallback(EntryCompletionGenerator); while (status == InputStatus::kContinue) { // get user entry if (multiline) @@ -53,7 +53,7 @@ Input::Input(string& entry, vector& autocompletion_list, string prompt, /// @param text the text after wich the user entered TAB /// @param lc the completion object to add strings with linenoiseAddCompletion() /// -void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) { +void Input::EntryCompletionGenerator(const char* text, linenoiseCompletions* lc) { if (Input::ac_list_ == nullptr || text == nullptr) return; int text_len = strnlen(text, 6); @@ -68,6 +68,6 @@ void Input::entry_completion_generator(const char* text, linenoiseCompletions* l if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str()); } -void Input::preload(const char* preloadText) { +void Input::Preload(const char* preloadText) { if (preloadText != nullptr) linenoisePreloadBuffer(preloadText); } diff --git a/src/input.hpp b/src/input.hpp index 896749c..171775b 100644 --- a/src/input.hpp +++ b/src/input.hpp @@ -6,8 +6,7 @@ #include #include #include -using std::string; -using std::vector; +using std::string, std::vector; #include "linenoise.h" @@ -16,10 +15,10 @@ class Input { Input(string& entry, vector& autocompletion_list, string prompt = "rpn> ", string multiline_prompt = ">"); enum class InputStatus { kOk, kContinue, kAbort, kCtrlc, kError } status; - static void preload(const char* preloadText); + static void Preload(const char* preloadText); private: - static void entry_completion_generator(const char* text, linenoiseCompletions* lc); + static void EntryCompletionGenerator(const char* text, linenoiseCompletions* lc); static vector* ac_list_; }; diff --git a/src/lexer.cpp b/src/lexer.cpp index 7479504..98b4ab8 100644 --- a/src/lexer.cpp +++ b/src/lexer.cpp @@ -2,7 +2,7 @@ #include "lexer.hpp" -bool Lexer::lexer(string& entry, map& keywords, vector& elements, +bool Lexer::Analyse(string& entry, map& keywords, vector& elements, vector& errors) { size_t jump; for (size_t i = 0; i < entry.size(); i++) { @@ -10,31 +10,31 @@ bool Lexer::lexer(string& entry, map& keywords, vector& keywords, vector& errors, +bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry[0] is at least '"' for (size_t i = idx + 1; i < entry.size(); i++) { @@ -66,7 +66,7 @@ bool Lexer::parseString(string& entry, size_t idx, size_t& next_idx, vector& errors, +bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry[0] is at least '\'' for (size_t i = idx + 1; i < entry.size(); i++) { @@ -81,7 +81,7 @@ bool Lexer::parseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, +bool Lexer::ParseProgram(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { // here we are sure that entry is at least "<<" // find last ">>" or "»" @@ -92,7 +92,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector' && entry[i + 1] == '>') || (entry.substr(i, 2) == "»")) { if (countNested == 0) { string prg = entry.substr(idx + 2, i - idx - 2); - trim(prg); + Trim(prg); elements.push_back({kProgram, .value = prg}); next_idx = i + 2; return true; @@ -102,13 +102,13 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector 62) return false; if (numberIdx != 0) token = token.substr(numberIdx); *r = new mpreal; @@ -180,11 +180,11 @@ bool Lexer::getNumberAt(string& entry, size_t idx, size_t& next_idx, int& base, return false; } -bool Lexer::parseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, +bool Lexer::ParseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { mpreal* r = nullptr; int base = 10; - if (getNumberAt(entry, idx, next_idx, base, &r)) { + if (GetNUmberAt(entry, idx, next_idx, base, &r)) { elements.push_back({kNumber, .re = r, .re_base = base}); return true; } else { @@ -193,7 +193,7 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, +bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements) { mpreal* re = nullptr; mpreal* im = nullptr; @@ -203,7 +203,7 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& next_idx, vector& elements, +bool Lexer::ParseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements, map& keywords) { stringstream ss(entry.substr(idx)); string token; @@ -245,7 +245,7 @@ bool Lexer::parseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements) { +bool Lexer::ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector& elements) { stringstream ss(entry.substr(idx)); string token; ss >> token; diff --git a/src/lexer.hpp b/src/lexer.hpp index c921537..532ee23 100644 --- a/src/lexer.hpp +++ b/src/lexer.hpp @@ -7,11 +7,9 @@ using mpfr::mpreal; #include -#include #include -using std::map; -using std::string; -using std::vector; +#include +using std::map, std::string, std::vector; #include "object.hpp" @@ -49,27 +47,27 @@ class Lexer { /// @param[in] keywords reserved keywords /// @return false=errors, the lexer must stop /// - bool lexer(string& entry, map& keywords, vector& elements, - vector& errors); + bool Analyse(string& entry, map& keywords, vector& elements, + vector& errors); private: - bool parseString(string& entry, size_t idx, size_t& next_idx, vector& errors, + bool ParseString(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, + bool ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseProgram(string& entry, size_t idx, size_t& next_idx, vector& errors, + bool ParseProgram(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, + bool ParseNumber(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseComplex(string& entry, size_t idx, size_t& next_idx, vector& errors, + bool ParseComplex(string& entry, size_t idx, size_t& next_idx, vector& errors, vector& elements); - bool parseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements, + bool ParseReserved(string& entry, size_t idx, size_t& next_idx, vector& elements, map& keywords); - bool parseUnknown(string& entry, size_t idx, size_t& next_idx, vector& elements); + bool ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector& elements); - void trim(string& s); - int getBaseAt(string& entry, size_t& next_idx, bool& positive); - bool getNumberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim = ' '); + void Trim(string& s); + int GetBaseAt(string& entry, size_t& next_idx, bool& positive); + bool GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim = ' '); }; #endif // SRC_LEXER_HPP_ diff --git a/src/main.cpp b/src/main.cpp index 8179141..9f5d2b5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -18,7 +18,7 @@ static void ExitInteractive() { struct passwd* pw = getpwuid(getuid()); if (pw != nullptr) { stringstream history_path; - history_path << pw->pw_dir << "/.rpn_history"; + history_path << pw->pw_dir << "/.RpnHistory"; // trunc current history ofstream history(history_path.str(), ios_base::out | ios_base::trunc); @@ -38,7 +38,7 @@ static void EnterInteractive() { struct passwd* pw = getpwuid(getuid()); if (pw != nullptr) { stringstream history_path; - history_path << pw->pw_dir << "/.rpn_history"; + history_path << pw->pw_dir << "/.RpnHistory"; // don't care about errors linenoiseHistorySetMaxLen(100); @@ -78,7 +78,7 @@ int main(int argc, char* argv[]) { bool go_on = true; // apply default configuration - program::apply_default(); + program::ApplyDefault(); // run with interactive prompt if (argc == 1) { @@ -93,15 +93,15 @@ int main(int argc, char* argv[]) { // make program from interactive entry program prog(stack, heap); string entry; - switch (Input(entry, program::getAutocompletionWords()).status) { + switch (Input(entry, program::GetAutocompletionWords()).status) { case Input::InputStatus::kOk: // user could stop prog with CtrlC CatchSignals(&prog); // run it - if (prog.parse(entry) == kOk && prog.run() == kGoodbye) + if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye) go_on = false; else - prog.show_stack(); + prog.ShowStack(); break; case Input::InputStatus::kCtrlc: go_on = false; @@ -124,14 +124,14 @@ int main(int argc, char* argv[]) { for (i = 1; i < argc; i++) entry += string(argv[i]) + ' '; // make program - ret = prog.parse(entry); + ret = prog.Parse(entry); if (ret == kOk) { // user could stop prog with CtrlC CatchSignals(&prog); // run it - ret = prog.run(); - prog.show_stack(false); + ret = prog.Run(); + prog.ShowStack(false); } } diff --git a/src/mpreal-out.hpp b/src/mpreal-out.hpp index ddab132..a830da6 100644 --- a/src/mpreal-out.hpp +++ b/src/mpreal-out.hpp @@ -8,8 +8,7 @@ using mpfr::mpreal; #include #include -using std::string; -using std::ostream; +using std::string, std::ostream; ostream& MprealOutput10Base(ostream& out, const string& fmt, const mpreal& value); ostream& MprealOutputNBase(ostream& out, int base, const mpreal& value); diff --git a/src/object.cpp b/src/object.cpp index 43ba057..840266e 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -3,5 +3,5 @@ #include "object.hpp" // number statics -Number::mode_enum Number::mode = Number::DEFAULT_MODE; +Number::mode_enum Number::mode = Number::kDefaultMode; int Number::digits = kDefaultDecimalDigits; diff --git a/src/object.hpp b/src/object.hpp index 760b9c0..68eff2e 100644 --- a/src/object.hpp +++ b/src/object.hpp @@ -10,10 +10,7 @@ using mpfr::mpreal; #include #include #include -using std::complex; -using std::ostream; -using std::string; -using std::stringstream; +using std::complex, std::ostream, std::string, std::stringstream; #include "mpreal-out.hpp" @@ -63,20 +60,18 @@ struct Object { explicit Object(ObjectType type = kUndef) : _type(type) {} virtual ~Object() {} ObjectType _type; - virtual Object* clone() { + virtual Object* Clone() { Object* o = new Object(); if (o != nullptr) *o = *this; return o; } - virtual string name() { return string("Object"); } - virtual ostream& show(ostream& out) { - out << "(" << name() << " - unknown representation)"; + virtual string Name() { return string("Object"); } + virtual ostream& Show(ostream& out) { + out << "(" << Name() << " - unknown representation)"; return out; } - friend ostream& operator<<(ostream& os, Object* o) { return o->show(os); } - - unsigned int size() { return sizeof(*this); } + friend ostream& operator<<(ostream& os, Object* o) { return o->Show(os); } }; /// @brief stack objects derived from Object @@ -89,14 +84,14 @@ struct Number : Object { int base; mpreal value; - virtual Object* clone() { return new Number(value, base); } - virtual string name() { return string("number"); } - virtual ostream& show(ostream& out) { return showValue(out, value, mode, digits, base); } + virtual Object* Clone() { return new Number(value, base); } + virtual string Name() { return string("number"); } + virtual ostream& Show(ostream& out) { return ShowValue(out, value, mode, digits, base); } // representation mode typedef enum { kStd, kFix, kSci } mode_enum; static mode_enum mode; - static constexpr mode_enum DEFAULT_MODE = Number::kStd; + static constexpr mode_enum kDefaultMode = Number::kStd; // precision static constexpr mpfr_prec_t kMpfrDefaultPrecBits = 128; @@ -104,7 +99,7 @@ struct Number : Object { static int digits; // clang-format off - static string _makeNumberFormat(mode_enum mode, int digits) { + static string MakeNumberFormat(mode_enum mode, int digits) { stringstream format; format << "%." << digits; switch ( mode ) { @@ -116,9 +111,9 @@ struct Number : Object { } // clang-format on - static ostream& showValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base) { + static ostream& ShowValue(ostream& out, const mpreal& value, mode_enum mode, int digits, int base) { if (base == 10) - return MprealOutput10Base(out, _makeNumberFormat(mode, digits), value); + return MprealOutput10Base(out, MakeNumberFormat(mode, digits), value); else return MprealOutputNBase(out, base, value); } @@ -141,13 +136,13 @@ struct Complex : Object { int re_base, im_base; complex value; - virtual Object* clone() { return new Complex(value, re_base, im_base); } - virtual string name() { return string("complex"); } - virtual ostream& show(ostream& out) { + virtual Object* Clone() { return new Complex(value, re_base, im_base); } + virtual string Name() { return string("complex"); } + virtual ostream& Show(ostream& out) { out << '('; - Number::showValue(out, value.real(), Number::mode, Number::digits, re_base); + Number::ShowValue(out, value.real(), Number::mode, Number::digits, re_base); out << ','; - Number::showValue(out, value.imag(), Number::mode, Number::digits, im_base); + Number::ShowValue(out, value.imag(), Number::mode, Number::digits, im_base); return out << ')'; } }; @@ -155,18 +150,18 @@ struct Complex : Object { struct String : Object { String() : Object(kString) {} explicit String(const string& value__) : Object(kString), value(value__) {} - virtual Object* clone() { return new String(value); } - virtual string name() { return string("string"); } - virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; } + virtual Object* Clone() { return new String(value); } + virtual string Name() { return string("string"); } + virtual ostream& Show(ostream& out) { return out << "\"" << value << "\""; } string value; }; struct Program : Object { Program() : Object(kProgram) {} explicit Program(const string& value__) : Object(kProgram), value(value__) {} - virtual Object* clone() { return new Program(value); } - virtual string name() { return string("program"); } - virtual ostream& show(ostream& out) { return out << "«" << value << "»"; } + virtual Object* Clone() { return new Program(value); } + virtual string Name() { return string("program"); } + virtual ostream& Show(ostream& out) { return out << "«" << value << "»"; } string value; }; @@ -174,9 +169,9 @@ struct Symbol : Object { explicit Symbol(bool auto_eval__ = true) : Object(kSymbol), auto_eval(auto_eval__) {} explicit Symbol(const string& value__, bool auto_eval__ = true) : Object(kSymbol), value(value__), auto_eval(auto_eval__) {} - virtual Object* clone() { return new Symbol(value, auto_eval); } - virtual string name() { return string("symbol"); } - virtual ostream& show(ostream& out) { return out << "'" << value << "'"; } + virtual Object* Clone() { return new Symbol(value, auto_eval); } + virtual string Name() { return string("symbol"); } + virtual ostream& Show(ostream& out) { return out << "'" << value << "'"; } bool auto_eval; string value; }; @@ -184,8 +179,8 @@ struct Symbol : Object { struct Keyword : Object { Keyword() : Object(kKeyword) {} explicit Keyword(program_fn_t fn__, const string& value__) : Object(kKeyword), fn(fn__), value(value__) {} - virtual Object* clone() { return new Keyword(fn, value); } - virtual string name() { return string("keyword"); } + virtual Object* Clone() { return new Keyword(fn, value); } + virtual string Name() { return string("keyword"); } program_fn_t fn; string value; }; @@ -208,8 +203,8 @@ struct Branch : Object { arg_bool = other.arg_bool; value = other.value; } - virtual Object* clone() { return new Branch(*this); } - virtual string name() { return string("branch"); } + virtual Object* Clone() { return new Branch(*this); } + virtual string Name() { return string("branch"); } branch_fn_t fn; size_t arg1, arg2, arg3; mpreal first_index, last_index; diff --git a/src/program.cpp b/src/program.cpp index 30c9550..0276800 100644 --- a/src/program.cpp +++ b/src/program.cpp @@ -6,205 +6,205 @@ vector program::keywords_{ // GENERAL {kUndef, "", nullptr, "\nGENERAL"}, - {kKeyword, "nop", &program::rpn_nop, "no operation"}, - {kKeyword, "help", &program::rpn_help, "this help message"}, - {kKeyword, "h", &program::rpn_help, ""}, - {kKeyword, "?", &program::rpn_help, ""}, - {kKeyword, "quit", &program::rpn_good_bye, "quit software"}, - {kKeyword, "q", &program::rpn_good_bye, ""}, - {kKeyword, "exit", &program::rpn_good_bye, ""}, - {kKeyword, "test", &program::rpn_test, ""}, // not seen by user - {kKeyword, "version", &program::rpn_version, "show rpn version"}, - {kKeyword, "uname", &program::rpn_uname, "show rpn complete identification string"}, - {kKeyword, "history", &program::rpn_history, "see commands history"}, + {kKeyword, "nop", &program::RpnNop, "no operation"}, + {kKeyword, "help", &program::RpnHelp, "this help message"}, + {kKeyword, "h", &program::RpnHelp, ""}, + {kKeyword, "?", &program::RpnHelp, ""}, + {kKeyword, "quit", &program::RpnQuit, "quit software"}, + {kKeyword, "q", &program::RpnQuit, ""}, + {kKeyword, "exit", &program::RpnQuit, ""}, + {kKeyword, "test", &program::RpnTest, ""}, // not seen by user + {kKeyword, "version", &program::RpnVersion, "show rpn version"}, + {kKeyword, "uname", &program::RpnUname, "show rpn complete identification string"}, + {kKeyword, "history", &program::RpnHistory, "see commands history"}, // USUAL OPERATIONS ON REALS AND COMPLEXES {kUndef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"}, - {kKeyword, "+", &program::rpn_plus, "addition"}, - {kKeyword, "-", &program::rpn_minus, "substraction"}, - {kKeyword, "*", &program::rpn_mul, "multiplication"}, - {kKeyword, "/", &program::rpn_div, "division"}, - {kKeyword, "inv", &program::rpn_inv, "inverse"}, - {kKeyword, "chs", &program::rpn_neg, "negation"}, - {kKeyword, "neg", &program::rpn_neg, ""}, - {kKeyword, "^", &program::rpn_power, "power"}, - {kKeyword, "pow", &program::rpn_power, ""}, - {kKeyword, "sqrt", &program::rpn_squareroot, "rpn_square root"}, - {kKeyword, "sq", &program::rpn_square, "rpn_square"}, - {kKeyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"}, - {kKeyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"}, + {kKeyword, "+", &program::RpnPlus, "addition"}, + {kKeyword, "-", &program::RpnMinus, "substraction"}, + {kKeyword, "*", &program::RpnMul, "multiplication"}, + {kKeyword, "/", &program::RpnDiv, "division"}, + {kKeyword, "inv", &program::RpnInv, "inverse"}, + {kKeyword, "chs", &program::RpnNeg, "negation"}, + {kKeyword, "neg", &program::RpnNeg, ""}, + {kKeyword, "^", &program::RpnPower, "power"}, + {kKeyword, "pow", &program::RpnPower, ""}, + {kKeyword, "sqrt", &program::RpnSquareroot, "RpnSquare root"}, + {kKeyword, "sq", &program::RpnSquare, "RpnSquare"}, + {kKeyword, "abs", &program::RpnAbs, "absolute value (norm for a complex)"}, + {kKeyword, "sign", &program::RpnSign, "sign of a number or z/|z| for a complex"}, // OPERATIONS ON REALS {kUndef, "", nullptr, "\nOPERATIONS ON REALS"}, - {kKeyword, "%", &program::rpn_purcent, "purcent"}, - {kKeyword, "%CH", &program::rpn_purcentCH, "inverse purcent"}, - {kKeyword, "mod", &program::rpn_modulo, "modulo"}, - {kKeyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"}, - {kKeyword, "mant", &program::rpn_mant, "mantissa of a real number"}, - {kKeyword, "xpon", &program::rpn_xpon, "exponant of a real number"}, - {kKeyword, "floor", &program::rpn_floor, "largest number <="}, - {kKeyword, "ceil", &program::rpn_ceil, "smallest number >="}, - {kKeyword, "ip", &program::rpn_ip, "integer part"}, - {kKeyword, "fp", &program::rpn_fp, "fractional part"}, - {kKeyword, "min", &program::rpn_min, "min of 2 real numbers"}, - {kKeyword, "max", &program::rpn_max, "max of 2 real numbers"}, + {kKeyword, "%", &program::RpnPurcent, "purcent"}, + {kKeyword, "%CH", &program::RpnPurcentCH, "inverse purcent"}, + {kKeyword, "mod", &program::RpnModulo, "modulo"}, + {kKeyword, "fact", &program::RpnFact, "n! for integer n or Gamma(x+1) for fractional x"}, + {kKeyword, "mant", &program::RpnMant, "mantissa of a real number"}, + {kKeyword, "xpon", &program::RpnXpon, "exponant of a real number"}, + {kKeyword, "floor", &program::RpnFloor, "largest number <="}, + {kKeyword, "ceil", &program::RpnCeil, "smallest number >="}, + {kKeyword, "ip", &program::RpnIp, "integer part"}, + {kKeyword, "fp", &program::RpnFp, "fractional part"}, + {kKeyword, "min", &program::RpnMin, "min of 2 real numbers"}, + {kKeyword, "max", &program::RpnMax, "max of 2 real numbers"}, // OPERATIONS ON COMPLEXES {kUndef, "", nullptr, "\nOPERATIONS ON COMPLEXES"}, - {kKeyword, "re", &program::rpn_re, "complex real part"}, - {kKeyword, "im", &program::rpn_im, "complex imaginary part"}, - {kKeyword, "conj", &program::rpn_conj, "complex conjugate"}, - {kKeyword, "arg", &program::rpn_arg, "complex argument in radians"}, - {kKeyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"}, - {kKeyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"}, - {kKeyword, "p->r", &program::rpn_p2r, "cartesian to polar"}, - {kKeyword, "r->p", &program::rpn_r2p, "polar to cartesian"}, + {kKeyword, "re", &program::RpnReal, "complex real part"}, + {kKeyword, "im", &program::RpnImag, "complex imaginary part"}, + {kKeyword, "conj", &program::RpnConj, "complex conjugate"}, + {kKeyword, "arg", &program::RpnArg, "complex argument in radians"}, + {kKeyword, "c->r", &program::RpnC2r, "transform a complex in 2 reals"}, + {kKeyword, "r->c", &program::RpnR2c, "transform 2 reals in a complex"}, + {kKeyword, "p->r", &program::RpnP2r, "cartesian to polar"}, + {kKeyword, "r->p", &program::RpnR2p, "polar to cartesian"}, // MODE {kUndef, "", nullptr, "\nMODE"}, - {kKeyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"}, - {kKeyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"}, - {kKeyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"}, - {kKeyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec"}, - {kKeyword, "round", &program::rpn_round, + {kKeyword, "std", &program::RpnStd, "standard floating numbers representation. ex: std"}, + {kKeyword, "fix", &program::RpnFix, "fixed point representation. ex: 6 fix"}, + {kKeyword, "sci", &program::RpnSci, "scientific floating point representation. ex: 20 sci"}, + {kKeyword, "prec", &program::RpnPrecision, "set float precision in bits. ex: 256 prec"}, + {kKeyword, "round", &program::RpnRound, "set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward " "+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"] round"}, - {kKeyword, "default", &program::rpn_default, "set float representation and precision to default"}, - {kKeyword, "type", &program::rpn_type, "show type of stack first entry"}, - {kKeyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"}, - {kKeyword, "dec", &program::rpn_dec, "decimal representation, applies on stack level 0 only"}, - {kKeyword, "bin", &program::rpn_bin, "binary representation, applies on stack level 0 only"}, - {kKeyword, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"}, + {kKeyword, "default", &program::RpnDefault, "set float representation and precision to default"}, + {kKeyword, "type", &program::RpnType, "show type of stack first entry"}, + {kKeyword, "hex", &program::RpnHex, "hexadecimal representation, applies on stack level 0 only"}, + {kKeyword, "dec", &program::RpnDec, "decimal representation, applies on stack level 0 only"}, + {kKeyword, "bin", &program::RpnBin, "binary representation, applies on stack level 0 only"}, + {kKeyword, "base", &program::RpnBase, "arbitrary base representation, applies on stack level 0 only"}, // TESTS {kUndef, "", nullptr, "\nTEST"}, - {kKeyword, ">", &program::rpn_sup, "binary operator >"}, - {kKeyword, ">=", &program::rpn_sup_eq, "binary operator >="}, - {kKeyword, "<", &program::rpn_inf, "binary operator <"}, - {kKeyword, "<=", &program::rpn_inf_eq, "binary operator <="}, - {kKeyword, "!=", &program::rpn_diff, "binary operator != (different)"}, - {kKeyword, "==", &program::rpn_eq, "binary operator == (equal)"}, - {kKeyword, "and", &program::rpn_test_and, "boolean operator and"}, - {kKeyword, "or", &program::rpn_test_or, "boolean operator or"}, - {kKeyword, "xor", &program::rpn_test_xor, "boolean operator xor"}, - {kKeyword, "not", &program::rpn_test_not, "boolean operator not"}, - {kKeyword, "same", &program::rpn_same, "boolean operator same (equal)"}, + {kKeyword, ">", &program::RpnSup, "binary operator >"}, + {kKeyword, ">=", &program::RpnSupEq, "binary operator >="}, + {kKeyword, "<", &program::RpnInf, "binary operator <"}, + {kKeyword, "<=", &program::RpnInfEq, "binary operator <="}, + {kKeyword, "!=", &program::RpnDiff, "binary operator != (different)"}, + {kKeyword, "==", &program::RpnEq, "binary operator == (equal)"}, + {kKeyword, "and", &program::RpnTestAnd, "boolean operator and"}, + {kKeyword, "or", &program::RpnTestOr, "boolean operator or"}, + {kKeyword, "xor", &program::RpnTestXor, "boolean operator xor"}, + {kKeyword, "not", &program::RpnTestNot, "boolean operator not"}, + {kKeyword, "same", &program::RpnSame, "boolean operator same (equal)"}, // STACK {kUndef, "", nullptr, "\nSTACK"}, - {kKeyword, "swap", &program::rpn_swap, "swap 2 first stack entries"}, - {kKeyword, "drop", &program::rpn_drop, "drop first stack entry"}, - {kKeyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"}, - {kKeyword, "dropn", &program::rpn_dropn, "drop n first stack entries"}, - {kKeyword, "del", &program::rpn_erase, "drop all stack entries"}, - {kKeyword, "erase", &program::rpn_erase, ""}, - {kKeyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"}, - {kKeyword, "dup", &program::rpn_dup, "duplicate first stack entry"}, - {kKeyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries"}, - {kKeyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries"}, - {kKeyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack"}, - {kKeyword, "depth", &program::rpn_depth, "give stack depth"}, - {kKeyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack"}, - {kKeyword, "rolld", &program::rpn_rolld, "move the element on top of the stack to a higher stack position"}, - {kKeyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"}, + {kKeyword, "swap", &program::RpnSwap, "swap 2 first stack entries"}, + {kKeyword, "drop", &program::RpnDrop, "drop first stack entry"}, + {kKeyword, "drop2", &program::RpnDrop2, "drop 2 first stack entries"}, + {kKeyword, "dropn", &program::RpnDropn, "drop n first stack entries"}, + {kKeyword, "del", &program::RpnErase, "drop all stack entries"}, + {kKeyword, "erase", &program::RpnErase, ""}, + {kKeyword, "rot", &program::RpnRot, "rotate 3 first stack entries"}, + {kKeyword, "dup", &program::RpnDup, "duplicate first stack entry"}, + {kKeyword, "dup2", &program::RpnDup2, "duplicate 2 first stack entries"}, + {kKeyword, "dupn", &program::RpnDupn, "duplicate n first stack entries"}, + {kKeyword, "pick", &program::RpnPick, "push a copy of the given stack level onto the stack"}, + {kKeyword, "depth", &program::RpnDepth, "give stack depth"}, + {kKeyword, "roll", &program::RpnRoll, "move a stack entry to the top of the stack"}, + {kKeyword, "rolld", &program::RpnRolld, "move the element on top of the stack to a higher stack position"}, + {kKeyword, "over", &program::RpnOver, "push a copy of the element in stack level 2 onto the stack"}, // STRING {kUndef, "", nullptr, "\nSTRING"}, - {kKeyword, "->str", &program::rpn_instr, "convert an object into a string"}, - {kKeyword, "str->", &program::rpn_strout, "convert a string into an object"}, - {kKeyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"}, - {kKeyword, "num", &program::rpn_num, + {kKeyword, "->str", &program::RpnInstr, "convert an object into a string"}, + {kKeyword, "str->", &program::RpnStrout, "convert a string into an object"}, + {kKeyword, "chr", &program::RpnChr, "convert ASCII character code in stack level 1 into a string"}, + {kKeyword, "num", &program::RpnNum, "return ASCII code of the first character of the string in stack level 1 as a real number"}, - {kKeyword, "size", &program::rpn_strsize, "return the length of the string"}, - {kKeyword, "pos", &program::rpn_strpos, "seach for the string in level 1 within the string in level 2"}, - {kKeyword, "sub", &program::rpn_strsub, "return a substring of the string in level 3"}, + {kKeyword, "size", &program::RpnStrsize, "return the length of the string"}, + {kKeyword, "pos", &program::RpnStrpos, "seach for the string in level 1 within the string in level 2"}, + {kKeyword, "sub", &program::RpnStrsub, "return a substring of the string in level 3"}, // BRANCH {kUndef, "", nullptr, "\nBRANCH"}, - {kBranch, "if", (program_fn_t)&program::rpn_if, + {kBranch, "if", (program_fn_t)&program::RpnIf, "if then else " "end"}, - {kBranch, "then", (program_fn_t)&program::rpn_then, "used with if"}, - {kBranch, "else", (program_fn_t)&program::rpn_else, "used with if"}, - {kBranch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"}, - {kBranch, "start", (program_fn_t)&program::rpn_start, " start next| step"}, - {kBranch, "for", (program_fn_t)&program::rpn_for, + {kBranch, "then", (program_fn_t)&program::RpnThen, "used with if"}, + {kBranch, "else", (program_fn_t)&program::RpnElse, "used with if"}, + {kBranch, "end", (program_fn_t)&program::RpnEnd, "used with various branch instructions"}, + {kBranch, "start", (program_fn_t)&program::RpnStart, " start next| step"}, + {kBranch, "for", (program_fn_t)&program::RpnFor, " for next| step"}, - {kBranch, "next", (program_fn_t)&program::rpn_next, "used with start and for"}, - {kBranch, "step", (program_fn_t)&program::rpn_step, "used with start and for"}, - {kKeyword, "ift", &program::rpn_ift, "similar to if-then-end, ift"}, - {kKeyword, "ifte", &program::rpn_ifte, + {kBranch, "next", (program_fn_t)&program::RpnNext, "used with start and for"}, + {kBranch, "step", (program_fn_t)&program::RpnStep, "used with start and for"}, + {kKeyword, "ift", &program::RpnIft, "similar to if-then-end, ift"}, + {kKeyword, "ifte", &program::RpnIfte, "similar to if-then-else-end, " " ifte"}, - {kBranch, "do", (program_fn_t)&program::rpn_do, "do until end"}, - {kBranch, "until", (program_fn_t)&program::rpn_until, "used with do"}, - {kBranch, "while", (program_fn_t)&program::rpn_while, "while repeat end"}, - {kBranch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"}, + {kBranch, "do", (program_fn_t)&program::RpnDo, "do until end"}, + {kBranch, "until", (program_fn_t)&program::RpnUntil, "used with do"}, + {kBranch, "while", (program_fn_t)&program::RpnWhile, "while repeat end"}, + {kBranch, "repeat", (program_fn_t)&program::RpnRepeat, "used with while"}, // STORE {kUndef, "", nullptr, "\nSTORE"}, - {kKeyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"}, - {kKeyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"}, - {kKeyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"}, - {kKeyword, "vars", &program::rpn_vars, "list all variables"}, - {kKeyword, "clusr", &program::rpn_clusr, "erase all variables"}, - {kKeyword, "edit", &program::rpn_edit, "edit a variable content"}, - {kKeyword, "sto+", &program::rpn_stoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, - {kKeyword, "sto-", &program::rpn_stosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, - {kKeyword, "sto*", &program::rpn_stomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, - {kKeyword, "sto/", &program::rpn_stodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, - {kKeyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"}, - {kKeyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"}, + {kKeyword, "sto", &program::RpnSto, "store a variable. ex: 1 'name' sto"}, + {kKeyword, "rcl", &program::RpnRcl, "recall a variable. ex: 'name' rcl"}, + {kKeyword, "purge", &program::RpnPurge, "delete a variable. ex: 'name' purge"}, + {kKeyword, "vars", &program::RpnVars, "list all variables"}, + {kKeyword, "clusr", &program::RpnClusr, "erase all variables"}, + {kKeyword, "edit", &program::RpnEdit, "edit a variable content"}, + {kKeyword, "sto+", &program::RpnStoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, + {kKeyword, "sto-", &program::RpnStosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, + {kKeyword, "sto*", &program::RpnStomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, + {kKeyword, "sto/", &program::RpnStodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, + {kKeyword, "sneg", &program::RpnStoneg, "negate a variable. ex: 'name' sneg"}, + {kKeyword, "sinv", &program::RpnStoinv, "inverse a variable. ex: 1 'name' sinv"}, // PROGRAM {kUndef, "", nullptr, "\nPROGRAM"}, - {kKeyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, - {kBranch, "->", (program_fn_t)&program::rpn_inprog, + {kKeyword, "eval", &program::RpnEval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, + {kBranch, "->", (program_fn_t)&program::RpnInprog, "load program local variables. ex: << -> n m << 0 n m for i i + next >> " ">>"}, // TRIG ON REALS AND COMPLEXES {kUndef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"}, - {kKeyword, "pi", &program::rpn_pi, "pi constant"}, - {kKeyword, "sin", &program::rpn_sin, "sinus"}, - {kKeyword, "asin", &program::rpn_asin, "arg sinus"}, - {kKeyword, "cos", &program::rpn_cos, "cosinus"}, - {kKeyword, "acos", &program::rpn_acos, "arg cosinus"}, - {kKeyword, "tan", &program::rpn_tan, "tangent"}, - {kKeyword, "atan", &program::rpn_atan, "arg tangent"}, - {kKeyword, "d->r", &program::rpn_d2r, "convert degrees to radians"}, - {kKeyword, "r->d", &program::rpn_r2d, "convert radians to degrees"}, + {kKeyword, "pi", &program::RpnPi, "pi constant"}, + {kKeyword, "sin", &program::RpnSin, "sinus"}, + {kKeyword, "asin", &program::RpnAsin, "arg sinus"}, + {kKeyword, "cos", &program::RpnCos, "cosinus"}, + {kKeyword, "acos", &program::RpnAcos, "arg cosinus"}, + {kKeyword, "tan", &program::RpnTan, "tangent"}, + {kKeyword, "atan", &program::RpnAtan, "arg tangent"}, + {kKeyword, "d->r", &program::RpnD2r, "convert degrees to radians"}, + {kKeyword, "r->d", &program::RpnR2d, "convert radians to degrees"}, // LOGS ON REALS AND COMPLEXES {kUndef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"}, - {kKeyword, "e", &program::rpn_e, "Euler constant"}, - {kKeyword, "ln", &program::rpn_ln, "logarithm base e"}, - {kKeyword, "log", &program::rpn_ln, ""}, - {kKeyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"}, - {kKeyword, "exp", &program::rpn_exp, "exponential"}, - {kKeyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"}, - {kKeyword, "log10", &program::rpn_log10, "logarithm base 10"}, - {kKeyword, "alog10", &program::rpn_alog10, "exponential base 10"}, - {kKeyword, "exp10", &program::rpn_alog10, ""}, - {kKeyword, "log2", &program::rpn_log2, "logarithm base 2"}, - {kKeyword, "alog2", &program::rpn_alog2, "exponential base 2"}, - {kKeyword, "exp2", &program::rpn_alog2, ""}, - {kKeyword, "sinh", &program::rpn_sinh, "hyperbolic sine"}, - {kKeyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"}, - {kKeyword, "cosh", &program::rpn_cosh, "hyperbolic cosine"}, - {kKeyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"}, - {kKeyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"}, - {kKeyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"}, + {kKeyword, "e", &program::RpnE, "Euler constant"}, + {kKeyword, "ln", &program::RpnLn, "logarithm base e"}, + {kKeyword, "log", &program::RpnLn, ""}, + {kKeyword, "lnp1", &program::RpnLnp1, "ln(1+x) which is useful when x is close to 0"}, + {kKeyword, "exp", &program::RpnExp, "exponential"}, + {kKeyword, "expm", &program::RpnExpm, "exp(x)-1 which is useful when x is close to 0"}, + {kKeyword, "log10", &program::RpnLog10, "logarithm base 10"}, + {kKeyword, "alog10", &program::RpnAlog10, "exponential base 10"}, + {kKeyword, "exp10", &program::RpnAlog10, ""}, + {kKeyword, "log2", &program::RpnLog2, "logarithm base 2"}, + {kKeyword, "alog2", &program::RpnAlog2, "exponential base 2"}, + {kKeyword, "exp2", &program::RpnAlog2, ""}, + {kKeyword, "sinh", &program::RpnSinh, "hyperbolic sine"}, + {kKeyword, "asinh", &program::RpnAsinh, "inverse hyperbolic sine"}, + {kKeyword, "cosh", &program::RpnCosh, "hyperbolic cosine"}, + {kKeyword, "acosh", &program::RpnAcosh, "inverse hyperbolic cosine"}, + {kKeyword, "tanh", &program::RpnTanh, "hyperbolic tangent"}, + {kKeyword, "atanh", &program::RpnAtanh, "inverse hyperbolic tangent"}, // TIME AND DATE {kUndef, "", nullptr, "\nTIME AND DATE"}, - {kKeyword, "time", &program::rpn_time, "time in local format"}, - {kKeyword, "date", &program::rpn_date, "date in local format"}, - {kKeyword, "ticks", &program::rpn_ticks, "system tick in µs"}, + {kKeyword, "time", &program::RpnTime, "time in local format"}, + {kKeyword, "date", &program::RpnDate, "date in local format"}, + {kKeyword, "ticks", &program::RpnTicks, "system tick in µs"}, }; /// autocompletion vector for linenoise autocompletion -vector& program::getAutocompletionWords() { +vector& program::GetAutocompletionWords() { static vector autocompletion_words; if (autocompletion_words.empty()) for (auto& kw : keywords_) @@ -216,7 +216,7 @@ vector& program::getAutocompletionWords() { /// /// @return RetValue see this type /// -RetValue program::run() { +RetValue program::Run() { bool go_out = false; RetValue ret = kOk; ObjectType type; @@ -225,7 +225,7 @@ RetValue program::run() { err_context_ = ""; // branches for 'if' - ret = preprocess(); + ret = Preprocess(); if (ret != kOk) { // free allocated for (Object* o : *this) delete o; @@ -239,7 +239,7 @@ RetValue program::run() { switch (o->_type) { // could be an auto-evaluated symbol case kSymbol: - auto_rcl(reinterpret_cast(o)); + AutoRcl(reinterpret_cast(o)); i++; break; @@ -265,7 +265,7 @@ RetValue program::run() { if (err_ == kTestFailed) ret = kTestFailed; // error: show it - if (show_error(err_, err_context_) == kDeadlyError) + if (ShowError(err_, err_context_) == kDeadlyError) // pb showing error -> go out software ret = kGoodbye; break; @@ -284,7 +284,7 @@ RetValue program::run() { i++; // meaning 'next command' break; case kRtError: // runtime error - (void)show_error(err_, err_context_); + (void)ShowError(err_, err_context_); go_out = true; break; default: @@ -297,7 +297,7 @@ RetValue program::run() { default: // not a command, but a stack entry, manage it // copy the program stack entry to the running stack - stack_.push_front(o->clone()); + stack_.push_front(o->Clone()); i++; break; } @@ -317,7 +317,7 @@ RetValue program::run() { /// /// @return RetValue see this type /// -RetValue program::preprocess(void) { +RetValue program::Preprocess() { struct if_layout_t { if_layout_t() : index_then_or_unti_or_repeat(-1), @@ -355,17 +355,17 @@ RetValue program::preprocess(void) { // nothing after 'then' -> error if (next == kStepOut) { // error: show it - show_syntax_error("missing end after then"); + ShowSyntaxError("missing end after then"); return kSyntaxError; } if (layout_index < 0) { // error: show it - show_syntax_error("missing if before then"); + ShowSyntaxError("missing if before then"); return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it - show_syntax_error("duplicate then"); + ShowSyntaxError("duplicate then"); return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; @@ -378,22 +378,22 @@ RetValue program::preprocess(void) { // nothing after 'else' -> error if (next == kStepOut) { // error: show it - show_syntax_error("missing end after else"); + ShowSyntaxError("missing end after else"); return kSyntaxError; } if (layout_index < 0) { // error: show it - show_syntax_error("missing if before else"); + ShowSyntaxError("missing if before else"); return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it - show_syntax_error("missing then before else"); + ShowSyntaxError("missing then before else"); return kSyntaxError; } if (vlayout[layout_index].index_else != -1) { // error: show it - show_syntax_error("duplicate else"); + ShowSyntaxError("duplicate else"); return kSyntaxError; } vlayout[layout_index].index_else = i; @@ -409,7 +409,7 @@ RetValue program::preprocess(void) { } else if (k->value == "next") { if (vstart_index.size() == 0) { // error: show it - show_syntax_error("missing start or for before next"); + ShowSyntaxError("missing start or for before next"); return kSyntaxError; } k->arg1 = vstart_index[vstart_index.size() - 1]; // 'next' arg1 = 'start' index @@ -419,7 +419,7 @@ RetValue program::preprocess(void) { } else if (k->value == "step") { if (vstart_index.size() == 0) { // error: show it - show_syntax_error("missing start or for before step"); + ShowSyntaxError("missing start or for before step"); return kSyntaxError; } k->arg1 = vstart_index[vstart_index.size() - 1]; // fill 'step' branch1 = 'start' index @@ -441,17 +441,17 @@ RetValue program::preprocess(void) { // nothing after 'unti' -> error if (next == kStepOut) { // error: show it - show_syntax_error("missing end"); + ShowSyntaxError("missing end"); return kSyntaxError; } if (layout_index < 0 || !vlayout[layout_index].is_do_unti) { // error: show it - show_syntax_error("missing do"); + ShowSyntaxError("missing do"); return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it - show_syntax_error("duplicate until"); + ShowSyntaxError("duplicate until"); return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; @@ -464,12 +464,12 @@ RetValue program::preprocess(void) { } else if (k->value == "repeat") { if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) { // error: show it - show_syntax_error("missing while"); + ShowSyntaxError("missing while"); return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) { // error: show it - show_syntax_error("duplicate repeat"); + ShowSyntaxError("duplicate repeat"); return kSyntaxError; } vlayout[layout_index].index_then_or_unti_or_repeat = i; @@ -479,20 +479,20 @@ RetValue program::preprocess(void) { if (layout_index < 0) { // error: show it - show_syntax_error("missing branch instruction before end"); + ShowSyntaxError("missing branch instruction before end"); return kSyntaxError; } else { if (vlayout[layout_index].is_do_unti) { // this end closes a do..unti if (vlayout[layout_index].index_end != -1) { // error: show it - show_syntax_error("duplicate end"); + ShowSyntaxError("duplicate end"); return kSyntaxError; } if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it - show_syntax_error("missing until"); + ShowSyntaxError("missing until"); return kSyntaxError; } @@ -502,7 +502,7 @@ RetValue program::preprocess(void) { // this end closes a while..repeat if (vlayout[layout_index].index_end != -1) { // error: show it - show_syntax_error("duplicate end"); + ShowSyntaxError("duplicate end"); return kSyntaxError; } @@ -510,7 +510,7 @@ RetValue program::preprocess(void) { if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) { // error: show it - show_syntax_error("missing repeat"); + ShowSyntaxError("missing repeat"); return kSyntaxError; } @@ -521,7 +521,7 @@ RetValue program::preprocess(void) { // this end closes an if..then..(else) if (vlayout[layout_index].index_end != -1) { // error: show it - show_syntax_error("duplicate end"); + ShowSyntaxError("duplicate end"); return kSyntaxError; } if (vlayout[layout_index].index_else != -1) { @@ -534,7 +534,7 @@ RetValue program::preprocess(void) { ->arg2 = i; } else { // error: show it - show_syntax_error("missing then"); + ShowSyntaxError("missing then"); return kSyntaxError; } } @@ -546,12 +546,12 @@ RetValue program::preprocess(void) { } if (layout_index >= 0) { // error: show it - show_syntax_error("missing end"); + ShowSyntaxError("missing end"); return kSyntaxError; } if (vstart_index.size() > 0) { // error: show it - show_syntax_error("missing next or step after for or start"); + ShowSyntaxError("missing next or step after for or start"); return kSyntaxError; } return kOk; @@ -563,7 +563,7 @@ RetValue program::preprocess(void) { /// @param prog the program to be filled /// @return RetValue see this type /// -RetValue program::parse(string& entry) { +RetValue program::Parse(string& entry) { static map keywords_map; vector elements; vector errors; @@ -575,7 +575,7 @@ RetValue program::parse(string& entry) { if (!kw.name.empty()) keywords_map[kw.name] = {kw.type, kw.fn}; // separate the entry string - if (lexer(entry, keywords_map, elements, errors)) { + if (Analyse(entry, keywords_map, elements, errors)) { // make objects from parsed elements for (Lexer::SynElement& element : elements) { switch (element.type) { @@ -601,14 +601,14 @@ RetValue program::parse(string& entry) { push_back(new Branch((branch_fn_t)element.fn, element.value)); break; default: - show_error(kUnknownError, "error creating program from entry"); + ShowError(kUnknownError, "error creating program from entry"); break; } if (element.re != nullptr) delete element.re; if (element.im != nullptr) delete element.im; } } else { - for (SynError& err : errors) show_syntax_error(err.err.c_str()); + for (SynError& err : errors) ShowSyntaxError(err.err.c_str()); } return ret; @@ -618,7 +618,7 @@ RetValue program::parse(string& entry) { /// /// @return RetValue see this type /// -RetValue program::show_error() { +RetValue program::ShowError() { RetValue ret; // clang-format off map errorStrings{{kOk, "ok"}, {kUnknownError, "unknown command"}, @@ -650,11 +650,11 @@ RetValue program::show_error() { /// @param context a context string /// @return RetValue see this type /// -RetValue program::show_error(RetValue err, string& context) { +RetValue program::ShowError(RetValue err, string& context) { // record error err_ = err; err_context_ = context; - return show_error(); + return ShowError(); } /// @brief record an error as the last error set and show it @@ -663,11 +663,11 @@ RetValue program::show_error(RetValue err, string& context) { /// @param context a context string /// @return RetValue see this type /// -RetValue program::show_error(RetValue err, const char* context) { +RetValue program::ShowError(RetValue err, const char* context) { // record error err_ = err; err_context_ = context; - return show_error(); + return ShowError(); } /// @brief set the last error as being a syntax error and show it @@ -676,25 +676,25 @@ RetValue program::show_error(RetValue err, const char* context) { /// @param context a context string /// @return RetValue see this type /// -void program::show_syntax_error(const char* context) { +void program::ShowSyntaxError(const char* context) { // record error err_ = kSyntaxError; err_context_ = context; - (void)show_error(); + (void)ShowError(); } /// @brief return the last error set /// /// @return RetValue see this type /// -RetValue program::get_err(void) { return err_; } +RetValue program::GetLastError(void) { return err_; } /// @brief show a stack (show its different objects) /// generally a stack is associated to a running program /// /// @param show_separator whether to show a stack level prefix or not /// -void program::show_stack(bool show_separator) { +void program::ShowStack(bool show_separator) { if (stack_.size() == 1) { cout << stack_[0] << endl; } else { @@ -707,9 +707,9 @@ void program::show_stack(bool show_separator) { /// @brief apply default precision mode and digits /// -void program::apply_default() { +void program::ApplyDefault() { // default float precision, float mode - Number::mode = Number::DEFAULT_MODE; + Number::mode = Number::kDefaultMode; Number::digits = Number::kDefaultDecimalDigits; mpreal::set_default_prec(Number::kMpfrDefaultPrecBits); diff --git a/src/program.hpp b/src/program.hpp index b3dab55..1df080f 100644 --- a/src/program.hpp +++ b/src/program.hpp @@ -29,25 +29,23 @@ class program : public deque, public Lexer { } // parser - RetValue parse(string& entry); - static RetValue get_fn(const char* fn_name, program_fn_t& fn, ObjectType& type); + RetValue Parse(string& entry); // running - RetValue run(); - void stop(); - RetValue preprocess(void); + RetValue Run(); + RetValue Preprocess(); - RetValue show_error(); - RetValue show_error(RetValue err, string& context); - RetValue show_error(RetValue err, const char* context); - void show_syntax_error(const char* context); - RetValue get_err(void); + RetValue ShowError(); + RetValue ShowError(RetValue err, string& context); + RetValue ShowError(RetValue err, const char* context); + void ShowSyntaxError(const char* context); + RetValue GetLastError(void); - void show_stack(bool show_separator = true); + void ShowStack(bool show_separator = true); - static void apply_default(); + static void ApplyDefault(); - static vector& getAutocompletionWords(); + static vector& GetAutocompletionWords(); private: // current error and its context @@ -80,178 +78,177 @@ class program : public deque, public Lexer { //// // branch - size_t rpn_if(Branch& myobj); - size_t rpn_then(Branch& myobj); - size_t rpn_else(Branch& myobj); - size_t rpn_end(Branch& myobj); - size_t rpn_do(Branch& myobj); - size_t rpn_until(Branch& myobj); - void rpn_ift(void); - void rpn_ifte(void); - size_t rpn_while(Branch& myobj); - size_t rpn_repeat(Branch& myobj); - size_t rpn_start(Branch& myobj); - size_t rpn_for(Branch& myobj); - size_t rpn_next(Branch& myobj); - size_t rpn_step(Branch& myobj); + size_t RpnIf(Branch& myobj); + size_t RpnThen(Branch& myobj); + size_t RpnElse(Branch& myobj); + size_t RpnEnd(Branch& myobj); + size_t RpnDo(Branch& myobj); + size_t RpnUntil(Branch& myobj); + void RpnIft(void); + void RpnIfte(void); + size_t RpnWhile(Branch& myobj); + size_t RpnRepeat(Branch& myobj); + size_t RpnStart(Branch& myobj); + size_t RpnFor(Branch& myobj); + size_t RpnNext(Branch& myobj); + size_t RpnStep(Branch& myobj); enum { kStepOut = static_cast(-1), kRtError = static_cast(-2) }; // complex - void rpn_re(); - void rpn_im(); - void rpn_arg(); - void rpn_conj(); - void rpn_r2c(); - void rpn_c2r(); - void rpn_r2p(); - void rpn_p2r(); + void RpnReal(); + void RpnImag(); + void RpnArg(); + void RpnConj(); + void RpnR2c(); + void RpnC2r(); + void RpnR2p(); + void RpnP2r(); // general - void rpn_nop(); - void rpn_good_bye(); - void rpn_help(); - void rpn_std(); - void rpn_fix(); - void rpn_sci(); - void rpn_version(); - void rpn_uname(); - void rpn_history(); - void rpn_type(); - void rpn_default(); - void rpn_precision(); - void rpn_round(); + void RpnNop(); + void RpnQuit(); + void RpnHelp(); + void RpnStd(); + void RpnFix(); + void RpnSci(); + void RpnVersion(); + void RpnUname(); + void RpnHistory(); + void RpnType(); + void RpnDefault(); + void RpnPrecision(); + void RpnRound(); // logs - void rpn_e(void); - void rpn_log10(); - void rpn_alog10(); - void rpn_log2(); - void rpn_alog2(); - void rpn_ln(); - void rpn_exp(); - void rpn_expm(); - void rpn_lnp1(); - void rpn_sinh(); - void rpn_asinh(); - void rpn_cosh(); - void rpn_acosh(); - void rpn_tanh(); - void rpn_atanh(); + void RpnE(void); + void RpnLog10(); + void RpnAlog10(); + void RpnLog2(); + void RpnAlog2(); + void RpnLn(); + void RpnExp(); + void RpnExpm(); + void RpnLnp1(); + void RpnSinh(); + void RpnAsinh(); + void RpnCosh(); + void RpnAcosh(); + void RpnTanh(); + void RpnAtanh(); // program - bool find_variable(string& variable, Object*& obj); - void rpn_eval(void); - int rpn_inprog(Branch& inprog_obj); + bool FindVariable(string& variable, Object*& obj); + void RpnEval(void); + int RpnInprog(Branch& inprog_obj); // real - void rpn_plus(); - void rpn_minus(); - void rpn_mul(); - void do_divide_complexes(); - void rpn_div(); - void rpn_neg(); - void rpn_inv(); - void rpn_purcent(); - void rpn_purcentCH(); - void rpn_power(); - void rpn_squareroot(); - void rpn_square(); - void rpn_modulo(); - void rpn_abs(); - void rpn_hex(); - void rpn_bin(); - void rpn_dec(); - void rpn_base(); - void rpn_fact(); - void rpn_sign(); - void rpn_mant(); - void rpn_xpon(); - void rpn_floor(); - void rpn_ceil(); - void rpn_fp(); - void rpn_ip(); - void rpn_min(); - void rpn_max(); + void RpnPlus(); + void RpnMinus(); + void RpnMul(); + void RpnDiv(); + void RpnNeg(); + void RpnInv(); + void RpnPurcent(); + void RpnPurcentCH(); + void RpnPower(); + void RpnSquareroot(); + void RpnSquare(); + void RpnModulo(); + void RpnAbs(); + void RpnHex(); + void RpnBin(); + void RpnDec(); + void RpnBase(); + void RpnFact(); + void RpnSign(); + void RpnMant(); + void RpnXpon(); + void RpnFloor(); + void RpnCeil(); + void RpnFp(); + void RpnIp(); + void RpnMin(); + void RpnMax(); // stack - void rpn_swap(void); - void rpn_drop(void); - void rpn_drop2(void); - void rpn_dropn(void); - void rpn_erase(void); - void rpn_dup(void); - void rpn_dup2(void); - void rpn_dupn(void); - void rpn_pick(void); - void rpn_rot(void); - void rpn_depth(void); - void rpn_roll(void); - void rpn_rolld(void); - void rpn_over(void); + void RpnSwap(void); + void RpnDrop(void); + void RpnDrop2(void); + void RpnDropn(void); + void RpnErase(void); + void RpnDup(void); + void RpnDup2(void); + void RpnDupn(void); + void RpnPick(void); + void RpnRot(void); + void RpnDepth(void); + void RpnRoll(void); + void RpnRolld(void); + void RpnOver(void); // store - void rpn_sto(void); - void rpn_stoadd(void); - void rpn_stosub(void); - void rpn_stomul(void); - void rpn_stodiv(void); - void rpn_stoneg(void); - void rpn_stoinv(void); - void rpn_rcl(void); - void rpn_edit(void); - void auto_rcl(Symbol* symb); - void rpn_purge(void); - void rpn_vars(void); - void rpn_clusr(void); + void RpnSto(void); + void RpnStoadd(void); + void RpnStosub(void); + void RpnStomul(void); + void RpnStodiv(void); + void RpnStoneg(void); + void RpnStoinv(void); + void RpnRcl(void); + void RpnEdit(void); + void AutoRcl(Symbol* symb); + void RpnPurge(void); + void RpnVars(void); + void RpnClusr(void); // string - void rpn_instr(); - void rpn_strout(); - void rpn_chr(); - void rpn_num(); - void rpn_strsize(); - void rpn_strpos(); - void rpn_strsub(); + void RpnInstr(); + void RpnStrout(); + void RpnChr(); + void RpnNum(); + void RpnStrsize(); + void RpnStrpos(); + void RpnStrsub(); // test-core - void rpn_test(); - void test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, + void RpnTest(); + void RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed); // test - void rpn_sup(void); - void rpn_sup_eq(void); - void rpn_inf(void); - void rpn_inf_eq(void); - void rpn_diff(void); - void rpn_eq(void); - void rpn_test_and(void); - void rpn_test_or(void); - void rpn_test_xor(void); - void rpn_test_not(void); - void rpn_same(void); + void RpnSup(void); + void RpnSupEq(void); + void RpnInf(void); + void RpnInfEq(void); + void RpnDiff(void); + void RpnEq(void); + void RpnTestAnd(void); + void RpnTestOr(void); + void RpnTestXor(void); + void RpnTestNot(void); + void RpnSame(void); // trig - void rpn_pi(void); - void rpn_d2r(void); - void rpn_r2d(void); - void rpn_sin(void); - void rpn_asin(void); - void rpn_cos(void); - void rpn_acos(void); - void rpn_tan(void); - void rpn_atan(void); + void RpnPi(void); + void RpnD2r(void); + void RpnR2d(void); + void RpnSin(void); + void RpnAsin(void); + void RpnCos(void); + void RpnAcos(void); + void RpnTan(void); + void RpnAtan(void); // time - void rpn_time(); - void rpn_date(); - void rpn_ticks(); + void RpnTime(); + void RpnDate(); + void RpnTicks(); }; // convenience macros for rpn_xx function // carefull : some of these macros modify program flow -#define setErrorContext(err) \ +#define ERROR_CONTEXT(err) \ do { \ err_ = (err); \ err_context_ = __FUNCTION__; \ @@ -260,7 +257,7 @@ class program : public deque, public Lexer { #define MIN_ARGUMENTS(num) \ do { \ if ((num) >= 0 && stack_.size() < (num)) { \ - setErrorContext(kMissingOperand); \ + ERROR_CONTEXT(kMissingOperand); \ return; \ } \ } while (0) @@ -268,7 +265,7 @@ class program : public deque, public Lexer { #define MIN_ARGUMENTS_RET(num, ret) \ do { \ if ((num) >= 0 && stack_.size() < (num)) { \ - setErrorContext(kMissingOperand); \ + ERROR_CONTEXT(kMissingOperand); \ return (ret); \ } \ } while (0) @@ -276,7 +273,7 @@ class program : public deque, public Lexer { #define ARG_MUST_BE_OF_TYPE(num, type) \ do { \ if ((num) >= 0 && stack_.at(num)->_type != (type)) { \ - setErrorContext(kBadOperandType); \ + ERROR_CONTEXT(kBadOperandType); \ return; \ } \ } while (0) @@ -284,7 +281,7 @@ class program : public deque, public Lexer { #define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \ do { \ if ((num) >= 0 && stack_.at(num)->_type != (type)) { \ - setErrorContext(kBadOperandType); \ + ERROR_CONTEXT(kBadOperandType); \ return (ret); \ } \ } while (0) diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cpp index efab5dc..133c2f8 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cpp @@ -9,7 +9,7 @@ /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_if(Branch& myobj) { +size_t program::RpnIf(Branch& myobj) { // myobj.arg1 = 'if' condition evaluation value MIN_ARGUMENTS_RET(1, kRtError); ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); @@ -29,7 +29,7 @@ size_t program::rpn_if(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort Branch /// -size_t program::rpn_then(Branch& myobj) { +size_t program::RpnThen(Branch& myobj) { // myobj.arg1 = index of then + 1 // myobj.arg2 = index of else + 1 or end + 1 // myobj.arg3 = index of if @@ -37,7 +37,7 @@ size_t program::rpn_then(Branch& myobj) { // else -> arg2 (= jump to else + 1 or end + 1) Branch* if_cmd; if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } if_cmd = reinterpret_cast(at(myobj.arg3)); @@ -54,7 +54,7 @@ size_t program::rpn_then(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_else(Branch& myobj) { +size_t program::RpnElse(Branch& myobj) { // myobj.arg1 = index of else + 1 // myobj.arg2 = index of end + 1 // myobj.arg3 = index of if @@ -62,7 +62,7 @@ size_t program::rpn_else(Branch& myobj) { // if condition was true -> arg2 (= jump to end + 1) Branch* if_cmd; if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } if_cmd = reinterpret_cast(at(myobj.arg3)); @@ -79,7 +79,7 @@ size_t program::rpn_else(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_end(Branch& myobj) { +size_t program::RpnEnd(Branch& myobj) { size_t ret = kStepOut; // arg1 = index of do+1 in case of do..unti..end @@ -106,7 +106,7 @@ size_t program::rpn_end(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_do(Branch& myobj) { +size_t program::RpnDo(Branch& myobj) { // nothing return kStepOut; } @@ -118,7 +118,7 @@ size_t program::rpn_do(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort Branch /// -size_t program::rpn_until(Branch& myobj) { +size_t program::RpnUntil(Branch& myobj) { // nothing return kStepOut; } @@ -130,7 +130,7 @@ size_t program::rpn_until(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -void program::rpn_ift(void) { +void program::RpnIft(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -149,7 +149,7 @@ void program::rpn_ift(void) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -void program::rpn_ifte(void) { +void program::RpnIfte(void) { MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(2, kNumber); @@ -170,7 +170,7 @@ void program::rpn_ifte(void) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_while(Branch& myobj) { +size_t program::RpnWhile(Branch& myobj) { // nothing return kStepOut; } @@ -182,7 +182,7 @@ size_t program::rpn_while(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_repeat(Branch& myobj) { +size_t program::RpnRepeat(Branch& myobj) { size_t ret = kStepOut; MIN_ARGUMENTS_RET(1, kRtError); @@ -203,7 +203,7 @@ size_t program::rpn_repeat(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_start(Branch& myobj) { +size_t program::RpnStart(Branch& myobj) { size_t ret = kStepOut; MIN_ARGUMENTS_RET(2, kRtError); @@ -232,7 +232,7 @@ size_t program::rpn_start(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_for(Branch& myobj) { +size_t program::RpnFor(Branch& myobj) { size_t ret; MIN_ARGUMENTS_RET(2, kRtError); @@ -241,7 +241,7 @@ size_t program::rpn_for(Branch& myobj) { Symbol* sym; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kSymbol) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } sym = reinterpret_cast(at(myobj.arg1)); // arg1 = loop variable index @@ -263,7 +263,7 @@ size_t program::rpn_for(Branch& myobj) { delete it->second; local_heap_.erase(it); } - local_heap_[sym->value] = stack_.obj(1).clone(); + local_heap_[sym->value] = stack_.obj(1).Clone(); ret = myobj.arg1 + 1; } @@ -279,12 +279,12 @@ size_t program::rpn_for(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_next(Branch& myobj) { +size_t program::RpnNext(Branch& myobj) { // arg1 = loop variable index // first_index = current point in the loop Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } start_or_for = reinterpret_cast(at(myobj.arg1)); @@ -302,7 +302,7 @@ size_t program::rpn_next(Branch& myobj) { Object* obj; Symbol* var; if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } var = reinterpret_cast(at(start_or_for->arg1)); @@ -332,7 +332,7 @@ size_t program::rpn_next(Branch& myobj) { /// @return kStepOut next object to run in the current program is current + 1 /// @return kRtError something went wrong with preprocess, abort branch /// -size_t program::rpn_step(Branch& myobj) { +size_t program::RpnStep(Branch& myobj) { size_t ret; MIN_ARGUMENTS_RET(1, kRtError); ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError); @@ -348,7 +348,7 @@ size_t program::rpn_step(Branch& myobj) { // first_index = current count Branch* start_or_for; if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } start_or_for = reinterpret_cast(at(myobj.arg1)); @@ -367,7 +367,7 @@ size_t program::rpn_step(Branch& myobj) { // for command: increment symbol too if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) { - setErrorContext(kMissingOperand); + ERROR_CONTEXT(kMissingOperand); return kRtError; } var = reinterpret_cast(at(start_or_for->arg1)); diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cpp index e3c24c2..c0b01e5 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cpp @@ -5,7 +5,7 @@ /// @brief re keyword implementation /// the result is stacked on current program stack /// -void program::rpn_re() { +void program::RpnReal() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.push_front(new Number(real(stack_.value(0)))); @@ -15,7 +15,7 @@ void program::rpn_re() { /// @brief im keyword implementation /// the result is stacked on current program stack /// -void program::rpn_im() { +void program::RpnImag() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.push_front(new Number(imag(stack_.value(0)))); @@ -25,7 +25,7 @@ void program::rpn_im() { /// @brief arg keyword implementation /// the result is stacked on current program stack /// -void program::rpn_arg() { +void program::RpnArg() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.push_front(new Number(arg(stack_.value(0)))); @@ -35,7 +35,7 @@ void program::rpn_arg() { /// @brief conj keyword implementation /// the result is stacked on current program stack /// -void program::rpn_conj() { +void program::RpnConj() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.value(0) = conj(stack_.value(0)); @@ -44,7 +44,7 @@ void program::rpn_conj() { /// @brief r2c keyword implementation /// the result is stacked on current program stack /// -void program::rpn_r2c() { +void program::RpnR2c() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -55,7 +55,7 @@ void program::rpn_r2c() { /// @brief c2r keyword implementation /// the result is stacked on current program stack /// -void program::rpn_c2r() { +void program::RpnC2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.push(new Number(real(stack_.value(0)), stack_.obj(0).re_base)); @@ -66,7 +66,7 @@ void program::rpn_c2r() { /// @brief r2p keyword implementation /// the result is stacked on current program stack /// -void program::rpn_r2p() { +void program::RpnR2p() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); mpreal rho = abs(stack_.value(0)); @@ -78,7 +78,7 @@ void program::rpn_r2p() { /// @brief p2r keyword implementation /// the result is stacked on current program stack /// -void program::rpn_p2r() { +void program::RpnP2r() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kComplex); stack_.value(0) = polar(abs(stack_.value(0)), arg(stack_.value(0))); diff --git a/src/rpn-general.cpp b/src/rpn-general.cpp index 23e44d2..abe720e 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cpp @@ -3,9 +3,7 @@ #include #include #include -using std::cout; -using std::string; -using std::pair; +using std::cout, std::string, std::pair; #include "linenoise.h" #include "program.hpp" @@ -34,18 +32,18 @@ static const char _syntax[] = ATTR_BOLD "Syntax" ATTR_OFF ": rpn [command]\nwith /// @brief nop keyword implementation /// -void program::rpn_nop() { +void program::RpnNop() { // nop } /// @brief quit keyword implementation /// -void program::rpn_good_bye() { setErrorContext(kGoodbye); } +void program::RpnQuit() { ERROR_CONTEXT(kGoodbye); } /// @brief nop keyword implementation /// the result is written on stdout /// -void program::rpn_help() { +void program::RpnHelp() { // software name cout << endl << ATTR_BOLD << RPN_UNAME << ATTR_OFF << endl; @@ -106,7 +104,7 @@ static bool check_decimal_digits(int precision) { return precision >= 0; } /// @brief std keyword implementation /// -void program::rpn_std() { +void program::RpnStd() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -118,13 +116,13 @@ void program::rpn_std() { Number::digits = digits; stack_.pop(); } else { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); } } /// @brief fix keyword implementation /// -void program::rpn_fix() { +void program::RpnFix() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -136,13 +134,13 @@ void program::rpn_fix() { Number::digits = digits; stack_.pop(); } else { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); } } /// @brief sci keyword implementation /// -void program::rpn_sci() { +void program::RpnSci() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -154,21 +152,21 @@ void program::rpn_sci() { Number::digits = digits; stack_.pop(); } else { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); } } /// @brief _version keyword implementation /// -void program::rpn_version() { stack_.push_front(new String(RPN_VERSION)); } +void program::RpnVersion() { stack_.push_front(new String(RPN_VERSION)); } /// @brief _uname keyword implementation /// -void program::rpn_uname() { stack_.push_front(new String(RPN_UNAME)); } +void program::RpnUname() { stack_.push_front(new String(RPN_UNAME)); } /// @brief history keyword implementation /// -void program::rpn_history() { +void program::RpnHistory() { // see command history on stdout int index = 0; char* line = linenoiseHistoryLine(index); @@ -181,19 +179,19 @@ void program::rpn_history() { /// @brief type keyword implementation /// -void program::rpn_type() { +void program::RpnType() { MIN_ARGUMENTS(1); - stack_.push(new String(stack_.at(0)->name())); + stack_.push(new String(stack_.at(0)->Name())); stack_.erase(1); } /// @brief default keyword implementation /// -void program::rpn_default() { program::apply_default(); } +void program::RpnDefault() { program::ApplyDefault(); } /// @brief prec keyword implementation /// -void program::rpn_precision() { +void program::RpnPrecision() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -209,13 +207,13 @@ void program::rpn_precision() { } stack_.pop(); } else { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); } } /// @brief round keyword implementation /// -void program::rpn_round() { +void program::RpnRound() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); @@ -225,6 +223,6 @@ void program::rpn_round() { if (found != matchRound.end()) mpreal::set_default_rnd(found->second); else - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); stack_.pop(); } diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cpp index 224ec5b..1568dd8 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cpp @@ -4,172 +4,172 @@ /// @brief e keyword implementation /// -void program::rpn_e(void) { stack_.push(new Number(mpfr::const_euler())); } +void program::RpnE(void) { stack_.push(new Number(mpfr::const_euler())); } /// @brief log10 keyword implementation /// -void program::rpn_log10() { +void program::RpnLog10() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = log10(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = log10(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief alog10 keyword implementation /// -void program::rpn_alog10() { +void program::RpnAlog10() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = exp(log(mpreal(10)) * stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = exp(log(mpreal(10)) * stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief log2 keyword implementation /// -void program::rpn_log2() { +void program::RpnLog2() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = log(stack_.value(0)) / mpfr::const_log2(); else if (stack_.type(0) == kComplex) stack_.value(0) = log(stack_.value(0)) / mpfr::const_log2(); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief alog2 keyword implementation /// -void program::rpn_alog2() { +void program::RpnAlog2() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = exp(mpfr::const_log2() * stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = exp(mpfr::const_log2() * stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief ln keyword implementation /// -void program::rpn_ln() { +void program::RpnLn() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = log(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = log(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief exp keyword implementation /// -void program::rpn_exp() { +void program::RpnExp() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = exp(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = exp(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief expm keyword implementation /// -void program::rpn_expm() { +void program::RpnExpm() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = exp(stack_.value(0)) - mpreal(1); else if (stack_.type(0) == kComplex) stack_.value(0) = exp(stack_.value(0)) - mpreal(1); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief lnp1 keyword implementation /// -void program::rpn_lnp1() { +void program::RpnLnp1() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = log(stack_.value(0) + 1); else if (stack_.type(0) == kComplex) stack_.value(0) = log(stack_.value(0) + mpreal(1)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief sinh keyword implementation /// -void program::rpn_sinh() { +void program::RpnSinh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = sinh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = sinh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief asinh keyword implementation /// -void program::rpn_asinh() { +void program::RpnAsinh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = asinh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = asinh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief cosh keyword implementation /// -void program::rpn_cosh() { +void program::RpnCosh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = cosh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = cosh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief acosh keyword implementation /// -void program::rpn_acosh() { +void program::RpnAcosh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = acosh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = acosh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief tanh keyword implementation /// -void program::rpn_tanh() { +void program::RpnTanh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = tanh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = tanh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief atanh keyword implementation /// -void program::rpn_atanh() { +void program::RpnAtanh() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = atanh(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = atanh(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } diff --git a/src/rpn-program.cpp b/src/rpn-program.cpp index 93e1ab0..7bc7006 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cpp @@ -9,7 +9,7 @@ /// @return true variable was found /// @return false variable was not found /// -bool program::find_variable(string& variable, Object*& obj) { +bool program::FindVariable(string& variable, Object*& obj) { bool found = false; program* parent = parent_; @@ -33,7 +33,7 @@ bool program::find_variable(string& variable, Object*& obj) { /// @brief eval keyword implementation /// -void program::rpn_eval(void) { +void program::RpnEval(void) { bool run_prog = false; string prog_text; @@ -45,7 +45,7 @@ void program::rpn_eval(void) { stack_.pop(); // if variable holds a program, run this program - if (find_variable(variable, obj)) { + if (FindVariable(variable, obj)) { if (obj->_type == kProgram) { prog_text = stack_.value(0); stack_.pop(); @@ -55,7 +55,7 @@ void program::rpn_eval(void) { stack_.push_front(obj); } } else { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); } } else if (stack_.type(0) == kProgram) { // eval a program @@ -63,7 +63,7 @@ void program::rpn_eval(void) { stack_.pop(); run_prog = true; } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } // run prog if any @@ -71,22 +71,22 @@ void program::rpn_eval(void) { program prog(stack_, heap_, this); // make program from entry - if (prog.parse(prog_text) == kOk) { + if (prog.Parse(prog_text) == kOk) { // run it - prog.run(); + prog.Run(); } } } /// @brief -> keyword (Branch) implementation /// -int program::rpn_inprog(Branch& inprog_obj) { +int program::RpnInprog(Branch& inprog_obj) { string context("->"); // for showing errors int count_symbols = 0; bool prog_found = false; if (inprog_obj.arg1 == -1) { - setErrorContext(kUnknownError); + ERROR_CONTEXT(kUnknownError); return -1; } @@ -104,36 +104,36 @@ int program::rpn_inprog(Branch& inprog_obj) { break; } else { // found something other than symbol - setErrorContext(kBadOperandType); - show_error(err_, context); + ERROR_CONTEXT(kBadOperandType); + ShowError(err_, context); return -1; } } // found 0 symbols if (count_symbols == 0) { - setErrorContext(kSyntaxError); - show_error(err_, context); + ERROR_CONTEXT(kSyntaxError); + ShowError(err_, context); return -1; } // is missing if (!prog_found) { - setErrorContext(kSyntaxError); - show_error(err_, context); + ERROR_CONTEXT(kSyntaxError); + ShowError(err_, context); return -1; } // check symbols Number vs stack_ size if (stack_.size() < count_symbols) { - setErrorContext(kMissingOperand); - show_error(err_, context); + ERROR_CONTEXT(kMissingOperand); + ShowError(err_, context); return -1; } // load variables for (unsigned int i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) { - local_heap_[reinterpret_cast(at(i))->value] = stack_.at(0)->clone(); + local_heap_[reinterpret_cast(at(i))->value] = stack_.at(0)->Clone(); stack_.pop(); } @@ -142,9 +142,9 @@ int program::rpn_inprog(Branch& inprog_obj) { program prog(stack_, heap_, this); // make the program from entry - if (prog.parse(entry) == kOk) { + if (prog.Parse(entry) == kOk) { // run it - prog.run(); + prog.Run(); } // point on next command diff --git a/src/rpn-real.cpp b/src/rpn-real.cpp index 17b0eef..53750c3 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cpp @@ -4,7 +4,7 @@ /// @brief + keyword implementation /// -void program::rpn_plus() { +void program::RpnPlus() { MIN_ARGUMENTS(2); if (stack_.type(0) == kString && stack_.type(1) == kString) { stack_.value(1) += stack_.value(0); @@ -19,17 +19,17 @@ void program::rpn_plus() { stack_.value(1) += stack_.value(0); stack_.pop(); } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { - rpn_swap(); + RpnSwap(); stack_.value(1) += stack_.value(0); stack_.pop(); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief - keyword implementation /// -void program::rpn_minus() { +void program::RpnMinus() { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.value(1) -= stack_.value(0); @@ -41,17 +41,17 @@ void program::rpn_minus() { stack_.value(1) -= stack_.value(0); stack_.pop(); } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { - rpn_swap(); + RpnSwap(); stack_.value(1) = stack_.value(0) - stack_.value(1); stack_.pop(); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief * keyword implementation /// -void program::rpn_mul() { +void program::RpnMul() { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.value(1) *= stack_.value(0); @@ -63,17 +63,17 @@ void program::rpn_mul() { stack_.value(1) *= stack_.value(0); stack_.pop(); } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { - rpn_swap(); + RpnSwap(); stack_.value(1) *= stack_.value(0); stack_.pop(); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief / keyword implementation /// -void program::rpn_div() { +void program::RpnDiv() { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.value(1) /= stack_.value(0); @@ -85,41 +85,41 @@ void program::rpn_div() { stack_.value(1) /= stack_.value(0); stack_.pop(); } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { - rpn_swap(); + RpnSwap(); stack_.value(1) = stack_.value(0) / stack_.value(1); stack_.pop(); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief neg keyword implementation /// -void program::rpn_neg() { +void program::RpnNeg() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = -stack_.value(0); else if (stack_.type(0) == kComplex) stack_.value(0) = -stack_.value(0); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief inv keyword implementation /// -void program::rpn_inv() { +void program::RpnInv() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = 1 / stack_.value(0); else if (stack_.type(0) == kComplex) stack_.value(0) = mpreal(1) / stack_.value(0); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief power keyword implementation /// -void program::rpn_power() { +void program::RpnPower() { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { if (stack_.value(1) >= 0) { @@ -138,17 +138,17 @@ void program::rpn_power() { stack_.value(1) = pow(stack_.value(1), stack_.value(0)); stack_.pop(); } else if (stack_.type(0) == kComplex && stack_.type(1) == kNumber) { - rpn_swap(); + RpnSwap(); stack_.value(1) = pow(stack_.value(0), stack_.value(1)); stack_.pop(); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief sqrt keyword implementation /// -void program::rpn_squareroot() { +void program::RpnSquareroot() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) { if (stack_.value(0) >= 0) { @@ -164,13 +164,13 @@ void program::rpn_squareroot() { } else if (stack_.type(0) == kComplex) { stack_.value(0) = sqrt(stack_.value(0)); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief hex keyword implementation /// -void program::rpn_hex() { +void program::RpnHex() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) { stack_.obj(0).base = 16; @@ -178,13 +178,13 @@ void program::rpn_hex() { stack_.obj(0).re_base = 16; stack_.obj(0).im_base = 16; } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief bin keyword implementation /// -void program::rpn_bin() { +void program::RpnBin() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) { stack_.obj(0).base = 2; @@ -192,13 +192,13 @@ void program::rpn_bin() { stack_.obj(0).re_base = 2; stack_.obj(0).im_base = 2; } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief dec keyword implementation /// -void program::rpn_dec() { +void program::RpnDec() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) { stack_.obj(0).base = 10; @@ -206,13 +206,13 @@ void program::rpn_dec() { stack_.obj(0).re_base = 10; stack_.obj(0).im_base = 10; } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief base keyword implementation /// -void program::rpn_base() { +void program::RpnBase() { MIN_ARGUMENTS(2); if (stack_.type(1) == kNumber || stack_.type(1) == kComplex) { int base = static_cast(stack_.value(0).toLong()); @@ -225,16 +225,16 @@ void program::rpn_base() { stack_.obj(0).im_base = base; } } else { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); } } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief % (purcent) keyword implementation /// -void program::rpn_purcent() { +void program::RpnPurcent() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -244,7 +244,7 @@ void program::rpn_purcent() { /// @brief %CH keyword implementation /// -void program::rpn_purcentCH() { +void program::RpnPurcentCH() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -254,19 +254,19 @@ void program::rpn_purcentCH() { /// @brief sq keyword implementation /// -void program::rpn_square() { +void program::RpnSquare() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) *= stack_.value(0); else if (stack_.at(0)->_type == kComplex) stack_.value(0) *= stack_.value(0); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief mod keyword implementation /// -void program::rpn_modulo() { +void program::RpnModulo() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -276,7 +276,7 @@ void program::rpn_modulo() { /// @brief abs keyword implementation /// -void program::rpn_abs() { +void program::RpnAbs() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) { stack_.value(0) = abs(stack_.value(0)); @@ -284,13 +284,13 @@ void program::rpn_abs() { stack_.push(new Number(abs(stack_.value(0)))); stack_.erase(1); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief fact (factorial) keyword implementation /// -void program::rpn_fact() { +void program::RpnFact() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); // fact(n) = gamma(n+1) @@ -299,23 +299,23 @@ void program::rpn_fact() { /// @brief sign keyword implementation /// -void program::rpn_sign() { +void program::RpnSign() { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = sgn(stack_.value(0)); else if (stack_.at(0)->_type == kComplex) stack_.value(0) = stack_.value(0) / abs(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief mant keyword implementation /// -void program::rpn_mant() { +void program::RpnMant() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); if (!isfinite(stack_.value(0))) { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); return; } mp_exp_t exp; @@ -324,11 +324,11 @@ void program::rpn_mant() { /// @brief xpon keyword implementation /// -void program::rpn_xpon() { +void program::RpnXpon() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); if (!isfinite(stack_.value(0))) { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); return; } mp_exp_t exp; @@ -338,7 +338,7 @@ void program::rpn_xpon() { /// @brief floor keyword implementation /// -void program::rpn_floor() { +void program::RpnFloor() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) = floor(stack_.value(0)); @@ -346,7 +346,7 @@ void program::rpn_floor() { /// @brief ceil keyword implementation /// -void program::rpn_ceil() { +void program::RpnCeil() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) = ceil(stack_.value(0)); @@ -354,7 +354,7 @@ void program::rpn_ceil() { /// @brief fp keyword implementation /// -void program::rpn_fp() { +void program::RpnFp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) = frac(stack_.value(0)); @@ -362,7 +362,7 @@ void program::rpn_fp() { /// @brief ip keyword implementation /// -void program::rpn_ip() { +void program::RpnIp() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) = trunc(stack_.value(0)); @@ -370,7 +370,7 @@ void program::rpn_ip() { /// @brief min keyword implementation /// -void program::rpn_min() { +void program::RpnMin() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -380,7 +380,7 @@ void program::rpn_min() { /// @brief max keyword implementation /// -void program::rpn_max() { +void program::RpnMax() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cpp index 66e2247..f4e3d1d 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cpp @@ -4,7 +4,7 @@ /// @brief swap keyword implementation /// -void program::rpn_swap(void) { +void program::RpnSwap(void) { MIN_ARGUMENTS(2); Object* tmp = stack_.front(); stack_.erase(0, 1, false); @@ -13,21 +13,21 @@ void program::rpn_swap(void) { /// @brief drop keyword implementation /// -void program::rpn_drop(void) { +void program::RpnDrop(void) { MIN_ARGUMENTS(1); stack_.pop(); } /// @brief drop2 keyword implementation /// -void program::rpn_drop2(void) { +void program::RpnDrop2(void) { MIN_ARGUMENTS(2); stack_.erase(0, 2); } /// @brief dropn keyword implementation /// -void program::rpn_dropn(void) { +void program::RpnDropn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -38,18 +38,18 @@ void program::rpn_dropn(void) { /// @brief erase / del keyword implementation /// -void program::rpn_erase(void) { stack_.erase(0, stack_.size()); } +void program::RpnErase(void) { stack_.erase(0, stack_.size()); } /// @brief dup keyword implementation /// -void program::rpn_dup(void) { +void program::RpnDup(void) { MIN_ARGUMENTS(1); - stack_.push_front(stack_.at(0)->clone()); + stack_.push_front(stack_.at(0)->Clone()); } /// @brief dupn keyword implementation /// -void program::rpn_dupn(void) { +void program::RpnDupn(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -57,20 +57,20 @@ void program::rpn_dupn(void) { stack_.pop(); MIN_ARGUMENTS(args); - for (int i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->clone()); + for (int i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->Clone()); } /// @brief dup2 keyword implementation /// -void program::rpn_dup2(void) { +void program::RpnDup2(void) { MIN_ARGUMENTS(2); - stack_.push_front(stack_.at(1)->clone()); - stack_.push_front(stack_.at(1)->clone()); + stack_.push_front(stack_.at(1)->Clone()); + stack_.push_front(stack_.at(1)->Clone()); } /// @brief pick keyword implementation /// -void program::rpn_pick(void) { +void program::RpnPick(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -79,16 +79,16 @@ void program::rpn_pick(void) { // treat stack_ depth errors if ((to_pick == 0) || (to_pick > stack_.size())) { - setErrorContext(kOutOfRange); + ERROR_CONTEXT(kOutOfRange); return; } - stack_.push_front(stack_.at(to_pick - 1)->clone()); + stack_.push_front(stack_.at(to_pick - 1)->Clone()); } /// @brief rot keyword implementation /// -void program::rpn_rot(void) { +void program::RpnRot(void) { MIN_ARGUMENTS(3); Object* tmp = stack_.at(2); stack_.erase(2, 1, false); @@ -97,11 +97,11 @@ void program::rpn_rot(void) { /// @brief depth keyword implementation /// -void program::rpn_depth(void) { stack_.push_front(new Number(stack_.size())); } +void program::RpnDepth(void) { stack_.push_front(new Number(stack_.size())); } /// @brief roll keyword implementation /// -void program::rpn_roll(void) { +void program::RpnRoll(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -116,7 +116,7 @@ void program::rpn_roll(void) { /// @brief rolld keyword implementation /// -void program::rpn_rolld(void) { +void program::RpnRolld(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -131,7 +131,7 @@ void program::rpn_rolld(void) { /// @brief over keyword implementation /// -void program::rpn_over(void) { +void program::RpnOver(void) { MIN_ARGUMENTS(2); - stack_.push_front(stack_.at(1)->clone()); + stack_.push_front(stack_.at(1)->Clone()); } diff --git a/src/rpn-store.cpp b/src/rpn-store.cpp index c9ea63d..e387703 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cpp @@ -5,7 +5,7 @@ /// @brief sto keyword implementation /// -void program::rpn_sto(void) { +void program::RpnSto(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); @@ -15,113 +15,113 @@ void program::rpn_sto(void) { delete it->second; heap_.erase(it); } - heap_[stack_.value(0)] = stack_.at(1)->clone(); + heap_[stack_.value(0)] = stack_.at(1)->Clone(); stack_.erase(0, 2); } /// @brief sto+ keyword implementation /// -void program::rpn_stoadd(void) { +void program::RpnStoadd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); // TODO(louis) is rcl the good one? it will recall local variables too - rpn_rot(); - rpn_plus(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); // TODO(louis) is rcl the good one? it will recall local variables too + RpnRot(); + RpnPlus(); + RpnSwap(); + RpnSto(); } /// @brief sto- keyword implementation /// -void program::rpn_stosub(void) { +void program::RpnStosub(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); - rpn_rot(); - rpn_minus(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); + RpnRot(); + RpnMinus(); + RpnSwap(); + RpnSto(); } /// @brief sto* keyword implementation /// -void program::rpn_stomul(void) { +void program::RpnStomul(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); - rpn_rot(); - rpn_mul(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); + RpnRot(); + RpnMul(); + RpnSwap(); + RpnSto(); } /// @brief sto/ keyword implementation /// -void program::rpn_stodiv(void) { +void program::RpnStodiv(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); - rpn_rot(); - rpn_div(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); + RpnRot(); + RpnDiv(); + RpnSwap(); + RpnSto(); } /// @brief stosneg keyword implementation /// -void program::rpn_stoneg(void) { +void program::RpnStoneg(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); - rpn_neg(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); + RpnNeg(); + RpnSwap(); + RpnSto(); } /// @brief sinv keyword implementation /// -void program::rpn_stoinv(void) { +void program::RpnStoinv(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); if (heap_.find(stack_.value(0)) == heap_.end()) { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); return; } - rpn_dup(); - rpn_rcl(); - rpn_inv(); - rpn_swap(); - rpn_sto(); + RpnDup(); + RpnRcl(); + RpnInv(); + RpnSwap(); + RpnSto(); } /// @brief rcl keyword implementation /// -void program::rpn_rcl(void) { +void program::RpnRcl(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); @@ -130,53 +130,53 @@ void program::rpn_rcl(void) { string variable(stack_.value(0)); // mind the order of heaps - if (find_variable(variable, obj)) { + if (FindVariable(variable, obj)) { (void)stack_.pop(); - stack_.push_front(obj->clone()); + stack_.push_front(obj->Clone()); } else { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); } } /// @brief edit keyword implementation /// -void program::rpn_edit(void) { +void program::RpnEdit(void) { MIN_ARGUMENTS(1); ostringstream st; // re-write stack_ objet in a stream - stack_.at(0)->show(st); + stack_.at(0)->Show(st); stack_.pop(); // set it as the linenoise line entry - Input::preload(st.str().c_str()); + Input::Preload(st.str().c_str()); } /// @brief recall then eval a symbol variable if it is auto-evaluable /// /// @param symb the smlbol to recall and autoeval /// -void program::auto_rcl(Symbol* symb) { +void program::AutoRcl(Symbol* symb) { if (symb->auto_eval) { Object* obj; string variable(symb->value); // mind the order of heaps - if (find_variable(variable, obj)) { - stack_.push_front(obj->clone()); - if (obj->_type == kProgram) rpn_eval(); + if (FindVariable(variable, obj)) { + stack_.push_front(obj->Clone()); + if (obj->_type == kProgram) RpnEval(); } else { - stack_.push_front(symb->clone()); + stack_.push_front(symb->Clone()); } } else { - stack_.push_front(symb->clone()); + stack_.push_front(symb->Clone()); } } /// @brief purge keyword implementation /// -void program::rpn_purge(void) { +void program::RpnPurge(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kSymbol); @@ -185,14 +185,14 @@ void program::rpn_purge(void) { delete i->second; heap_.erase(i); } else { - setErrorContext(kUnknownVariable); + ERROR_CONTEXT(kUnknownVariable); } stack_.pop(); } /// @brief vars keyword implementation /// -void program::rpn_vars(void) { +void program::RpnVars(void) { Object* obj; program* parent = parent_; string name; @@ -200,21 +200,21 @@ void program::rpn_vars(void) { // heap variables for (auto i : heap_) { - cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; - i.second->show(cout) << endl; + cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->Name() << ", value "; + i.second->Show(cout) << endl; } // local variables for (auto i : local_heap_) { - cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; - i.second->show(cout) << endl; + cout << "var " << index++ << ": name '" << i.first << "', type " << i.second->Name() << ", value "; + i.second->Show(cout) << endl; } // parents local variables while (parent != nullptr) { for (auto i : parent->local_heap_) { - cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->name() << ", value "; - obj->show(cout) << endl; + cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->Name() << ", value "; + obj->Show(cout) << endl; } parent = parent->parent_; } @@ -222,4 +222,4 @@ void program::rpn_vars(void) { /// @brief clusr keyword implementation /// -void program::rpn_clusr(void) { heap_.clear(); } +void program::RpnClusr(void) { heap_.clear(); } diff --git a/src/rpn-string.cpp b/src/rpn-string.cpp index 4908265..69199cf 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cpp @@ -6,7 +6,7 @@ /// @brief ->str keyword implementation /// -void program::rpn_instr() { +void program::RpnInstr() { MIN_ARGUMENTS(1); // stringify only if not already a string @@ -20,7 +20,7 @@ void program::rpn_instr() { /// @brief str-> keyword implementation /// -void program::rpn_strout() { +void program::RpnStrout() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); @@ -29,14 +29,14 @@ void program::rpn_strout() { stack_.pop(); // make program from string in stack_ level 1 - if (prog.parse(entry) == kOk) + if (prog.Parse(entry) == kOk) // run it - prog.run(); + prog.Run(); } /// @brief chr keyword implementation /// -void program::rpn_chr() { +void program::RpnChr() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); char the_chr = static_cast(stack_.value(0).toLong()); @@ -47,7 +47,7 @@ void program::rpn_chr() { /// @brief num keyword implementation /// -void program::rpn_num() { +void program::RpnNum() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); if (stack_.value(0).size() > 0) @@ -59,7 +59,7 @@ void program::rpn_num() { /// @brief size keyword implementation /// -void program::rpn_strsize() { +void program::RpnStrsize() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); stack_.push_front(new Number(stack_.value(0).size())); @@ -68,7 +68,7 @@ void program::rpn_strsize() { /// @brief pos keyword implementation /// -void program::rpn_strpos() { +void program::RpnStrpos() { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kString); ARG_MUST_BE_OF_TYPE(1, kString); @@ -80,7 +80,7 @@ void program::rpn_strpos() { /// @brief sub keyword implementation /// -void program::rpn_strsub() { +void program::RpnStrsub() { MIN_ARGUMENTS(3); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cpp index d2a91bb..7e68476 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cpp @@ -11,7 +11,7 @@ static const char FG_RED[] = "\33[31m"; static const char FG_GREEN[] = "\33[32m"; static const char COLOR_OFF[] = "\33[m"; -static void findAndReplaceAll(string& data, string toSearch, string replaceStr) { +static void FindAndReplaceAll(string& data, string toSearch, string replaceStr) { // Get the first occurrence size_t pos = data.find(toSearch); // Repeat till end is reached @@ -28,17 +28,17 @@ static void findAndReplaceAll(string& data, string toSearch, string replaceStr) /// @param stack_is the output string /// @param stk the stack /// -static void getStackAsString(string& stack_is, rpnstack& stk) { +static void GetStackAsString(string& stack_is, rpnstack& stk) { ostringstream st; if (stk.empty()) { stack_is.clear(); return; } - stk[stk.size() - 1]->show(st); + stk[stk.size() - 1]->Show(st); stack_is += st.str(); for (int i = static_cast(stk.size()) - 2; i >= 0; i--) { ostringstream st; - stk[i]->show(st); + stk[i]->Show(st); stack_is += ", " + st.str(); } } @@ -51,7 +51,7 @@ static void getStackAsString(string& stack_is, rpnstack& stk) { /// @param steps steps nb /// @param steps_failed failed steps nb /// -static void testShowResult(string title, int tests, int tests_failed, int steps, int steps_failed) { +static void ShowTestResult(string title, int tests, int tests_failed, int steps, int steps_failed) { if (!title.empty()) cout << title << ": "; cout << "run " << tests << " tests: " << tests - tests_failed << " passed, "; if (tests_failed > 0) cout << FG_RED; @@ -67,7 +67,7 @@ static void testShowResult(string title, int tests, int tests_failed, int steps, /// @brief test keyword implementation /// -void program::rpn_test() { +void program::RpnTest() { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kString); @@ -79,8 +79,8 @@ void program::rpn_test() { string test_filename = stack_.value(0); stack_.pop(); cout << endl << "rpn version is " << RPN_VERSION << endl; - test(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); - testShowResult("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); + RunTestFile(test_filename, total_tests, total_tests_failed, total_steps, total_steps_failed); + ShowTestResult("\nTotal", total_tests, total_tests_failed, total_steps, total_steps_failed); // notify to caller that test succeeded or not if (total_tests_failed > 0) { @@ -97,7 +97,7 @@ void program::rpn_test() { /// @param total_steps the total steps nb /// @param total_steps_failed the total failed steps nb /// -void program::test(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, +void program::RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps, int& total_steps_failed) { const string stack_size("-> stack size should be "); const string stack_value("-> stack should be "); @@ -131,7 +131,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail if (entry.empty()) continue; if (entry.substr(0, 8) == "@include") { - test(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed); + RunTestFile(entry.substr(9), total_tests, total_tests_failed, total_steps, total_steps_failed); } else if (entry.substr(0, 2) == "# ") { cout << endl << test_filename << ": " << entry.substr(2) << endl; } else if (entry.substr(0, 3) == "## ") { @@ -179,7 +179,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail string stack_should_be = entry.substr(stack_value.size()); string stack_is; - getStackAsString(stack_is, stk); + GetStackAsString(stack_is, stk); if (stack_is != stack_should_be) { // count fail test and step @@ -242,14 +242,14 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail failed = true; } else { // parse entry and run line - findAndReplaceAll(entry, "`", ""); + FindAndReplaceAll(entry, "`", ""); if (!entry.empty()) { program prog(stk, hp); - ret = prog.parse(entry); + ret = prog.Parse(entry); if (ret == kOk) { // run it - (void)prog.run(); - last_err = static_cast(prog.get_err()); + (void)prog.Run(); + last_err = static_cast(prog.GetLastError()); } } } @@ -264,7 +264,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail // conclusion: show and keep for total if (tests != 0) { - testShowResult("", tests, tests_failed, steps, steps_failed); + ShowTestResult("", tests, tests_failed, steps, steps_failed); total_tests += tests; total_tests_failed += tests_failed; diff --git a/src/rpn-test.cpp b/src/rpn-test.cpp index 57df584..2ce25a5 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cpp @@ -17,7 +17,7 @@ static int CmpStringOnStackTop(rpnstack& stk) { /// @brief > keyword implementation /// -void program::rpn_sup(void) { +void program::RpnSup(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.push_front(new Number(stack_.value(1) > stack_.value(0))); @@ -26,13 +26,13 @@ void program::rpn_sup(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) == 1)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief >= keyword implementation /// -void program::rpn_sup_eq(void) { +void program::RpnSupEq(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.push_front(new Number(stack_.value(1) >= stack_.value(0))); @@ -41,13 +41,13 @@ void program::rpn_sup_eq(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) != -1)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief < keyword implementation /// -void program::rpn_inf(void) { +void program::RpnInf(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { @@ -57,13 +57,13 @@ void program::rpn_inf(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) == -1)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief <= keyword implementation /// -void program::rpn_inf_eq(void) { +void program::RpnInfEq(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.push_front(new Number(stack_.value(1) <= stack_.value(0))); @@ -72,13 +72,13 @@ void program::rpn_inf_eq(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) != 1)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief != keyword implementation /// -void program::rpn_diff(void) { +void program::RpnDiff(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.push_front(new Number(stack_.value(1) != stack_.value(0))); @@ -90,13 +90,13 @@ void program::rpn_diff(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) != 0)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief == keyword implementation /// -void program::rpn_eq(void) { +void program::RpnEq(void) { MIN_ARGUMENTS(2); if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) { stack_.push_front(new Number(stack_.value(1) == stack_.value(0))); @@ -108,13 +108,13 @@ void program::rpn_eq(void) { stack_.push_front(new Number(CmpStringOnStackTop(stack_) == 0)); stack_.erase(1, 2); } else { - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } } /// @brief and keyword implementation /// -void program::rpn_test_and(void) { +void program::RpnTestAnd(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -127,7 +127,7 @@ void program::rpn_test_and(void) { /// @brief or keyword implementation /// -void program::rpn_test_or(void) { +void program::RpnTestOr(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -140,7 +140,7 @@ void program::rpn_test_or(void) { /// @brief xor keyword implementation /// -void program::rpn_test_xor(void) { +void program::RpnTestXor(void) { MIN_ARGUMENTS(2); ARG_MUST_BE_OF_TYPE(0, kNumber); ARG_MUST_BE_OF_TYPE(1, kNumber); @@ -153,7 +153,7 @@ void program::rpn_test_xor(void) { /// @brief not keyword implementation /// -void program::rpn_test_not(void) { +void program::RpnTestNot(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); @@ -163,4 +163,4 @@ void program::rpn_test_not(void) { /// @brief test same implementation /// -void program::rpn_same(void) { rpn_eq(); } +void program::RpnSame(void) { RpnEq(); } diff --git a/src/rpn-time.cpp b/src/rpn-time.cpp index 3a8cb1f..84e9e71 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cpp @@ -6,7 +6,7 @@ /// @brief time keyword implementation /// -void program::rpn_time() { +void program::RpnTime() { struct timespec ts; struct tm* tm; double date; @@ -25,13 +25,13 @@ void program::rpn_time() { stack_.push(new Number(date)); stack_.value(0) /= 10000000000.0; } else { - setErrorContext(kInternalError); + ERROR_CONTEXT(kInternalError); } } /// @brief date keyword implementation /// -void program::rpn_date() { +void program::RpnDate() { struct timespec ts; struct tm* tm; double date; @@ -51,13 +51,13 @@ void program::rpn_date() { stack_.push(new Number(date)); stack_.value(0) /= 1000000.0; } else { - setErrorContext(kInternalError); + ERROR_CONTEXT(kInternalError); } } /// @brief ticks keyword implementation /// -void program::rpn_ticks() { +void program::RpnTicks() { struct timespec ts; struct tm* tm; double date; @@ -71,6 +71,6 @@ void program::rpn_ticks() { date = 1000000.0 * static_cast(ts.tv_sec) + static_cast(ts.tv_nsec / 1000); stack_.push(new Number(date)); } else { - setErrorContext(kInternalError); + ERROR_CONTEXT(kInternalError); } } diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cpp index 61c7da8..0fa99f1 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cpp @@ -4,13 +4,13 @@ /// @brief pi keyword implementation /// -void program::rpn_pi(void) { +void program::RpnPi(void) { stack_.push_front(new Number(mpfr::const_pi())); } /// @brief d->r keyword implementation /// -void program::rpn_d2r(void) { +void program::RpnD2r(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) *= mpfr::const_pi(); @@ -19,7 +19,7 @@ void program::rpn_d2r(void) { /// @brief r->d keyword implementation /// -void program::rpn_r2d(void) { +void program::RpnR2d(void) { MIN_ARGUMENTS(1); ARG_MUST_BE_OF_TYPE(0, kNumber); stack_.value(0) /= mpfr::const_pi(); @@ -28,72 +28,72 @@ void program::rpn_r2d(void) { /// @brief sin keyword implementation /// -void program::rpn_sin(void) { +void program::RpnSin(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = sin(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = sin(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief asin keyword implementation /// -void program::rpn_asin(void) { +void program::RpnAsin(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = asin(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = asin(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief cos keyword implementation /// -void program::rpn_cos(void) { +void program::RpnCos(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = cos(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = cos(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief acos keyword implementation /// -void program::rpn_acos(void) { +void program::RpnAcos(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = acos(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = acos(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief tan keyword implementation /// -void program::rpn_tan(void) { +void program::RpnTan(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = tan(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = tan(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } /// @brief atan keyword implementation /// -void program::rpn_atan(void) { +void program::RpnAtan(void) { MIN_ARGUMENTS(1); if (stack_.type(0) == kNumber) stack_.value(0) = atan(stack_.value(0)); else if (stack_.type(0) == kComplex) stack_.value(0) = atan(stack_.value(0)); else - setErrorContext(kBadOperandType); + ERROR_CONTEXT(kBadOperandType); } diff --git a/src/stack.hpp b/src/stack.hpp index fc69912..abc216e 100644 --- a/src/stack.hpp +++ b/src/stack.hpp @@ -3,11 +3,11 @@ #ifndef SRC_STACK_HPP_ #define SRC_STACK_HPP_ -#include #include #include #include -using namespace std; +#include +using std::deque, std::map, std::string; #include "object.hpp" From 25dc731559e978b560ea4415f2f9083a2be134b9 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Fri, 25 Feb 2022 16:13:20 +0100 Subject: [PATCH 45/57] cpp files to cc, hpp files to h --- CMakeLists.txt | 38 +++++++++---------- src/{input.cpp => input.cc} | 2 +- src/{input.hpp => input.h} | 0 src/{lexer.cpp => lexer.cc} | 2 +- src/{lexer.hpp => lexer.h} | 2 +- src/{main.cpp => main.cc} | 4 +- src/{mpreal-out.cpp => mpreal-out.cc} | 2 +- src/{mpreal-out.hpp => mpreal-out.h} | 0 src/{object.cpp => object.cc} | 2 +- src/{object.hpp => object.h} | 8 ++-- src/{program.cpp => program.cc} | 2 +- src/{program.hpp => program.h} | 6 +-- src/{rpn-branch.cpp => rpn-branch.cc} | 2 +- src/{rpn-complex.cpp => rpn-complex.cc} | 2 +- src/{rpn-general.cpp => rpn-general.cc} | 2 +- src/{rpn-logs.cpp => rpn-logs.cc} | 2 +- src/{rpn-program.cpp => rpn-program.cc} | 2 +- src/{rpn-real.cpp => rpn-real.cc} | 2 +- src/{rpn-stack.cpp => rpn-stack.cc} | 2 +- src/{rpn-store.cpp => rpn-store.cc} | 4 +- src/{rpn-string.cpp => rpn-string.cc} | 2 +- ...st-framework.cpp => rpn-test-framework.cc} | 2 +- src/{rpn-test.cpp => rpn-test.cc} | 2 +- src/{rpn-time.cpp => rpn-time.cc} | 2 +- src/{rpn-trig.cpp => rpn-trig.cc} | 2 +- src/{stack.hpp => stack.h} | 2 +- 26 files changed, 49 insertions(+), 49 deletions(-) rename src/{input.cpp => input.cc} (99%) rename src/{input.hpp => input.h} (100%) rename src/{lexer.cpp => lexer.cc} (99%) rename src/{lexer.hpp => lexer.h} (99%) rename src/{main.cpp => main.cc} (98%) rename src/{mpreal-out.cpp => mpreal-out.cc} (99%) rename src/{mpreal-out.hpp => mpreal-out.h} (100%) rename src/{object.cpp => object.cc} (87%) rename src/{object.hpp => object.h} (98%) rename src/{program.cpp => program.cc} (99%) rename src/{program.hpp => program.h} (99%) rename src/{rpn-branch.cpp => rpn-branch.cc} (99%) rename src/{rpn-complex.cpp => rpn-complex.cc} (99%) rename src/{rpn-general.cpp => rpn-general.cc} (99%) rename src/{rpn-logs.cpp => rpn-logs.cc} (99%) rename src/{rpn-program.cpp => rpn-program.cc} (99%) rename src/{rpn-real.cpp => rpn-real.cc} (99%) rename src/{rpn-stack.cpp => rpn-stack.cc} (99%) rename src/{rpn-store.cpp => rpn-store.cc} (99%) rename src/{rpn-string.cpp => rpn-string.cc} (99%) rename src/{rpn-test-framework.cpp => rpn-test-framework.cc} (99%) rename src/{rpn-test.cpp => rpn-test.cc} (99%) rename src/{rpn-time.cpp => rpn-time.cc} (98%) rename src/{rpn-trig.cpp => rpn-trig.cc} (99%) rename src/{stack.hpp => stack.h} (98%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 801a9d0..2a75c5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,25 +51,25 @@ include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng # build add_executable( rpn - ${PROJECT_SOURCE_DIR}/src/main.cpp - ${PROJECT_SOURCE_DIR}/src/object.cpp - ${PROJECT_SOURCE_DIR}/src/mpreal-out.cpp - ${PROJECT_SOURCE_DIR}/src/program.cpp - ${PROJECT_SOURCE_DIR}/src/lexer.cpp - ${PROJECT_SOURCE_DIR}/src/input.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-branch.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-complex.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-general.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-logs.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-program.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-real.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-stack.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-store.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-string.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-test.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-time.cpp - ${PROJECT_SOURCE_DIR}/src/rpn-trig.cpp + ${PROJECT_SOURCE_DIR}/src/main.cc + ${PROJECT_SOURCE_DIR}/src/object.cc + ${PROJECT_SOURCE_DIR}/src/mpreal-out.cc + ${PROJECT_SOURCE_DIR}/src/program.cc + ${PROJECT_SOURCE_DIR}/src/lexer.cc + ${PROJECT_SOURCE_DIR}/src/input.cc + ${PROJECT_SOURCE_DIR}/src/rpn-branch.cc + ${PROJECT_SOURCE_DIR}/src/rpn-complex.cc + ${PROJECT_SOURCE_DIR}/src/rpn-general.cc + ${PROJECT_SOURCE_DIR}/src/rpn-logs.cc + ${PROJECT_SOURCE_DIR}/src/rpn-program.cc + ${PROJECT_SOURCE_DIR}/src/rpn-real.cc + ${PROJECT_SOURCE_DIR}/src/rpn-stack.cc + ${PROJECT_SOURCE_DIR}/src/rpn-store.cc + ${PROJECT_SOURCE_DIR}/src/rpn-string.cc + ${PROJECT_SOURCE_DIR}/src/rpn-test.cc + ${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc + ${PROJECT_SOURCE_DIR}/src/rpn-time.cc + ${PROJECT_SOURCE_DIR}/src/rpn-trig.cc ${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp diff --git a/src/input.cpp b/src/input.cc similarity index 99% rename from src/input.cpp rename to src/input.cc index 7c84f5b..c9c50bf 100644 --- a/src/input.cpp +++ b/src/input.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "input.hpp" +#include "input.h" #include diff --git a/src/input.hpp b/src/input.h similarity index 100% rename from src/input.hpp rename to src/input.h diff --git a/src/lexer.cpp b/src/lexer.cc similarity index 99% rename from src/lexer.cpp rename to src/lexer.cc index 98b4ab8..79cee56 100644 --- a/src/lexer.cpp +++ b/src/lexer.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "lexer.hpp" +#include "lexer.h" bool Lexer::Analyse(string& entry, map& keywords, vector& elements, vector& errors) { diff --git a/src/lexer.hpp b/src/lexer.h similarity index 99% rename from src/lexer.hpp rename to src/lexer.h index 532ee23..e31ba0a 100644 --- a/src/lexer.hpp +++ b/src/lexer.h @@ -11,7 +11,7 @@ using mpfr::mpreal; #include using std::map, std::string, std::vector; -#include "object.hpp" +#include "object.h" class Lexer { public: diff --git a/src/main.cpp b/src/main.cc similarity index 98% rename from src/main.cpp rename to src/main.cc index 9f5d2b5..374b0f9 100644 --- a/src/main.cpp +++ b/src/main.cc @@ -9,8 +9,8 @@ using std::cerr; // internal includes -#include "input.hpp" -#include "program.hpp" +#include "input.h" +#include "program.h" /// @brief actions to be done at rpn exit /// diff --git a/src/mpreal-out.cpp b/src/mpreal-out.cc similarity index 99% rename from src/mpreal-out.cpp rename to src/mpreal-out.cc index 6b71028..dfb5d4b 100644 --- a/src/mpreal-out.cpp +++ b/src/mpreal-out.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "mpreal-out.hpp" +#include "mpreal-out.h" #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(h, i) ((h) > (i) ? (h) : (i)) diff --git a/src/mpreal-out.hpp b/src/mpreal-out.h similarity index 100% rename from src/mpreal-out.hpp rename to src/mpreal-out.h diff --git a/src/object.cpp b/src/object.cc similarity index 87% rename from src/object.cpp rename to src/object.cc index 840266e..36deefd 100644 --- a/src/object.cpp +++ b/src/object.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "object.hpp" +#include "object.h" // number statics Number::mode_enum Number::mode = Number::kDefaultMode; diff --git a/src/object.hpp b/src/object.h similarity index 98% rename from src/object.hpp rename to src/object.h index 68eff2e..bf56f39 100644 --- a/src/object.hpp +++ b/src/object.h @@ -1,7 +1,7 @@ // Copyright (c) 2014-2022 Louis Rubet -#ifndef SRC_OBJECT_HPP_ -#define SRC_OBJECT_HPP_ +#ifndef SRC_OBJECT_H_ +#define SRC_OBJECT_H_ #include using mpfr::mpreal; @@ -12,7 +12,7 @@ using mpfr::mpreal; #include using std::complex, std::ostream, std::string, std::stringstream; -#include "mpreal-out.hpp" +#include "mpreal-out.h" // definitions for objects /// @@ -212,4 +212,4 @@ struct Branch : Object { string value; }; -#endif // SRC_OBJECT_HPP_ +#endif // SRC_OBJECT_H_ diff --git a/src/program.cpp b/src/program.cc similarity index 99% rename from src/program.cpp rename to src/program.cc index 0276800..12e5ef4 100644 --- a/src/program.cpp +++ b/src/program.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" //< language reserved keywords (allowed types are kKeyword, kBranch or kUndef) vector program::keywords_{ diff --git a/src/program.hpp b/src/program.h similarity index 99% rename from src/program.hpp rename to src/program.h index 1df080f..cfe5827 100644 --- a/src/program.hpp +++ b/src/program.h @@ -14,9 +14,9 @@ using namespace std; using mpfr::mpreal; // internal includes -#include "lexer.hpp" -#include "object.hpp" -#include "stack.hpp" +#include "lexer.h" +#include "object.h" +#include "stack.h" //< program class: the class containing a string parser, all the programs keywords, a stack for running the program class program : public deque, public Lexer { diff --git a/src/rpn-branch.cpp b/src/rpn-branch.cc similarity index 99% rename from src/rpn-branch.cpp rename to src/rpn-branch.cc index 133c2f8..e72d0cf 100644 --- a/src/rpn-branch.cpp +++ b/src/rpn-branch.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief if keyword (branch) implementation /// diff --git a/src/rpn-complex.cpp b/src/rpn-complex.cc similarity index 99% rename from src/rpn-complex.cpp rename to src/rpn-complex.cc index c0b01e5..55d3aed 100644 --- a/src/rpn-complex.cpp +++ b/src/rpn-complex.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief re keyword implementation /// the result is stacked on current program stack diff --git a/src/rpn-general.cpp b/src/rpn-general.cc similarity index 99% rename from src/rpn-general.cpp rename to src/rpn-general.cc index abe720e..7437f8f 100644 --- a/src/rpn-general.cpp +++ b/src/rpn-general.cc @@ -6,7 +6,7 @@ using std::cout, std::string, std::pair; #include "linenoise.h" -#include "program.hpp" +#include "program.h" #include "version.h" // description diff --git a/src/rpn-logs.cpp b/src/rpn-logs.cc similarity index 99% rename from src/rpn-logs.cpp rename to src/rpn-logs.cc index 1568dd8..379ad79 100644 --- a/src/rpn-logs.cpp +++ b/src/rpn-logs.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief e keyword implementation /// diff --git a/src/rpn-program.cpp b/src/rpn-program.cc similarity index 99% rename from src/rpn-program.cpp rename to src/rpn-program.cc index 7bc7006..c4d0199 100644 --- a/src/rpn-program.cpp +++ b/src/rpn-program.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief find variable by its name in local heap, successive parents heaps, global heap /// diff --git a/src/rpn-real.cpp b/src/rpn-real.cc similarity index 99% rename from src/rpn-real.cpp rename to src/rpn-real.cc index 53750c3..93f9901 100644 --- a/src/rpn-real.cpp +++ b/src/rpn-real.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief + keyword implementation /// diff --git a/src/rpn-stack.cpp b/src/rpn-stack.cc similarity index 99% rename from src/rpn-stack.cpp rename to src/rpn-stack.cc index f4e3d1d..92b2892 100644 --- a/src/rpn-stack.cpp +++ b/src/rpn-stack.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief swap keyword implementation /// diff --git a/src/rpn-store.cpp b/src/rpn-store.cc similarity index 99% rename from src/rpn-store.cpp rename to src/rpn-store.cc index e387703..3e9c316 100644 --- a/src/rpn-store.cpp +++ b/src/rpn-store.cc @@ -1,7 +1,7 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "input.hpp" -#include "program.hpp" +#include "input.h" +#include "program.h" /// @brief sto keyword implementation /// diff --git a/src/rpn-string.cpp b/src/rpn-string.cc similarity index 99% rename from src/rpn-string.cpp rename to src/rpn-string.cc index 69199cf..83b3340 100644 --- a/src/rpn-string.cpp +++ b/src/rpn-string.cc @@ -2,7 +2,7 @@ #include -#include "program.hpp" +#include "program.h" /// @brief ->str keyword implementation /// diff --git a/src/rpn-test-framework.cpp b/src/rpn-test-framework.cc similarity index 99% rename from src/rpn-test-framework.cpp rename to src/rpn-test-framework.cc index 7e68476..f0e4742 100644 --- a/src/rpn-test-framework.cpp +++ b/src/rpn-test-framework.cc @@ -3,7 +3,7 @@ #include using std::string; -#include "program.hpp" +#include "program.h" #include "version.h" // foreground colors diff --git a/src/rpn-test.cpp b/src/rpn-test.cc similarity index 99% rename from src/rpn-test.cpp rename to src/rpn-test.cc index 2ce25a5..fe610b0 100644 --- a/src/rpn-test.cpp +++ b/src/rpn-test.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief compared 2 strings on top of the stack_ /// diff --git a/src/rpn-time.cpp b/src/rpn-time.cc similarity index 98% rename from src/rpn-time.cpp rename to src/rpn-time.cc index 84e9e71..f763dba 100644 --- a/src/rpn-time.cpp +++ b/src/rpn-time.cc @@ -2,7 +2,7 @@ #include -#include "program.hpp" +#include "program.h" /// @brief time keyword implementation /// diff --git a/src/rpn-trig.cpp b/src/rpn-trig.cc similarity index 99% rename from src/rpn-trig.cpp rename to src/rpn-trig.cc index 0fa99f1..d31ceb3 100644 --- a/src/rpn-trig.cpp +++ b/src/rpn-trig.cc @@ -1,6 +1,6 @@ // Copyright (c) 2014-2022 Louis Rubet -#include "program.hpp" +#include "program.h" /// @brief pi keyword implementation /// diff --git a/src/stack.hpp b/src/stack.h similarity index 98% rename from src/stack.hpp rename to src/stack.h index abc216e..96cf050 100644 --- a/src/stack.hpp +++ b/src/stack.h @@ -9,7 +9,7 @@ #include using std::deque, std::map, std::string; -#include "object.hpp" +#include "object.h" /// @brief stack object, parens of program, storing execution stack values or programs /// From 261ae2a57c997b407fbb26ef26af9b53a503e0ad Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Sat, 26 Feb 2022 15:22:26 +0100 Subject: [PATCH 46/57] git tag used as rpn version --- CMakeLists.txt | 79 ++++++++++++++++++------------------- Changelog.md | 1 + liv/rpn-2.1-amd64.deb | Bin 322310 -> 0 bytes liv/rpn-2.1-amd64.rpm | Bin 327476 -> 0 bytes liv/rpn-2.1-amd64.tar.gz | Bin 321809 -> 0 bytes liv/rpn-2.2-amd64.deb | Bin 332530 -> 0 bytes liv/rpn-2.2-amd64.rpm | Bin 339459 -> 0 bytes liv/rpn-2.2-amd64.tar.gz | Bin 332050 -> 0 bytes liv/rpn-2.3-amd64.deb | Bin 99746 -> 0 bytes liv/rpn-2.3-amd64.rpm | Bin 108227 -> 0 bytes liv/rpn-2.3-amd64.tar.gz | Bin 98787 -> 0 bytes liv/rpn-2.3.1-amd64.deb | Bin 104262 -> 0 bytes liv/rpn-2.3.1-amd64.rpm | Bin 113594 -> 0 bytes liv/rpn-2.3.1-amd64.tar.gz | Bin 103310 -> 0 bytes liv/rpn-2.3.2-amd64.deb | Bin 134106 -> 0 bytes liv/rpn-2.3.2-amd64.rpm | Bin 143265 -> 0 bytes liv/rpn-2.3.2-amd64.tar.gz | Bin 133131 -> 0 bytes src/version.h | 2 +- 18 files changed, 40 insertions(+), 42 deletions(-) delete mode 100644 liv/rpn-2.1-amd64.deb delete mode 100644 liv/rpn-2.1-amd64.rpm delete mode 100644 liv/rpn-2.1-amd64.tar.gz delete mode 100644 liv/rpn-2.2-amd64.deb delete mode 100644 liv/rpn-2.2-amd64.rpm delete mode 100644 liv/rpn-2.2-amd64.tar.gz delete mode 100644 liv/rpn-2.3-amd64.deb delete mode 100644 liv/rpn-2.3-amd64.rpm delete mode 100644 liv/rpn-2.3-amd64.tar.gz delete mode 100644 liv/rpn-2.3.1-amd64.deb delete mode 100644 liv/rpn-2.3.1-amd64.rpm delete mode 100644 liv/rpn-2.3.1-amd64.tar.gz delete mode 100644 liv/rpn-2.3.2-amd64.deb delete mode 100644 liv/rpn-2.3.2-amd64.rpm delete mode 100644 liv/rpn-2.3.2-amd64.tar.gz diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a75c5f..8f96e47 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,9 @@ # -*- mode: CMAKE; -*- -cmake_minimum_required(VERSION 2.6) - project(rpn) +cmake_minimum_required(VERSION 3.22) + if((NOT CMAKE_BUILD_TYPE MATCHES Debug) AND (NOT CMAKE_BUILD_TYPE MATCHES Release)) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build, options are: None Debug Release" FORCE) @@ -11,12 +11,37 @@ endif() message(STATUS "Build mode: ${CMAKE_BUILD_TYPE}") +if(EXISTS ${PROJECT_SOURCE_DIR}/.git) + EXECUTE_PROCESS( + COMMAND git rev-parse --abbrev-ref --short=10 HEAD + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE "BRANCH") + MESSAGE( STATUS "Source Git Branch: ${GIT_BRANCH}" ) + EXECUTE_PROCESS( + COMMAND git describe --dirty --tags --long --always + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE "TAG" + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + MESSAGE( STATUS "Source Git Tag: ${GIT_TAG}" ) + EXECUTE_PROCESS( + COMMAND echo ${TAG}-${BRANCH} + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}" + OUTPUT_VARIABLE "GIT_VERSION" + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + MESSAGE( STATUS "Source Git version: ${GIT_VERSION}" ) + add_definitions(-DGIT_VERSION="${GIT_VERSION}") + else(EXISTS ${PROJECT_SOURCE_DIR}/.git) + add_definitions(-DGIT_VERSION="unknown") + message("Warning, built outside of a git repo, version set to ${GIT_VERSION}") +endif(EXISTS ${PROJECT_SOURCE_DIR}/.git) + # INFO -set(RPN_VERSION "2.4") set(RPN_DISPLAY_NAME "rpn") set(RPN_URL_INFO_ABOUT "https://github.com/louisrubet/rpn") set(RPN_CONTACT "Louis Rubet ") -set(RPN_FRIENDLY_STRING "rpn - Reverse Polish Notation math language") +set(RPN_FRIENDLY_STRING "Reverse Polish Notation math language") set(RPN_LICENSE "LGPLv3") set(RPN_LICENSE_FILE "${PROJECT_SOURCE_DIR}/LICENSE") set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md") @@ -33,16 +58,16 @@ endif() # custom linenoise-ng if(NOT EXISTS "${PROJECT_SOURCE_DIR}/linenoise-ng/.git") - execute_process(COMMAND git submodule init ${PROJECT_SOURCE_DIR}/linenoise-ng) - execute_process(COMMAND git submodule update ${PROJECT_SOURCE_DIR}/linenoise-ng) - execute_process(COMMAND git checkout v1.1.1-rpn WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/linenoise-ng) + execute_process(command git submodule init ${PROJECT_SOURCE_DIR}/linenoise-ng) + execute_process(command git submodule update ${PROJECT_SOURCE_DIR}/linenoise-ng) + execute_process(command git checkout v1.1.1-rpn WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/linenoise-ng) endif() # custom mpreal if(NOT EXISTS "${PROJECT_SOURCE_DIR}/mpreal/.git") - execute_process(COMMAND git submodule init ${PROJECT_SOURCE_DIR}/mpreal) - execute_process(COMMAND git submodule update ${PROJECT_SOURCE_DIR}/mpreal) - execute_process(COMMAND git checkout mpfrc++-3.6.9 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/mpreal) + execute_process(command git submodule init ${PROJECT_SOURCE_DIR}/mpreal) + execute_process(command git submodule update ${PROJECT_SOURCE_DIR}/mpreal) + execute_process(command git checkout mpfrc++-3.6.9 WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/mpreal) endif() # includes @@ -74,45 +99,17 @@ add_executable( ${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp ${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp ) + target_link_libraries(rpn mpfr) target_link_libraries(rpn gmp) # man add_custom_target(man ALL) add_custom_command( - TARGET man - COMMAND gzip -f -k ${CMAKE_CURRENT_SOURCE_DIR}/doc/rpn.1 - OUTPUTS ${CMAKE_CURRENT_SOURCE_DIR}/doc/rpn.1.gz + OUTPUT ${PROJECT_SOURCE_DIR}/doc/rpn.1.gz + COMMAND gzip -f -k ${PROJECT_SOURCE_DIR}/doc/rpn.1 ) # install install(TARGETS rpn DESTINATION bin) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/doc/rpn.1.gz DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man1) - -# packages (common variables for all packages) -set(CPACK_PACKAGE_NAME ${RPN_DISPLAY_NAME}) -set(CPACK_PACKAGE_VENDOR ${RPN_CONTACT}) -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY ${RPN_FRIENDLY_STRING}) -set(CPACK_PACKAGE_DESCRIPTION ${RPN_FRIENDLY_STRING}) -set(CPACK_PACKAGE_DESCRIPTION_FILE ${RPN_DESCRIPTION_FILE}) -set(CPACK_RESOURCE_FILE_LICENSE ${RPN_LICENSE_FILE}) -set(CPACK_RESOURCE_FILE_README ${RPN_DESCRIPTION_FILE}) - -set(CPACK_PACKAGE_FILE_NAME "${RPN_DISPLAY_NAME}-${RPN_VERSION}-amd64") -set(CPACK_PACKAGE_VERSION ${RPN_VERSION}) -#set(CPACK_PACKAGE_RELEASE 0) -set(CPACK_PACKAGE_CONTACT ${RPN_CONTACT}) -set(CPACK_PACKAGE_LICENSE ${RPN_LICENSE}) -set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - -# DEB package -set(CPACK_GENERATOR "DEB;RPM;TGZ") -set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${RPN_CONTACT}) -set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${SYSTEM_PROCESSOR}) -set(CPACK_DEBIAN_PACKAGE_SECTION "math") -set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional") - -include(CPack) - -# RPM package -set(CPACK_RPM_PACKAGE_REQUIRES "mpfr") diff --git a/Changelog.md b/Changelog.md index 18bc9a7..db89c4a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -22,6 +22,7 @@ Changelog - Test files are now markdown (.md) files, tests result are slightly changed - Delivery as flatpak and snap - error string are slightly different, althought error codes are still the same +- automatic version string from git, slightly change from previous versions New - `«` and `»` are now valid as program delimiters. `<<` and `>>` are still valid diff --git a/liv/rpn-2.1-amd64.deb b/liv/rpn-2.1-amd64.deb deleted file mode 100644 index 9123f61c70aa0c055a77b46419c83948509aafae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 322310 zcmafacTf{P{I-gKGF4mwnKBe)6$AuXWp7#m0YRXE z?7hn_P)c|E`n!AYec%7yTrQW~CAsAJ~gTcks$-~iC+{we&F);kj zojcNU%8D||%8If||MF5&QvXk?ASZX{&cFD-!y5(}2`L6=Ki_wOe%=!A90MiXBmV#G zWu@f*PkX_nYnOP48djHRj|{KqyD9M#Yp+!1b+pJyxoEt>$AD{%f3zNc4rVsh=NtU^>8IGhj+4ZGB8{u9 zzXnZ&)~nUzyJGq#<3yb4>JRefA2Qp%dCRwrJiL=*awW$H>EaX@{l5klB%U`+mMt@% z!~D0P({5w0j6G5J2$T=926)KJh(qv;Mk+Y=^JHYRJhT1=Yl=~(MH+%z!W)WrMbi&}2cgaGWju=;pvOWGbygD)fN%Vx#3sm;B(*eJ(Lw zy2Rk(_|EbFK>ZKL|DUyFWu%p)rT+);Hw^z5?Zc?+KvSJrtdB==miVFS$L_-y9S!jk z<4>aJ8j?yq@>-(huD`I>GrmS-p`EvV|Dh_lYU|GCOV z{arx?P^jXPt2kBu7V5Y^q_eMFeNyDKs`N$6ns*jfemaLUT1=gfRC+Oc!0%3b=E8 zZR$^LO`QOo?%M1dZu*G%;K)p)d9x21XQ*_Tr?s^0U(dwDh+>7RW$(KCMEg4+XoWn{ z-uU2QL)Axe_H7caqg5&{a4X4Sv);bT2-4-b76~RlMlNedSA3GQ4ROyvO$(T2PBstT zAF7=Z&Nv)KVQ&DT9p|$SB+$b!z`wdx!b7z{QiP58p7G7@ny>0L95(h^hz~gxh5yR7 z7xpR(BJ4B#DuGNjh;8VAhGIs}@h3z~sJCG2-3UVSAY^{Q=~wAVIf4{Xq5BHgYl~Z= zDPze>+mXxu67rbAq)&16i<5RD^X0qK$o{LJqR%SIE-}Am`oZ63DRwq4>5*5J+pkwr zR_D%Rsa=Zm%+PDjKQDsaHW9bd)SH7>k z+dsL#z^@)1P1tu|DQvRSyLNp%^2t6u-BH$S0*A@-wT*%6Ry`SF`eHs;WFXp^ZL^Cm!& z{!bhgmC(f5$AxUyZn^TzvCzGwH5XO47h_IlzLr_qKh8RyaY5jScI-d-sw?){Q%^uf z>f|%wa`d>?^l566SLBB)A4+8lc`m!&I-_c}k zsi>@{(pQ|mujoF)4^n2b3@b|e`=atrZ-T~ChDmx5J%h*(4tj%61}}9+)yAQpdJ1F9 zm_y=Yg=2rt#a^w&BwK7h-%Bym8NI^B8b?1<%g*)s?;YCSf>O=q%IN#e1vhRrUDP|> zV=|Q9tuJM{UMW1vJak{LwNqn4?cr5V_)Fm{$tmKHD&Fd-$*H%>AWu()i(dc zBz`!*i_x+k2j!OLmP_)(zrz;LZ6bHxgr_$J!|r#FAHF6oj56{bd!OU1UqEO6wy1o6 zkx^R!Gwr-%mK`^#Sj=H)Eh2ME%EpU@<#DATugoml?Oo%+*)LQ5HLEkB);6s^aRNjx=p6MpynUjFE!od;&y0dRC-Zjntgk^Xb{wdv$pzBcO<^6fT*Sf|(w#(p|ip4%d~IkVJ6@kVZ%;kSn$lUDfJ z#$sdyhp&h-7C(+{(A)L8+2z3On)1FT9?M&#mNLiD<=b~4>%W|e3jG-@0;4BB?7p=9 zpwuDG>w1>D(Z!Q_`t3_u+D56G4`Tyw58D`}YAIje_7O#`VG%zu>Y{>Alo_}AveJt3 z2N8gt19yM&l~pk9Y@jG-F))6Pz0E!*kbjt2RI!+JsqD%y!Uz<5#+$WTy!0WEci2u8 zTeK8^>ymk<<@p=Y>HlbBpUhCKjrO1XU@g0xC2W-Y#Dk@bHp|>-LDPf2Oo-rCaJs+_ zU0z>cTg9@tz^YjGuC)zl?$MM9W?eR-dorQT&Gdjnk1s1s^tw@;=8KOqOvBeig^Ja# zK42eyE9zXF93vwzd{vZH`|C$+Zt|>Lm)p;2rU#6AELlH{0*mL0+v*H7Y|FL3UM{;a ztS_4OB%EpZv1sFe;H$0zS$HE3Eh`3B+N{q;iFF0d{&uXcLRtTo8FLxeu({}Bks6Jw zY8JANV$i0+x=mZ^5Pje)8rcqJg3hj!FN@L_cU|6oC8`^XF#JgjE$*V8!D|bS|A!aYoq8rz1V}b(72!S*H=aQg73o=f6D*EsdR87Sj}E!4dd9B zTU4qotv&QajlR~jXzQL&OcmQ|=h}Xp$t73eEZv)6rrMyQk@$ui!}tD&kMRvW!`7m_ z#cFqd?>r2n%4NMu@QFQ85Jg-IE{w&h7OSytKM;j#K8!vSo0+GX?KWc3RKB_`m8DqR zMZ3+Fm1&8Rvqh{Cv9Xq0k6{4%S+tQx^sR=dr%O$JUXh&ca{^ZZq24afpjM0U2;}}& zsMqL%J?a7_s1fA7x3}5KM%T>&t3F^<1o+^dk#fcTlvS1w8e08v+x5psc5bD|-4CN0 z?wth&)<9WpQKTbhho#9vigRR$e~CF}r@KRKZEA)E{VH;0k2EOx@Ma-nH!o{dA!dt$ ziSxABZ&v!N)M~KU+*!44_#%g7YMgC~Zxmbvz3Dd$hJdzrYm-b<3b6c#R#R~u9Bm;#zKG7{mKanlU|bzeo$h(b zEG-DnJP)k$%Y{-lh6z0DrfiZODg_0ZAYrGlenmrXJGlSc6s-Ax9@(WFxxy*GLY2WD z{3`Q<1>Hlx?wyq$sP7btv`Zm}FU-UW%KIH1E0pxS1gPCoiR{_s987_p>g&KuQaN-@ zFVxzqswiP&Fmr^Q9cFEE4EEB#g5MFh-ApD&NJ8G8<%{!QntkY{H(1SO+(s^59t~L; zmk0;#cXX?ZT-XH$&u*|4E~&DaOW4ZAHENk+f^Z3rjCbuEdb*f;&>kMz-@&XeNBU6ew&FPLPKD)}1qlV^cq2rzwMlJb~cIwVQ_3uHLgB(=vl*R&qQ1XMTwP$J$M`!FA+E{jK8O@dJ|=U!>5F zEck}4r&tJDYUs@`4cAlsajbu*{WPRv6$AX>P9uve#ZITm*QGcL|5O!L*=snDrduCv zHkb=EF6c(yF?RSkO=m`k6x>N_VzjRkjU2D}c=8X;b~5 zz0I>znez(usKBEp-%n8e;`PFP(_h&&$KEzY zAP=*@vUa}7i)iG!0JKoe>~?Te9`ZHrd|gXc;86&yKHOzJ?p&d}j|Cej(ShS_3O+i> z;51-vj@MX{bzQ*hIaCh|V*hL|YIGbENZo#lSf;?Jw#AO3who=)UV zum98|9$%{zxv@LE-m|ajSd-n_5m;GgQ$EW2uD>-iv^uBlJZT{Xnry(@3EwiUFm=Ym z%Cn)$Q|iL#vO!3|w0c!;6!Gvx=uQ>MSHz|T_{pi+_b9S6Ey5G23jqB(acRIDQ?hiC zIzKJ#FNl;4CcT$O8aCA8)FAaer+tqP8Pb0(3o6Y^D1 zy~)pT($SmEIqldy)s|`iCS5eR%@r5R{;cgd&(z2^5_!Z4PmWY}H+!4SECL6)hhkhJ zci(Z9TOqLEch4rLX5BG%H!15Dx|K)f4xX~W!?@4NC*9?04&uQAwJV`uBGGX*3V{5) z7yl9fItI<?+k~oMP$a?NARtn^m3^Cb#CNF7`*y2SKznSnKobY3pUs!Pdz$ zP7$bt;$t6~LqhsY{J}K2VRav?VXx9UpI7rz0c;T%xLYyUx%#_Nu?{4STiX9^!OQfL z7&g3f_=R`5^Dsd6Pp2!u%z?Uqk$rWGF2@=+*Rt?aSk<})U@znDws_LCdp9rc9Bu_f zzX2j!-4NWLucFFw6nI-JI7U8m^gHYW>8dT98Z_+W)l}1?@m&n z{5T=}a0Xw4*~v9uY}GU}I4sY5yy&a;P$u4zh!aF~g>I!hl#);l88D}!t6B|8Y)%f~u0?Y|0pc-mwDm7#`pzXp68Bny?`nl2XXN>bYXQ*;a zEeZFw}wI;H`J0$+>8)RXi&_*2;M7j8WGkj5!a+Yw^lVbp#!pU|~av#L#4Qh~) zPlB=yKO96gmJu41;qlAxJb2U}PHhngtYBX8@%gg?qUjfeO1_dh+&WrY{cvR`^SV#3 z-?r_%bkJ!*s6g@oT*Fe4dN8%-=T;p~Fj;8Lo=Gm4uItMV&!pFR(PLP^>MPsxcJAyv z|L-5!3qFuSZN=i}H6G+21HZ_VCn@dNl|`OL-F*uba>E=eA~;9djOCubr8X@)NPhjP zpb<5B5$oVhsU;Fp+nYB*9o<2o)j*rZa}@yitkY2&YZ_N<2g8Fl$3q8qd;l~L!bjtz zeZ2CyZmTKb4v>P$wvm{0BL7Zn7^P$o{l#l`YswPyJZ-g-zFSGbDWDSt-tAT>eKtoQ zWq^IjxD;}p9MX;HJdc=cKA7%2Y7e}~_K+2f-25**T9aXb1 z-{%}uO><8G=5XfPV$YdJ8qHQ;%=-Y&VVE0^=bNSEZ|q4myDj0}?ZaH15f;#VJB`iJ zr_P8qRz@rxIqQuou>1CaE7}hw2)l4xflTX;wtpHw`hnG`_+AUMT?mw6UBJ0c*Z+1%~?U~|D}3Rjbte?YEz)M;1^Bq9G?zj@aI+lKDxX7q?@;6##6 z3I8?9`oUB}!PqnuLS5kR8-*rW1yogBK_BS2&GFS@2+~w{8G3s9C=biBD{v+P48{Hj z0Q+Cvf3<2r_=c4gq*#VN-$EZzxH>1)@h9h1uQ*$NsQO_#WC__w+LmQr`Da)H^hZsG zYUvlhu0RFm0aTmM*3Wge#cuo);Nf|+yQ=R(o_8)`G1s9*!P}|T%eR~S9Pzzd#E#qu z%-E|M$HMctmrzItu)V6}_pO0S-M|ZWbzJWm5!VS7Acc&U`1Q7R{FJ2L4;rd3VwHe& zPkUy9Y@S?9^Soryo%N9>?~NCkF@NiG5~%#Uw)5o}4Ug1DpLJj_1RF*_vBIRr$Ct)Z5WhrFy`tCP&pryU=)%V89vP7XNq_!@qv)d??V2yjb zSUSCDcwv9x+X!&Sgu6Uzp$}%0PzL1P zP4g;2lkJgwe{B6x_}U-$XRvfO94WJTQxRhmfhIL8$`p!rt&;yt-kIK-TsI6AJb&BF z8FPr2YK z9aU*+?HjXM8FA&p<-#?}{yu-N5Nmq6Q@ev3v?$WL;VnK`dUE661|dXkUh_r?!f%;% zWK{;q^}BoXr-SCUI{AFG;1x9*$lqJwQY@cU#ZubNoO0xrx zGE>!7d>7VSW6GNLh14ZH`?-|PY)zK5#!73JlDYKM495isd)i%jstr2+H&BDKI54- z`3un2PI(Zf9fLUB0z3+V(c;3rw( zDcY3-o1|St{l3{|ItUlFY)JLP?IFYfWXL9cD82`UOE-)HTsY=K2(zSJv<3iMu&c`w z3)(NoeNBTBeyk3$`kt0p(38&Lxe!nsu_q1Rj%oy*=zzB7XAOz}x*p;OY+}j;+nYb* zuCw6(td#>y$!lcNE`Athwkb$R*JcKUMFIjvvCi>qq^8C>L$arQR*p^3r)!dl8x10Tc>p3%Qy~|9WtGU_CI|sZUK1qr z0M48No%qwgE&qT@6a+PrcGr0TZKDXK+Ov{)e$qLF@3yf;blO=ACyslN19VW(d6nZ?W-Tx88p4jTJ+j#6c&0T9BSl~&P&f~iRUgG};8hzakD<${7x**8R5 zJ1cUcNPGk3ZY_%l*+a+&HM);Rhx*Vp5M1NgM3--!mdk~$D(kZx1)$D4>6k1^_|EDn z<6HxN#uc_KfPNX<%7@u~_qSd`e&Gn0vHgYn@n;bEkCP>*T-&wRgav;{W*XjXkrh1s zrpjdaWNGRBvW2Pcil8a|FYT?c<$;9R%uT_RH{?^&@D^Sz^<|^6QYu)c{ZzKN@>z9( zOe`Ny@zP|5mFjFd^ycWDmUN!*gVTeuw_PZ!8BpXe#6GugThA6soqaKHsJJa_X#Hxh z;Tn#|w}Ak^3w!!C(reGP%v++VcC(7VJtQB!& z3^994HC`?qduuoha>ofKfYm-#r`0?N)>T8LK<%zq!_K>H0cf7Pa03NjDxPKsma*FddQl46Yqn(9D!%W`Jvy`{mpg?r%PYUz7FIqthpQztQ|T_?ier-M3ya*AfO^GRPEkdP_(7tRYK#@xIDvIN z1Tnhcm*_C3b_r8Xm#M9k8hK;Ig3NvZmXXLuE;y?uSrUO=!}Q+@UXO&@-J9|IJ+STg z3-Y%p3YRqvPr_l=|GiPxU8vrLJs;ioQm7{^-}IZvU-yXOqTJr#$d{y(&twIE-=q0e z=E*dBSEHDbH#;!a&II!-WF;vRL%oM(({K#Ti-`z)EPyoDRzS)4^I5EuCTE?2>dEMU ztNS%#kRf-~7I@>$G0ClLz$2+^M|GQz;^1*OT+dr1v@Ya{QGLGWp*vS!zVu>eQBRJTr}*sI-S@_f&6=e6x0s6L#@qnS>{x`N60d8L`&(~kL!X-VUeL5+Yp z>Syn+nY#k)(dZ4nz7i#el=-&Zi8TJ?uu%mi`^atdy^=?LW)u1>4x3#EF&CxhQQrZh zbrde|)q35PF<=%LPhSlPNZ?$H$l@6MBw~EyVBAn@#3k_0lXjh=RbQj(#-oL`Ff->P zaB|{Y>BAWdT#9ahootsxc2KuV{;W=QLF-M2B?e-9+BBFM`RB4NSUo#OV`=b0k#&HQ z^A%V)Ku~;E9}K@)OROj~VH#VV)SLl1{9=uD;+sgSkrem^f2O);`RiEq@?b0zeKVkW zKCF8xYduEy8`b}F%Ad>LBKk=YmNvEVXx$B!hL6pVq_!`E4yckSO`x^dsVwiy)=xWu zAx|5Kl@4xLpZKsS+to+kxZrcI9*Sp8W7i@^(pn2Wx8Y0E3NuXKpDVtXS z;nvHR@Cc@bc-t8W#0cP^8}$e-(F#D7*HN;>4*NW9XPFr1qnwRdcI=f_JAM zTwLB!EcFfSY$}x^QI`onAw z67h*0f!&_-f=4Dn=HRZ5|CI{mJL903bxhJGMw zj)D9r7T&}}zS_qb7_~BdH1sSEyd1Y4)mcIjJ#(YW4=r4;1|V;QI<8dfOM@d7dM+#) z1K@ENA_Dj`;IFN&7>JE-=azAG44c%k5uj%Q%sTkM`No)O8nA%p1G?WR@3fhgb76WH zYW|M}HkWn`hf~HFh z&t1GZ`y=`-Rto0JZh;}NL!S}rKCRnAC8nIib)wQ9HeBSH634A8uVro;mK0VHrN~^Zez@M=3*g+HAg%16M`UJ)P zVDsj@W~dJFV(yJF(qx2HsSYHAW%K=ggqUMVaLyk)&Hm@8dpGQa`;wsfMNp} z_P5xxfR(7fH;=l$@r$4Usf-Sxl~|Vp;7MWU0DjKw0S6$5aJ}&KU5t^c@+B z?Hjf`!IC}4wsy4IWAEBWhpha~#WZT11+yX}!_{Xfpe7OIga(%sYad4ZG8u2e)~D)3 z^(z*rgt(rOxDK)%K_hQ|2J?wniVXx*b_9~)Rl49qW^=04M&@E2A^SFHhmL=k>YaZG z6I=&oNl2-Fd5>e%mX36mh4W&VV zUJ&I2_VdMW^42&9SG?FE={jF%-{0g_l>|=bLggcma1iQ#Eu0-8)gG)#Qo(8)A@F|9 zBYlKQLn{DYwx=^}MKe9y=0mvDAflQgwbdHVu<*4r8Orh-O1tUR+$&hMMilb0qDB^z zz=C5lB_>NqvHq)8!nLORwPzSnc65Ayg+&{ap1?WVWNt&aF+Z{K+L6tCb~VLT?z}{b z_4`-ER-?coo&{sxOS0IyTbO!J&2TSc#dDUEjOV&_rE4Fr zJWd0Lo^@&YeD}*Vx@+KMUkjApe01f&VU6h3h8jR~`Lw}5hL=CH1Tc_4Wk9TmBz))Q zZuXZkXAHivb}#@wRF|+0bs~yPDW#1IDt$Q0E`ohNa>Br$0)HAcRb^X}?|1{6t`Gdj zKs20mkYh0$$tJv|@^hh12;p3_St=)-rfq=nm_4%+-7R9Jr@-u+mFhWGjczhx)6ZqDcO!~(1N23EJ^t!Rn9;f< z{~$?Ic}()S+@}x3Gb05f+!2`n509Yb-wu)NVBGm@{{|bycBI`e^-Fqen-aoB@aPXK z{D>&=UUGlfhiTGi$y~fa-U?zuBBof^h%GeRr#c(}K+rP*R*kY}>dHb8_;!T|OMge* zmD%ijI#lgvX5AW~=!?d%N14bgzkJ>*>h1hSw}RgY*zZ4>ZRMOk1k%pRYDlO`rcCqbl$k_~u+qb&^Gz}EtDfTANHbD?OS(HpCtVmIP0jc=9G@QN@f>TywH5Z7z5L}e(LyP62xW>Rj?%xGa#0Orh z2}i(Gkn@6MHAP!(Ob0f_XayMkjj~g7u=r-_uB%X?;&(w)>mWArZnW!LWH&GJU^tYmj4`gea+-RXQ#A z`|lXn;+5|Y(F$QJC2!gK!htHhWWnIz5!oW3%8A-!@W`MOIfl!<%vGk_C*~mGCVI$K z-b$6Em=dzt{vks=dG-10YS#&UU*Ph_fj7Mx!oz4ci0vGE4*!D|(E=`O5zV8q!6mC^ zm6q_aVvTIEi_7pH;PWAyWQSvboEG`@W=G%V@Z~UxD$*-qLzn~ATX%pH!5E2f-@sQf z#0rL8-xMCc)}>9VUqV@&c>D-$T z9B50%hRP6Rb#}okx-gzKg2@MDNtgrQ2LJrddqj}woQhMDieFQZ31647p%C;6V%34ExO1MdZ; zCXujJ=Qc!zb?-pzpf1wizM?}`-TOVW&t~{_HO~0OUX#3#IoLhP<@CV`xNJMOk#CB> zt=Oa$*@e`z7Iuz!3C@J(m7FX=OD%OJ94Y1|I6DU?N?jM*0aCxq?+(F3hXL*-JaChJ zc`M-Q{r#Gqo5HODb7M%ZZ0@GB(}s0Cck?e?a8bTPAKnu9-}FDv1@yc+0`iufVC<@+ zPeI=le2?51COWO$TJ%ezRF-h|8Ez0Xs#q8LB>qX8ABhQ2K9P@U6u3YNw+Jz3FGBLd zd`m5hEh3UbLCZx2H735YFq(~ z7Y-f6gpvVbtq!2Bi>3+zwy;jZf0F4Z^=hPXD=hH^kLM(s0iT z5utS#;HSD<|Lr{XGp`OCt9T}oyvh#R-07$Wg)8D=Bd?RwhR>6sRdZAhHAEWWC*p4M zKvy*3%hJl1O(hOHM{=t(*?{ijh2G($KCJAh-WsN#e78{%=3?)+Cl_0uR{>!0EE@Z!?u*U<%lgfC!V1wPu zBY(s1@rtJdvH`2MnF9k!NJS^9H0#}W8rayTDiEiCgc29G% z|0VYZef(vE@3kth@K4D}B)o@whxM2@knCU#-$&my&o38<1vCoGt~R_l3l_V5lqZ1k z=WqGTyh&~nv?8h-`LdR*R;2Zk&0&5Ch(Qkxm!lK4p`@d)8dd(QSM$;-zsM10?}7G^ zU-$=(g>agUOd~)Nw4Tz`8@EyueL%aDX_io40@x9CB-d|rc|{YfW@sR6zX&hdC|^Vm z2Ob}~_q&DzwFL6Mp^eue*_+|Y>O1aj%a%h3$7eFCO9DqWoJ*{Fkw0-!+>6u{l!dP& z8F)=qj%V{W^A1h;inGSR=Ldj#(6RPX0($B_a;bKMQ(~Q9QaPR(RnbZpyQ<25WOMUa z@szw;GinK|&Vo|ic^q`GH+0<6F_i44ftb2&4mRZ0vX*0 z#0O|eW(5uT{L=$PjyDw3*v($-ppcQ^Z~!DgX&9^sfZu+EMZ){=-(Uj^NCeH8VL$0V zr*46dA)V(OJJ|8@WbMdr=5t?zchka;f1|C{$HAtL#!$-A0*0NvC*Rw~YWJcqOzWW$ zJlp2cpk6^sYNEiAyYjycMTpwKGn?+Jzq)hR*_^^xwSg~Kl?K~ao&-H}1~qKR3%42? z`;La$zQ@-VTf(h;I9gRsNWjY*NV5 zfC;E2m?|(KpkiZwS+kDhhsJ8~b{cY-Tz|)f1b`ZYs1g=}eFBJ>^d1xWRff~dP2n|i2X6g?=m)R)% zqaQSL2J~b7$MUWXk3xs#A)NI`%)v&Gy$%Cl|EdEv0G@`la6iSplRa(}qHts*eH7q0 zn7(vj-^3c4sOHNbcM$1uYt!oig18=zbBeXc^pOg!PrFV$fD-zGzqjy81MPn3RcRw! zx2m**JJ%piC3TY`u)y~DzjbXR4Z$}nKdz!>NeJ|IvHI(%q4PwldP25;!I@|wHR=kg zDk2X90fZW*QOEk&+Nd9n_}1`j=&N5=m%?sNrff9qC6AlJ4jFn+Hu zQbO0hZiE%+gHE!Bdg79 z{+-oGg|U#?-c{x`%0RVNDXUNEFWs#J3!6ekt{&WSJWG#eVe4Mc7DozZNaoeSBU1dI z9Kd7q{Kdn>Q@86H;Mr{AQJcN$?E`~*1ljFGJbNthoktkxJ-SRM%4j`koP=dlI74^i zNM}y()(n`|fJ2*5*BnI&78l@l2}Q8Kt4aV2cDp|Vet+tR_d5%BAB>7mM9j54ehLcR ztq0(`wgLrO1Bv0LhI`o)np2wX9!nKS(F9gwU$K6b=?3mR-HZ*}fJl1>$Lw!$cWagW zzQzPZScy^$u3P|a&XOlR^bK+NZ>#OANf%$JDc@*;tLCSqiPj~_{h#~jAdW~JdWwDv z2ekr~o znE?xyL)llbI+U*BT#Q2!^YYH=!`c{KBaMGTszbvyh8R*y-86|t2DMRJm?69}qUU0a z7;^_^NS{vobT7UFZ%5(t%@;t^F@Q^W7Z#gZzvg$YGu!`aYrYE6_KrD1^#)A+lEI&> z21%W)f^&YJhcIuzH#D5n3!A~0wnJ`^k&{-{kQ9F)tJ6}Yd9_z$T|tBR83`dk;umY~ zP2GO8((v@3Z_-giPo;lh9qAT{Mw*`R{nJ}%4lwFv&50~k6JCqEQ^?jA@(u_H02Cs% zNZZ1|t}Wt@EFS$9(n#p8r^pGoKO8vdKVAYm9|03_NHu7~HFW0OSmbV~nfDi}##}n3 z!h!*Q`i{>Ao`snI>JQg8!Ikj_@JsftHdiEtU|yWN>)9qlzf`a~7!!>Qb3YO}NzF9q zIhN$j6Rx7$%2&xvqh|qWJyD-b`a4dfb`VLR3?gqqfPDqs5CTtqfBHdJT4MEN)e#pn zRKq^Dx(5UuWu{p)zn(%I1OkG%_qBiMf>?s81va(%yEKvx-psRvtKFJ{Y&$aL#IK+E zjgV_aw&2>+p8yad4R3a50-}$kKV-o~jX}w70N;6Mq1^d z766BaWs>kE@x~hLiNWrVHBhFNIVcO`RXMh8czOMG^y^!cV{U3xM#@{iB*nT@G7CnW z0Xw008tS(5O^cKYVe3O;aMvqyBbF>ow!S{7da%4bHnO`?KsuTe9eO)5*1VX!m8RU8 z@@z=y@oJ9KSWDZIn|uEBR^V5=3~7(^YtG;2|2x^e8DQQyspMlc(p?(c>Rs!-RA%I7WT{d6&U}s| zqd|E~J0F*9`%aQ=XOb22qtyR6$(JKt%`oJTznQ9*UB4>|sB>tfX*#;#v$d~4dH0U^ zr_MuZWM*h-pT*DbH7x3zCq>3dJD_KYoQ|P6KG%P;{qWVl5}tD94rl3$1uhEokC;kd z;enL$==Fzvrb2T{bA9~b#~+!-W*m0ST-E>fL}r)inZ+19bGva3c3mx5%AnOH*XN|Y z|J4@DtDNLxzVaxQiYMPEw%+Bsarx}*J*%4kax~`nZ9~N~6wj;EIP~=rWVa%@=!Oq2 za^W`ZW6Opg<3GMJTIYL=`R4|WDzpl2#}U4o)3}TAyH$+lI0m|J)p66vI3>%>B)gUW zJ$7lmn?V)PH}QRJVDTi8c4a}oy*kwRSxLcVDLJf?+^MJKu zo!@-C&?^QS|zV6oWOwmJaI#_PJV#)FI=1aJoUzo%(;PD;J!fx#@M|jNx+t0kT(9#B% z%(w=5p8UP*%8i%4W%9j>seNSDtrIa79-jd2Jx>TUry)S4Ry?YUF+rUdCR#1nV5T7a zcZ|cTr6P?29p%C&6AwHM;Hm^D@io}-Yp7c2k)TXnMd{A^rkJO$RxJ{M0>}x8NQld3+t1H>Y?)n$K%tHr0-2|2(t2ftB z4YF%VA1Cz&q+9lWVP8mho&}C>^)Z=?C+XRI_#(?E`;$RsP2>2n^Ruzn50i3koc$** zG<(;zeboF>$y*)&B-!s75d)7i`^COa9vLVC^F4|khDL&(b67Uiv~<}Hc?e_a7Pc=1 z>1u>5)@bG~9dn!b*8cap4Ewo3b4B91{-Zey6V@)9p@M@ue_6%lb|a%{eO-nWkSa^E zwr;IiUSkh9-7;hkTY!^t-O^2$s6C23UGs;}O!|E4wKKU-Xxln7f!R{-a&Fg?X*k#D zOzdCKKj(j=oHP(>#J+1A3Hxd;&x5v8Sg&edsf}556Mofqt*6!7Txc%F`_|BnXKyVt z4OH%59(3E4S;`E%!Vwv_D7L*bpYU4qw}Mrx=7sQ$ThIHR