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>
|
#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)
|
Input::Input(string& entry, vector<string>& autocompletion_list, string prompt, string multiline_prompt)
|
||||||
: status(cont) {
|
: status(InputStatus::kContinue) {
|
||||||
char* c_entry = nullptr;
|
char* c_entry = nullptr;
|
||||||
bool multiline = false;
|
bool multiline = false;
|
||||||
int entry_len;
|
int entry_len;
|
||||||
|
|
||||||
_ac_list = &autocompletion_list;
|
ac_list_ = &autocompletion_list;
|
||||||
|
|
||||||
// linenoise for entry
|
// linenoise for entry
|
||||||
linenoiseSetCompletionCallback(entry_completion_generator);
|
linenoiseSetCompletionCallback(entry_completion_generator);
|
||||||
while (status == cont) {
|
while (status == InputStatus::kContinue) {
|
||||||
// get user entry
|
// get user entry
|
||||||
if (multiline)
|
if (multiline)
|
||||||
c_entry = linenoise(multiline_prompt.c_str(), &entry_len);
|
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
|
// Ctrl-C
|
||||||
if (linenoiseKeyType() == 1) {
|
if (linenoiseKeyType() == 1) {
|
||||||
if (entry_len > 0 || multiline)
|
if (entry_len > 0 || multiline)
|
||||||
status = abort;
|
status = InputStatus::kAbort;
|
||||||
else
|
else
|
||||||
status = ctrlc;
|
status = InputStatus::kCtrlc;
|
||||||
} else if (linenoiseKeyType() == 3) {
|
} else if (linenoiseKeyType() == 3) {
|
||||||
multiline = true;
|
multiline = true;
|
||||||
if (c_entry != nullptr) entry += c_entry;
|
if (c_entry != nullptr) entry += c_entry;
|
||||||
|
@ -38,9 +38,9 @@ Input::Input(string& entry, vector<string>& autocompletion_list, string prompt,
|
||||||
entry += c_entry;
|
entry += c_entry;
|
||||||
// keep history
|
// keep history
|
||||||
if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str());
|
if (c_entry[0] != 0) (void)linenoiseHistoryAdd(entry.c_str());
|
||||||
status = ok;
|
status = InputStatus::kOk;
|
||||||
} else {
|
} 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()
|
/// @param lc the completion object to add strings with linenoiseAddCompletion()
|
||||||
///
|
///
|
||||||
void Input::entry_completion_generator(const char* text, linenoiseCompletions* lc) {
|
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);
|
int text_len = strnlen(text, 6);
|
||||||
|
|
||||||
if (text_len == 0)
|
if (text_len == 0)
|
||||||
// propose all keywords
|
// 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
|
else
|
||||||
// propose only keywords matching to text begining
|
// 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
|
// compare list entry with text, return if match
|
||||||
if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str());
|
if (ac.compare(0, text_len, text) == 0) linenoiseAddCompletion(lc, ac.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,13 @@ using std::vector;
|
||||||
class Input {
|
class Input {
|
||||||
public:
|
public:
|
||||||
Input(string& entry, vector<string>& autocompletion_list, string prompt = "rpn> ", string multiline_prompt = ">");
|
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);
|
static void preload(const char* preloadText);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void entry_completion_generator(const char* text, linenoiseCompletions* lc);
|
static void entry_completion_generator(const char* text, linenoiseCompletions* lc);
|
||||||
static vector<string>* _ac_list;
|
static vector<string>* ac_list_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SRC_INPUT_HPP_
|
#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++) {
|
for (size_t i = idx + 1; i < entry.size(); i++) {
|
||||||
if (entry[i] == '"') {
|
if (entry[i] == '"') {
|
||||||
if (entry[i] - 1 != '\\') {
|
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;
|
next_idx = i + 1;
|
||||||
return true;
|
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();
|
next_idx = entry.size();
|
||||||
return true;
|
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 '\''
|
// here we are sure that entry[0] is at least '\''
|
||||||
for (size_t i = idx + 1; i < entry.size(); i++) {
|
for (size_t i = idx + 1; i < entry.size(); i++) {
|
||||||
if (entry[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;
|
next_idx = i + 1;
|
||||||
return true;
|
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();
|
next_idx = entry.size();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ bool Lexer::parseProgram(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
||||||
if (countNested == 0) {
|
if (countNested == 0) {
|
||||||
string prg = entry.substr(idx + 2, i - idx - 2);
|
string prg = entry.substr(idx + 2, i - idx - 2);
|
||||||
trim(prg);
|
trim(prg);
|
||||||
elements.push_back({cmd_program, .value = prg});
|
elements.push_back({kProgram, .value = prg});
|
||||||
next_idx = i + 2;
|
next_idx = i + 2;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} 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);
|
string prg = entry.substr(idx + 2, entry.size() - idx - 2);
|
||||||
trim(prg);
|
trim(prg);
|
||||||
elements.push_back({cmd_program, .value = prg});
|
elements.push_back({kProgram, .value = prg});
|
||||||
next_idx = entry.size();
|
next_idx = entry.size();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +185,7 @@ bool Lexer::parseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynE
|
||||||
mpreal* r = nullptr;
|
mpreal* r = nullptr;
|
||||||
int base = 10;
|
int base = 10;
|
||||||
if (getNumberAt(entry, idx, next_idx, base, &r)) {
|
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;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
errors.push_back({entry.size(), "unterminated number"});
|
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;
|
mpreal* im = nullptr;
|
||||||
int reBase, imBase = 10;
|
int reBase, imBase = 10;
|
||||||
if (idx + 1 == entry.size()) {
|
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();
|
next_idx = entry.size();
|
||||||
return true; // complex format error, return a symbol
|
return true; // complex format error, return a symbol
|
||||||
}
|
}
|
||||||
if (!getNumberAt(entry, idx + 1, next_idx, reBase, &re, ',')) {
|
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();
|
next_idx = entry.size();
|
||||||
return true; // complex format error, return a symbol
|
return true; // complex format error, return a symbol
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t i = next_idx;
|
size_t i = next_idx;
|
||||||
if (i >= entry.size()) {
|
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();
|
next_idx = entry.size();
|
||||||
if (re != nullptr) delete re;
|
if (re != nullptr) delete re;
|
||||||
if (im != nullptr) delete im;
|
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, ')')) {
|
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();
|
next_idx = entry.size();
|
||||||
if (re != nullptr) delete re;
|
if (re != nullptr) delete re;
|
||||||
if (im != nullptr) delete im;
|
if (im != nullptr) delete im;
|
||||||
return true; // complex format error, return a symbol
|
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++;
|
next_idx++;
|
||||||
return true;
|
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));
|
stringstream ss(entry.substr(idx));
|
||||||
string token;
|
string token;
|
||||||
ss >> 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;
|
next_idx = token.size() + idx;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ class Lexer {
|
||||||
public:
|
public:
|
||||||
// a structure to describe a syntaxical element and its value
|
// a structure to describe a syntaxical element and its value
|
||||||
struct SynElement {
|
struct SynElement {
|
||||||
cmd_type_t type;
|
ObjectType type;
|
||||||
string value;
|
string value;
|
||||||
mpreal* re;
|
mpreal* re;
|
||||||
mpreal* im;
|
mpreal* im;
|
||||||
|
@ -35,7 +35,7 @@ class Lexer {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ReservedWord {
|
struct ReservedWord {
|
||||||
cmd_type_t type;
|
ObjectType type;
|
||||||
program_fn_t fn;
|
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);
|
program prog(stack, heap);
|
||||||
string entry;
|
string entry;
|
||||||
switch (Input(entry, program::getAutocompletionWords()).status) {
|
switch (Input(entry, program::getAutocompletionWords()).status) {
|
||||||
case Input::ok:
|
case Input::InputStatus::kOk:
|
||||||
// user could stop prog with CtrlC
|
// user could stop prog with CtrlC
|
||||||
CatchSignals(&prog);
|
CatchSignals(&prog);
|
||||||
// run it
|
// run it
|
||||||
if (prog.parse(entry) == ret_ok && prog.run() == ret_good_bye)
|
if (prog.parse(entry) == kOk && prog.run() == kGoodbye)
|
||||||
go_on = false;
|
go_on = false;
|
||||||
else
|
else
|
||||||
prog.show_stack();
|
prog.show_stack();
|
||||||
break;
|
break;
|
||||||
case Input::ctrlc:
|
case Input::InputStatus::kCtrlc:
|
||||||
go_on = false;
|
go_on = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -125,7 +125,7 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
// make program
|
// make program
|
||||||
ret = prog.parse(entry);
|
ret = prog.parse(entry);
|
||||||
if (ret == ret_ok) {
|
if (ret == kOk) {
|
||||||
// user could stop prog with CtrlC
|
// user could stop prog with CtrlC
|
||||||
CatchSignals(&prog);
|
CatchSignals(&prog);
|
||||||
|
|
||||||
|
@ -137,6 +137,6 @@ int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
mpfr_free_cache();
|
mpfr_free_cache();
|
||||||
|
|
||||||
if (ret != ret_ok) return EXIT_FAILURE;
|
if (ret != kOk) return EXIT_FAILURE;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
105
src/object.hpp
105
src/object.hpp
|
@ -20,37 +20,36 @@ using std::complex;
|
||||||
// definitions for objects
|
// definitions for objects
|
||||||
///
|
///
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ret_ok,
|
kOk,
|
||||||
ret_unknown_err,
|
kUnknownError,
|
||||||
ret_missing_operand,
|
kMissingOperand,
|
||||||
ret_bad_operand_type,
|
kBadOperandType,
|
||||||
ret_out_of_range,
|
kOutOfRange,
|
||||||
ret_unknown_variable,
|
kUnknownVariable,
|
||||||
ret_internal,
|
kInternalError,
|
||||||
ret_deadly,
|
kDeadlyError,
|
||||||
ret_good_bye,
|
kGoodbye,
|
||||||
ret_not_impl,
|
kNotImplemented,
|
||||||
ret_nop,
|
kNop,
|
||||||
ret_syntax,
|
kSyntaxError,
|
||||||
ret_div_by_zero,
|
kDivByZero,
|
||||||
ret_runtime_error,
|
kRuntimeError,
|
||||||
ret_abort_current_entry,
|
kAbortCurrentEntry,
|
||||||
ret_out_of_memory,
|
kOutOfMemory,
|
||||||
ret_bad_value,
|
kBadValue,
|
||||||
ret_test_failed
|
kTestFailed
|
||||||
} ret_value;
|
} RetValue;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
cmd_undef,
|
kUndef,
|
||||||
cmd_number, // floating point number
|
kNumber, // 3.1416, 1e-1234, 0x12ab, 2b110, 50ba12
|
||||||
cmd_complex, // complex, couple of floating point numbers
|
kComplex, // (1,2)
|
||||||
cmd_string, // "string"
|
kString, // "string"
|
||||||
cmd_symbol, // 'symbol'
|
kSymbol, // 'symbol'
|
||||||
cmd_program, // << instructions >> «instructions»
|
kProgram, // << instructions >> «instructions»
|
||||||
cmd_keyword, // langage (reserved) keyword
|
kKeyword, // langage (reserved) keyword (rot, dup, swap ..)
|
||||||
cmd_branch, // langage (reserved) branch keyword
|
kBranch // langage (reserved) branch keyword (for, if, then ..)
|
||||||
cmd_max
|
} ObjectType;
|
||||||
} cmd_type_t;
|
|
||||||
|
|
||||||
class program;
|
class program;
|
||||||
class Branch;
|
class Branch;
|
||||||
|
@ -61,9 +60,9 @@ typedef size_t (program::*branch_fn_t)(Branch&);
|
||||||
/// @brief Object - a generic stack object
|
/// @brief Object - a generic stack object
|
||||||
///
|
///
|
||||||
struct Object {
|
struct Object {
|
||||||
explicit Object(cmd_type_t type = cmd_undef) : _type(type) {}
|
explicit Object(ObjectType type = kUndef) : _type(type) {}
|
||||||
virtual ~Object() {}
|
virtual ~Object() {}
|
||||||
cmd_type_t _type;
|
ObjectType _type;
|
||||||
virtual Object* clone() {
|
virtual Object* clone() {
|
||||||
Object* o = new Object();
|
Object* o = new Object();
|
||||||
if (o != nullptr) *o = *this;
|
if (o != nullptr) *o = *this;
|
||||||
|
@ -83,9 +82,9 @@ struct Object {
|
||||||
/// @brief stack objects derived from Object
|
/// @brief stack objects derived from Object
|
||||||
///
|
///
|
||||||
struct Number : Object {
|
struct Number : Object {
|
||||||
Number() : Object(cmd_number), base(10) {}
|
Number() : Object(kNumber), base(10) {}
|
||||||
explicit Number(const mpreal& value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {}
|
explicit Number(const mpreal& value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {}
|
||||||
explicit Number(int value_, int base_ = 10) : Object(cmd_number), base(base_), value(value_) {}
|
explicit Number(int value_, int base_ = 10) : Object(kNumber), base(base_), value(value_) {}
|
||||||
|
|
||||||
int base;
|
int base;
|
||||||
mpreal value;
|
mpreal value;
|
||||||
|
@ -95,9 +94,9 @@ struct Number : Object {
|
||||||
virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); }
|
virtual ostream& show(ostream& out) { return showValue(out, value, s_mode, s_digits, base); }
|
||||||
|
|
||||||
// representation mode
|
// representation mode
|
||||||
typedef enum { std, fix, sci } mode_enum;
|
typedef enum { kStd, kFix, kSci } mode_enum;
|
||||||
static mode_enum s_mode;
|
static mode_enum s_mode;
|
||||||
static constexpr mode_enum DEFAULT_MODE = Number::std;
|
static constexpr mode_enum DEFAULT_MODE = Number::kStd;
|
||||||
|
|
||||||
// precision
|
// precision
|
||||||
static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128;
|
static constexpr mpfr_prec_t MPFR_DEFAULT_PREC_BITS = 128;
|
||||||
|
@ -109,9 +108,9 @@ struct Number : Object {
|
||||||
stringstream format;
|
stringstream format;
|
||||||
format << "%." << digits;
|
format << "%." << digits;
|
||||||
switch ( mode ) {
|
switch ( mode ) {
|
||||||
case std: format << "R*g"; break;
|
case kStd: format << "R*g"; break;
|
||||||
case fix: format << "R*f"; break;
|
case kFix: format << "R*f"; break;
|
||||||
case sci: format << "R*e"; break;
|
case kSci: format << "R*e"; break;
|
||||||
}
|
}
|
||||||
return format.str();
|
return format.str();
|
||||||
}
|
}
|
||||||
|
@ -128,13 +127,13 @@ struct Number : Object {
|
||||||
/// @brief stack objects inheriting Object
|
/// @brief stack objects inheriting Object
|
||||||
///
|
///
|
||||||
struct Complex : 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)
|
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_;
|
value = value_;
|
||||||
}
|
}
|
||||||
explicit Complex(mpreal& re_, mpreal& im_, int reb = 10, int imb = 10)
|
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.real(re_);
|
||||||
value.imag(im_);
|
value.imag(im_);
|
||||||
}
|
}
|
||||||
|
@ -154,8 +153,8 @@ struct Complex : Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct String : Object {
|
struct String : Object {
|
||||||
String() : Object(cmd_string) {}
|
String() : Object(kString) {}
|
||||||
explicit String(const string& value_) : Object(cmd_string), value(value_) {}
|
explicit String(const string& value_) : Object(kString), value(value_) {}
|
||||||
virtual Object* clone() { return new String(value); }
|
virtual Object* clone() { return new String(value); }
|
||||||
virtual string name() { return string("string"); }
|
virtual string name() { return string("string"); }
|
||||||
virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; }
|
virtual ostream& show(ostream& out) { return out << "\"" << value << "\""; }
|
||||||
|
@ -163,8 +162,8 @@ struct String : Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Program : Object {
|
struct Program : Object {
|
||||||
Program() : Object(cmd_program) {}
|
Program() : Object(kProgram) {}
|
||||||
explicit Program(const string& value_) : Object(cmd_program), value(value_) {}
|
explicit Program(const string& value_) : Object(kProgram), value(value_) {}
|
||||||
virtual Object* clone() { return new Program(value); }
|
virtual Object* clone() { return new Program(value); }
|
||||||
virtual string name() { return string("program"); }
|
virtual string name() { return string("program"); }
|
||||||
virtual ostream& show(ostream& out) { return out << "«" << value << "»"; }
|
virtual ostream& show(ostream& out) { return out << "«" << value << "»"; }
|
||||||
|
@ -172,9 +171,9 @@ struct Program : Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Symbol : 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)
|
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 Object* clone() { return new Symbol(value, autoEval); }
|
||||||
virtual string name() { return string("symbol"); }
|
virtual string name() { return string("symbol"); }
|
||||||
virtual ostream& show(ostream& out) { return out << "'" << value << "'"; }
|
virtual ostream& show(ostream& out) { return out << "'" << value << "'"; }
|
||||||
|
@ -183,8 +182,8 @@ struct Symbol : Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Keyword : Object {
|
struct Keyword : Object {
|
||||||
Keyword() : Object(cmd_keyword) {}
|
Keyword() : Object(kKeyword) {}
|
||||||
explicit Keyword(program_fn_t fn_, const string& value_) : Object(cmd_keyword), fn(fn_), value(value_) {}
|
explicit Keyword(program_fn_t fn_, const string& value_) : Object(kKeyword), fn(fn_), value(value_) {}
|
||||||
virtual Object* clone() { return new Keyword(fn, value); }
|
virtual Object* clone() { return new Keyword(fn, value); }
|
||||||
virtual string name() { return string("keyword"); }
|
virtual string name() { return string("keyword"); }
|
||||||
program_fn_t fn;
|
program_fn_t fn;
|
||||||
|
@ -192,8 +191,8 @@ struct Keyword : Object {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Branch : Object {
|
struct Branch : Object {
|
||||||
Branch() : Object(cmd_branch) {}
|
Branch() : Object(kBranch) {}
|
||||||
explicit Branch(branch_fn_t fn_, const string& value_) : Object(cmd_branch) {
|
explicit Branch(branch_fn_t fn_, const string& value_) : Object(kBranch) {
|
||||||
fn = fn_;
|
fn = fn_;
|
||||||
arg1 = static_cast<size_t>(-1);
|
arg1 = static_cast<size_t>(-1);
|
||||||
arg2 = static_cast<size_t>(-1);
|
arg2 = static_cast<size_t>(-1);
|
||||||
|
@ -201,7 +200,7 @@ struct Branch : Object {
|
||||||
arg_bool = 0;
|
arg_bool = 0;
|
||||||
value = value_;
|
value = value_;
|
||||||
}
|
}
|
||||||
explicit Branch(Branch& other) : Object(cmd_branch) {
|
explicit Branch(Branch& other) : Object(kBranch) {
|
||||||
fn = other.fn;
|
fn = other.fn;
|
||||||
arg1 = other.arg1;
|
arg1 = other.arg1;
|
||||||
arg2 = other.arg2;
|
arg2 = other.arg2;
|
||||||
|
|
494
src/program.cpp
494
src/program.cpp
|
@ -2,205 +2,205 @@
|
||||||
|
|
||||||
#include "program.hpp"
|
#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{
|
vector<program::keyword_t> program::_keywords{
|
||||||
// GENERAL
|
// GENERAL
|
||||||
{cmd_undef, "", nullptr, "\nGENERAL"},
|
{kUndef, "", nullptr, "\nGENERAL"},
|
||||||
{cmd_keyword, "nop", &program::rpn_nop, "no operation"},
|
{kKeyword, "nop", &program::rpn_nop, "no operation"},
|
||||||
{cmd_keyword, "help", &program::rpn_help, "this help message"},
|
{kKeyword, "help", &program::rpn_help, "this help message"},
|
||||||
{cmd_keyword, "h", &program::rpn_help, ""},
|
{kKeyword, "h", &program::rpn_help, ""},
|
||||||
{cmd_keyword, "?", &program::rpn_help, ""},
|
{kKeyword, "?", &program::rpn_help, ""},
|
||||||
{cmd_keyword, "quit", &program::rpn_good_bye, "quit software"},
|
{kKeyword, "quit", &program::rpn_good_bye, "quit software"},
|
||||||
{cmd_keyword, "q", &program::rpn_good_bye, ""},
|
{kKeyword, "q", &program::rpn_good_bye, ""},
|
||||||
{cmd_keyword, "exit", &program::rpn_good_bye, ""},
|
{kKeyword, "exit", &program::rpn_good_bye, ""},
|
||||||
{cmd_keyword, "test", &program::rpn_test, ""}, // not seen by user
|
{kKeyword, "test", &program::rpn_test, ""}, // not seen by user
|
||||||
{cmd_keyword, "version", &program::rpn_version, "show rpn version"},
|
{kKeyword, "version", &program::rpn_version, "show rpn version"},
|
||||||
{cmd_keyword, "uname", &program::rpn_uname, "show rpn complete identification string"},
|
{kKeyword, "uname", &program::rpn_uname, "show rpn complete identification string"},
|
||||||
{cmd_keyword, "history", &program::rpn_history, "see commands history"},
|
{kKeyword, "history", &program::rpn_history, "see commands history"},
|
||||||
|
|
||||||
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||||
{cmd_undef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
{kUndef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||||
{cmd_keyword, "+", &program::rpn_plus, "addition"},
|
{kKeyword, "+", &program::rpn_plus, "addition"},
|
||||||
{cmd_keyword, "-", &program::rpn_minus, "substraction"},
|
{kKeyword, "-", &program::rpn_minus, "substraction"},
|
||||||
{cmd_keyword, "*", &program::rpn_mul, "multiplication"},
|
{kKeyword, "*", &program::rpn_mul, "multiplication"},
|
||||||
{cmd_keyword, "/", &program::rpn_div, "division"},
|
{kKeyword, "/", &program::rpn_div, "division"},
|
||||||
{cmd_keyword, "inv", &program::rpn_inv, "inverse"},
|
{kKeyword, "inv", &program::rpn_inv, "inverse"},
|
||||||
{cmd_keyword, "chs", &program::rpn_neg, "negation"},
|
{kKeyword, "chs", &program::rpn_neg, "negation"},
|
||||||
{cmd_keyword, "neg", &program::rpn_neg, ""},
|
{kKeyword, "neg", &program::rpn_neg, ""},
|
||||||
{cmd_keyword, "^", &program::rpn_power, "power"},
|
{kKeyword, "^", &program::rpn_power, "power"},
|
||||||
{cmd_keyword, "pow", &program::rpn_power, ""},
|
{kKeyword, "pow", &program::rpn_power, ""},
|
||||||
{cmd_keyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
|
{kKeyword, "sqrt", &program::rpn_squareroot, "rpn_square root"},
|
||||||
{cmd_keyword, "sq", &program::rpn_square, "rpn_square"},
|
{kKeyword, "sq", &program::rpn_square, "rpn_square"},
|
||||||
{cmd_keyword, "abs", &program::rpn_abs, "absolute value (norm for a complex)"},
|
{kKeyword, "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"},
|
{kKeyword, "sign", &program::rpn_sign, "sign of a number or z/|z| for a complex"},
|
||||||
|
|
||||||
// OPERATIONS ON REALS
|
// OPERATIONS ON REALS
|
||||||
{cmd_undef, "", nullptr, "\nOPERATIONS ON REALS"},
|
{kUndef, "", nullptr, "\nOPERATIONS ON REALS"},
|
||||||
{cmd_keyword, "%", &program::rpn_purcent, "purcent"},
|
{kKeyword, "%", &program::rpn_purcent, "purcent"},
|
||||||
{cmd_keyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
|
{kKeyword, "%CH", &program::rpn_purcentCH, "inverse purcent"},
|
||||||
{cmd_keyword, "mod", &program::rpn_modulo, "modulo"},
|
{kKeyword, "mod", &program::rpn_modulo, "modulo"},
|
||||||
{cmd_keyword, "fact", &program::rpn_fact, "n! for integer n or Gamma(x+1) for fractional x"},
|
{kKeyword, "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"},
|
{kKeyword, "mant", &program::rpn_mant, "mantissa of a real number"},
|
||||||
{cmd_keyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
|
{kKeyword, "xpon", &program::rpn_xpon, "exponant of a real number"},
|
||||||
{cmd_keyword, "floor", &program::rpn_floor, "largest number <="},
|
{kKeyword, "floor", &program::rpn_floor, "largest number <="},
|
||||||
{cmd_keyword, "ceil", &program::rpn_ceil, "smallest number >="},
|
{kKeyword, "ceil", &program::rpn_ceil, "smallest number >="},
|
||||||
{cmd_keyword, "ip", &program::rpn_ip, "integer part"},
|
{kKeyword, "ip", &program::rpn_ip, "integer part"},
|
||||||
{cmd_keyword, "fp", &program::rpn_fp, "fractional part"},
|
{kKeyword, "fp", &program::rpn_fp, "fractional part"},
|
||||||
{cmd_keyword, "min", &program::rpn_min, "min of 2 real numbers"},
|
{kKeyword, "min", &program::rpn_min, "min of 2 real numbers"},
|
||||||
{cmd_keyword, "max", &program::rpn_max, "max of 2 real numbers"},
|
{kKeyword, "max", &program::rpn_max, "max of 2 real numbers"},
|
||||||
|
|
||||||
// OPERATIONS ON COMPLEXES
|
// OPERATIONS ON COMPLEXES
|
||||||
{cmd_undef, "", nullptr, "\nOPERATIONS ON COMPLEXES"},
|
{kUndef, "", nullptr, "\nOPERATIONS ON COMPLEXES"},
|
||||||
{cmd_keyword, "re", &program::rpn_re, "complex real part"},
|
{kKeyword, "re", &program::rpn_re, "complex real part"},
|
||||||
{cmd_keyword, "im", &program::rpn_im, "complex imaginary part"},
|
{kKeyword, "im", &program::rpn_im, "complex imaginary part"},
|
||||||
{cmd_keyword, "conj", &program::rpn_conj, "complex conjugate"},
|
{kKeyword, "conj", &program::rpn_conj, "complex conjugate"},
|
||||||
{cmd_keyword, "arg", &program::rpn_arg, "complex argument in radians"},
|
{kKeyword, "arg", &program::rpn_arg, "complex argument in radians"},
|
||||||
{cmd_keyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"},
|
{kKeyword, "c->r", &program::rpn_c2r, "transform a complex in 2 reals"},
|
||||||
{cmd_keyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
|
{kKeyword, "r->c", &program::rpn_r2c, "transform 2 reals in a complex"},
|
||||||
{cmd_keyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
|
{kKeyword, "p->r", &program::rpn_p2r, "cartesian to polar"},
|
||||||
{cmd_keyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
|
{kKeyword, "r->p", &program::rpn_r2p, "polar to cartesian"},
|
||||||
|
|
||||||
// MODE
|
// MODE
|
||||||
{cmd_undef, "", nullptr, "\nMODE"},
|
{kUndef, "", nullptr, "\nMODE"},
|
||||||
{cmd_keyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"},
|
{kKeyword, "std", &program::rpn_std, "standard floating numbers representation. ex: std"},
|
||||||
{cmd_keyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"},
|
{kKeyword, "fix", &program::rpn_fix, "fixed point representation. ex: 6 fix"},
|
||||||
{cmd_keyword, "sci", &program::rpn_sci, "scientific floating point representation. ex: 20 sci"},
|
{kKeyword, "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"},
|
{kKeyword, "prec", &program::rpn_precision, "set float precision in bits. ex: 256 prec"},
|
||||||
{cmd_keyword, "round", &program::rpn_round,
|
{kKeyword, "round", &program::rpn_round,
|
||||||
"set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward "
|
"set float rounding mode.\n\tex: [\"nearest (even)\", \"toward zero\", \"toward "
|
||||||
"+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\"] round"},
|
"+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"},
|
{kKeyword, "default", &program::rpn_default, "set float representation and precision to default"},
|
||||||
{cmd_keyword, "type", &program::rpn_type, "show type of stack first entry"},
|
{kKeyword, "type", &program::rpn_type, "show type of stack first entry"},
|
||||||
{cmd_keyword, "hex", &program::rpn_hex, "hexadecimal representation, applies on stack level 0 only"},
|
{kKeyword, "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"},
|
{kKeyword, "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"},
|
{kKeyword, "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, "base", &program::rpn_base, "arbitrary base representation, applies on stack level 0 only"},
|
||||||
|
|
||||||
// TESTS
|
// TESTS
|
||||||
{cmd_undef, "", nullptr, "\nTEST"},
|
{kUndef, "", nullptr, "\nTEST"},
|
||||||
{cmd_keyword, ">", &program::rpn_sup, "binary operator >"},
|
{kKeyword, ">", &program::rpn_sup, "binary operator >"},
|
||||||
{cmd_keyword, ">=", &program::rpn_sup_eq, "binary operator >="},
|
{kKeyword, ">=", &program::rpn_sup_eq, "binary operator >="},
|
||||||
{cmd_keyword, "<", &program::rpn_inf, "binary operator <"},
|
{kKeyword, "<", &program::rpn_inf, "binary operator <"},
|
||||||
{cmd_keyword, "<=", &program::rpn_inf_eq, "binary operator <="},
|
{kKeyword, "<=", &program::rpn_inf_eq, "binary operator <="},
|
||||||
{cmd_keyword, "!=", &program::rpn_diff, "binary operator != (different)"},
|
{kKeyword, "!=", &program::rpn_diff, "binary operator != (different)"},
|
||||||
{cmd_keyword, "==", &program::rpn_eq, "binary operator == (equal)"},
|
{kKeyword, "==", &program::rpn_eq, "binary operator == (equal)"},
|
||||||
{cmd_keyword, "and", &program::rpn_test_and, "boolean operator and"},
|
{kKeyword, "and", &program::rpn_test_and, "boolean operator and"},
|
||||||
{cmd_keyword, "or", &program::rpn_test_or, "boolean operator or"},
|
{kKeyword, "or", &program::rpn_test_or, "boolean operator or"},
|
||||||
{cmd_keyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
|
{kKeyword, "xor", &program::rpn_test_xor, "boolean operator xor"},
|
||||||
{cmd_keyword, "not", &program::rpn_test_not, "boolean operator not"},
|
{kKeyword, "not", &program::rpn_test_not, "boolean operator not"},
|
||||||
{cmd_keyword, "same", &program::rpn_same, "boolean operator same (equal)"},
|
{kKeyword, "same", &program::rpn_same, "boolean operator same (equal)"},
|
||||||
|
|
||||||
// STACK
|
// STACK
|
||||||
{cmd_undef, "", nullptr, "\nSTACK"},
|
{kUndef, "", nullptr, "\nSTACK"},
|
||||||
{cmd_keyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
|
{kKeyword, "swap", &program::rpn_swap, "swap 2 first stack entries"},
|
||||||
{cmd_keyword, "drop", &program::rpn_drop, "drop first stack entry"},
|
{kKeyword, "drop", &program::rpn_drop, "drop first stack entry"},
|
||||||
{cmd_keyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"},
|
{kKeyword, "drop2", &program::rpn_drop2, "drop 2 first stack entries"},
|
||||||
{cmd_keyword, "dropn", &program::rpn_dropn, "drop n first stack entries"},
|
{kKeyword, "dropn", &program::rpn_dropn, "drop n first stack entries"},
|
||||||
{cmd_keyword, "del", &program::rpn_erase, "drop all stack entries"},
|
{kKeyword, "del", &program::rpn_erase, "drop all stack entries"},
|
||||||
{cmd_keyword, "erase", &program::rpn_erase, ""},
|
{kKeyword, "erase", &program::rpn_erase, ""},
|
||||||
{cmd_keyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
|
{kKeyword, "rot", &program::rpn_rot, "rotate 3 first stack entries"},
|
||||||
{cmd_keyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
|
{kKeyword, "dup", &program::rpn_dup, "duplicate first stack entry"},
|
||||||
{cmd_keyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries"},
|
{kKeyword, "dup2", &program::rpn_dup2, "duplicate 2 first stack entries"},
|
||||||
{cmd_keyword, "dupn", &program::rpn_dupn, "duplicate n first stack entries"},
|
{kKeyword, "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"},
|
{kKeyword, "pick", &program::rpn_pick, "push a copy of the given stack level onto the stack"},
|
||||||
{cmd_keyword, "depth", &program::rpn_depth, "give stack depth"},
|
{kKeyword, "depth", &program::rpn_depth, "give stack depth"},
|
||||||
{cmd_keyword, "roll", &program::rpn_roll, "move a stack entry to the top of the stack"},
|
{kKeyword, "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"},
|
{kKeyword, "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"},
|
{kKeyword, "over", &program::rpn_over, "push a copy of the element in stack level 2 onto the stack"},
|
||||||
|
|
||||||
// STRING
|
// STRING
|
||||||
{cmd_undef, "", nullptr, "\nSTRING"},
|
{kUndef, "", nullptr, "\nSTRING"},
|
||||||
{cmd_keyword, "->str", &program::rpn_instr, "convert an object into a string"},
|
{kKeyword, "->str", &program::rpn_instr, "convert an object into a string"},
|
||||||
{cmd_keyword, "str->", &program::rpn_strout, "convert a string into an object"},
|
{kKeyword, "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"},
|
{kKeyword, "chr", &program::rpn_chr, "convert ASCII character code in stack level 1 into a string"},
|
||||||
{cmd_keyword, "num", &program::rpn_num,
|
{kKeyword, "num", &program::rpn_num,
|
||||||
"return ASCII code of the first character of the string in stack level 1 as a real number"},
|
"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"},
|
{kKeyword, "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"},
|
{kKeyword, "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, "sub", &program::rpn_strsub, "return a substring of the string in level 3"},
|
||||||
|
|
||||||
// BRANCH
|
// BRANCH
|
||||||
{cmd_undef, "", nullptr, "\nBRANCH"},
|
{kUndef, "", nullptr, "\nBRANCH"},
|
||||||
{cmd_branch, "if", (program_fn_t)&program::rpn_if,
|
{kBranch, "if", (program_fn_t)&program::rpn_if,
|
||||||
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
||||||
"end"},
|
"end"},
|
||||||
{cmd_branch, "then", (program_fn_t)&program::rpn_then, "used with if"},
|
{kBranch, "then", (program_fn_t)&program::rpn_then, "used with if"},
|
||||||
{cmd_branch, "else", (program_fn_t)&program::rpn_else, "used with if"},
|
{kBranch, "else", (program_fn_t)&program::rpn_else, "used with if"},
|
||||||
{cmd_branch, "end", (program_fn_t)&program::rpn_end, "used with various branch instructions"},
|
{kBranch, "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"},
|
{kBranch, "start", (program_fn_t)&program::rpn_start, "<start> <end> start <instructions> next|<step> step"},
|
||||||
{cmd_branch, "for", (program_fn_t)&program::rpn_for,
|
{kBranch, "for", (program_fn_t)&program::rpn_for,
|
||||||
"<start> <end> for <variable> <instructions> next|<step> step"},
|
"<start> <end> for <variable> <instructions> next|<step> step"},
|
||||||
{cmd_branch, "next", (program_fn_t)&program::rpn_next, "used with start and for"},
|
{kBranch, "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"},
|
{kBranch, "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"},
|
{kKeyword, "ift", &program::rpn_ift, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||||
{cmd_keyword, "ifte", &program::rpn_ifte,
|
{kKeyword, "ifte", &program::rpn_ifte,
|
||||||
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
||||||
"<false-instruction> ifte"},
|
"<false-instruction> ifte"},
|
||||||
{cmd_branch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end"},
|
{kBranch, "do", (program_fn_t)&program::rpn_do, "do <instructions> until <condition> end"},
|
||||||
{cmd_branch, "until", (program_fn_t)&program::rpn_until, "used with do"},
|
{kBranch, "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"},
|
{kBranch, "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, "repeat", (program_fn_t)&program::rpn_repeat, "used with while"},
|
||||||
|
|
||||||
// STORE
|
// STORE
|
||||||
{cmd_undef, "", nullptr, "\nSTORE"},
|
{kUndef, "", nullptr, "\nSTORE"},
|
||||||
{cmd_keyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"},
|
{kKeyword, "sto", &program::rpn_sto, "store a variable. ex: 1 'name' sto"},
|
||||||
{cmd_keyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"},
|
{kKeyword, "rcl", &program::rpn_rcl, "recall a variable. ex: 'name' rcl"},
|
||||||
{cmd_keyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"},
|
{kKeyword, "purge", &program::rpn_purge, "delete a variable. ex: 'name' purge"},
|
||||||
{cmd_keyword, "vars", &program::rpn_vars, "list all variables"},
|
{kKeyword, "vars", &program::rpn_vars, "list all variables"},
|
||||||
{cmd_keyword, "clusr", &program::rpn_clusr, "erase all variables"},
|
{kKeyword, "clusr", &program::rpn_clusr, "erase all variables"},
|
||||||
{cmd_keyword, "edit", &program::rpn_edit, "edit a variable content"},
|
{kKeyword, "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+"},
|
{kKeyword, "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-"},
|
{kKeyword, "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*"},
|
{kKeyword, "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/"},
|
{kKeyword, "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"},
|
{kKeyword, "sneg", &program::rpn_stoneg, "negate a variable. ex: 'name' sneg"},
|
||||||
{cmd_keyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"},
|
{kKeyword, "sinv", &program::rpn_stoinv, "inverse a variable. ex: 1 'name' sinv"},
|
||||||
// PROGRAM
|
// PROGRAM
|
||||||
{cmd_undef, "", nullptr, "\nPROGRAM"},
|
{kUndef, "", nullptr, "\nPROGRAM"},
|
||||||
{cmd_keyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
{kKeyword, "eval", &program::rpn_eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||||
{cmd_branch, "->", (program_fn_t)&program::rpn_inprog,
|
{kBranch, "->", (program_fn_t)&program::rpn_inprog,
|
||||||
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
||||||
">>"},
|
">>"},
|
||||||
|
|
||||||
// TRIG ON REALS AND COMPLEXES
|
// TRIG ON REALS AND COMPLEXES
|
||||||
{cmd_undef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"},
|
{kUndef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"},
|
||||||
{cmd_keyword, "pi", &program::rpn_pi, "pi constant"},
|
{kKeyword, "pi", &program::rpn_pi, "pi constant"},
|
||||||
{cmd_keyword, "sin", &program::rpn_sin, "sinus"},
|
{kKeyword, "sin", &program::rpn_sin, "sinus"},
|
||||||
{cmd_keyword, "asin", &program::rpn_asin, "arg sinus"},
|
{kKeyword, "asin", &program::rpn_asin, "arg sinus"},
|
||||||
{cmd_keyword, "cos", &program::rpn_cos, "cosinus"},
|
{kKeyword, "cos", &program::rpn_cos, "cosinus"},
|
||||||
{cmd_keyword, "acos", &program::rpn_acos, "arg cosinus"},
|
{kKeyword, "acos", &program::rpn_acos, "arg cosinus"},
|
||||||
{cmd_keyword, "tan", &program::rpn_tan, "tangent"},
|
{kKeyword, "tan", &program::rpn_tan, "tangent"},
|
||||||
{cmd_keyword, "atan", &program::rpn_atan, "arg tangent"},
|
{kKeyword, "atan", &program::rpn_atan, "arg tangent"},
|
||||||
{cmd_keyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
|
{kKeyword, "d->r", &program::rpn_d2r, "convert degrees to radians"},
|
||||||
{cmd_keyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
|
{kKeyword, "r->d", &program::rpn_r2d, "convert radians to degrees"},
|
||||||
|
|
||||||
// LOGS ON REALS AND COMPLEXES
|
// LOGS ON REALS AND COMPLEXES
|
||||||
{cmd_undef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"},
|
{kUndef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"},
|
||||||
{cmd_keyword, "e", &program::rpn_e, "Euler constant"},
|
{kKeyword, "e", &program::rpn_e, "Euler constant"},
|
||||||
{cmd_keyword, "ln", &program::rpn_ln, "logarithm base e"},
|
{kKeyword, "ln", &program::rpn_ln, "logarithm base e"},
|
||||||
{cmd_keyword, "log", &program::rpn_ln, ""},
|
{kKeyword, "log", &program::rpn_ln, ""},
|
||||||
{cmd_keyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"},
|
{kKeyword, "lnp1", &program::rpn_lnp1, "ln(1+x) which is useful when x is close to 0"},
|
||||||
{cmd_keyword, "exp", &program::rpn_exp, "exponential"},
|
{kKeyword, "exp", &program::rpn_exp, "exponential"},
|
||||||
{cmd_keyword, "expm", &program::rpn_expm, "exp(x)-1 which is useful when x is close to 0"},
|
{kKeyword, "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"},
|
{kKeyword, "log10", &program::rpn_log10, "logarithm base 10"},
|
||||||
{cmd_keyword, "alog10", &program::rpn_alog10, "exponential base 10"},
|
{kKeyword, "alog10", &program::rpn_alog10, "exponential base 10"},
|
||||||
{cmd_keyword, "exp10", &program::rpn_alog10, ""},
|
{kKeyword, "exp10", &program::rpn_alog10, ""},
|
||||||
{cmd_keyword, "log2", &program::rpn_log2, "logarithm base 2"},
|
{kKeyword, "log2", &program::rpn_log2, "logarithm base 2"},
|
||||||
{cmd_keyword, "alog2", &program::rpn_alog2, "exponential base 2"},
|
{kKeyword, "alog2", &program::rpn_alog2, "exponential base 2"},
|
||||||
{cmd_keyword, "exp2", &program::rpn_alog2, ""},
|
{kKeyword, "exp2", &program::rpn_alog2, ""},
|
||||||
{cmd_keyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
|
{kKeyword, "sinh", &program::rpn_sinh, "hyperbolic sine"},
|
||||||
{cmd_keyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
|
{kKeyword, "asinh", &program::rpn_asinh, "inverse hyperbolic sine"},
|
||||||
{cmd_keyword, "cosh", &program::rpn_cosh, "hyperbolic cosine"},
|
{kKeyword, "cosh", &program::rpn_cosh, "hyperbolic cosine"},
|
||||||
{cmd_keyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"},
|
{kKeyword, "acosh", &program::rpn_acosh, "inverse hyperbolic cosine"},
|
||||||
{cmd_keyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
{kKeyword, "tanh", &program::rpn_tanh, "hyperbolic tangent"},
|
||||||
{cmd_keyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
|
{kKeyword, "atanh", &program::rpn_atanh, "inverse hyperbolic tangent"},
|
||||||
|
|
||||||
// TIME AND DATE
|
// TIME AND DATE
|
||||||
{cmd_undef, "", nullptr, "\nTIME AND DATE"},
|
{kUndef, "", nullptr, "\nTIME AND DATE"},
|
||||||
{cmd_keyword, "time", &program::rpn_time, "time in local format"},
|
{kKeyword, "time", &program::rpn_time, "time in local format"},
|
||||||
{cmd_keyword, "date", &program::rpn_date, "date in local format"},
|
{kKeyword, "date", &program::rpn_date, "date in local format"},
|
||||||
{cmd_keyword, "ticks", &program::rpn_ticks, "system tick in µs"},
|
{kKeyword, "ticks", &program::rpn_ticks, "system tick in µs"},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// autocompletion vector for linenoise autocompletion
|
/// autocompletion vector for linenoise autocompletion
|
||||||
|
@ -214,19 +214,19 @@ vector<string>& program::getAutocompletionWords() {
|
||||||
|
|
||||||
/// @brief run a program on a stack and a heap
|
/// @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;
|
bool go_out = false;
|
||||||
ret_value ret = ret_ok;
|
RetValue ret = kOk;
|
||||||
cmd_type_t type;
|
ObjectType type;
|
||||||
|
|
||||||
_err = ret_ok;
|
_err = kOk;
|
||||||
_err_context = "";
|
_err_context = "";
|
||||||
|
|
||||||
// branches for 'if'
|
// branches for 'if'
|
||||||
ret = preprocess();
|
ret = preprocess();
|
||||||
if (ret != ret_ok) {
|
if (ret != kOk) {
|
||||||
// free allocated
|
// free allocated
|
||||||
for (Object* o : *this) delete o;
|
for (Object* o : *this) delete o;
|
||||||
_local_heap.clear();
|
_local_heap.clear();
|
||||||
|
@ -238,36 +238,36 @@ ret_value program::run() {
|
||||||
Object* o = at(i);
|
Object* o = at(i);
|
||||||
switch (o->_type) {
|
switch (o->_type) {
|
||||||
// could be an auto-evaluated symbol
|
// could be an auto-evaluated symbol
|
||||||
case cmd_symbol:
|
case kSymbol:
|
||||||
auto_rcl(reinterpret_cast<Symbol*>(o));
|
auto_rcl(reinterpret_cast<Symbol*>(o));
|
||||||
i++;
|
i++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// a keyword
|
// a keyword
|
||||||
case cmd_keyword: {
|
case kKeyword: {
|
||||||
Keyword* k = reinterpret_cast<Keyword*>(o);
|
Keyword* k = reinterpret_cast<Keyword*>(o);
|
||||||
// call the matching function
|
// call the matching function
|
||||||
(this->*(k->fn))();
|
(this->*(k->fn))();
|
||||||
switch (_err) {
|
switch (_err) {
|
||||||
// no pb -> go on
|
// no pb -> go on
|
||||||
case ret_ok:
|
case kOk:
|
||||||
break;
|
break;
|
||||||
// explicit go out software
|
// explicit go out software
|
||||||
case ret_good_bye:
|
case kGoodbye:
|
||||||
go_out = true;
|
go_out = true;
|
||||||
ret = ret_good_bye;
|
ret = kGoodbye;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// error: abort prog
|
// error: abort prog
|
||||||
go_out = true;
|
go_out = true;
|
||||||
|
|
||||||
// test error: make rpn return EXIT_FAILURE
|
// test error: make rpn return EXIT_FAILURE
|
||||||
if (_err == ret_test_failed) ret = ret_test_failed;
|
if (_err == kTestFailed) ret = kTestFailed;
|
||||||
|
|
||||||
// error: show it
|
// error: show it
|
||||||
if (show_error(_err, _err_context) == ret_deadly)
|
if (show_error(_err, _err_context) == kDeadlyError)
|
||||||
// pb showing error -> go out software
|
// pb showing error -> go out software
|
||||||
ret = ret_good_bye;
|
ret = kGoodbye;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
@ -275,15 +275,15 @@ ret_value program::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// a branch keyword
|
// a branch keyword
|
||||||
case cmd_branch: {
|
case kBranch: {
|
||||||
// call matching function
|
// call matching function
|
||||||
Branch* b = reinterpret_cast<Branch*>(o);
|
Branch* b = reinterpret_cast<Branch*>(o);
|
||||||
size_t next_cmd = (this->*(b->fn))(*b);
|
size_t next_cmd = (this->*(b->fn))(*b);
|
||||||
switch (next_cmd) {
|
switch (next_cmd) {
|
||||||
case step_out: // step out
|
case kStepOut: // step out
|
||||||
i++; // meaning 'next command'
|
i++; // meaning 'next command'
|
||||||
break;
|
break;
|
||||||
case runtime_error: // runtime error
|
case kRtError: // runtime error
|
||||||
(void)show_error(_err, _err_context);
|
(void)show_error(_err, _err_context);
|
||||||
go_out = true;
|
go_out = true;
|
||||||
break;
|
break;
|
||||||
|
@ -315,9 +315,9 @@ ret_value program::run() {
|
||||||
/// inner members of branch or keyword objects are filled by this function
|
/// 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.
|
/// 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 {
|
struct if_layout_t {
|
||||||
if_layout_t()
|
if_layout_t()
|
||||||
: index_then_or_unti_or_repeat(-1),
|
: index_then_or_unti_or_repeat(-1),
|
||||||
|
@ -341,7 +341,7 @@ ret_value program::preprocess(void) {
|
||||||
// analyse if-then-else-end branches
|
// analyse if-then-else-end branches
|
||||||
// analyse start-{next, step} branches
|
// analyse start-{next, step} branches
|
||||||
for (size_t i = 0; i < size(); i++) {
|
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));
|
Branch* k = reinterpret_cast<Branch*>(at(i));
|
||||||
if (k->value == "if") {
|
if (k->value == "if") {
|
||||||
if_layout_t layout;
|
if_layout_t layout;
|
||||||
|
@ -350,51 +350,51 @@ ret_value program::preprocess(void) {
|
||||||
layout_index++;
|
layout_index++;
|
||||||
} else if (k->value == "then") {
|
} else if (k->value == "then") {
|
||||||
size_t next = i + 1;
|
size_t next = i + 1;
|
||||||
if (next >= size()) next = step_out;
|
if (next >= size()) next = kStepOut;
|
||||||
|
|
||||||
// nothing after 'then' -> error
|
// nothing after 'then' -> error
|
||||||
if (next == step_out) {
|
if (next == kStepOut) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing end after then");
|
show_syntax_error("missing end after then");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (layout_index < 0) {
|
if (layout_index < 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing if before then");
|
show_syntax_error("missing if before then");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate then");
|
show_syntax_error("duplicate then");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
||||||
k->arg1 = next;
|
k->arg1 = next;
|
||||||
k->arg3 = vlayout[layout_index].index_if_or_do_or_while;
|
k->arg3 = vlayout[layout_index].index_if_or_do_or_while;
|
||||||
} else if (k->value == "else") {
|
} else if (k->value == "else") {
|
||||||
size_t next = i + 1;
|
size_t next = i + 1;
|
||||||
if (next >= size()) next = step_out;
|
if (next >= size()) next = kStepOut;
|
||||||
|
|
||||||
// nothing after 'else' -> error
|
// nothing after 'else' -> error
|
||||||
if (next == step_out) {
|
if (next == kStepOut) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing end after else");
|
show_syntax_error("missing end after else");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (layout_index < 0) {
|
if (layout_index < 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing if before else");
|
show_syntax_error("missing if before else");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing then before else");
|
show_syntax_error("missing then before else");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_else != -1) {
|
if (vlayout[layout_index].index_else != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate else");
|
show_syntax_error("duplicate else");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
vlayout[layout_index].index_else = i;
|
vlayout[layout_index].index_else = i;
|
||||||
k->arg1 = next; // fill branch1 (if was false) of 'else'
|
k->arg1 = next; // fill branch1 (if was false) of 'else'
|
||||||
|
@ -410,7 +410,7 @@ ret_value program::preprocess(void) {
|
||||||
if (vstart_index.size() == 0) {
|
if (vstart_index.size() == 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing start or for before next");
|
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
|
k->arg1 = vstart_index[vstart_index.size() - 1]; // 'next' arg1 = 'start' index
|
||||||
reinterpret_cast<Branch*>(at(vstart_index[vstart_index.size() - 1]))->arg2 =
|
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) {
|
if (vstart_index.size() == 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing start or for before step");
|
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
|
k->arg1 = vstart_index[vstart_index.size() - 1]; // fill 'step' branch1 = 'start' index
|
||||||
reinterpret_cast<Branch*>(at(vstart_index[vstart_index.size() - 1]))->arg2 =
|
reinterpret_cast<Branch*>(at(vstart_index[vstart_index.size() - 1]))->arg2 =
|
||||||
|
@ -436,23 +436,23 @@ ret_value program::preprocess(void) {
|
||||||
layout_index++;
|
layout_index++;
|
||||||
} else if (k->value == "until") {
|
} else if (k->value == "until") {
|
||||||
size_t next = i + 1;
|
size_t next = i + 1;
|
||||||
if (next >= size()) next = step_out;
|
if (next >= size()) next = kStepOut;
|
||||||
|
|
||||||
// nothing after 'unti' -> error
|
// nothing after 'unti' -> error
|
||||||
if (next == step_out) {
|
if (next == kStepOut) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing end");
|
show_syntax_error("missing end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (layout_index < 0 || !vlayout[layout_index].is_do_unti) {
|
if (layout_index < 0 || !vlayout[layout_index].is_do_unti) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing do");
|
show_syntax_error("missing do");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate until");
|
show_syntax_error("duplicate until");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
||||||
} else if (k->value == "while") {
|
} else if (k->value == "while") {
|
||||||
|
@ -465,35 +465,35 @@ ret_value program::preprocess(void) {
|
||||||
if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) {
|
if (layout_index < 0 || !vlayout[layout_index].is_while_repeat) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing while");
|
show_syntax_error("missing while");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate repeat");
|
show_syntax_error("duplicate repeat");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
vlayout[layout_index].index_then_or_unti_or_repeat = i;
|
||||||
} else if (k->value == "end") {
|
} else if (k->value == "end") {
|
||||||
size_t next = i + 1;
|
size_t next = i + 1;
|
||||||
if (next >= size()) next = step_out;
|
if (next >= size()) next = kStepOut;
|
||||||
|
|
||||||
if (layout_index < 0) {
|
if (layout_index < 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing branch instruction before end");
|
show_syntax_error("missing branch instruction before end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
} else {
|
} else {
|
||||||
if (vlayout[layout_index].is_do_unti) {
|
if (vlayout[layout_index].is_do_unti) {
|
||||||
// this end closes a do..unti
|
// this end closes a do..unti
|
||||||
if (vlayout[layout_index].index_end != -1) {
|
if (vlayout[layout_index].index_end != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate end");
|
show_syntax_error("duplicate end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing until");
|
show_syntax_error("missing until");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
|
|
||||||
k->arg1 = vlayout[layout_index].index_if_or_do_or_while + 1;
|
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) {
|
if (vlayout[layout_index].index_end != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate end");
|
show_syntax_error("duplicate end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
|
|
||||||
k->arg2 = vlayout[layout_index].index_if_or_do_or_while + 1;
|
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) {
|
if (vlayout[layout_index].index_then_or_unti_or_repeat == -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing repeat");
|
show_syntax_error("missing repeat");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill 'repeat' arg1 with 'end+1'
|
// fill 'repeat' arg1 with 'end+1'
|
||||||
|
@ -522,7 +522,7 @@ ret_value program::preprocess(void) {
|
||||||
if (vlayout[layout_index].index_end != -1) {
|
if (vlayout[layout_index].index_end != -1) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("duplicate end");
|
show_syntax_error("duplicate end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vlayout[layout_index].index_else != -1) {
|
if (vlayout[layout_index].index_else != -1) {
|
||||||
// fill 'end' branch of 'else'
|
// fill 'end' branch of 'else'
|
||||||
|
@ -535,7 +535,7 @@ ret_value program::preprocess(void) {
|
||||||
} else {
|
} else {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing then");
|
show_syntax_error("missing then");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
layout_index--;
|
layout_index--;
|
||||||
|
@ -547,27 +547,27 @@ ret_value program::preprocess(void) {
|
||||||
if (layout_index >= 0) {
|
if (layout_index >= 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing end");
|
show_syntax_error("missing end");
|
||||||
return ret_syntax;
|
return kSyntaxError;
|
||||||
}
|
}
|
||||||
if (vstart_index.size() > 0) {
|
if (vstart_index.size() > 0) {
|
||||||
// error: show it
|
// error: show it
|
||||||
show_syntax_error("missing next or step after for or start");
|
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
|
/// @brief parse an entry string: cut it into objects chunks and add them to a program
|
||||||
///
|
///
|
||||||
/// @param entry the entry string
|
/// @param entry the entry string
|
||||||
/// @param prog the program to be filled
|
/// @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;
|
static map<string, Lexer::ReservedWord> keywords_map;
|
||||||
vector<Lexer::SynElement> elements;
|
vector<Lexer::SynElement> elements;
|
||||||
vector<Lexer::SynError> errors;
|
vector<Lexer::SynError> errors;
|
||||||
ret_value ret = ret_ok;
|
RetValue ret = kOk;
|
||||||
|
|
||||||
// prepare map for finding reserved keywords
|
// prepare map for finding reserved keywords
|
||||||
if (keywords_map.empty())
|
if (keywords_map.empty())
|
||||||
|
@ -579,29 +579,29 @@ ret_value program::parse(string& entry) {
|
||||||
// make objects from parsed elements
|
// make objects from parsed elements
|
||||||
for (Lexer::SynElement& element : elements) {
|
for (Lexer::SynElement& element : elements) {
|
||||||
switch (element.type) {
|
switch (element.type) {
|
||||||
case cmd_number:
|
case kNumber:
|
||||||
push_back(new Number(*element.re, element.reBase));
|
push_back(new Number(*element.re, element.reBase));
|
||||||
break;
|
break;
|
||||||
case cmd_complex:
|
case kComplex:
|
||||||
push_back(new Complex(*element.re, *element.im, element.reBase, element.imBase));
|
push_back(new Complex(*element.re, *element.im, element.reBase, element.imBase));
|
||||||
break;
|
break;
|
||||||
case cmd_string:
|
case kString:
|
||||||
push_back(new String(element.value));
|
push_back(new String(element.value));
|
||||||
break;
|
break;
|
||||||
case cmd_symbol:
|
case kSymbol:
|
||||||
push_back(new Symbol(element.value, element.autoEval));
|
push_back(new Symbol(element.value, element.autoEval));
|
||||||
break;
|
break;
|
||||||
case cmd_program:
|
case kProgram:
|
||||||
push_back(new Program(element.value));
|
push_back(new Program(element.value));
|
||||||
break;
|
break;
|
||||||
case cmd_keyword:
|
case kKeyword:
|
||||||
push_back(new Keyword(element.fn, element.value));
|
push_back(new Keyword(element.fn, element.value));
|
||||||
break;
|
break;
|
||||||
case cmd_branch:
|
case kBranch:
|
||||||
push_back(new Branch((branch_fn_t)element.fn, element.value));
|
push_back(new Branch((branch_fn_t)element.fn, element.value));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
show_error(ret_unknown_err, "error creating program from entry");
|
show_error(kUnknownError, "error creating program from entry");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (element.re != nullptr) delete element.re;
|
if (element.re != nullptr) delete element.re;
|
||||||
|
@ -616,27 +616,29 @@ ret_value program::parse(string& entry) {
|
||||||
|
|
||||||
/// @brief show the last error set
|
/// @brief show the last error set
|
||||||
///
|
///
|
||||||
/// @return ret_value see this type
|
/// @return RetValue see this type
|
||||||
///
|
///
|
||||||
ret_value program::show_error() {
|
RetValue program::show_error() {
|
||||||
ret_value ret;
|
RetValue ret;
|
||||||
// clang-format off
|
// clang-format off
|
||||||
vector<string> errorStrings {"ok", "unknown command", "missing operand", "bad operand type",
|
map<RetValue, string> errorStrings{{kOk, "ok"}, {kUnknownError, "unknown command"},
|
||||||
"out of range", "unknown variable", "internal error, aborting", "deadly", "goodbye", "not implemented",
|
{kMissingOperand, "missing operand"}, {kBadOperandType, "bad operand type"},
|
||||||
"no operation", "syntax error", "division by zero", "runtime error", "aborted current entry", "out of memory",
|
{kOutOfRange, "out of range"}, {kUnknownVariable, "unknown variable"},
|
||||||
"bad value", "test failed"};
|
{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
|
// clang-format on
|
||||||
// show last recorded error
|
|
||||||
if (static_cast<size_t>(_err) < errorStrings.size())
|
|
||||||
cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl;
|
cerr << _err_context << ": error " << _err << ": " << errorStrings[_err] << endl;
|
||||||
else
|
|
||||||
cerr << _err_context << " (unknown error code)" << endl;
|
|
||||||
switch (_err) {
|
switch (_err) {
|
||||||
case ret_internal:
|
case kInternalError:
|
||||||
case ret_deadly:
|
case kDeadlyError:
|
||||||
ret = ret_deadly;
|
ret = kDeadlyError;
|
||||||
default:
|
default:
|
||||||
ret = ret_ok;
|
ret = kOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -646,9 +648,9 @@ ret_value program::show_error() {
|
||||||
///
|
///
|
||||||
/// @param err the error to record
|
/// @param err the error to record
|
||||||
/// @param context a context string
|
/// @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
|
// record error
|
||||||
_err = err;
|
_err = err;
|
||||||
_err_context = context;
|
_err_context = context;
|
||||||
|
@ -659,9 +661,9 @@ ret_value program::show_error(ret_value err, string& context) {
|
||||||
///
|
///
|
||||||
/// @param err the error to record
|
/// @param err the error to record
|
||||||
/// @param context a context string
|
/// @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
|
// record error
|
||||||
_err = err;
|
_err = err;
|
||||||
_err_context = context;
|
_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 err the error to record
|
||||||
/// @param context a context string
|
/// @param context a context string
|
||||||
/// @return ret_value see this type
|
/// @return RetValue see this type
|
||||||
///
|
///
|
||||||
void program::show_syntax_error(const char* context) {
|
void program::show_syntax_error(const char* context) {
|
||||||
// record error
|
// record error
|
||||||
_err = ret_syntax;
|
_err = kSyntaxError;
|
||||||
_err_context = context;
|
_err_context = context;
|
||||||
(void)show_error();
|
(void)show_error();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief return the last error set
|
/// @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)
|
/// @brief show a stack (show its different objects)
|
||||||
/// generally a stack is associated to a running program
|
/// generally a stack is associated to a running program
|
||||||
|
|
|
@ -28,19 +28,19 @@ class program : public deque<Object*>, public Lexer {
|
||||||
}
|
}
|
||||||
|
|
||||||
// parser
|
// parser
|
||||||
ret_value parse(string& entry);
|
RetValue parse(string& entry);
|
||||||
static ret_value get_fn(const char* fn_name, program_fn_t& fn, cmd_type_t& type);
|
static RetValue get_fn(const char* fn_name, program_fn_t& fn, ObjectType& type);
|
||||||
|
|
||||||
// running
|
// running
|
||||||
ret_value run();
|
RetValue run();
|
||||||
void stop();
|
void stop();
|
||||||
ret_value preprocess(void);
|
RetValue preprocess(void);
|
||||||
|
|
||||||
ret_value show_error();
|
RetValue show_error();
|
||||||
ret_value show_error(ret_value err, string& context);
|
RetValue show_error(RetValue err, string& context);
|
||||||
ret_value show_error(ret_value err, const char* context);
|
RetValue show_error(RetValue err, const char* context);
|
||||||
void show_syntax_error(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);
|
void show_stack(bool show_separator = true);
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// current error and its context
|
// current error and its context
|
||||||
ret_value _err;
|
RetValue _err;
|
||||||
string _err_context;
|
string _err_context;
|
||||||
|
|
||||||
// global stack holding results for user
|
// global stack holding results for user
|
||||||
|
@ -68,7 +68,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
private:
|
private:
|
||||||
// keywords
|
// keywords
|
||||||
struct keyword_t {
|
struct keyword_t {
|
||||||
cmd_type_t type;
|
ObjectType type;
|
||||||
string name;
|
string name;
|
||||||
program_fn_t fn;
|
program_fn_t fn;
|
||||||
string comment;
|
string comment;
|
||||||
|
@ -93,7 +93,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
size_t rpn_for(Branch& myobj);
|
size_t rpn_for(Branch& myobj);
|
||||||
size_t rpn_next(Branch& myobj);
|
size_t rpn_next(Branch& myobj);
|
||||||
size_t rpn_step(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
|
// complex
|
||||||
void rpn_re();
|
void rpn_re();
|
||||||
|
@ -259,7 +259,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
#define MIN_ARGUMENTS(num) \
|
#define MIN_ARGUMENTS(num) \
|
||||||
do { \
|
do { \
|
||||||
if ((num) >= 0 && _stack.size() < (num)) { \
|
if ((num) >= 0 && _stack.size() < (num)) { \
|
||||||
setErrorContext(ret_missing_operand); \
|
setErrorContext(kMissingOperand); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -267,7 +267,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
#define MIN_ARGUMENTS_RET(num, ret) \
|
#define MIN_ARGUMENTS_RET(num, ret) \
|
||||||
do { \
|
do { \
|
||||||
if ((num) >= 0 && _stack.size() < (num)) { \
|
if ((num) >= 0 && _stack.size() < (num)) { \
|
||||||
setErrorContext(ret_missing_operand); \
|
setErrorContext(kMissingOperand); \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -275,7 +275,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
#define ARG_MUST_BE_OF_TYPE(num, type) \
|
#define ARG_MUST_BE_OF_TYPE(num, type) \
|
||||||
do { \
|
do { \
|
||||||
if ((num) >= 0 && _stack.at(num)->_type != (type)) { \
|
if ((num) >= 0 && _stack.at(num)->_type != (type)) { \
|
||||||
setErrorContext(ret_bad_operand_type); \
|
setErrorContext(kBadOperandType); \
|
||||||
return; \
|
return; \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -283,7 +283,7 @@ class program : public deque<Object*>, public Lexer {
|
||||||
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
|
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
|
||||||
do { \
|
do { \
|
||||||
if ((num) >= 0 && _stack.at(num)->_type != (type)) { \
|
if ((num) >= 0 && _stack.at(num)->_type != (type)) { \
|
||||||
setErrorContext(ret_bad_operand_type); \
|
setErrorContext(kBadOperandType); \
|
||||||
return (ret); \
|
return (ret); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
|
@ -6,28 +6,28 @@
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_if(Branch& myobj) {
|
size_t program::rpn_if(Branch& myobj) {
|
||||||
// myobj.arg1 = 'if' condition evaluation value
|
// myobj.arg1 = 'if' condition evaluation value
|
||||||
MIN_ARGUMENTS_RET(1, runtime_error);
|
MIN_ARGUMENTS_RET(1, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
|
|
||||||
if (_stack.value<Number>(0) != 0)
|
if (_stack.value<Number>(0) != 0)
|
||||||
myobj.arg1 = 1;
|
myobj.arg1 = 1;
|
||||||
else
|
else
|
||||||
myobj.arg1 = 0;
|
myobj.arg1 = 0;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
return step_out;
|
return kStepOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief then keyword (branch) implementation
|
/// @brief then keyword (branch) implementation
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort Branch
|
/// @return kRtError something went wrong with preprocess, abort Branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_then(Branch& myobj) {
|
size_t program::rpn_then(Branch& myobj) {
|
||||||
// myobj.arg1 = index of then + 1
|
// myobj.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)
|
// if condition is true -> arg1 (= jump to then + 1)
|
||||||
// else -> arg2 (= jump to else + 1 or end + 1)
|
// else -> arg2 (= jump to else + 1 or end + 1)
|
||||||
Branch* if_cmd;
|
Branch* if_cmd;
|
||||||
if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) {
|
if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
if_cmd = reinterpret_cast<Branch*>(at(myobj.arg3));
|
if_cmd = reinterpret_cast<Branch*>(at(myobj.arg3));
|
||||||
if (if_cmd->arg1 == 1)
|
if (if_cmd->arg1 == 1)
|
||||||
|
@ -51,8 +51,8 @@ size_t program::rpn_then(Branch& myobj) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_else(Branch& myobj) {
|
size_t program::rpn_else(Branch& myobj) {
|
||||||
// myobj.arg1 = index of else + 1
|
// myobj.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 false -> arg1 (= jump to else + 1)
|
||||||
// if condition was true -> arg2 (= jump to end + 1)
|
// if condition was true -> arg2 (= jump to end + 1)
|
||||||
Branch* if_cmd;
|
Branch* if_cmd;
|
||||||
if (myobj.arg3 >= size() || at(myobj.arg3)->_type != cmd_branch) {
|
if (myobj.arg3 >= size() || at(myobj.arg3)->_type != kBranch) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
if_cmd = reinterpret_cast<Branch*>(at(myobj.arg3));
|
if_cmd = reinterpret_cast<Branch*>(at(myobj.arg3));
|
||||||
if (if_cmd->arg1 == 1)
|
if (if_cmd->arg1 == 1)
|
||||||
|
@ -76,22 +76,22 @@ size_t program::rpn_else(Branch& myobj) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_end(Branch& myobj) {
|
size_t program::rpn_end(Branch& myobj) {
|
||||||
size_t ret = step_out;
|
size_t ret = kStepOut;
|
||||||
|
|
||||||
// arg1 = index of do+1 in case of do..unti..end
|
// arg1 = index of do+1 in case of do..unti..end
|
||||||
if (myobj.arg1 != -1) {
|
if (myobj.arg1 != -1) {
|
||||||
// in a template do..until..end
|
// in a template do..until..end
|
||||||
MIN_ARGUMENTS_RET(1, runtime_error);
|
MIN_ARGUMENTS_RET(1, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
|
|
||||||
// check arg
|
// check arg
|
||||||
if (_stack.value<Number>(0) == 0) ret = myobj.arg1;
|
if (_stack.value<Number>(0) == 0) ret = myobj.arg1;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else if (myobj.arg2 != step_out) {
|
} else if (myobj.arg2 != kStepOut) {
|
||||||
// arg2 = index of while+1 in case of while..repeat..end
|
// arg2 = index of while+1 in case of while..repeat..end
|
||||||
ret = myobj.arg2;
|
ret = myobj.arg2;
|
||||||
}
|
}
|
||||||
|
@ -103,36 +103,36 @@ size_t program::rpn_end(Branch& myobj) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_do(Branch& myobj) {
|
size_t program::rpn_do(Branch& myobj) {
|
||||||
// nothing
|
// nothing
|
||||||
return step_out;
|
return kStepOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief until keyword (branch) implementation
|
/// @brief until keyword (branch) implementation
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort Branch
|
/// @return kRtError something went wrong with preprocess, abort Branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_until(Branch& myobj) {
|
size_t program::rpn_until(Branch& myobj) {
|
||||||
// nothing
|
// nothing
|
||||||
return step_out;
|
return kStepOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief ift keyword (branch) implementation
|
/// @brief ift keyword (branch) implementation
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
void program::rpn_ift(void) {
|
void program::rpn_ift(void) {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
|
|
||||||
// check ift arg
|
// check ift arg
|
||||||
// arg is true if Number != 0 or if is nan or +/-inf
|
// 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
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
void program::rpn_ifte(void) {
|
void program::rpn_ifte(void) {
|
||||||
MIN_ARGUMENTS(3);
|
MIN_ARGUMENTS(3);
|
||||||
ARG_MUST_BE_OF_TYPE(2, cmd_number);
|
ARG_MUST_BE_OF_TYPE(2, kNumber);
|
||||||
|
|
||||||
// check ifte arg
|
// check ifte arg
|
||||||
if (_stack.value<Number>(2) != 0) {
|
if (_stack.value<Number>(2) != 0) {
|
||||||
|
@ -167,26 +167,26 @@ void program::rpn_ifte(void) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_while(Branch& myobj) {
|
size_t program::rpn_while(Branch& myobj) {
|
||||||
// nothing
|
// nothing
|
||||||
return step_out;
|
return kStepOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief repeat keyword (branch) implementation
|
/// @brief repeat keyword (branch) implementation
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_repeat(Branch& myobj) {
|
size_t program::rpn_repeat(Branch& myobj) {
|
||||||
size_t ret = step_out;
|
size_t ret = kStepOut;
|
||||||
|
|
||||||
MIN_ARGUMENTS_RET(1, runtime_error);
|
MIN_ARGUMENTS_RET(1, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
|
|
||||||
// check arg
|
// check arg
|
||||||
// myobj.arg1 is end+1
|
// myobj.arg1 is end+1
|
||||||
|
@ -200,15 +200,15 @@ size_t program::rpn_repeat(Branch& myobj) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_start(Branch& myobj) {
|
size_t program::rpn_start(Branch& myobj) {
|
||||||
size_t ret = step_out;
|
size_t ret = kStepOut;
|
||||||
|
|
||||||
MIN_ARGUMENTS_RET(2, runtime_error);
|
MIN_ARGUMENTS_RET(2, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(1, kNumber, kRtError);
|
||||||
|
|
||||||
// loop boundaries
|
// loop boundaries
|
||||||
myobj.firstIndex = _stack.value<Number>(1);
|
myobj.firstIndex = _stack.value<Number>(1);
|
||||||
|
@ -229,20 +229,20 @@ size_t program::rpn_start(Branch& myobj) {
|
||||||
///
|
///
|
||||||
/// @param myobj the current branch object
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_for(Branch& myobj) {
|
size_t program::rpn_for(Branch& myobj) {
|
||||||
size_t ret;
|
size_t ret;
|
||||||
|
|
||||||
MIN_ARGUMENTS_RET(2, runtime_error);
|
MIN_ARGUMENTS_RET(2, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(1, kNumber, kRtError);
|
||||||
|
|
||||||
Symbol* sym;
|
Symbol* sym;
|
||||||
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_symbol) {
|
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kSymbol) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
sym = reinterpret_cast<Symbol*>(at(myobj.arg1)); // arg1 = loop variable index
|
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
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_next(Branch& myobj) {
|
size_t program::rpn_next(Branch& myobj) {
|
||||||
// arg1 = loop variable index
|
// arg1 = loop variable index
|
||||||
// firstIndex = current point in the loop
|
// firstIndex = current point in the loop
|
||||||
Branch* start_or_for;
|
Branch* start_or_for;
|
||||||
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) {
|
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
start_or_for = reinterpret_cast<Branch*>(at(myobj.arg1));
|
start_or_for = reinterpret_cast<Branch*>(at(myobj.arg1));
|
||||||
if (!myobj.arg_bool) {
|
if (!myobj.arg_bool) {
|
||||||
|
@ -301,9 +301,9 @@ size_t program::rpn_next(Branch& myobj) {
|
||||||
if (start_or_for->arg1 != -1) {
|
if (start_or_for->arg1 != -1) {
|
||||||
Object* obj;
|
Object* obj;
|
||||||
Symbol* var;
|
Symbol* var;
|
||||||
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) {
|
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
var = reinterpret_cast<Symbol*>(at(start_or_for->arg1));
|
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) {
|
if (myobj.firstIndex > start_or_for->lastIndex) {
|
||||||
// end of loop
|
// end of loop
|
||||||
myobj.arg_bool = false; // init again next time
|
myobj.arg_bool = false; // init again next time
|
||||||
return step_out;
|
return kStepOut;
|
||||||
} else {
|
} else {
|
||||||
// for command: next instruction will be after symbol variable
|
// for command: next instruction will be after symbol variable
|
||||||
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
|
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
|
/// @param myobj the current branch object
|
||||||
/// @return size_t index of the next object to run in the current program
|
/// @return size_t index of the next object to run in the current program
|
||||||
/// @return step_out next object to run in the current program is current + 1
|
/// @return kStepOut next object to run in the current program is current + 1
|
||||||
/// @return runtime_error something went wrong with preprocess, abort branch
|
/// @return kRtError something went wrong with preprocess, abort branch
|
||||||
///
|
///
|
||||||
size_t program::rpn_step(Branch& myobj) {
|
size_t program::rpn_step(Branch& myobj) {
|
||||||
size_t ret;
|
size_t ret;
|
||||||
MIN_ARGUMENTS_RET(1, runtime_error);
|
MIN_ARGUMENTS_RET(1, kRtError);
|
||||||
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, runtime_error);
|
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||||
|
|
||||||
mpreal step = _stack.value<Number>(0);
|
mpreal step = _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
|
||||||
// end of loop if step is negative or zero
|
// end of loop if step is negative or zero
|
||||||
if (step <= 0) {
|
if (step <= 0) {
|
||||||
ret = step_out;
|
ret = kStepOut;
|
||||||
} else {
|
} else {
|
||||||
// arg1 = loop variable index
|
// arg1 = loop variable index
|
||||||
// firstIndex = current count
|
// firstIndex = current count
|
||||||
Branch* start_or_for;
|
Branch* start_or_for;
|
||||||
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != cmd_branch) {
|
if (myobj.arg1 >= size() || at(myobj.arg1)->_type != kBranch) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
start_or_for = reinterpret_cast<Branch*>(at(myobj.arg1));
|
start_or_for = reinterpret_cast<Branch*>(at(myobj.arg1));
|
||||||
if (!myobj.arg_bool) {
|
if (!myobj.arg_bool) {
|
||||||
|
@ -366,9 +366,9 @@ size_t program::rpn_step(Branch& myobj) {
|
||||||
Symbol* var;
|
Symbol* var;
|
||||||
|
|
||||||
// for command: increment symbol too
|
// for command: increment symbol too
|
||||||
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != cmd_symbol) {
|
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
return runtime_error;
|
return kRtError;
|
||||||
}
|
}
|
||||||
var = reinterpret_cast<Symbol*>(at(start_or_for->arg1));
|
var = reinterpret_cast<Symbol*>(at(start_or_for->arg1));
|
||||||
// increase symbol variable
|
// increase symbol variable
|
||||||
|
@ -379,7 +379,7 @@ size_t program::rpn_step(Branch& myobj) {
|
||||||
if (myobj.firstIndex > start_or_for->lastIndex) {
|
if (myobj.firstIndex > start_or_for->lastIndex) {
|
||||||
// end of loop
|
// end of loop
|
||||||
myobj.arg_bool = false; // init again next time
|
myobj.arg_bool = false; // init again next time
|
||||||
ret = step_out;
|
ret = kStepOut;
|
||||||
} else {
|
} else {
|
||||||
// for command: next instruction will be after symbol variable
|
// for command: next instruction will be after symbol variable
|
||||||
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
|
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
///
|
///
|
||||||
void program::rpn_re() {
|
void program::rpn_re() {
|
||||||
MIN_ARGUMENTS(1);
|
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.push_front(new Number(real(_stack.value<Complex>(0))));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ void program::rpn_re() {
|
||||||
///
|
///
|
||||||
void program::rpn_im() {
|
void program::rpn_im() {
|
||||||
MIN_ARGUMENTS(1);
|
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.push_front(new Number(imag(_stack.value<Complex>(0))));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ void program::rpn_im() {
|
||||||
///
|
///
|
||||||
void program::rpn_arg() {
|
void program::rpn_arg() {
|
||||||
MIN_ARGUMENTS(1);
|
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.push_front(new Number(arg(_stack.value<Complex>(0))));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ void program::rpn_arg() {
|
||||||
///
|
///
|
||||||
void program::rpn_conj() {
|
void program::rpn_conj() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_stack.value<Complex>(0) = conj(_stack.value<Complex>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,8 +46,8 @@ void program::rpn_conj() {
|
||||||
///
|
///
|
||||||
void program::rpn_r2c() {
|
void program::rpn_r2c() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
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.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);
|
_stack.erase(1, 2);
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ void program::rpn_r2c() {
|
||||||
///
|
///
|
||||||
void program::rpn_c2r() {
|
void program::rpn_c2r() {
|
||||||
MIN_ARGUMENTS(1);
|
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(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.push(new Number(imag(_stack.value<Complex>(1)), _stack.obj<Complex>(1).imBase));
|
||||||
_stack.erase(2);
|
_stack.erase(2);
|
||||||
|
@ -68,7 +68,7 @@ void program::rpn_c2r() {
|
||||||
///
|
///
|
||||||
void program::rpn_r2p() {
|
void program::rpn_r2p() {
|
||||||
MIN_ARGUMENTS(1);
|
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 rho = abs(_stack.value<Complex>(0));
|
||||||
mpreal theta = arg(_stack.value<Complex>(0));
|
mpreal theta = arg(_stack.value<Complex>(0));
|
||||||
_stack.value<Complex>(0).real(rho);
|
_stack.value<Complex>(0).real(rho);
|
||||||
|
@ -80,6 +80,6 @@ void program::rpn_r2p() {
|
||||||
///
|
///
|
||||||
void program::rpn_p2r() {
|
void program::rpn_p2r() {
|
||||||
MIN_ARGUMENTS(1);
|
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)));
|
_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
|
/// @brief quit keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_good_bye() { setErrorContext(ret_good_bye); }
|
void program::rpn_good_bye() { setErrorContext(kGoodbye); }
|
||||||
|
|
||||||
/// @brief nop keyword implementation
|
/// @brief nop keyword implementation
|
||||||
/// the result is written on stdout
|
/// the result is written on stdout
|
||||||
|
@ -60,23 +60,23 @@ void program::rpn_help() {
|
||||||
for (auto& kw : _keywords)
|
for (auto& kw : _keywords)
|
||||||
if (!kw.comment.empty()) {
|
if (!kw.comment.empty()) {
|
||||||
// titles in bold
|
// titles in bold
|
||||||
if (kw.type == cmd_undef) cout << ATTR_BOLD;
|
if (kw.type == kUndef) cout << ATTR_BOLD;
|
||||||
// show title or keyword + comment
|
// show title or keyword + comment
|
||||||
cout << kw.name << '\t' << kw.comment << endl;
|
cout << kw.name << '\t' << kw.comment << endl;
|
||||||
if (kw.type == cmd_undef) cout << ATTR_OFF;
|
if (kw.type == kUndef) cout << ATTR_OFF;
|
||||||
}
|
}
|
||||||
cout << endl;
|
cout << endl;
|
||||||
|
|
||||||
// show mode
|
// show mode
|
||||||
cout << "Current float mode is ";
|
cout << "Current float mode is ";
|
||||||
switch (Number::s_mode) {
|
switch (Number::s_mode) {
|
||||||
case Number::std:
|
case Number::kStd:
|
||||||
cout << "'std'";
|
cout << "'std'";
|
||||||
break;
|
break;
|
||||||
case Number::fix:
|
case Number::kFix:
|
||||||
cout << "'fix'";
|
cout << "'fix'";
|
||||||
break;
|
break;
|
||||||
case Number::sci:
|
case Number::kSci:
|
||||||
cout << "'sci'";
|
cout << "'sci'";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -108,17 +108,17 @@ static bool check_decimal_digits(int precision) { return precision >= 0; }
|
||||||
///
|
///
|
||||||
void program::rpn_std() {
|
void program::rpn_std() {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int digits = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
|
|
||||||
if (check_decimal_digits(digits)) {
|
if (check_decimal_digits(digits)) {
|
||||||
// set mode, decimal digits and print format
|
// set mode, decimal digits and print format
|
||||||
Number::s_mode = Number::std;
|
Number::s_mode = Number::kStd;
|
||||||
Number::s_digits = digits;
|
Number::s_digits = digits;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,17 +126,17 @@ void program::rpn_std() {
|
||||||
///
|
///
|
||||||
void program::rpn_fix() {
|
void program::rpn_fix() {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int digits = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
|
|
||||||
if (check_decimal_digits(digits)) {
|
if (check_decimal_digits(digits)) {
|
||||||
// set mode, decimal digits and print format
|
// set mode, decimal digits and print format
|
||||||
Number::s_mode = Number::fix;
|
Number::s_mode = Number::kFix;
|
||||||
Number::s_digits = digits;
|
Number::s_digits = digits;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,17 +144,17 @@ void program::rpn_fix() {
|
||||||
///
|
///
|
||||||
void program::rpn_sci() {
|
void program::rpn_sci() {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int digits = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
|
|
||||||
if (check_decimal_digits(digits)) {
|
if (check_decimal_digits(digits)) {
|
||||||
// set mode, decimal digits and print format
|
// set mode, decimal digits and print format
|
||||||
Number::s_mode = Number::sci;
|
Number::s_mode = Number::kSci;
|
||||||
Number::s_digits = digits;
|
Number::s_digits = digits;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ void program::rpn_default() { program::apply_default(); }
|
||||||
///
|
///
|
||||||
void program::rpn_precision() {
|
void program::rpn_precision() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
|
|
||||||
// set precision
|
// set precision
|
||||||
int prec = static_cast<int>(_stack.value<Number>(0).toLong());
|
int prec = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
|
@ -203,13 +203,13 @@ void program::rpn_precision() {
|
||||||
mpreal::set_default_prec(prec);
|
mpreal::set_default_prec(prec);
|
||||||
|
|
||||||
// modify digits seen by user if std mode
|
// 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
|
// calc max nb of digits user can see with the current bit precision
|
||||||
Number::s_digits = mpfr::bits2digits(mpreal::get_default_prec());
|
Number::s_digits = mpfr::bits2digits(mpreal::get_default_prec());
|
||||||
}
|
}
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +217,7 @@ void program::rpn_precision() {
|
||||||
///
|
///
|
||||||
void program::rpn_round() {
|
void program::rpn_round() {
|
||||||
MIN_ARGUMENTS(1);
|
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};
|
map<string, mpfr_rnd_t> matchRound{MPFR_ROUND};
|
||||||
|
|
||||||
|
@ -225,6 +225,6 @@ void program::rpn_round() {
|
||||||
if (found != matchRound.end())
|
if (found != matchRound.end())
|
||||||
mpreal::set_default_rnd(found->second);
|
mpreal::set_default_rnd(found->second);
|
||||||
else
|
else
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,166 +10,166 @@ void program::rpn_e(void) { _stack.push(new Number(mpfr::const_euler())); }
|
||||||
///
|
///
|
||||||
void program::rpn_log10() {
|
void program::rpn_log10() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = log10(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = log10(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief alog10 keyword implementation
|
/// @brief alog10 keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_alog10() {
|
void program::rpn_alog10() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_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));
|
_stack.value<Complex>(0) = exp(log(mpreal(10)) * _stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief log2 keyword implementation
|
/// @brief log2 keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_log2() {
|
void program::rpn_log2() {
|
||||||
MIN_ARGUMENTS(1);
|
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();
|
_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();
|
_stack.value<Complex>(0) = log(_stack.value<Complex>(0)) / mpfr::const_log2();
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief alog2 keyword implementation
|
/// @brief alog2 keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_alog2() {
|
void program::rpn_alog2() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_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));
|
_stack.value<Complex>(0) = exp(mpfr::const_log2() * _stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief ln keyword implementation
|
/// @brief ln keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_ln() {
|
void program::rpn_ln() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = log(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = log(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief exp keyword implementation
|
/// @brief exp keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_exp() {
|
void program::rpn_exp() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = exp(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = exp(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief expm keyword implementation
|
/// @brief expm keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_expm() {
|
void program::rpn_expm() {
|
||||||
MIN_ARGUMENTS(1);
|
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);
|
_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);
|
_stack.value<Complex>(0) = exp(_stack.value<Complex>(0)) - mpreal(1);
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief lnp1 keyword implementation
|
/// @brief lnp1 keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_lnp1() {
|
void program::rpn_lnp1() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = log(_stack.value<Number>(0) + 1);
|
_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));
|
_stack.value<Complex>(0) = log(_stack.value<Complex>(0) + mpreal(1));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief sinh keyword implementation
|
/// @brief sinh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_sinh() {
|
void program::rpn_sinh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = sinh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = sinh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief asinh keyword implementation
|
/// @brief asinh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_asinh() {
|
void program::rpn_asinh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = asinh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = asinh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief cosh keyword implementation
|
/// @brief cosh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_cosh() {
|
void program::rpn_cosh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = cosh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = cosh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief acosh keyword implementation
|
/// @brief acosh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_acosh() {
|
void program::rpn_acosh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = acosh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = acosh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief tanh keyword implementation
|
/// @brief tanh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_tanh() {
|
void program::rpn_tanh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = tanh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = tanh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief atanh keyword implementation
|
/// @brief atanh keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_atanh() {
|
void program::rpn_atanh() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = atanh(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = atanh(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ void program::rpn_eval(void) {
|
||||||
string prog_text;
|
string prog_text;
|
||||||
|
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_symbol) {
|
if (_stack.type(0) == kSymbol) {
|
||||||
// recall a variable
|
// recall a variable
|
||||||
Object* obj;
|
Object* obj;
|
||||||
string variable(_stack.value<Symbol>(0));
|
string variable(_stack.value<Symbol>(0));
|
||||||
|
@ -46,7 +46,7 @@ void program::rpn_eval(void) {
|
||||||
|
|
||||||
// if variable holds a program, run this program
|
// if variable holds a program, run this program
|
||||||
if (find_variable(variable, obj)) {
|
if (find_variable(variable, obj)) {
|
||||||
if (obj->_type == cmd_program) {
|
if (obj->_type == kProgram) {
|
||||||
prog_text = _stack.value<Program>(0);
|
prog_text = _stack.value<Program>(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
run_prog = true;
|
run_prog = true;
|
||||||
|
@ -55,15 +55,15 @@ void program::rpn_eval(void) {
|
||||||
_stack.push_front(obj);
|
_stack.push_front(obj);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
}
|
}
|
||||||
} else if (_stack.type(0) == cmd_program) {
|
} else if (_stack.type(0) == kProgram) {
|
||||||
// eval a program
|
// eval a program
|
||||||
prog_text = _stack.value<Program>(0);
|
prog_text = _stack.value<Program>(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
run_prog = true;
|
run_prog = true;
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
// run prog if any
|
// run prog if any
|
||||||
|
@ -71,7 +71,7 @@ void program::rpn_eval(void) {
|
||||||
program prog(_stack, _heap, this);
|
program prog(_stack, _heap, this);
|
||||||
|
|
||||||
// make program from entry
|
// make program from entry
|
||||||
if (prog.parse(prog_text) == ret_ok) {
|
if (prog.parse(prog_text) == kOk) {
|
||||||
// run it
|
// run it
|
||||||
prog.run();
|
prog.run();
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ int program::rpn_inprog(Branch& inprog_obj) {
|
||||||
bool prog_found = false;
|
bool prog_found = false;
|
||||||
|
|
||||||
if (inprog_obj.arg1 == -1) {
|
if (inprog_obj.arg1 == -1) {
|
||||||
setErrorContext(ret_unknown_err);
|
setErrorContext(kUnknownError);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,15 +96,15 @@ int program::rpn_inprog(Branch& inprog_obj) {
|
||||||
// find next Program object
|
// find next Program object
|
||||||
for (unsigned int i = inprog_obj.arg1 + 1; i < size(); i++) {
|
for (unsigned int i = inprog_obj.arg1 + 1; i < size(); i++) {
|
||||||
// count symbol
|
// count symbol
|
||||||
if (at(i)->_type == cmd_symbol) {
|
if (at(i)->_type == kSymbol) {
|
||||||
count_symbols++;
|
count_symbols++;
|
||||||
} else if (at(i)->_type == cmd_program) {
|
} else if (at(i)->_type == kProgram) {
|
||||||
// stop if prog
|
// stop if prog
|
||||||
prog_found = true;
|
prog_found = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// found something other than symbol
|
// found something other than symbol
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
show_error(_err, context);
|
show_error(_err, context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -112,21 +112,21 @@ int program::rpn_inprog(Branch& inprog_obj) {
|
||||||
|
|
||||||
// found 0 symbols
|
// found 0 symbols
|
||||||
if (count_symbols == 0) {
|
if (count_symbols == 0) {
|
||||||
setErrorContext(ret_syntax);
|
setErrorContext(kSyntaxError);
|
||||||
show_error(_err, context);
|
show_error(_err, context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// <program> is missing
|
// <program> is missing
|
||||||
if (!prog_found) {
|
if (!prog_found) {
|
||||||
setErrorContext(ret_syntax);
|
setErrorContext(kSyntaxError);
|
||||||
show_error(_err, context);
|
show_error(_err, context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check symbols Number vs stack size
|
// check symbols Number vs stack size
|
||||||
if (_stack.size() < count_symbols) {
|
if (_stack.size() < count_symbols) {
|
||||||
setErrorContext(ret_missing_operand);
|
setErrorContext(kMissingOperand);
|
||||||
show_error(_err, context);
|
show_error(_err, context);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +142,7 @@ int program::rpn_inprog(Branch& inprog_obj) {
|
||||||
program prog(_stack, _heap, this);
|
program prog(_stack, _heap, this);
|
||||||
|
|
||||||
// make the program from entry
|
// make the program from entry
|
||||||
if (prog.parse(entry) == ret_ok) {
|
if (prog.parse(entry) == kOk) {
|
||||||
// run it
|
// run it
|
||||||
prog.run();
|
prog.run();
|
||||||
}
|
}
|
||||||
|
|
152
src/rpn-real.cpp
152
src/rpn-real.cpp
|
@ -6,24 +6,24 @@
|
||||||
///
|
///
|
||||||
void program::rpn_plus() {
|
void program::rpn_plus() {
|
||||||
MIN_ARGUMENTS(2);
|
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.value<String>(1) += _stack.value<String>(0);
|
||||||
_stack.pop();
|
_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.value<Number>(1) += _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) += _stack.value<Complex>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) += _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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();
|
rpn_swap();
|
||||||
_stack.value<Complex>(1) += _stack.value<Number>(0);
|
_stack.value<Complex>(1) += _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,21 +31,21 @@ void program::rpn_plus() {
|
||||||
///
|
///
|
||||||
void program::rpn_minus() {
|
void program::rpn_minus() {
|
||||||
MIN_ARGUMENTS(2);
|
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.value<Number>(1) -= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) -= _stack.value<Complex>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) -= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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();
|
rpn_swap();
|
||||||
_stack.value<Complex>(1) = _stack.value<Number>(0) - _stack.value<Complex>(1);
|
_stack.value<Complex>(1) = _stack.value<Number>(0) - _stack.value<Complex>(1);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,21 +53,21 @@ void program::rpn_minus() {
|
||||||
///
|
///
|
||||||
void program::rpn_mul() {
|
void program::rpn_mul() {
|
||||||
MIN_ARGUMENTS(2);
|
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.value<Number>(1) *= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) *= _stack.value<Complex>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) *= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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();
|
rpn_swap();
|
||||||
_stack.value<Complex>(1) *= _stack.value<Number>(0);
|
_stack.value<Complex>(1) *= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,21 +75,21 @@ void program::rpn_mul() {
|
||||||
///
|
///
|
||||||
void program::rpn_div() {
|
void program::rpn_div() {
|
||||||
MIN_ARGUMENTS(2);
|
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.value<Number>(1) /= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) /= _stack.value<Complex>(0);
|
||||||
_stack.pop();
|
_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.value<Complex>(1) /= _stack.value<Number>(0);
|
||||||
_stack.pop();
|
_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();
|
rpn_swap();
|
||||||
_stack.value<Complex>(1) = _stack.value<Number>(0) / _stack.value<Complex>(1);
|
_stack.value<Complex>(1) = _stack.value<Number>(0) / _stack.value<Complex>(1);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,31 +97,31 @@ void program::rpn_div() {
|
||||||
///
|
///
|
||||||
void program::rpn_neg() {
|
void program::rpn_neg() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = -_stack.value<Number>(0);
|
_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);
|
_stack.value<Complex>(0) = -_stack.value<Complex>(0);
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief inv keyword implementation
|
/// @brief inv keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_inv() {
|
void program::rpn_inv() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = 1 / _stack.value<Number>(0);
|
_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);
|
_stack.value<Complex>(0) = mpreal(1) / _stack.value<Complex>(0);
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief power keyword implementation
|
/// @brief power keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_power() {
|
void program::rpn_power() {
|
||||||
MIN_ARGUMENTS(2);
|
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) {
|
if (_stack.value<Number>(1) >= 0) {
|
||||||
_stack.value<Number>(1) = pow(_stack.value<Number>(1), _stack.value<Number>(0));
|
_stack.value<Number>(1) = pow(_stack.value<Number>(1), _stack.value<Number>(0));
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
@ -131,18 +131,18 @@ void program::rpn_power() {
|
||||||
_stack.value<Complex>(0) = pow(_stack.value<Complex>(0), _stack.value<Number>(1));
|
_stack.value<Complex>(0) = pow(_stack.value<Complex>(0), _stack.value<Number>(1));
|
||||||
_stack.erase(1, 2);
|
_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.value<Complex>(1) = pow(_stack.value<Complex>(1), _stack.value<Complex>(0));
|
||||||
_stack.pop();
|
_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.value<Complex>(1) = pow(_stack.value<Complex>(1), _stack.value<Number>(0));
|
||||||
_stack.pop();
|
_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();
|
rpn_swap();
|
||||||
_stack.value<Complex>(1) = pow(_stack.value<Number>(0), _stack.value<Complex>(1));
|
_stack.value<Complex>(1) = pow(_stack.value<Number>(0), _stack.value<Complex>(1));
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ void program::rpn_power() {
|
||||||
///
|
///
|
||||||
void program::rpn_squareroot() {
|
void program::rpn_squareroot() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
if (_stack.value<Number>(0) >= 0) {
|
if (_stack.value<Number>(0) >= 0) {
|
||||||
_stack.value<Number>(0) = sqrt(_stack.value<Number>(0));
|
_stack.value<Number>(0) = sqrt(_stack.value<Number>(0));
|
||||||
} else {
|
} else {
|
||||||
|
@ -161,10 +161,10 @@ void program::rpn_squareroot() {
|
||||||
_stack.value<Complex>(0) = sqrt(_stack.value<Complex>(0));
|
_stack.value<Complex>(0) = sqrt(_stack.value<Complex>(0));
|
||||||
_stack.erase(1);
|
_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));
|
_stack.value<Complex>(0) = sqrt(_stack.value<Complex>(0));
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,13 +172,13 @@ void program::rpn_squareroot() {
|
||||||
///
|
///
|
||||||
void program::rpn_hex() {
|
void program::rpn_hex() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
_stack.obj<Number>(0).base = 16;
|
_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).reBase = 16;
|
||||||
_stack.obj<Complex>(0).imBase = 16;
|
_stack.obj<Complex>(0).imBase = 16;
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,13 +186,13 @@ void program::rpn_hex() {
|
||||||
///
|
///
|
||||||
void program::rpn_bin() {
|
void program::rpn_bin() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
_stack.obj<Number>(0).base = 2;
|
_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).reBase = 2;
|
||||||
_stack.obj<Complex>(0).imBase = 2;
|
_stack.obj<Complex>(0).imBase = 2;
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,13 +200,13 @@ void program::rpn_bin() {
|
||||||
///
|
///
|
||||||
void program::rpn_dec() {
|
void program::rpn_dec() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
_stack.obj<Number>(0).base = 10;
|
_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).reBase = 10;
|
||||||
_stack.obj<Complex>(0).imBase = 10;
|
_stack.obj<Complex>(0).imBase = 10;
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,21 +214,21 @@ void program::rpn_dec() {
|
||||||
///
|
///
|
||||||
void program::rpn_base() {
|
void program::rpn_base() {
|
||||||
MIN_ARGUMENTS(2);
|
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());
|
int base = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
if (base >= 2 && base <= 62) {
|
if (base >= 2 && base <= 62) {
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
_stack.obj<Number>(0).base = base;
|
_stack.obj<Number>(0).base = base;
|
||||||
} else {
|
} else {
|
||||||
_stack.obj<Complex>(0).reBase = base;
|
_stack.obj<Complex>(0).reBase = base;
|
||||||
_stack.obj<Complex>(0).imBase = base;
|
_stack.obj<Complex>(0).imBase = base;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ void program::rpn_base() {
|
||||||
///
|
///
|
||||||
void program::rpn_purcent() {
|
void program::rpn_purcent() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
_stack.value<Number>(1) *= _stack.value<Number>(0) / 100;
|
_stack.value<Number>(1) *= _stack.value<Number>(0) / 100;
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
}
|
}
|
||||||
|
@ -246,8 +246,8 @@ void program::rpn_purcent() {
|
||||||
///
|
///
|
||||||
void program::rpn_purcentCH() {
|
void program::rpn_purcentCH() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
_stack.value<Number>(1) = (_stack.value<Number>(0) * 100) / _stack.value<Number>(1);
|
_stack.value<Number>(1) = (_stack.value<Number>(0) * 100) / _stack.value<Number>(1);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
}
|
}
|
||||||
|
@ -256,20 +256,20 @@ void program::rpn_purcentCH() {
|
||||||
///
|
///
|
||||||
void program::rpn_square() {
|
void program::rpn_square() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) *= _stack.value<Number>(0);
|
_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);
|
_stack.value<Complex>(0) *= _stack.value<Complex>(0);
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief mod keyword implementation
|
/// @brief mod keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_modulo() {
|
void program::rpn_modulo() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
_stack.value<Number>(1) = fmod(_stack.value<Number>(1), _stack.value<Number>(0));
|
_stack.value<Number>(1) = fmod(_stack.value<Number>(1), _stack.value<Number>(0));
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
}
|
}
|
||||||
|
@ -278,13 +278,13 @@ void program::rpn_modulo() {
|
||||||
///
|
///
|
||||||
void program::rpn_abs() {
|
void program::rpn_abs() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number) {
|
if (_stack.type(0) == kNumber) {
|
||||||
_stack.value<Number>(0) = abs(_stack.value<Number>(0));
|
_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.push(new Number(abs(_stack.value<Complex>(0))));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ void program::rpn_abs() {
|
||||||
///
|
///
|
||||||
void program::rpn_fact() {
|
void program::rpn_fact() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
// fact(n) = gamma(n+1)
|
// fact(n) = gamma(n+1)
|
||||||
_stack.value<Number>(0) = gamma(_stack.value<Number>(0) + 1);
|
_stack.value<Number>(0) = gamma(_stack.value<Number>(0) + 1);
|
||||||
}
|
}
|
||||||
|
@ -301,21 +301,21 @@ void program::rpn_fact() {
|
||||||
///
|
///
|
||||||
void program::rpn_sign() {
|
void program::rpn_sign() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = sgn(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = _stack.value<Complex>(0) / abs(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief mant keyword implementation
|
/// @brief mant keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_mant() {
|
void program::rpn_mant() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
if (!isfinite(_stack.value<Number>(0))) {
|
if (!isfinite(_stack.value<Number>(0))) {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mp_exp_t exp;
|
mp_exp_t exp;
|
||||||
|
@ -326,9 +326,9 @@ void program::rpn_mant() {
|
||||||
///
|
///
|
||||||
void program::rpn_xpon() {
|
void program::rpn_xpon() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
if (!isfinite(_stack.value<Number>(0))) {
|
if (!isfinite(_stack.value<Number>(0))) {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mp_exp_t exp;
|
mp_exp_t exp;
|
||||||
|
@ -340,7 +340,7 @@ void program::rpn_xpon() {
|
||||||
///
|
///
|
||||||
void program::rpn_floor() {
|
void program::rpn_floor() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_stack.value<Number>(0) = floor(_stack.value<Number>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ void program::rpn_floor() {
|
||||||
///
|
///
|
||||||
void program::rpn_ceil() {
|
void program::rpn_ceil() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_stack.value<Number>(0) = ceil(_stack.value<Number>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@ void program::rpn_ceil() {
|
||||||
///
|
///
|
||||||
void program::rpn_fp() {
|
void program::rpn_fp() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_stack.value<Number>(0) = frac(_stack.value<Number>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +364,7 @@ void program::rpn_fp() {
|
||||||
///
|
///
|
||||||
void program::rpn_ip() {
|
void program::rpn_ip() {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
_stack.value<Number>(0) = trunc(_stack.value<Number>(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,8 +372,8 @@ void program::rpn_ip() {
|
||||||
///
|
///
|
||||||
void program::rpn_min() {
|
void program::rpn_min() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
_stack.value<Number>(0) = min(_stack.value<Number>(0), _stack.value<Number>(1));
|
_stack.value<Number>(0) = min(_stack.value<Number>(0), _stack.value<Number>(1));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
@ -382,8 +382,8 @@ void program::rpn_min() {
|
||||||
///
|
///
|
||||||
void program::rpn_max() {
|
void program::rpn_max() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
_stack.value<Number>(0) = max(_stack.value<Number>(0), _stack.value<Number>(1));
|
_stack.value<Number>(0) = max(_stack.value<Number>(0), _stack.value<Number>(1));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ void program::rpn_drop2(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_dropn(void) {
|
void program::rpn_dropn(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int args = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
MIN_ARGUMENTS(args + 1);
|
MIN_ARGUMENTS(args + 1);
|
||||||
|
@ -51,7 +51,7 @@ void program::rpn_dup(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_dupn(void) {
|
void program::rpn_dupn(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int args = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
@ -72,14 +72,14 @@ void program::rpn_dup2(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_pick(void) {
|
void program::rpn_pick(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int to_pick = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
|
||||||
// treat stack depth errors
|
// treat stack depth errors
|
||||||
if ((to_pick == 0) || (to_pick > _stack.size())) {
|
if ((to_pick == 0) || (to_pick > _stack.size())) {
|
||||||
setErrorContext(ret_out_of_range);
|
setErrorContext(kOutOfRange);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ void program::rpn_depth(void) { _stack.push_front(new Number(_stack.size())); }
|
||||||
///
|
///
|
||||||
void program::rpn_roll(void) {
|
void program::rpn_roll(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
int args = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
@ -118,7 +118,7 @@ void program::rpn_roll(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_rolld(void) {
|
void program::rpn_rolld(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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());
|
int args = static_cast<int>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
///
|
///
|
||||||
void program::rpn_sto(void) {
|
void program::rpn_sto(void) {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||||
|
|
||||||
// store symbol with first value
|
// store symbol with first value
|
||||||
const auto it = _heap.find(_stack.value<String>(0));
|
const auto it = _heap.find(_stack.value<String>(0));
|
||||||
|
@ -23,9 +23,9 @@ void program::rpn_sto(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stoadd(void) {
|
void program::rpn_stoadd(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -40,9 +40,9 @@ void program::rpn_stoadd(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stosub(void) {
|
void program::rpn_stosub(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -57,9 +57,9 @@ void program::rpn_stosub(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stomul(void) {
|
void program::rpn_stomul(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -74,9 +74,9 @@ void program::rpn_stomul(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stodiv(void) {
|
void program::rpn_stodiv(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -91,9 +91,9 @@ void program::rpn_stodiv(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stoneg(void) {
|
void program::rpn_stoneg(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -107,9 +107,9 @@ void program::rpn_stoneg(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_stoinv(void) {
|
void program::rpn_stoinv(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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()) {
|
if (_heap.find(_stack.value<String>(0)) == _heap.end()) {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rpn_dup();
|
rpn_dup();
|
||||||
|
@ -123,7 +123,7 @@ void program::rpn_stoinv(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_rcl(void) {
|
void program::rpn_rcl(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
|
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||||
|
|
||||||
// recall a variable
|
// recall a variable
|
||||||
Object* obj;
|
Object* obj;
|
||||||
|
@ -134,7 +134,7 @@ void program::rpn_rcl(void) {
|
||||||
(void)_stack.pop();
|
(void)_stack.pop();
|
||||||
_stack.push_front(obj->clone());
|
_stack.push_front(obj->clone());
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,7 +165,7 @@ void program::auto_rcl(Symbol* symb) {
|
||||||
// mind the order of heaps
|
// mind the order of heaps
|
||||||
if (find_variable(variable, obj)) {
|
if (find_variable(variable, obj)) {
|
||||||
_stack.push_front(obj->clone());
|
_stack.push_front(obj->clone());
|
||||||
if (obj->_type == cmd_program) rpn_eval();
|
if (obj->_type == kProgram) rpn_eval();
|
||||||
} else {
|
} else {
|
||||||
_stack.push_front(symb->clone());
|
_stack.push_front(symb->clone());
|
||||||
}
|
}
|
||||||
|
@ -178,14 +178,14 @@ void program::auto_rcl(Symbol* symb) {
|
||||||
///
|
///
|
||||||
void program::rpn_purge(void) {
|
void program::rpn_purge(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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));
|
const auto i = _heap.find(_stack.value<Symbol>(0));
|
||||||
if (i != _heap.end()) {
|
if (i != _heap.end()) {
|
||||||
delete i->second;
|
delete i->second;
|
||||||
_heap.erase(i);
|
_heap.erase(i);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_unknown_variable);
|
setErrorContext(kUnknownVariable);
|
||||||
}
|
}
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ void program::rpn_instr() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
|
|
||||||
// stringify only if not already a string
|
// stringify only if not already a string
|
||||||
if (_stack.type(0) != cmd_string) {
|
if (_stack.type(0) != kString) {
|
||||||
stringstream ss;
|
stringstream ss;
|
||||||
ss << _stack.at(0);
|
ss << _stack.at(0);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
@ -22,14 +22,14 @@ void program::rpn_instr() {
|
||||||
///
|
///
|
||||||
void program::rpn_strout() {
|
void program::rpn_strout() {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||||
|
|
||||||
string entry(_stack.value<String>(0));
|
string entry(_stack.value<String>(0));
|
||||||
program prog(_stack, _heap);
|
program prog(_stack, _heap);
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
|
|
||||||
// make program from string in stack level 1
|
// make program from string in stack level 1
|
||||||
if (prog.parse(entry) == ret_ok)
|
if (prog.parse(entry) == kOk)
|
||||||
// run it
|
// run it
|
||||||
prog.run();
|
prog.run();
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ void program::rpn_strout() {
|
||||||
///
|
///
|
||||||
void program::rpn_chr() {
|
void program::rpn_chr() {
|
||||||
MIN_ARGUMENTS(1);
|
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());
|
char the_chr = static_cast<char>(_stack.value<Number>(0).toLong());
|
||||||
_stack.pop();
|
_stack.pop();
|
||||||
if (the_chr < 32 || the_chr > 126) the_chr = '.';
|
if (the_chr < 32 || the_chr > 126) the_chr = '.';
|
||||||
|
@ -49,7 +49,7 @@ void program::rpn_chr() {
|
||||||
///
|
///
|
||||||
void program::rpn_num() {
|
void program::rpn_num() {
|
||||||
MIN_ARGUMENTS(1);
|
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)
|
if (_stack.value<String>(0).size() > 0)
|
||||||
_stack.push_front(new Number(_stack.value<String>(0)[0]));
|
_stack.push_front(new Number(_stack.value<String>(0)[0]));
|
||||||
else
|
else
|
||||||
|
@ -61,7 +61,7 @@ void program::rpn_num() {
|
||||||
///
|
///
|
||||||
void program::rpn_strsize() {
|
void program::rpn_strsize() {
|
||||||
MIN_ARGUMENTS(1);
|
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.push_front(new Number(_stack.value<String>(0).size()));
|
||||||
_stack.erase(1);
|
_stack.erase(1);
|
||||||
}
|
}
|
||||||
|
@ -70,8 +70,8 @@ void program::rpn_strsize() {
|
||||||
///
|
///
|
||||||
void program::rpn_strpos() {
|
void program::rpn_strpos() {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_string);
|
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_string);
|
ARG_MUST_BE_OF_TYPE(1, kString);
|
||||||
|
|
||||||
size_t pos = _stack.value<String>(1).find(_stack.value<String>(0)) + 1;
|
size_t pos = _stack.value<String>(1).find(_stack.value<String>(0)) + 1;
|
||||||
_stack.erase(0, 2);
|
_stack.erase(0, 2);
|
||||||
|
@ -82,9 +82,9 @@ void program::rpn_strpos() {
|
||||||
///
|
///
|
||||||
void program::rpn_strsub() {
|
void program::rpn_strsub() {
|
||||||
MIN_ARGUMENTS(3);
|
MIN_ARGUMENTS(3);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(2, cmd_string);
|
ARG_MUST_BE_OF_TYPE(2, kString);
|
||||||
|
|
||||||
size_t first = _stack.value<Number>(1).toULong();
|
size_t first = _stack.value<Number>(1).toULong();
|
||||||
size_t len = _stack.value<Number>(0).toULong() - first + 1;
|
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() {
|
void program::rpn_test() {
|
||||||
MIN_ARGUMENTS(1);
|
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 = 0;
|
||||||
int total_tests_failed = 0;
|
int total_tests_failed = 0;
|
||||||
|
@ -84,7 +84,7 @@ void program::rpn_test() {
|
||||||
|
|
||||||
// notify to caller that test succeeded or not
|
// notify to caller that test succeeded or not
|
||||||
if (total_tests_failed > 0) {
|
if (total_tests_failed > 0) {
|
||||||
_err = ret_test_failed;
|
_err = kTestFailed;
|
||||||
_err_context = string("rpn version ") + RPN_VERSION + ", test file " + test_filename;
|
_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()) {
|
if (test_file.is_open()) {
|
||||||
string test_title;
|
string test_title;
|
||||||
string entry;
|
string entry;
|
||||||
ret_value ret;
|
RetValue ret;
|
||||||
rpnstack stk;
|
rpnstack stk;
|
||||||
heap hp;
|
heap hp;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
@ -246,7 +246,7 @@ void program::test(string test_filename, int& total_tests, int& total_tests_fail
|
||||||
if (!entry.empty()) {
|
if (!entry.empty()) {
|
||||||
program prog(stk, hp);
|
program prog(stk, hp);
|
||||||
ret = prog.parse(entry);
|
ret = prog.parse(entry);
|
||||||
if (ret == ret_ok) {
|
if (ret == kOk) {
|
||||||
// run it
|
// run it
|
||||||
(void)prog.run();
|
(void)prog.run();
|
||||||
last_err = static_cast<int>(prog.get_err());
|
last_err = static_cast<int>(prog.get_err());
|
||||||
|
|
|
@ -19,14 +19,14 @@ static int CmpStringOnStackTop(rpnstack& stk) {
|
||||||
///
|
///
|
||||||
void program::rpn_sup(void) {
|
void program::rpn_sup(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) > _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) == 1));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,14 +34,14 @@ void program::rpn_sup(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_sup_eq(void) {
|
void program::rpn_sup_eq(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) >= _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) != -1));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,14 +50,14 @@ void program::rpn_sup_eq(void) {
|
||||||
void program::rpn_inf(void) {
|
void program::rpn_inf(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) < _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) == -1));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,14 +65,14 @@ void program::rpn_inf(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_inf_eq(void) {
|
void program::rpn_inf_eq(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) <= _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) != 1));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,17 +80,17 @@ void program::rpn_inf_eq(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_diff(void) {
|
void program::rpn_diff(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) != _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(_stack.value<Complex>(1) != _stack.value<Complex>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) != 0));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,17 +98,17 @@ void program::rpn_diff(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_eq(void) {
|
void program::rpn_eq(void) {
|
||||||
MIN_ARGUMENTS(2);
|
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.push_front(new Number(_stack.value<Number>(1) == _stack.value<Number>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(_stack.value<Complex>(1) == _stack.value<Complex>(0)));
|
||||||
_stack.erase(1, 2);
|
_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.push_front(new Number(CmpStringOnStackTop(_stack) == 0));
|
||||||
_stack.erase(1, 2);
|
_stack.erase(1, 2);
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,8 +116,8 @@ void program::rpn_eq(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_test_and(void) {
|
void program::rpn_test_and(void) {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
if (_stack.value<Number>(0) != 0 && _stack.value<Number>(1) != 0)
|
if (_stack.value<Number>(0) != 0 && _stack.value<Number>(1) != 0)
|
||||||
_stack.push(new Number(1));
|
_stack.push(new Number(1));
|
||||||
else
|
else
|
||||||
|
@ -129,8 +129,8 @@ void program::rpn_test_and(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_test_or(void) {
|
void program::rpn_test_or(void) {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
if (_stack.value<Number>(0) != 0 || _stack.value<Number>(1) != 0)
|
if (_stack.value<Number>(0) != 0 || _stack.value<Number>(1) != 0)
|
||||||
_stack.push(new Number(1));
|
_stack.push(new Number(1));
|
||||||
else
|
else
|
||||||
|
@ -142,8 +142,8 @@ void program::rpn_test_or(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_test_xor(void) {
|
void program::rpn_test_xor(void) {
|
||||||
MIN_ARGUMENTS(2);
|
MIN_ARGUMENTS(2);
|
||||||
ARG_MUST_BE_OF_TYPE(0, cmd_number);
|
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||||
ARG_MUST_BE_OF_TYPE(1, cmd_number);
|
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||||
if (_stack.value<Number>(0) != 0 ^ _stack.value<Number>(1) != 0)
|
if (_stack.value<Number>(0) != 0 ^ _stack.value<Number>(1) != 0)
|
||||||
_stack.push(new Number(1));
|
_stack.push(new Number(1));
|
||||||
else
|
else
|
||||||
|
@ -155,7 +155,7 @@ void program::rpn_test_xor(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_test_not(void) {
|
void program::rpn_test_not(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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.push(new Number(_stack.value<Number>(0) == 0 ? 1 : 0));
|
||||||
_stack.erase(1, 1);
|
_stack.erase(1, 1);
|
||||||
|
|
|
@ -25,7 +25,7 @@ void program::rpn_time() {
|
||||||
_stack.push(new Number(date));
|
_stack.push(new Number(date));
|
||||||
_stack.value<Number>(0) /= 10000000000.0;
|
_stack.value<Number>(0) /= 10000000000.0;
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_internal);
|
setErrorContext(kInternalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ void program::rpn_date() {
|
||||||
_stack.push(new Number(date));
|
_stack.push(new Number(date));
|
||||||
_stack.value<Number>(0) /= 1000000.0;
|
_stack.value<Number>(0) /= 1000000.0;
|
||||||
} else {
|
} 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);
|
date = 1000000.0 * static_cast<double>(ts.tv_sec) + static_cast<double>(ts.tv_nsec / 1000);
|
||||||
_stack.push(new Number(date));
|
_stack.push(new Number(date));
|
||||||
} else {
|
} else {
|
||||||
setErrorContext(ret_internal);
|
setErrorContext(kInternalError);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ void program::rpn_pi(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_d2r(void) {
|
void program::rpn_d2r(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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) *= mpfr::const_pi();
|
||||||
_stack.value<Number>(0) /= 180;
|
_stack.value<Number>(0) /= 180;
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ void program::rpn_d2r(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_r2d(void) {
|
void program::rpn_r2d(void) {
|
||||||
MIN_ARGUMENTS(1);
|
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) /= mpfr::const_pi();
|
||||||
_stack.value<Number>(0) *= 180;
|
_stack.value<Number>(0) *= 180;
|
||||||
}
|
}
|
||||||
|
@ -30,70 +30,70 @@ void program::rpn_r2d(void) {
|
||||||
///
|
///
|
||||||
void program::rpn_sin(void) {
|
void program::rpn_sin(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = sin(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = sin(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief asin keyword implementation
|
/// @brief asin keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_asin(void) {
|
void program::rpn_asin(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = asin(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = asin(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief cos keyword implementation
|
/// @brief cos keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_cos(void) {
|
void program::rpn_cos(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = cos(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = cos(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief acos keyword implementation
|
/// @brief acos keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_acos(void) {
|
void program::rpn_acos(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = acos(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = acos(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief tan keyword implementation
|
/// @brief tan keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_tan(void) {
|
void program::rpn_tan(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = tan(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = tan(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief atan keyword implementation
|
/// @brief atan keyword implementation
|
||||||
///
|
///
|
||||||
void program::rpn_atan(void) {
|
void program::rpn_atan(void) {
|
||||||
MIN_ARGUMENTS(1);
|
MIN_ARGUMENTS(1);
|
||||||
if (_stack.type(0) == cmd_number)
|
if (_stack.type(0) == kNumber)
|
||||||
_stack.value<Number>(0) = atan(_stack.value<Number>(0));
|
_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));
|
_stack.value<Complex>(0) = atan(_stack.value<Complex>(0));
|
||||||
else
|
else
|
||||||
setErrorContext(ret_bad_operand_type);
|
setErrorContext(kBadOperandType);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class rpnstack : public deque<Object*> {
|
||||||
|
|
||||||
// access helpers
|
// access helpers
|
||||||
//
|
//
|
||||||
cmd_type_t type(int level) {
|
ObjectType type(int level) {
|
||||||
// carefull: caller must ensure that level is correct
|
// carefull: caller must ensure that level is correct
|
||||||
return at(level)->_type;
|
return at(level)->_type;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue