mirror of
https://github.com/louisrubet/rpn
synced 2025-02-01 07:57:52 +01:00
enum names and values
This commit is contained in:
parent
d0c7304ffd
commit
2a980eb74d
22 changed files with 676 additions and 675 deletions
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -94,16 +94,16 @@ int main(int argc, char* argv[]) {
|
|||
program prog(stack, heap);
|
||||
string entry;
|
||||
switch (Input(entry, program::getAutocompletionWords()).status) {
|
||||
case Input::ok:
|
||||
case Input::InputStatus::kOk:
|
||||
// user could stop prog with CtrlC
|
||||
CatchSignals(&prog);
|
||||
// run it
|
||||
if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye)
|
||||
if (prog.parse(entry) == kOk && prog.run() == kGoodbye)
|
||||
go_on = false;
|
||||
else
|
||||
prog.show_stack();
|
||||
break;
|
||||
case Input::ctrlc:
|
||||
case Input::InputStatus::kCtrlc:
|
||||
go_on = false;
|
||||
break;
|
||||
default:
|
||||
|
@ -125,7 +125,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
// make program
|
||||
ret = prog.parse(entry);
|
||||
if (ret == ret_ok) {
|
||||
if (ret == kOk) {
|
||||
// user could stop prog with CtrlC
|
||||
CatchSignals(&prog);
|
||||
|
||||
|
@ -137,6 +137,6 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
mpfr_free_cache();
|
||||
|
||||
if (ret != ret_ok) return EXIT_FAILURE;
|
||||
if (ret != kOk) return EXIT_FAILURE;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
105
src/object.hpp
105
src/object.hpp
|
@ -20,37 +20,36 @@ using std::complex;
|
|||
// definitions for objects
|
||||
///
|
||||
typedef enum {
|
||||
ret_ok,
|
||||
ret_unknown_err,
|
||||
ret_missing_operand,
|
||||
ret_bad_operand_type,
|
||||
ret_out_of_range,
|
||||
ret_unknown_variable,
|
||||
ret_internal,
|
||||
ret_deadly,
|
||||
ret_good_bye,
|
||||
ret_not_impl,
|
||||
ret_nop,
|
||||
ret_syntax,
|
||||
ret_div_by_zero,
|
||||
ret_runtime_error,
|
||||
ret_abort_current_entry,
|
||||
ret_out_of_memory,
|
||||
ret_bad_value,
|
||||
ret_test_failed
|
||||
} ret_value;
|
||||
kOk,
|
||||
kUnknownError,
|
||||
kMissingOperand,
|
||||
kBadOperandType,
|
||||
kOutOfRange,
|
||||
kUnknownVariable,
|
||||
kInternalError,
|
||||
kDeadlyError,
|
||||
kGoodbye,
|
||||
kNotImplemented,
|
||||
kNop,
|
||||
kSyntaxError,
|
||||
kDivByZero,
|
||||
kRuntimeError,
|
||||
kAbortCurrentEntry,
|
||||
kOutOfMemory,
|
||||
kBadValue,
|
||||
kTestFailed
|
||||
} RetValue;
|
||||
|
||||
typedef enum {
|
||||
cmd_undef,
|
||||
cmd_number, // floating point number
|
||||
cmd_complex, // complex, couple of floating point numbers
|
||||
cmd_string, // "string"
|
||||
cmd_symbol, // 'symbol'
|
||||
cmd_program, // << instructions >> «instructions»
|
||||
cmd_keyword, // langage (reserved) keyword
|
||||
cmd_branch, // langage (reserved) branch keyword
|
||||
cmd_max
|
||||
} cmd_type_t;
|
||||
kUndef,
|
||||
kNumber, // 3.1416, 1e-1234, 0x12ab, 2b110, 50ba12
|
||||
kComplex, // (1,2)
|
||||
kString, // "string"
|
||||
kSymbol, // 'symbol'
|
||||
kProgram, // << instructions >> «instructions»
|
||||
kKeyword, // langage (reserved) keyword (rot, dup, swap ..)
|
||||
kBranch // langage (reserved) branch keyword (for, if, then ..)
|
||||
} ObjectType;
|
||||
|
||||
class program;
|
||||
class Branch;
|
||||
|
@ -61,9 +60,9 @@ typedef size_t (program::*branch_fn_t)(Branch&);
|
|||
/// @brief Object - a generic stack object
|
||||
///
|
||||
struct Object {
|
||||
explicit Object(cmd_type_t type = cmd_undef) : _type(type) {}
|
||||
explicit Object(ObjectType type = kUndef) : _type(type) {}
|
||||
virtual ~Object() {}
|
||||
cmd_type_t _type;
|
||||
ObjectType _type;
|
||||
virtual Object* clone() {
|
||||
Object* o = new Object();
|
||||
if (o != nullptr) *o = *this;
|
||||
|
@ -83,9 +82,9 @@ struct Object {
|
|||
/// @brief stack objects derived from Object
|
||||
///
|
||||
struct Number : Object {
|
||||
Number() : Object(cmd_number), base(10) {}
|
||||
explicit Number(const mpreal& value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {}
|
||||
explicit Number(int value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {}
|
||||
Number() : Object(kNumber), base(10) {}
|
||||
explicit Number(const mpreal& value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {}
|
||||
explicit Number(int value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {}
|
||||
|
||||
int base;
|
||||
mpreal value;
|
||||
|
@ -95,9 +94,9 @@ struct Number : Object {
|
|||
virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); }
|
||||
|
||||
// representation mode
|
||||
typedef enum { std, fix, sci } mode_enum;
|
||||
typedef enum { kStd, kFix, kSci } mode_enum;
|
||||
static mode_enum s_mode;
|
||||
static constexpr mode_enum DEFAULT_MODE = Number::std;
|
||||
static constexpr mode_enum DEFAULT_MODE = Number::kStd;
|
||||
|
||||
// precision
|
||||
static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128;
|
||||
|
@ -109,9 +108,9 @@ struct Number : Object {
|
|||
stringstream format;
|
||||
format << "%." << digits;
|
||||
switch ( mode ) {
|
||||
case std: format << "R*g"; break;
|
||||
case fix: format << "R*f"; break;
|
||||
case sci: format << "R*e"; break;
|
||||
case kStd: format << "R*g"; break;
|
||||
case kFix: format << "R*f"; break;
|
||||
case kSci: format << "R*e"; break;
|
||||
}
|
||||
return format.str();
|
||||
}
|
||||
|
@ -128,13 +127,13 @@ struct Number : Object {
|
|||
/// @brief stack objects inheriting Object
|
||||
///
|
||||
struct Complex : Object {
|
||||
Complex() : Object(cmd_complex), reBase(10), imBase(10) {}
|
||||
Complex() : Object(kComplex), reBase(10), imBase(10) {}
|
||||
explicit Complex(complex<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;
|
||||
|
|
494
src/program.cpp
494
src/program.cpp
|
@ -2,205 +2,205 @@
|
|||
|
||||
#include "program.hpp"
|
||||
|
||||
//< language reserved keywords (allowed types are cmd_keyword, cmd_branch or cmd_undef)
|
||||
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
|
||||
vector<program::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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
152
src/rpn-real.cpp
152
src/rpn-real.cpp
|
@ -6,24 +6,24 @@
|
|||
///
|
||||
void program::rpn_plus() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (_stack.type(0) == cmd_string && _stack.type(1) == cmd_string) {
|
||||
if (_stack.type(0) == kString && _stack.type(1) == kString) {
|
||||
_stack.value<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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue