enum names and values

This commit is contained in:
Louis Rubet 2022-02-25 14:16:55 +01:00
parent d0c7304ffd
commit 2a980eb74d
22 changed files with 676 additions and 675 deletions

View file

@ -4,19 +4,19 @@
#include <cstring>
vector<string>* Input::_ac_list = nullptr;
vector<string>* Input::ac_list_ = nullptr;
Input::Input(string& entry, vector<string>& 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<string>& 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<string>& 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<string>& 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());
}

View file

@ -14,13 +14,13 @@ using std::vector;
class Input {
public:
Input(string& entry, vector<string>& 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<string>* _ac_list;
static vector<string>* ac_list_;
};
#endif // SRC_INPUT_HPP_

View file

@ -55,13 +55,13 @@ bool Lexer::parseString(string& entry, size_t idx, size_t& next_idx, vector<SynE
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)});
elements.push_back({kString, .value = entry.substr(idx + 1, i - idx - 1)});
next_idx = i + 1;
return true;
}
}
}
elements.push_back({cmd_string, .value = entry.substr(idx + 1, entry.size() - idx - 1)});
elements.push_back({kString, .value = entry.substr(idx + 1, entry.size() - idx - 1)});
next_idx = entry.size();
return true;
}
@ -71,12 +71,12 @@ bool Lexer::parseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynE
// 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});
elements.push_back({kSymbol, .value = entry.substr(idx + 1, i - idx - 1), .autoEval = false});
next_idx = i + 1;
return true;
}
}
elements.push_back({cmd_symbol, .value = entry.substr(idx + 1, entry.size() - idx - 1)});
elements.push_back({kSymbol, .value = entry.substr(idx + 1, entry.size() - idx - 1)});
next_idx = entry.size();
return true;
}
@ -93,7 +93,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector<Syn
if (countNested == 0) {
string prg = entry.substr(idx + 2, i - idx - 2);
trim(prg);
elements.push_back({cmd_program, .value = prg});
elements.push_back({kProgram, .value = prg});
next_idx = i + 2;
return true;
} else {
@ -103,7 +103,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector<Syn
}
string prg = entry.substr(idx + 2, entry.size() - idx - 2);
trim(prg);
elements.push_back({cmd_program, .value = prg});
elements.push_back({kProgram, .value = prg});
next_idx = entry.size();
return true;
}
@ -185,7 +185,7 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynE
mpreal* r = nullptr;
int base = 10;
if (getNumberAt(entry, idx, next_idx, base, &r)) {
elements.push_back({cmd_number, .re = r, .reBase = base});
elements.push_back({kNumber, .re = r, .reBase = base});
return true;
} else {
errors.push_back({entry.size(), "unterminated number"});
@ -199,19 +199,19 @@ bool Lexer::parseComplex(string& entry, size_t idx, size_t& next_idx, vector<Syn
mpreal* im = nullptr;
int reBase, imBase = 10;
if (idx + 1 == 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();
return true; // complex format error, return a symbol
}
if (!getNumberAt(entry, idx + 1, next_idx, reBase, &re, ',')) {
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();
return true; // complex format error, return a symbol
}
size_t i = next_idx;
if (i >= 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<Syn
}
if (!getNumberAt(entry, i, next_idx, imBase, &im, ')')) {
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;
return true; // complex format error, return a symbol
}
elements.push_back({cmd_complex, .re = re, .im = im, .reBase = reBase, .imBase = imBase});
elements.push_back({kComplex, .re = re, .im = im, .reBase = reBase, .imBase = imBase});
next_idx++;
return true;
}
@ -249,7 +249,7 @@ bool Lexer::parseUnknown(string& entry, size_t idx, size_t& next_idx, vector<Syn
stringstream ss(entry.substr(idx));
string token;
ss >> 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;
}

View file

@ -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;
};

View file

@ -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;
}

View file

@ -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<mpreal>& 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<size_t>(-1);
arg2 = static_cast<size_t>(-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;

View file

@ -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::keyword_t> 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 <test-instruction> then <true-instructions> else <false-instructions> "
"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> <end> start <instructions> next|<step> 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> <end> start <instructions> next|<step> step"},
{kBranch, "for", (program_fn_t)&program::rpn_for,
"<start> <end> for <variable> <instructions> next|<step> 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, <test-instruction> <true-instruction> 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, <test-instruction> <true-instruction> ift"},
{kKeyword, "ifte", &program::rpn_ifte,
"similar to if-then-else-end, <test-instruction> <true-instruction> "
"<false-instruction> ifte"},
{cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end"},
{cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"},
{cmd_branch, "while", (program_fn_t)&program::rpn_while, "while <test-instruction> repeat <loop-instructions> end"},
{cmd_branch, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"},
{kBranch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end"},
{kBranch, "until", (program_fn_t)&program::rpn_until, "used with do"},
{kBranch, "while", (program_fn_t)&program::rpn_while, "while <test-instruction> repeat <loop-instructions> 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<string>& 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<Symbol*>(o));
i++;
break;
// a keyword
case cmd_keyword: {
case kKeyword: {
Keyword* k = reinterpret_cast<Keyword*>(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<Branch*>(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<Branch*>(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<Branch*>(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<Branch*>(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<string, Lexer::ReservedWord> keywords_map;
vector<Lexer::SynElement> elements;
vector<Lexer::SynError> 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<string> 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<RetValue, string> 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<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:
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

View file

@ -28,19 +28,19 @@ class program : public deque<Object*>, 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<Object*>, 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<Object*>, 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<Object*>, 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<size_t>(-1), runtime_error = static_cast<size_t>(-2) };
enum { kStepOut = static_cast<size_t>(-1), kRtError = static_cast<size_t>(-2) };
// complex
void rpn_re();
@ -259,7 +259,7 @@ class program : public deque<Object*>, 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<Object*>, 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<Object*>, 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<Object*>, 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)

View file

@ -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<Number>(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<Branch*>(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<Branch*>(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<Number>(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<Number>(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<Number>(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<Symbol*>(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<Branch*>(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<Symbol*>(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<Number>(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<Branch*>(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<Symbol*>(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;

View file

@ -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<Complex>(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<Complex>(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<Complex>(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<Complex>(0) = conj(_stack.value<Complex>(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<Number>(1), _stack.value<Number>(0), _stack.obj<Complex>(1).reBase, _stack.obj<Complex>(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<Complex>(0)), _stack.obj<Complex>(0).reBase));
_stack.push(new Number(imag(_stack.value<Complex>(1)), _stack.obj<Complex>(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<Complex>(0));
mpreal theta = arg(_stack.value<Complex>(0));
_stack.value<Complex>(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<Complex>(0) = polar(abs(_stack.value<Complex>(0)), arg(_stack.value<Complex>(0)));
}

View file

@ -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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<string, mpfr_rnd_t> 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();
}

View file

@ -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<Number>(0) = log10(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = log10(_stack.value<Complex>(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<Number>(0) = exp(log(mpreal(10)) * _stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = exp(log(mpreal(10)) * _stack.value<Complex>(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<Number>(0) = log(_stack.value<Number>(0)) / mpfr::const_log2();
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = log(_stack.value<Complex>(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<Number>(0) = exp(mpfr::const_log2() * _stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = exp(mpfr::const_log2() * _stack.value<Complex>(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<Number>(0) = log(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = log(_stack.value<Complex>(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<Number>(0) = exp(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = exp(_stack.value<Complex>(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<Number>(0) = exp(_stack.value<Number>(0)) - mpreal(1);
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = exp(_stack.value<Complex>(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<Number>(0) = log(_stack.value<Number>(0) + 1);
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = log(_stack.value<Complex>(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<Number>(0) = sinh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = sinh(_stack.value<Complex>(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<Number>(0) = asinh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = asinh(_stack.value<Complex>(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<Number>(0) = cosh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = cosh(_stack.value<Complex>(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<Number>(0) = acosh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = acosh(_stack.value<Complex>(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<Number>(0) = tanh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = tanh(_stack.value<Complex>(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<Number>(0) = atanh(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = atanh(_stack.value<Complex>(0));
else
setErrorContext(ret_bad_operand_type);
setErrorContext(kBadOperandType);
}

View file

@ -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<Symbol>(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<Program>(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<Program>(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;
}
// <program> 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();
}

View file

@ -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<String>(1) += _stack.value<String>(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<Number>(1) += _stack.value<Number>(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<Complex>(1) += _stack.value<Complex>(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<Complex>(1) += _stack.value<Number>(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<Complex>(1) += _stack.value<Number>(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<Number>(1) -= _stack.value<Number>(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<Complex>(1) -= _stack.value<Complex>(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<Complex>(1) -= _stack.value<Number>(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<Complex>(1) = _stack.value<Number>(0) - _stack.value<Complex>(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<Number>(1) *= _stack.value<Number>(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<Complex>(1) *= _stack.value<Complex>(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<Complex>(1) *= _stack.value<Number>(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<Complex>(1) *= _stack.value<Number>(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<Number>(1) /= _stack.value<Number>(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<Complex>(1) /= _stack.value<Complex>(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<Complex>(1) /= _stack.value<Number>(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<Complex>(1) = _stack.value<Number>(0) / _stack.value<Complex>(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<Number>(0) = -_stack.value<Number>(0);
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = -_stack.value<Complex>(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<Number>(0) = 1 / _stack.value<Number>(0);
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = mpreal(1) / _stack.value<Complex>(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<Number>(1) >= 0) {
_stack.value<Number>(1) = pow(_stack.value<Number>(1), _stack.value<Number>(0));
_stack.pop();
@ -131,18 +131,18 @@ void program::rpn_power() {
_stack.value<Complex>(0) = pow(_stack.value<Complex>(0), _stack.value<Number>(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<Complex>(1) = pow(_stack.value<Complex>(1), _stack.value<Complex>(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<Complex>(1) = pow(_stack.value<Complex>(1), _stack.value<Number>(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<Complex>(1) = pow(_stack.value<Number>(0), _stack.value<Complex>(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<Number>(0) >= 0) {
_stack.value<Number>(0) = sqrt(_stack.value<Number>(0));
} else {
@ -161,10 +161,10 @@ void program::rpn_squareroot() {
_stack.value<Complex>(0) = sqrt(_stack.value<Complex>(0));
_stack.erase(1);
}
} else if (_stack.type(0) == cmd_complex) {
} else if (_stack.type(0) == kComplex) {
_stack.value<Complex>(0) = sqrt(_stack.value<Complex>(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<Number>(0).base = 16;
} else if (_stack.type(0) == cmd_complex) {
} else if (_stack.type(0) == kComplex) {
_stack.obj<Complex>(0).reBase = 16;
_stack.obj<Complex>(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<Number>(0).base = 2;
} else if (_stack.type(0) == cmd_complex) {
} else if (_stack.type(0) == kComplex) {
_stack.obj<Complex>(0).reBase = 2;
_stack.obj<Complex>(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<Number>(0).base = 10;
} else if (_stack.type(0) == cmd_complex) {
} else if (_stack.type(0) == kComplex) {
_stack.obj<Complex>(0).reBase = 10;
_stack.obj<Complex>(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<int>(_stack.value<Number>(0).toLong());
_stack.pop();
if (base >= 2 && base <= 62) {
if (_stack.type(0) == cmd_number) {
if (_stack.type(0) == kNumber) {
_stack.obj<Number>(0).base = base;
} else {
_stack.obj<Complex>(0).reBase = base;
_stack.obj<Complex>(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<Number>(1) *= _stack.value<Number>(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<Number>(1) = (_stack.value<Number>(0) * 100) / _stack.value<Number>(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<Number>(0) *= _stack.value<Number>(0);
else if (_stack.at(0)->_type == cmd_complex)
else if (_stack.at(0)->_type == kComplex)
_stack.value<Complex>(0) *= _stack.value<Complex>(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<Number>(1) = fmod(_stack.value<Number>(1), _stack.value<Number>(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<Number>(0) = abs(_stack.value<Number>(0));
} else if (_stack.type(0) == cmd_complex) {
} else if (_stack.type(0) == kComplex) {
_stack.push(new Number(abs(_stack.value<Complex>(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<Number>(0) = gamma(_stack.value<Number>(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<Number>(0) = sgn(_stack.value<Number>(0));
else if (_stack.at(0)->_type == cmd_complex)
else if (_stack.at(0)->_type == kComplex)
_stack.value<Complex>(0) = _stack.value<Complex>(0) / abs(_stack.value<Complex>(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<Number>(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<Number>(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<Number>(0) = floor(_stack.value<Number>(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<Number>(0) = ceil(_stack.value<Number>(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<Number>(0) = frac(_stack.value<Number>(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<Number>(0) = trunc(_stack.value<Number>(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<Number>(0) = min(_stack.value<Number>(0), _stack.value<Number>(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<Number>(0) = max(_stack.value<Number>(0), _stack.value<Number>(1));
_stack.erase(1);
}

View file

@ -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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(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<int>(_stack.value<Number>(0).toLong());
_stack.pop();

View file

@ -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<String>(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<String>(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<String>(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<String>(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<String>(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<String>(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<String>(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<Symbol>(0));
if (i != _heap.end()) {
delete i->second;
_heap.erase(i);
} else {
setErrorContext(ret_unknown_variable);
setErrorContext(kUnknownVariable);
}
_stack.pop();
}

View file

@ -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<String>(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<char>(_stack.value<Number>(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<String>(0).size() > 0)
_stack.push_front(new Number(_stack.value<String>(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<String>(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<String>(1).find(_stack.value<String>(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<Number>(1).toULong();
size_t len = _stack.value<Number>(0).toULong() - first + 1;

View file

@ -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<int>(prog.get_err());

View file

@ -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<Number>(1) > _stack.value<Number>(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<Number>(1) >= _stack.value<Number>(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<Number>(1) < _stack.value<Number>(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<Number>(1) <= _stack.value<Number>(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<Number>(1) != _stack.value<Number>(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<Complex>(1) != _stack.value<Complex>(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<Number>(1) == _stack.value<Number>(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<Complex>(1) == _stack.value<Complex>(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<Number>(0) != 0 && _stack.value<Number>(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<Number>(0) != 0 || _stack.value<Number>(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<Number>(0) != 0 ^ _stack.value<Number>(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<Number>(0) == 0 ? 1 : 0));
_stack.erase(1, 1);

View file

@ -25,7 +25,7 @@ void program::rpn_time() {
_stack.push(new Number(date));
_stack.value<Number>(0) /= 10000000000.0;
} else {
setErrorContext(ret_internal);
setErrorContext(kInternalError);
}
}
@ -51,7 +51,7 @@ void program::rpn_date() {
_stack.push(new Number(date));
_stack.value<Number>(0) /= 1000000.0;
} else {
setErrorContext(ret_internal);
setErrorContext(kInternalError);
}
}
@ -71,6 +71,6 @@ void program::rpn_ticks() {
date = 1000000.0 * static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec / 1000);
_stack.push(new Number(date));
} else {
setErrorContext(ret_internal);
setErrorContext(kInternalError);
}
}

View file

@ -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<Number>(0) *= mpfr::const_pi();
_stack.value<Number>(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<Number>(0) /= mpfr::const_pi();
_stack.value<Number>(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<Number>(0) = sin(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = sin(_stack.value<Complex>(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<Number>(0) = asin(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = asin(_stack.value<Complex>(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<Number>(0) = cos(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = cos(_stack.value<Complex>(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<Number>(0) = acos(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = acos(_stack.value<Complex>(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<Number>(0) = tan(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = tan(_stack.value<Complex>(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<Number>(0) = atan(_stack.value<Number>(0));
else if (_stack.type(0) == cmd_complex)
else if (_stack.type(0) == kComplex)
_stack.value<Complex>(0) = atan(_stack.value<Complex>(0));
else
setErrorContext(ret_bad_operand_type);
setErrorContext(kBadOperandType);
}

View file

@ -32,7 +32,7 @@ class rpnstack : public deque<Object*> {
// access helpers
//
cmd_type_t type(int level) {
ObjectType type(int level) {
// carefull: caller must ensure that level is correct
return at(level)->_type;
}