mirror of
https://github.com/louisrubet/rpn
synced 2025-01-18 10:26:57 +01:00
parse and link program only once at input time
This commit is contained in:
parent
d705cf277b
commit
29c839c873
24 changed files with 453 additions and 434 deletions
|
@ -50,10 +50,11 @@ include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng
|
|||
|
||||
# src
|
||||
set(RPN_SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/src/object.cc
|
||||
${PROJECT_SOURCE_DIR}/src/program.cc
|
||||
${PROJECT_SOURCE_DIR}/src/main.cc
|
||||
${PROJECT_SOURCE_DIR}/src/object.cc
|
||||
${PROJECT_SOURCE_DIR}/src/mpreal-out.cc
|
||||
${PROJECT_SOURCE_DIR}/src/program.cc
|
||||
${PROJECT_SOURCE_DIR}/src/lexer.cc
|
||||
${PROJECT_SOURCE_DIR}/src/input.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-branch.cc
|
||||
|
|
26
src/lexer.cc
26
src/lexer.cc
|
@ -5,7 +5,7 @@
|
|||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers
|
||||
|
||||
bool Lexer::Analyse(string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
bool Lexer::Analyse(const string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
vector<SynError>& errors) {
|
||||
size_t jump;
|
||||
for (size_t i = 0; i < entry.size(); i++) {
|
||||
|
@ -52,7 +52,7 @@ void Lexer::Trim(string& s) {
|
|||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { return !std::isspace(ch); }).base(), s.end());
|
||||
}
|
||||
|
||||
bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
bool Lexer::ParseString(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
vector<SynElement>& elements) {
|
||||
// here we are sure that entry[0] is at least '"'
|
||||
for (size_t i = idx + 1; i < entry.size(); i++) {
|
||||
|
@ -69,7 +69,7 @@ bool Lexer::ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynE
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
bool Lexer::ParseSymbol(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
vector<SynElement>& elements) {
|
||||
// here we are sure that entry[0] is at least '\''
|
||||
for (size_t i = idx + 1; i < entry.size(); i++) {
|
||||
|
@ -84,7 +84,7 @@ bool Lexer::ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynE
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Lexer::ParseProgram(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
bool Lexer::ParseProgram(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
vector<SynElement>& elements) {
|
||||
// here we are sure that entry is at least "<<"
|
||||
// find last ">>" or "»"
|
||||
|
@ -111,7 +111,7 @@ bool Lexer::ParseProgram(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
|||
return true;
|
||||
}
|
||||
|
||||
int Lexer::GetBaseAt(string& entry, size_t& next_idx, bool& positive) {
|
||||
int Lexer::GetBaseAt(const string& entry, size_t& next_idx, bool& positive) {
|
||||
// a regex could be "([+-])?((0[xX])|([0-9][0-9]?[bB]))"
|
||||
// regex is not use because dramatically slow
|
||||
// entry is scanned from idxStart, searching for [s]abc (sign and 3 first chars)
|
||||
|
@ -154,7 +154,7 @@ int Lexer::GetBaseAt(string& entry, size_t& next_idx, bool& positive) {
|
|||
return 10;
|
||||
}
|
||||
|
||||
bool Lexer::GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim) {
|
||||
bool Lexer::GetNumberAt(const string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim) {
|
||||
stringstream ss;
|
||||
string token;
|
||||
bool positive = true;
|
||||
|
@ -182,11 +182,11 @@ bool Lexer::GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Lexer::ParseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool Lexer::ParseNumber(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements) {
|
||||
mpreal* r = nullptr;
|
||||
int base = 10;
|
||||
if (GetNUmberAt(entry, idx, next_idx, base, &r)) {
|
||||
if (GetNumberAt(entry, idx, next_idx, base, &r)) {
|
||||
elements.push_back({kNumber, .re = r, .re_base = base});
|
||||
return true;
|
||||
} else {
|
||||
|
@ -195,7 +195,7 @@ bool Lexer::ParseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynE
|
|||
}
|
||||
}
|
||||
|
||||
bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
bool Lexer::ParseComplex(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
vector<SynElement>& elements) {
|
||||
mpreal* re = nullptr;
|
||||
mpreal* im = nullptr;
|
||||
|
@ -205,7 +205,7 @@ bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
|||
next_idx = entry.size();
|
||||
return true; // complex format error, return a symbol
|
||||
}
|
||||
if (!GetNUmberAt(entry, idx + 1, next_idx, re_base, &re, ',')) {
|
||||
if (!GetNumberAt(entry, idx + 1, next_idx, re_base, &re, ',')) {
|
||||
elements.push_back({kSymbol, .value = entry.substr(idx, entry.size() - idx)});
|
||||
next_idx = entry.size();
|
||||
return true; // complex format error, return a symbol
|
||||
|
@ -220,7 +220,7 @@ bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
|||
return true; // complex format error, return a symbol
|
||||
}
|
||||
|
||||
if (!GetNUmberAt(entry, i, next_idx, im_base, &im, ')')) {
|
||||
if (!GetNumberAt(entry, i, next_idx, im_base, &im, ')')) {
|
||||
elements.push_back({kSymbol, .value = entry.substr(idx, entry.size() - idx)});
|
||||
next_idx = entry.size();
|
||||
if (re != nullptr) delete re;
|
||||
|
@ -232,7 +232,7 @@ bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Lexer::ParseReserved(string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements,
|
||||
bool Lexer::ParseReserved(const string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements,
|
||||
map<string, ReservedWord>& keywords) {
|
||||
stringstream ss(entry.substr(idx));
|
||||
string token;
|
||||
|
@ -247,7 +247,7 @@ bool Lexer::ParseReserved(string& entry, size_t idx, size_t& next_idx, vector<Sy
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Lexer::ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements) {
|
||||
bool Lexer::ParseUnknown(const string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements) {
|
||||
stringstream ss(entry.substr(idx));
|
||||
string token;
|
||||
ss >> token;
|
||||
|
|
26
src/lexer.h
26
src/lexer.h
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2014-2022 Louis Rubet
|
||||
|
||||
#ifndef SRC_LEXER_HPP_
|
||||
#define SRC_LEXER_HPP_
|
||||
#ifndef SRC_LEXER_H_
|
||||
#define SRC_LEXER_H_
|
||||
|
||||
#include <mpreal.h>
|
||||
using mpfr::mpreal;
|
||||
|
@ -47,27 +47,27 @@ class Lexer {
|
|||
/// @param[in] keywords reserved keywords
|
||||
/// @return false=errors, the lexer must stop
|
||||
///
|
||||
bool Analyse(string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
bool Analyse(const string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
vector<SynError>& errors);
|
||||
|
||||
private:
|
||||
bool ParseString(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool ParseString(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements);
|
||||
bool ParseSymbol(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool ParseSymbol(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements);
|
||||
bool ParseProgram(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool ParseProgram(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements);
|
||||
bool ParseNumber(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool ParseNumber(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements);
|
||||
bool ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
bool ParseComplex(const string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors,
|
||||
vector<SynElement>& elements);
|
||||
bool ParseReserved(string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements,
|
||||
bool ParseReserved(const string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements,
|
||||
map<string, ReservedWord>& keywords);
|
||||
bool ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements);
|
||||
bool ParseUnknown(const string& entry, size_t idx, size_t& next_idx, vector<SynElement>& elements);
|
||||
|
||||
void Trim(string& s);
|
||||
int GetBaseAt(string& entry, size_t& next_idx, bool& positive);
|
||||
bool GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim = ' ');
|
||||
int GetBaseAt(const string& entry, size_t& next_idx, bool& positive);
|
||||
bool GetNumberAt(const string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim = ' ');
|
||||
};
|
||||
|
||||
#endif // SRC_LEXER_HPP_
|
||||
#endif // SRC_LEXER_H_
|
||||
|
|
10
src/main.cc
10
src/main.cc
|
@ -81,11 +81,11 @@ int main(int argc, char* argv[]) {
|
|||
bool go_on = true;
|
||||
|
||||
// apply default configuration
|
||||
program::ApplyDefault();
|
||||
Program::ApplyDefault();
|
||||
|
||||
// run with interactive prompt
|
||||
if (argc == 1) {
|
||||
program::Welcome();
|
||||
Program::Welcome();
|
||||
|
||||
// init history
|
||||
EnterInteractive();
|
||||
|
@ -99,9 +99,9 @@ int main(int argc, char* argv[]) {
|
|||
while (go_on) {
|
||||
//
|
||||
// make program from interactive entry
|
||||
program prog(stack, heap);
|
||||
Program prog(stack, heap);
|
||||
string entry;
|
||||
switch (Input(entry, program::GetAutocompletionWords()).status) {
|
||||
switch (Input(entry, Program::GetAutocompletionWords()).status) {
|
||||
case Input::InputStatus::kOk:
|
||||
// run it
|
||||
if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye)
|
||||
|
@ -122,7 +122,7 @@ int main(int argc, char* argv[]) {
|
|||
} else { // run with cmd line arguments
|
||||
heap heap;
|
||||
rpnstack stack;
|
||||
program prog(stack, heap);
|
||||
Program prog(stack, heap);
|
||||
string entry;
|
||||
int i;
|
||||
|
||||
|
|
29
src/object.h
29
src/object.h
|
@ -48,12 +48,6 @@ typedef enum {
|
|||
kBranch // langage (reserved) branch keyword (for, if, then ..)
|
||||
} ObjectType;
|
||||
|
||||
class program;
|
||||
class Branch;
|
||||
|
||||
typedef void (program::*program_fn_t)(void);
|
||||
typedef size_t (program::*branch_fn_t)(Branch&);
|
||||
|
||||
/// @brief Object - a generic stack object
|
||||
///
|
||||
struct Object {
|
||||
|
@ -74,6 +68,11 @@ struct Object {
|
|||
friend ostream& operator<<(ostream& os, Object* o) { return o->Show(os); }
|
||||
};
|
||||
|
||||
class Program;
|
||||
class Branch;
|
||||
typedef void (Program::*program_fn_t)(void);
|
||||
typedef size_t (Program::*branch_fn_t)(Branch&);
|
||||
|
||||
/// @brief stack objects derived from Object
|
||||
///
|
||||
struct Number : Object {
|
||||
|
@ -140,22 +139,18 @@ struct String : Object {
|
|||
string value;
|
||||
};
|
||||
|
||||
struct Program : Object {
|
||||
Program() : Object(kProgram) {}
|
||||
explicit Program(const string& value__) : Object(kProgram), value(value__) {}
|
||||
virtual Object* Clone() { return new Program(value); }
|
||||
virtual string Name() { return string("program"); }
|
||||
virtual ostream& Show(ostream& out) { return out << "«" << value << "»"; }
|
||||
string value;
|
||||
};
|
||||
|
||||
struct Symbol : Object {
|
||||
explicit Symbol(bool auto_eval__ = true) : Object(kSymbol), auto_eval(auto_eval__) {}
|
||||
explicit Symbol(const string& value__, bool auto_eval__ = true)
|
||||
: Object(kSymbol), value(value__), auto_eval(auto_eval__) {}
|
||||
virtual Object* Clone() { return new Symbol(value, auto_eval); }
|
||||
virtual string Name() { return string("symbol"); }
|
||||
virtual ostream& Show(ostream& out) { return out << "'" << value << "'"; }
|
||||
virtual ostream& Show(ostream& out) {
|
||||
if (auto_eval)
|
||||
return out << value;
|
||||
else
|
||||
return out << "'" << value << "'";
|
||||
}
|
||||
string value;
|
||||
bool auto_eval;
|
||||
};
|
||||
|
@ -165,6 +160,7 @@ struct Keyword : Object {
|
|||
explicit Keyword(program_fn_t fn__, const string& value__) : Object(kKeyword), fn(fn__), value(value__) {}
|
||||
virtual Object* Clone() { return new Keyword(fn, value); }
|
||||
virtual string Name() { return string("keyword"); }
|
||||
virtual ostream& Show(ostream& out) { return out << value; }
|
||||
program_fn_t fn;
|
||||
string value;
|
||||
};
|
||||
|
@ -189,6 +185,7 @@ struct Branch : Object {
|
|||
}
|
||||
virtual Object* Clone() { return new Branch(*this); }
|
||||
virtual string Name() { return string("branch"); }
|
||||
virtual ostream& Show(ostream& out) { return out << value; }
|
||||
branch_fn_t fn;
|
||||
size_t arg1, arg2, arg3;
|
||||
mpreal first_index, last_index;
|
||||
|
|
344
src/program.cc
344
src/program.cc
|
@ -5,207 +5,207 @@
|
|||
//< language reserved keywords (allowed types are kKeyword, kBranch or kUndef)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks
|
||||
vector<program::keyword_t> program::keywords_{
|
||||
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers
|
||||
vector<Program::keyword_t> Program::keywords_{
|
||||
// GENERAL
|
||||
{kUndef, "", nullptr, "\nGENERAL"},
|
||||
{kKeyword, "help", &program::RpnHelp, "this help message"},
|
||||
{kKeyword, "h", &program::RpnHelp, ""},
|
||||
{kKeyword, "?", &program::RpnHelp, ""},
|
||||
{kKeyword, "quit", &program::RpnQuit, "quit software"},
|
||||
{kKeyword, "q", &program::RpnQuit, ""},
|
||||
{kKeyword, "exit", &program::RpnQuit, ""},
|
||||
{kKeyword, "test", &program::RpnTest, ""}, // not seen by user
|
||||
{kKeyword, "version", &program::RpnVersion, "show rpn version"},
|
||||
{kKeyword, "uname", &program::RpnUname, "show rpn complete identification string"},
|
||||
{kKeyword, "history", &program::RpnHistory, "see commands history"},
|
||||
{kKeyword, "help", &Program::RpnHelp, "this help message"},
|
||||
{kKeyword, "h", &Program::RpnHelp, ""},
|
||||
{kKeyword, "?", &Program::RpnHelp, ""},
|
||||
{kKeyword, "quit", &Program::RpnQuit, "quit software"},
|
||||
{kKeyword, "q", &Program::RpnQuit, ""},
|
||||
{kKeyword, "exit", &Program::RpnQuit, ""},
|
||||
{kKeyword, "test", &Program::RpnTest, ""}, // not seen by user
|
||||
{kKeyword, "version", &Program::RpnVersion, "show rpn version"},
|
||||
{kKeyword, "uname", &Program::RpnUname, "show rpn complete identification string"},
|
||||
{kKeyword, "history", &Program::RpnHistory, "see commands history"},
|
||||
|
||||
// USUAL OPERATIONS ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nUSUAL OPERATIONS ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "+", &program::RpnPlus, "addition"},
|
||||
{kKeyword, "-", &program::RpnMinus, "substraction"},
|
||||
{kKeyword, "*", &program::RpnMul, "multiplication"},
|
||||
{kKeyword, "/", &program::RpnDiv, "division"},
|
||||
{kKeyword, "inv", &program::RpnInv, "inverse"},
|
||||
{kKeyword, "chs", &program::RpnNeg, "negation"},
|
||||
{kKeyword, "neg", &program::RpnNeg, ""},
|
||||
{kKeyword, "^", &program::RpnPower, "power"},
|
||||
{kKeyword, "pow", &program::RpnPower, ""},
|
||||
{kKeyword, "sqrt", &program::RpnSquareroot, "RpnSquare root"},
|
||||
{kKeyword, "sq", &program::RpnSquare, "RpnSquare"},
|
||||
{kKeyword, "abs", &program::RpnAbs, "absolute value (norm for a complex)"},
|
||||
{kKeyword, "sign", &program::RpnSign, "sign of a number or z/|z| for a complex"},
|
||||
{kKeyword, "+", &Program::RpnPlus, "addition"},
|
||||
{kKeyword, "-", &Program::RpnMinus, "substraction"},
|
||||
{kKeyword, "*", &Program::RpnMul, "multiplication"},
|
||||
{kKeyword, "/", &Program::RpnDiv, "division"},
|
||||
{kKeyword, "inv", &Program::RpnInv, "inverse"},
|
||||
{kKeyword, "chs", &Program::RpnNeg, "negation"},
|
||||
{kKeyword, "neg", &Program::RpnNeg, ""},
|
||||
{kKeyword, "^", &Program::RpnPower, "power"},
|
||||
{kKeyword, "pow", &Program::RpnPower, ""},
|
||||
{kKeyword, "sqrt", &Program::RpnSquareroot, "RpnSquare root"},
|
||||
{kKeyword, "sq", &Program::RpnSquare, "RpnSquare"},
|
||||
{kKeyword, "abs", &Program::RpnAbs, "absolute value (norm for a complex)"},
|
||||
{kKeyword, "sign", &Program::RpnSign, "sign of a number or z/|z| for a complex"},
|
||||
|
||||
// OPERATIONS ON REALS
|
||||
{kUndef, "", nullptr, "\nOPERATIONS ON REALS"},
|
||||
{kKeyword, "%", &program::RpnPurcent, "purcent"},
|
||||
{kKeyword, "%CH", &program::RpnPurcentCH, "inverse purcent"},
|
||||
{kKeyword, "mod", &program::RpnModulo, "modulo"},
|
||||
{kKeyword, "fact", &program::RpnFact, "n! for integer n or Gamma(x+1) for fractional x"},
|
||||
{kKeyword, "mant", &program::RpnMant, "mantissa of a real number"},
|
||||
{kKeyword, "xpon", &program::RpnXpon, "exponant of a real number"},
|
||||
{kKeyword, "floor", &program::RpnFloor, "largest number <="},
|
||||
{kKeyword, "ceil", &program::RpnCeil, "smallest number >="},
|
||||
{kKeyword, "ip", &program::RpnIp, "integer part"},
|
||||
{kKeyword, "fp", &program::RpnFp, "fractional part"},
|
||||
{kKeyword, "min", &program::RpnMin, "min of 2 real numbers"},
|
||||
{kKeyword, "max", &program::RpnMax, "max of 2 real numbers"},
|
||||
{kKeyword, "%", &Program::RpnPurcent, "purcent"},
|
||||
{kKeyword, "%CH", &Program::RpnPurcentCH, "inverse purcent"},
|
||||
{kKeyword, "mod", &Program::RpnModulo, "modulo"},
|
||||
{kKeyword, "fact", &Program::RpnFact, "n! for integer n or Gamma(x+1) for fractional x"},
|
||||
{kKeyword, "mant", &Program::RpnMant, "mantissa of a real number"},
|
||||
{kKeyword, "xpon", &Program::RpnXpon, "exponant of a real number"},
|
||||
{kKeyword, "floor", &Program::RpnFloor, "largest number <="},
|
||||
{kKeyword, "ceil", &Program::RpnCeil, "smallest number >="},
|
||||
{kKeyword, "ip", &Program::RpnIp, "integer part"},
|
||||
{kKeyword, "fp", &Program::RpnFp, "fractional part"},
|
||||
{kKeyword, "min", &Program::RpnMin, "min of 2 real numbers"},
|
||||
{kKeyword, "max", &Program::RpnMax, "max of 2 real numbers"},
|
||||
|
||||
// OPERATIONS ON COMPLEXES
|
||||
{kUndef, "", nullptr, "\nOPERATIONS ON COMPLEXES"},
|
||||
{kKeyword, "re", &program::RpnReal, "complex real part"},
|
||||
{kKeyword, "im", &program::RpnImag, "complex imaginary part"},
|
||||
{kKeyword, "conj", &program::RpnConj, "complex conjugate"},
|
||||
{kKeyword, "arg", &program::RpnArg, "complex argument in radians"},
|
||||
{kKeyword, "c->r", &program::RpnC2r, "transform a complex in 2 reals"},
|
||||
{kKeyword, "r->c", &program::RpnR2c, "transform 2 reals in a complex"},
|
||||
{kKeyword, "p->r", &program::RpnP2r, "cartesian to polar"},
|
||||
{kKeyword, "r->p", &program::RpnR2p, "polar to cartesian"},
|
||||
{kKeyword, "re", &Program::RpnReal, "complex real part"},
|
||||
{kKeyword, "im", &Program::RpnImag, "complex imaginary part"},
|
||||
{kKeyword, "conj", &Program::RpnConj, "complex conjugate"},
|
||||
{kKeyword, "arg", &Program::RpnArg, "complex argument in radians"},
|
||||
{kKeyword, "c->r", &Program::RpnC2r, "transform a complex in 2 reals"},
|
||||
{kKeyword, "r->c", &Program::RpnR2c, "transform 2 reals in a complex"},
|
||||
{kKeyword, "p->r", &Program::RpnP2r, "cartesian to polar"},
|
||||
{kKeyword, "r->p", &Program::RpnR2p, "polar to cartesian"},
|
||||
|
||||
// MODE
|
||||
{kUndef, "", nullptr, "\nMODE"},
|
||||
{kKeyword, "std", &program::RpnStd, "standard floating numbers representation. ex: std"},
|
||||
{kKeyword, "fix", &program::RpnFix, "fixed point representation. ex: 6 fix"},
|
||||
{kKeyword, "sci", &program::RpnSci, "scientific floating point representation. ex: 20 sci"},
|
||||
{kKeyword, "prec", &program::RpnPrecision, "set float precision in bits. ex: 256 prec"},
|
||||
{kKeyword, "round", &program::RpnRound,
|
||||
{kKeyword, "std", &Program::RpnStd, "standard floating numbers representation. ex: std"},
|
||||
{kKeyword, "fix", &Program::RpnFix, "fixed point representation. ex: 6 fix"},
|
||||
{kKeyword, "sci", &Program::RpnSci, "scientific floating point representation. ex: 20 sci"},
|
||||
{kKeyword, "prec", &Program::RpnPrecision, "set float precision in bits. ex: 256 prec"},
|
||||
{kKeyword, "round", &Program::RpnRound,
|
||||
"set float rounding mode in \n\t\"nearest (even)\", \"toward zero\", \"toward "
|
||||
"+inf\", \"toward -inf\", \"away from zero\", \"faithful rounding\", \"nearest (away from zero)\""
|
||||
"\n\tex: \"nearest (even)\" round"},
|
||||
{kKeyword, "default", &program::RpnDefault, "set float representation and precision to default"},
|
||||
{kKeyword, "type", &program::RpnType, "show type of stack first entry"},
|
||||
{kKeyword, "hex", &program::RpnHex, "hexadecimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "dec", &program::RpnDec, "decimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "bin", &program::RpnBin, "binary representation, applies on stack level 0 only"},
|
||||
{kKeyword, "base", &program::RpnBase, "arbitrary base representation, applies on stack level 0 only"},
|
||||
{kKeyword, "default", &Program::RpnDefault, "set float representation and precision to default"},
|
||||
{kKeyword, "type", &Program::RpnType, "show type of stack first entry"},
|
||||
{kKeyword, "hex", &Program::RpnHex, "hexadecimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "dec", &Program::RpnDec, "decimal representation, applies on stack level 0 only"},
|
||||
{kKeyword, "bin", &Program::RpnBin, "binary representation, applies on stack level 0 only"},
|
||||
{kKeyword, "base", &Program::RpnBase, "arbitrary base representation, applies on stack level 0 only"},
|
||||
|
||||
// TESTS
|
||||
{kUndef, "", nullptr, "\nTEST"},
|
||||
{kKeyword, ">", &program::RpnSup, "binary operator >"},
|
||||
{kKeyword, ">=", &program::RpnSupEq, "binary operator >="},
|
||||
{kKeyword, "<", &program::RpnInf, "binary operator <"},
|
||||
{kKeyword, "<=", &program::RpnInfEq, "binary operator <="},
|
||||
{kKeyword, "!=", &program::RpnDiff, "binary operator != (different)"},
|
||||
{kKeyword, "==", &program::RpnEq, "binary operator == (equal)"},
|
||||
{kKeyword, "and", &program::RpnTestAnd, "boolean operator and"},
|
||||
{kKeyword, "or", &program::RpnTestOr, "boolean operator or"},
|
||||
{kKeyword, "xor", &program::RpnTestXor, "boolean operator xor"},
|
||||
{kKeyword, "not", &program::RpnTestNot, "boolean operator not"},
|
||||
{kKeyword, "same", &program::RpnSame, "boolean operator same (equal)"},
|
||||
{kKeyword, ">", &Program::RpnSup, "binary operator >"},
|
||||
{kKeyword, ">=", &Program::RpnSupEq, "binary operator >="},
|
||||
{kKeyword, "<", &Program::RpnInf, "binary operator <"},
|
||||
{kKeyword, "<=", &Program::RpnInfEq, "binary operator <="},
|
||||
{kKeyword, "!=", &Program::RpnDiff, "binary operator != (different)"},
|
||||
{kKeyword, "==", &Program::RpnEq, "binary operator == (equal)"},
|
||||
{kKeyword, "and", &Program::RpnTestAnd, "boolean operator and"},
|
||||
{kKeyword, "or", &Program::RpnTestOr, "boolean operator or"},
|
||||
{kKeyword, "xor", &Program::RpnTestXor, "boolean operator xor"},
|
||||
{kKeyword, "not", &Program::RpnTestNot, "boolean operator not"},
|
||||
{kKeyword, "same", &Program::RpnSame, "boolean operator same (equal)"},
|
||||
|
||||
// STACK
|
||||
{kUndef, "", nullptr, "\nSTACK"},
|
||||
{kKeyword, "swap", &program::RpnSwap, "swap 2 first stack entries"},
|
||||
{kKeyword, "drop", &program::RpnDrop, "drop first stack entry"},
|
||||
{kKeyword, "drop2", &program::RpnDrop2, "drop 2 first stack entries"},
|
||||
{kKeyword, "dropn", &program::RpnDropn, "drop n first stack entries"},
|
||||
{kKeyword, "del", &program::RpnErase, "drop all stack entries"},
|
||||
{kKeyword, "erase", &program::RpnErase, ""},
|
||||
{kKeyword, "rot", &program::RpnRot, "rotate 3 first stack entries"},
|
||||
{kKeyword, "dup", &program::RpnDup, "duplicate first stack entry"},
|
||||
{kKeyword, "dup2", &program::RpnDup2, "duplicate 2 first stack entries"},
|
||||
{kKeyword, "dupn", &program::RpnDupn, "duplicate n first stack entries"},
|
||||
{kKeyword, "pick", &program::RpnPick, "push a copy of the given stack level onto the stack"},
|
||||
{kKeyword, "depth", &program::RpnDepth, "give stack depth"},
|
||||
{kKeyword, "roll", &program::RpnRoll, "move a stack entry to the top of the stack"},
|
||||
{kKeyword, "rolld", &program::RpnRolld, "move the element on top of the stack to a higher stack position"},
|
||||
{kKeyword, "over", &program::RpnOver, "push a copy of the element in stack level 2 onto the stack"},
|
||||
{kKeyword, "swap", &Program::RpnSwap, "swap 2 first stack entries"},
|
||||
{kKeyword, "drop", &Program::RpnDrop, "drop first stack entry"},
|
||||
{kKeyword, "drop2", &Program::RpnDrop2, "drop 2 first stack entries"},
|
||||
{kKeyword, "dropn", &Program::RpnDropn, "drop n first stack entries"},
|
||||
{kKeyword, "del", &Program::RpnErase, "drop all stack entries"},
|
||||
{kKeyword, "erase", &Program::RpnErase, ""},
|
||||
{kKeyword, "rot", &Program::RpnRot, "rotate 3 first stack entries"},
|
||||
{kKeyword, "dup", &Program::RpnDup, "duplicate first stack entry"},
|
||||
{kKeyword, "dup2", &Program::RpnDup2, "duplicate 2 first stack entries"},
|
||||
{kKeyword, "dupn", &Program::RpnDupn, "duplicate n first stack entries"},
|
||||
{kKeyword, "pick", &Program::RpnPick, "push a copy of the given stack level onto the stack"},
|
||||
{kKeyword, "depth", &Program::RpnDepth, "give stack depth"},
|
||||
{kKeyword, "roll", &Program::RpnRoll, "move a stack entry to the top of the stack"},
|
||||
{kKeyword, "rolld", &Program::RpnRolld, "move the element on top of the stack to a higher stack position"},
|
||||
{kKeyword, "over", &Program::RpnOver, "push a copy of the element in stack level 2 onto the stack"},
|
||||
|
||||
// STRING
|
||||
{kUndef, "", nullptr, "\nSTRING"},
|
||||
{kKeyword, "->str", &program::RpnInstr, "convert an object into a string"},
|
||||
{kKeyword, "str->", &program::RpnStrout, "convert a string into an object"},
|
||||
{kKeyword, "chr", &program::RpnChr, "convert ASCII character code in stack level 1 into a string"},
|
||||
{kKeyword, "num", &program::RpnNum,
|
||||
{kKeyword, "->str", &Program::RpnInstr, "convert an object into a string"},
|
||||
{kKeyword, "str->", &Program::RpnStrout, "convert a string into an object"},
|
||||
{kKeyword, "chr", &Program::RpnChr, "convert ASCII character code in stack level 1 into a string"},
|
||||
{kKeyword, "num", &Program::RpnNum,
|
||||
"return ASCII code of the first character of the string in stack level 1 as a real number"},
|
||||
{kKeyword, "size", &program::RpnStrsize, "return the length of the string"},
|
||||
{kKeyword, "pos", &program::RpnStrpos, "seach for the string in level 1 within the string in level 2"},
|
||||
{kKeyword, "sub", &program::RpnStrsub, "return a substring of the string in level 3"},
|
||||
{kKeyword, "size", &Program::RpnStrsize, "return the length of the string"},
|
||||
{kKeyword, "pos", &Program::RpnStrpos, "seach for the string in level 1 within the string in level 2"},
|
||||
{kKeyword, "sub", &Program::RpnStrsub, "return a substring of the string in level 3"},
|
||||
|
||||
// BRANCH
|
||||
{kUndef, "", nullptr, "\nBRANCH"},
|
||||
{kBranch, "if", (program_fn_t)&program::RpnIf,
|
||||
{kBranch, "if", (program_fn_t)&Program::RpnIf,
|
||||
"if <test-instruction> then <true-instructions> else <false-instructions> "
|
||||
"end"},
|
||||
{kBranch, "then", (program_fn_t)&program::RpnThen, "used with if"},
|
||||
{kBranch, "else", (program_fn_t)&program::RpnElse, "used with if"},
|
||||
{kBranch, "end", (program_fn_t)&program::RpnEnd, "used with various branch instructions"},
|
||||
{kBranch, "start", (program_fn_t)&program::RpnStart, "<start> <end> start <instructions> next|<step> step"},
|
||||
{kBranch, "for", (program_fn_t)&program::RpnFor, "<start> <end> for <variable> <instructions> next|<step> step"},
|
||||
{kBranch, "next", (program_fn_t)&program::RpnNext, "used with start and for"},
|
||||
{kBranch, "step", (program_fn_t)&program::RpnStep, "used with start and for"},
|
||||
{kKeyword, "ift", &program::RpnIft, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||
{kKeyword, "ifte", &program::RpnIfte,
|
||||
{kBranch, "then", (program_fn_t)&Program::RpnThen, "used with if"},
|
||||
{kBranch, "else", (program_fn_t)&Program::RpnElse, "used with if"},
|
||||
{kBranch, "end", (program_fn_t)&Program::RpnEnd, "used with various branch instructions"},
|
||||
{kBranch, "start", (program_fn_t)&Program::RpnStart, "<start> <end> start <instructions> next|<step> step"},
|
||||
{kBranch, "for", (program_fn_t)&Program::RpnFor, "<start> <end> for <variable> <instructions> next|<step> step"},
|
||||
{kBranch, "next", (program_fn_t)&Program::RpnNext, "used with start and for"},
|
||||
{kBranch, "step", (program_fn_t)&Program::RpnStep, "used with start and for"},
|
||||
{kKeyword, "ift", &Program::RpnIft, "similar to if-then-end, <test-instruction> <true-instruction> ift"},
|
||||
{kKeyword, "ifte", &Program::RpnIfte,
|
||||
"similar to if-then-else-end, <test-instruction> <true-instruction> "
|
||||
"<false-instruction> ifte"},
|
||||
{kBranch, "do", (program_fn_t)&program::RpnDo, "do <instructions> until <condition> end"},
|
||||
{kBranch, "until", (program_fn_t)&program::RpnUntil, "used with do"},
|
||||
{kBranch, "while", (program_fn_t)&program::RpnWhile, "while <test-instruction> repeat <loop-instructions> end"},
|
||||
{kBranch, "repeat", (program_fn_t)&program::RpnRepeat, "used with while"},
|
||||
{kBranch, "do", (program_fn_t)&Program::RpnDo, "do <instructions> until <condition> end"},
|
||||
{kBranch, "until", (program_fn_t)&Program::RpnUntil, "used with do"},
|
||||
{kBranch, "while", (program_fn_t)&Program::RpnWhile, "while <test-instruction> repeat <loop-instructions> end"},
|
||||
{kBranch, "repeat", (program_fn_t)&Program::RpnRepeat, "used with while"},
|
||||
|
||||
// STORE
|
||||
{kUndef, "", nullptr, "\nSTORE"},
|
||||
{kKeyword, "sto", &program::RpnSto, "store a variable. ex: 1 'name' sto"},
|
||||
{kKeyword, "rcl", &program::RpnRcl, "recall a variable. ex: 'name' rcl"},
|
||||
{kKeyword, "purge", &program::RpnPurge, "delete a variable. ex: 'name' purge"},
|
||||
{kKeyword, "vars", &program::RpnVars, "list all variables"},
|
||||
{kKeyword, "clusr", &program::RpnClusr, "erase all variables"},
|
||||
{kKeyword, "edit", &program::RpnEdit, "edit a variable content"},
|
||||
{kKeyword, "sto+", &program::RpnStoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||
{kKeyword, "sto-", &program::RpnStosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||
{kKeyword, "sto*", &program::RpnStomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||
{kKeyword, "sto/", &program::RpnStodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||
{kKeyword, "sneg", &program::RpnStoneg, "negate a variable. ex: 'name' sneg"},
|
||||
{kKeyword, "sinv", &program::RpnStoinv, "inverse a variable. ex: 1 'name' sinv"},
|
||||
{kKeyword, "sto", &Program::RpnSto, "store a variable. ex: 1 'name' sto"},
|
||||
{kKeyword, "rcl", &Program::RpnRcl, "recall a variable. ex: 'name' rcl"},
|
||||
{kKeyword, "purge", &Program::RpnPurge, "delete a variable. ex: 'name' purge"},
|
||||
{kKeyword, "vars", &Program::RpnVars, "list all variables"},
|
||||
{kKeyword, "clusr", &Program::RpnClusr, "erase all variables"},
|
||||
{kKeyword, "edit", &Program::RpnEdit, "edit a variable content"},
|
||||
{kKeyword, "sto+", &Program::RpnStoadd, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"},
|
||||
{kKeyword, "sto-", &Program::RpnStosub, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"},
|
||||
{kKeyword, "sto*", &Program::RpnStomul, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"},
|
||||
{kKeyword, "sto/", &Program::RpnStodiv, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"},
|
||||
{kKeyword, "sneg", &Program::RpnStoneg, "negate a variable. ex: 'name' sneg"},
|
||||
{kKeyword, "sinv", &Program::RpnStoinv, "inverse a variable. ex: 1 'name' sinv"},
|
||||
// PROGRAM
|
||||
{kUndef, "", nullptr, "\nPROGRAM"},
|
||||
{kKeyword, "eval", &program::RpnEval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||
{kBranch, "->", (program_fn_t)&program::RpnInprog,
|
||||
{kKeyword, "eval", &Program::RpnEval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"},
|
||||
{kBranch, "->", (program_fn_t)&Program::RpnInprog,
|
||||
"load program local variables. ex: << -> n m << 0 n m for i i + next >> "
|
||||
">>"},
|
||||
|
||||
// TRIG ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nTRIG ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "pi", &program::RpnPi, "pi constant"},
|
||||
{kKeyword, "sin", &program::RpnSin, "sinus"},
|
||||
{kKeyword, "asin", &program::RpnAsin, "arg sinus"},
|
||||
{kKeyword, "cos", &program::RpnCos, "cosinus"},
|
||||
{kKeyword, "acos", &program::RpnAcos, "arg cosinus"},
|
||||
{kKeyword, "tan", &program::RpnTan, "tangent"},
|
||||
{kKeyword, "atan", &program::RpnAtan, "arg tangent"},
|
||||
{kKeyword, "d->r", &program::RpnD2r, "convert degrees to radians"},
|
||||
{kKeyword, "r->d", &program::RpnR2d, "convert radians to degrees"},
|
||||
{kKeyword, "pi", &Program::RpnPi, "pi constant"},
|
||||
{kKeyword, "sin", &Program::RpnSin, "sinus"},
|
||||
{kKeyword, "asin", &Program::RpnAsin, "arg sinus"},
|
||||
{kKeyword, "cos", &Program::RpnCos, "cosinus"},
|
||||
{kKeyword, "acos", &Program::RpnAcos, "arg cosinus"},
|
||||
{kKeyword, "tan", &Program::RpnTan, "tangent"},
|
||||
{kKeyword, "atan", &Program::RpnAtan, "arg tangent"},
|
||||
{kKeyword, "d->r", &Program::RpnD2r, "convert degrees to radians"},
|
||||
{kKeyword, "r->d", &Program::RpnR2d, "convert radians to degrees"},
|
||||
|
||||
// LOGS ON REALS AND COMPLEXES
|
||||
{kUndef, "", nullptr, "\nLOGS ON REALS AND COMPLEXES"},
|
||||
{kKeyword, "e", &program::RpnE, "Euler constant"},
|
||||
{kKeyword, "ln", &program::RpnLn, "logarithm base e"},
|
||||
{kKeyword, "log", &program::RpnLn, ""},
|
||||
{kKeyword, "lnp1", &program::RpnLnp1, "ln(1+x) which is useful when x is close to 0"},
|
||||
{kKeyword, "exp", &program::RpnExp, "exponential"},
|
||||
{kKeyword, "expm", &program::RpnExpm, "exp(x)-1 which is useful when x is close to 0"},
|
||||
{kKeyword, "log10", &program::RpnLog10, "logarithm base 10"},
|
||||
{kKeyword, "alog10", &program::RpnAlog10, "exponential base 10"},
|
||||
{kKeyword, "exp10", &program::RpnAlog10, ""},
|
||||
{kKeyword, "log2", &program::RpnLog2, "logarithm base 2"},
|
||||
{kKeyword, "alog2", &program::RpnAlog2, "exponential base 2"},
|
||||
{kKeyword, "exp2", &program::RpnAlog2, ""},
|
||||
{kKeyword, "sinh", &program::RpnSinh, "hyperbolic sine"},
|
||||
{kKeyword, "asinh", &program::RpnAsinh, "inverse hyperbolic sine"},
|
||||
{kKeyword, "cosh", &program::RpnCosh, "hyperbolic cosine"},
|
||||
{kKeyword, "acosh", &program::RpnAcosh, "inverse hyperbolic cosine"},
|
||||
{kKeyword, "tanh", &program::RpnTanh, "hyperbolic tangent"},
|
||||
{kKeyword, "atanh", &program::RpnAtanh, "inverse hyperbolic tangent"},
|
||||
{kKeyword, "e", &Program::RpnE, "Euler constant"},
|
||||
{kKeyword, "ln", &Program::RpnLn, "logarithm base e"},
|
||||
{kKeyword, "log", &Program::RpnLn, ""},
|
||||
{kKeyword, "lnp1", &Program::RpnLnp1, "ln(1+x) which is useful when x is close to 0"},
|
||||
{kKeyword, "exp", &Program::RpnExp, "exponential"},
|
||||
{kKeyword, "expm", &Program::RpnExpm, "exp(x)-1 which is useful when x is close to 0"},
|
||||
{kKeyword, "log10", &Program::RpnLog10, "logarithm base 10"},
|
||||
{kKeyword, "alog10", &Program::RpnAlog10, "exponential base 10"},
|
||||
{kKeyword, "exp10", &Program::RpnAlog10, ""},
|
||||
{kKeyword, "log2", &Program::RpnLog2, "logarithm base 2"},
|
||||
{kKeyword, "alog2", &Program::RpnAlog2, "exponential base 2"},
|
||||
{kKeyword, "exp2", &Program::RpnAlog2, ""},
|
||||
{kKeyword, "sinh", &Program::RpnSinh, "hyperbolic sine"},
|
||||
{kKeyword, "asinh", &Program::RpnAsinh, "inverse hyperbolic sine"},
|
||||
{kKeyword, "cosh", &Program::RpnCosh, "hyperbolic cosine"},
|
||||
{kKeyword, "acosh", &Program::RpnAcosh, "inverse hyperbolic cosine"},
|
||||
{kKeyword, "tanh", &Program::RpnTanh, "hyperbolic tangent"},
|
||||
{kKeyword, "atanh", &Program::RpnAtanh, "inverse hyperbolic tangent"},
|
||||
|
||||
// TIME AND DATE
|
||||
{kUndef, "", nullptr, "\nTIME AND DATE"},
|
||||
{kKeyword, "time", &program::RpnTime, "local time in ISO 8601 format"},
|
||||
{kKeyword, "date", &program::RpnDate, "local date in ISO 8601 format"},
|
||||
{kKeyword, "ticks", &program::RpnTicks, "local date and time in µs"}
|
||||
};
|
||||
{kKeyword, "time", &Program::RpnTime, "local time in ISO 8601 format"},
|
||||
{kKeyword, "date", &Program::RpnDate, "local date in ISO 8601 format"},
|
||||
{kKeyword, "ticks", &Program::RpnTicks, "local date and time in µs"}};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/// autocompletion vector for linenoise autocompletion
|
||||
vector<string>& program::GetAutocompletionWords() {
|
||||
vector<string>& Program::GetAutocompletionWords() {
|
||||
static vector<string> autocompletion_words;
|
||||
if (autocompletion_words.empty())
|
||||
for (auto& kw : keywords_)
|
||||
|
@ -217,22 +217,13 @@ vector<string>& program::GetAutocompletionWords() {
|
|||
///
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::Run() {
|
||||
RetValue Program::Run() {
|
||||
bool go_out = false;
|
||||
RetValue ret = kOk;
|
||||
|
||||
err_ = kOk;
|
||||
err_context_ = "";
|
||||
|
||||
// branches for 'if'
|
||||
ret = Preprocess();
|
||||
if (ret != kOk) {
|
||||
// free allocated
|
||||
for (Object* o : *this) delete o;
|
||||
local_heap_.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// iterate commands
|
||||
for (size_t i = 0; (go_out == false) && (i < size());) {
|
||||
Object* o = at(i);
|
||||
|
@ -317,7 +308,7 @@ RetValue program::Run() {
|
|||
///
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::Preprocess() {
|
||||
RetValue Program::Preprocess() {
|
||||
struct if_layout_t {
|
||||
if_layout_t()
|
||||
: index_then_or_unti_or_repeat(-1),
|
||||
|
@ -563,7 +554,7 @@ RetValue program::Preprocess() {
|
|||
/// @param prog the program to be filled
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::Parse(string& entry) {
|
||||
RetValue Program::Parse(const string& entry) {
|
||||
static map<string, Lexer::ReservedWord> keywords_map;
|
||||
vector<Lexer::SynElement> elements;
|
||||
vector<Lexer::SynError> errors;
|
||||
|
@ -591,9 +582,19 @@ RetValue program::Parse(string& entry) {
|
|||
case kSymbol:
|
||||
push_back(new Symbol(element.value, element.auto_eval));
|
||||
break;
|
||||
case kProgram:
|
||||
push_back(new Program(element.value));
|
||||
break;
|
||||
case kProgram: {
|
||||
Program* p = new Program(stack_, heap_, this);
|
||||
if (p->Parse(element.value) == kOk) {
|
||||
stringstream ss;
|
||||
for (size_t i = 0; i < p->size(); i++)
|
||||
if (i > 0)
|
||||
ss << ' ' << p->at(i);
|
||||
else
|
||||
ss << p->at(i);
|
||||
p->value = ss.str();
|
||||
push_back(p);
|
||||
}
|
||||
} break;
|
||||
case kKeyword:
|
||||
push_back(new Keyword(element.fn, element.value));
|
||||
break;
|
||||
|
@ -610,6 +611,9 @@ RetValue program::Parse(string& entry) {
|
|||
if (element.re != nullptr) delete element.re;
|
||||
if (element.im != nullptr) delete element.im;
|
||||
}
|
||||
|
||||
// compute links between the objects
|
||||
return Preprocess();
|
||||
} else {
|
||||
for (SynError& err : errors) ShowSyntaxError(err.err.c_str());
|
||||
}
|
||||
|
@ -621,7 +625,7 @@ RetValue program::Parse(string& entry) {
|
|||
///
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::ShowError() {
|
||||
RetValue Program::ShowError() {
|
||||
RetValue ret;
|
||||
// clang-format off
|
||||
map<RetValue, string> errorStrings{{kOk, "ok"}, {kUnknownError, "unknown command"},
|
||||
|
@ -655,7 +659,7 @@ RetValue program::ShowError() {
|
|||
/// @param context a context string
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::ShowError(RetValue err, string& context) {
|
||||
RetValue Program::ShowError(RetValue err, string& context) {
|
||||
// record error
|
||||
err_ = err;
|
||||
err_context_ = context;
|
||||
|
@ -668,7 +672,7 @@ RetValue program::ShowError(RetValue err, string& context) {
|
|||
/// @param context a context string
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::ShowError(RetValue err, const char* context) {
|
||||
RetValue Program::ShowError(RetValue err, const char* context) {
|
||||
// record error
|
||||
err_ = err;
|
||||
err_context_ = context;
|
||||
|
@ -681,7 +685,7 @@ RetValue program::ShowError(RetValue err, const char* context) {
|
|||
/// @param context a context string
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
void program::ShowSyntaxError(const char* context) {
|
||||
void Program::ShowSyntaxError(const char* context) {
|
||||
// record error
|
||||
err_ = kSyntaxError;
|
||||
err_context_ = context;
|
||||
|
@ -692,14 +696,14 @@ void program::ShowSyntaxError(const char* context) {
|
|||
///
|
||||
/// @return RetValue see this type
|
||||
///
|
||||
RetValue program::GetLastError(void) { return err_; }
|
||||
RetValue Program::GetLastError(void) { return err_; }
|
||||
|
||||
/// @brief show a stack (show its different objects)
|
||||
/// generally a stack is associated to a running program
|
||||
///
|
||||
/// @param show_separator whether to show a stack level prefix or not
|
||||
///
|
||||
void program::ShowStack(bool show_separator) {
|
||||
void Program::ShowStack(bool show_separator) {
|
||||
if (stack_.size() == 1) {
|
||||
cout << stack_[0] << endl;
|
||||
} else {
|
||||
|
@ -712,7 +716,7 @@ void program::ShowStack(bool show_separator) {
|
|||
|
||||
/// @brief apply default precision mode and digits
|
||||
///
|
||||
void program::ApplyDefault() {
|
||||
void Program::ApplyDefault() {
|
||||
// default float precision, float mode
|
||||
Number::mode = Number::kDefaultMode;
|
||||
Number::digits = Number::kDefaultDecimalDigits;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Copyright (c) 2014-2022 Louis Rubet
|
||||
|
||||
#ifndef SRC_PROGRAM_HPP_
|
||||
#define SRC_PROGRAM_HPP_
|
||||
#ifndef SRC_PROGRAM_H_
|
||||
#define SRC_PROGRAM_H_
|
||||
|
||||
// std c++
|
||||
#include <deque>
|
||||
|
@ -18,18 +18,39 @@ using mpfr::mpreal;
|
|||
#include "object.h"
|
||||
#include "stack.h"
|
||||
|
||||
// struct Program : Object {
|
||||
// Program() : Object(kProgram) {}
|
||||
// explicit Program(const string& value__) : Object(kProgram), value(value__) {}
|
||||
// virtual Object* Clone() { return new Program(value); }
|
||||
// virtual string Name() { return string("program"); }
|
||||
// virtual ostream& Show(ostream& out) { return out << "«" << value << "»"; }
|
||||
// string value;
|
||||
// };
|
||||
|
||||
//< program class: the class containing a string parser, all the programs keywords, a stack for running the program
|
||||
class program : public deque<Object*>, public Lexer {
|
||||
class Program : public deque<Object*>, public Lexer, public Object {
|
||||
public:
|
||||
program(rpnstack& stack__, heap& heap__, program* parent__ = nullptr)
|
||||
: stack_(stack__), heap_(heap__), parent_(parent__) {}
|
||||
virtual ~program() {
|
||||
Program(rpnstack& stack__, heap& heap__, Program* parent__ = nullptr)
|
||||
: Object(kProgram), stack_(stack__), heap_(heap__), parent_(parent__) {}
|
||||
Program(const string& value__, rpnstack& stack__, heap& heap__, Program* parent__ = nullptr)
|
||||
: Object(kProgram), value(value__), stack_(stack__), heap_(heap__), parent_(parent__) {}
|
||||
|
||||
virtual ~Program() {
|
||||
local_heap_.clear();
|
||||
clear();
|
||||
}
|
||||
|
||||
virtual Object* Clone() {
|
||||
Program* prog = new Program(value, stack_, heap_, parent_);
|
||||
prog->value = value;
|
||||
for (auto& obj : *this) prog->push_back(obj->Clone());
|
||||
return prog;
|
||||
}
|
||||
virtual string Name() { return string("program"); }
|
||||
virtual ostream& Show(ostream& out) { return out << "« " << value << " »"; }
|
||||
|
||||
// parser
|
||||
RetValue Parse(string& entry);
|
||||
RetValue Parse(const string& entry);
|
||||
|
||||
// running
|
||||
RetValue Run();
|
||||
|
@ -43,6 +64,8 @@ class program : public deque<Object*>, public Lexer {
|
|||
|
||||
void ShowStack(bool show_separator = true);
|
||||
|
||||
string value;
|
||||
|
||||
static void ApplyDefault();
|
||||
static void Welcome();
|
||||
|
||||
|
@ -63,9 +86,8 @@ class program : public deque<Object*>, public Lexer {
|
|||
heap local_heap_;
|
||||
|
||||
// parent prog for inheriting heaps
|
||||
program* parent_;
|
||||
Program* parent_;
|
||||
|
||||
private:
|
||||
// keywords
|
||||
struct keyword_t {
|
||||
ObjectType type;
|
||||
|
@ -245,7 +267,7 @@ class program : public deque<Object*>, public Lexer {
|
|||
void RpnTicks();
|
||||
};
|
||||
|
||||
// convenience macros for rpn_xx function
|
||||
// convenience macros for RpnXxx functions
|
||||
// carefull : some of these macros modify program flow
|
||||
|
||||
#define ERROR_CONTEXT(err) \
|
||||
|
@ -254,36 +276,36 @@ class program : public deque<Object*>, public Lexer {
|
|||
err_context_ = __FUNCTION__; \
|
||||
} while (0)
|
||||
|
||||
#define MIN_ARGUMENTS(num) \
|
||||
do { \
|
||||
if (stack_.size() < (num)) { \
|
||||
ERROR_CONTEXT(kMissingOperand); \
|
||||
return; \
|
||||
} \
|
||||
#define MIN_ARGUMENTS(num) \
|
||||
do { \
|
||||
if (stack_.size() < (num)) { \
|
||||
ERROR_CONTEXT(kMissingOperand); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MIN_ARGUMENTS_RET(num, ret) \
|
||||
do { \
|
||||
if (stack_.size() < (num)) { \
|
||||
ERROR_CONTEXT(kMissingOperand); \
|
||||
return (ret); \
|
||||
} \
|
||||
#define MIN_ARGUMENTS_RET(num, ret) \
|
||||
do { \
|
||||
if (stack_.size() < (num)) { \
|
||||
ERROR_CONTEXT(kMissingOperand); \
|
||||
return (ret); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ARG_MUST_BE_OF_TYPE(num, type) \
|
||||
do { \
|
||||
#define ARG_MUST_BE_OF_TYPE(num, type) \
|
||||
do { \
|
||||
if (stack_.at(num)->_type != (type)) { \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return; \
|
||||
} \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
|
||||
do { \
|
||||
if (stack_.at(num)->_type != (type)) { \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return (ret); \
|
||||
} \
|
||||
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
|
||||
do { \
|
||||
if (stack_.at(num)->_type != (type)) { \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return (ret); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // SRC_PROGRAM_HPP_
|
||||
#endif // SRC_PROGRAM_H_
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnIf(Branch& myobj) {
|
||||
size_t Program::RpnIf(Branch& myobj) {
|
||||
// myobj.arg1 = 'if' condition evaluation value
|
||||
MIN_ARGUMENTS_RET(1, kRtError);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||
|
@ -29,7 +29,7 @@ size_t program::RpnIf(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort Branch
|
||||
///
|
||||
size_t program::RpnThen(Branch& myobj) {
|
||||
size_t Program::RpnThen(Branch& myobj) {
|
||||
// myobj.arg1 = index of then + 1
|
||||
// myobj.arg2 = index of else + 1 or end + 1
|
||||
// myobj.arg3 = index of if
|
||||
|
@ -54,7 +54,7 @@ size_t program::RpnThen(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnElse(Branch& myobj) {
|
||||
size_t Program::RpnElse(Branch& myobj) {
|
||||
// myobj.arg1 = index of else + 1
|
||||
// myobj.arg2 = index of end + 1
|
||||
// myobj.arg3 = index of if
|
||||
|
@ -79,7 +79,7 @@ size_t program::RpnElse(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnEnd(Branch& myobj) {
|
||||
size_t Program::RpnEnd(Branch& myobj) {
|
||||
size_t ret = kStepOut;
|
||||
|
||||
// arg1 = index of do+1 in case of do..unti..end
|
||||
|
@ -106,7 +106,7 @@ size_t program::RpnEnd(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnDo(Branch& myobj __attribute__((unused))) {
|
||||
size_t Program::RpnDo(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ size_t program::RpnDo(Branch& myobj __attribute__((unused))) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort Branch
|
||||
///
|
||||
size_t program::RpnUntil(Branch& myobj __attribute__((unused))) {
|
||||
size_t Program::RpnUntil(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ size_t program::RpnUntil(Branch& myobj __attribute__((unused))) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
void program::RpnIft(void) {
|
||||
void Program::RpnIft(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
||||
|
@ -149,7 +149,7 @@ void program::RpnIft(void) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
void program::RpnIfte(void) {
|
||||
void Program::RpnIfte(void) {
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(2, kNumber);
|
||||
|
||||
|
@ -170,7 +170,7 @@ void program::RpnIfte(void) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnWhile(Branch& myobj __attribute__((unused))) {
|
||||
size_t Program::RpnWhile(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ size_t program::RpnWhile(Branch& myobj __attribute__((unused))) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnRepeat(Branch& myobj) {
|
||||
size_t Program::RpnRepeat(Branch& myobj) {
|
||||
size_t ret = kStepOut;
|
||||
|
||||
MIN_ARGUMENTS_RET(1, kRtError);
|
||||
|
@ -203,7 +203,7 @@ size_t program::RpnRepeat(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnStart(Branch& myobj) {
|
||||
size_t Program::RpnStart(Branch& myobj) {
|
||||
size_t ret = kStepOut;
|
||||
|
||||
MIN_ARGUMENTS_RET(2, kRtError);
|
||||
|
@ -232,7 +232,7 @@ size_t program::RpnStart(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnFor(Branch& myobj) {
|
||||
size_t Program::RpnFor(Branch& myobj) {
|
||||
size_t ret;
|
||||
|
||||
MIN_ARGUMENTS_RET(2, kRtError);
|
||||
|
@ -279,7 +279,7 @@ size_t program::RpnFor(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnNext(Branch& myobj) {
|
||||
size_t Program::RpnNext(Branch& myobj) {
|
||||
// arg1 = loop variable index
|
||||
// first_index = current point in the loop
|
||||
Branch* start_or_for;
|
||||
|
@ -331,7 +331,7 @@ size_t program::RpnNext(Branch& myobj) {
|
|||
/// @return kStepOut next object to run in the current program is current + 1
|
||||
/// @return kRtError something went wrong with preprocess, abort branch
|
||||
///
|
||||
size_t program::RpnStep(Branch& myobj) {
|
||||
size_t Program::RpnStep(Branch& myobj) {
|
||||
size_t ret;
|
||||
MIN_ARGUMENTS_RET(1, kRtError);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
/// @brief re keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnReal() {
|
||||
void Program::RpnReal() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.push_front(new Number(real(stack_.value<Complex>(0))));
|
||||
|
@ -15,7 +15,7 @@ void program::RpnReal() {
|
|||
/// @brief im keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnImag() {
|
||||
void Program::RpnImag() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.push_front(new Number(imag(stack_.value<Complex>(0))));
|
||||
|
@ -25,7 +25,7 @@ void program::RpnImag() {
|
|||
/// @brief arg keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnArg() {
|
||||
void Program::RpnArg() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.push_front(new Number(arg(stack_.value<Complex>(0))));
|
||||
|
@ -35,7 +35,7 @@ void program::RpnArg() {
|
|||
/// @brief conj keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnConj() {
|
||||
void Program::RpnConj() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.value<Complex>(0) = conj(stack_.value<Complex>(0));
|
||||
|
@ -44,7 +44,7 @@ void program::RpnConj() {
|
|||
/// @brief r2c keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnR2c() {
|
||||
void Program::RpnR2c() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -55,7 +55,7 @@ void program::RpnR2c() {
|
|||
/// @brief c2r keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnC2r() {
|
||||
void Program::RpnC2r() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.push(new Number(real(stack_.value<Complex>(0)), stack_.obj<Complex>(0).re_base));
|
||||
|
@ -66,7 +66,7 @@ void program::RpnC2r() {
|
|||
/// @brief r2p keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnR2p() {
|
||||
void Program::RpnR2p() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
mpreal rho = abs(stack_.value<Complex>(0));
|
||||
|
@ -78,7 +78,7 @@ void program::RpnR2p() {
|
|||
/// @brief p2r keyword implementation
|
||||
/// the result is stacked on current program stack
|
||||
///
|
||||
void program::RpnP2r() {
|
||||
void Program::RpnP2r() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kComplex);
|
||||
stack_.value<Complex>(0) = polar(abs(stack_.value<Complex>(0)), arg(stack_.value<Complex>(0)));
|
||||
|
|
|
@ -29,12 +29,12 @@ static const char _welcome[] = ATTR_BOLD "rpn " RPN_VERSION ATTR_OFF "\nType h o
|
|||
|
||||
/// @brief quit keyword implementation
|
||||
///
|
||||
void program::RpnQuit() { ERROR_CONTEXT(kGoodbye); }
|
||||
void Program::RpnQuit() { ERROR_CONTEXT(kGoodbye); }
|
||||
|
||||
/// @brief nop keyword implementation
|
||||
/// the result is written on stdout
|
||||
///
|
||||
void program::RpnHelp() {
|
||||
void Program::RpnHelp() {
|
||||
// software name
|
||||
cout << endl << _uname << endl;
|
||||
|
||||
|
@ -86,7 +86,7 @@ void program::RpnHelp() {
|
|||
|
||||
/// @brief welcome string
|
||||
///
|
||||
void program::Welcome() { cout << _welcome << endl; }
|
||||
void Program::Welcome() { cout << _welcome << endl; }
|
||||
|
||||
/// @brief whether a printed precision is in the precision min/max
|
||||
///
|
||||
|
@ -98,7 +98,7 @@ static bool check_decimal_digits(int precision) { return precision >= 0; }
|
|||
|
||||
/// @brief std keyword implementation
|
||||
///
|
||||
void program::RpnStd() {
|
||||
void Program::RpnStd() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -116,7 +116,7 @@ void program::RpnStd() {
|
|||
|
||||
/// @brief fix keyword implementation
|
||||
///
|
||||
void program::RpnFix() {
|
||||
void Program::RpnFix() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -134,7 +134,7 @@ void program::RpnFix() {
|
|||
|
||||
/// @brief sci keyword implementation
|
||||
///
|
||||
void program::RpnSci() {
|
||||
void Program::RpnSci() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -152,15 +152,15 @@ void program::RpnSci() {
|
|||
|
||||
/// @brief _version keyword implementation
|
||||
///
|
||||
void program::RpnVersion() { stack_.push_front(new String(RPN_VERSION)); }
|
||||
void Program::RpnVersion() { stack_.push_front(new String(RPN_VERSION)); }
|
||||
|
||||
/// @brief _uname keyword implementation
|
||||
///
|
||||
void program::RpnUname() { stack_.push_front(new String(_uname)); }
|
||||
void Program::RpnUname() { stack_.push_front(new String(_uname)); }
|
||||
|
||||
/// @brief history keyword implementation
|
||||
///
|
||||
void program::RpnHistory() {
|
||||
void Program::RpnHistory() {
|
||||
// see command history on stdout
|
||||
int index = 0;
|
||||
char* line = linenoiseHistoryLine(index);
|
||||
|
@ -173,7 +173,7 @@ void program::RpnHistory() {
|
|||
|
||||
/// @brief type keyword implementation
|
||||
///
|
||||
void program::RpnType() {
|
||||
void Program::RpnType() {
|
||||
MIN_ARGUMENTS(1);
|
||||
stack_.push(new String(stack_.at(0)->Name()));
|
||||
stack_.erase(1);
|
||||
|
@ -181,11 +181,11 @@ void program::RpnType() {
|
|||
|
||||
/// @brief default keyword implementation
|
||||
///
|
||||
void program::RpnDefault() { program::ApplyDefault(); }
|
||||
void Program::RpnDefault() { Program::ApplyDefault(); }
|
||||
|
||||
/// @brief prec keyword implementation
|
||||
///
|
||||
void program::RpnPrecision() {
|
||||
void Program::RpnPrecision() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -207,7 +207,7 @@ void program::RpnPrecision() {
|
|||
|
||||
/// @brief round keyword implementation
|
||||
///
|
||||
void program::RpnRound() {
|
||||
void Program::RpnRound() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
|
||||
/// @brief e keyword implementation
|
||||
///
|
||||
void program::RpnE(void) { stack_.push(new Number(mpfr::const_euler())); }
|
||||
void Program::RpnE(void) { stack_.push(new Number(mpfr::const_euler())); }
|
||||
|
||||
/// @brief log10 keyword implementation
|
||||
///
|
||||
void program::RpnLog10() {
|
||||
void Program::RpnLog10() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = log10(stack_.value<Number>(0));
|
||||
|
@ -20,7 +20,7 @@ void program::RpnLog10() {
|
|||
|
||||
/// @brief alog10 keyword implementation
|
||||
///
|
||||
void program::RpnAlog10() {
|
||||
void Program::RpnAlog10() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = exp(log(mpreal(10)) * stack_.value<Number>(0));
|
||||
|
@ -32,7 +32,7 @@ void program::RpnAlog10() {
|
|||
|
||||
/// @brief log2 keyword implementation
|
||||
///
|
||||
void program::RpnLog2() {
|
||||
void Program::RpnLog2() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = log(stack_.value<Number>(0)) / mpfr::const_log2();
|
||||
|
@ -44,7 +44,7 @@ void program::RpnLog2() {
|
|||
|
||||
/// @brief alog2 keyword implementation
|
||||
///
|
||||
void program::RpnAlog2() {
|
||||
void Program::RpnAlog2() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = exp(mpfr::const_log2() * stack_.value<Number>(0));
|
||||
|
@ -56,7 +56,7 @@ void program::RpnAlog2() {
|
|||
|
||||
/// @brief ln keyword implementation
|
||||
///
|
||||
void program::RpnLn() {
|
||||
void Program::RpnLn() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = log(stack_.value<Number>(0));
|
||||
|
@ -68,7 +68,7 @@ void program::RpnLn() {
|
|||
|
||||
/// @brief exp keyword implementation
|
||||
///
|
||||
void program::RpnExp() {
|
||||
void Program::RpnExp() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = exp(stack_.value<Number>(0));
|
||||
|
@ -80,7 +80,7 @@ void program::RpnExp() {
|
|||
|
||||
/// @brief expm keyword implementation
|
||||
///
|
||||
void program::RpnExpm() {
|
||||
void Program::RpnExpm() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = exp(stack_.value<Number>(0)) - mpreal(1);
|
||||
|
@ -92,7 +92,7 @@ void program::RpnExpm() {
|
|||
|
||||
/// @brief lnp1 keyword implementation
|
||||
///
|
||||
void program::RpnLnp1() {
|
||||
void Program::RpnLnp1() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = log(stack_.value<Number>(0) + 1);
|
||||
|
@ -104,7 +104,7 @@ void program::RpnLnp1() {
|
|||
|
||||
/// @brief sinh keyword implementation
|
||||
///
|
||||
void program::RpnSinh() {
|
||||
void Program::RpnSinh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = sinh(stack_.value<Number>(0));
|
||||
|
@ -116,7 +116,7 @@ void program::RpnSinh() {
|
|||
|
||||
/// @brief asinh keyword implementation
|
||||
///
|
||||
void program::RpnAsinh() {
|
||||
void Program::RpnAsinh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = asinh(stack_.value<Number>(0));
|
||||
|
@ -128,7 +128,7 @@ void program::RpnAsinh() {
|
|||
|
||||
/// @brief cosh keyword implementation
|
||||
///
|
||||
void program::RpnCosh() {
|
||||
void Program::RpnCosh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = cosh(stack_.value<Number>(0));
|
||||
|
@ -140,7 +140,7 @@ void program::RpnCosh() {
|
|||
|
||||
/// @brief acosh keyword implementation
|
||||
///
|
||||
void program::RpnAcosh() {
|
||||
void Program::RpnAcosh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = acosh(stack_.value<Number>(0));
|
||||
|
@ -152,7 +152,7 @@ void program::RpnAcosh() {
|
|||
|
||||
/// @brief tanh keyword implementation
|
||||
///
|
||||
void program::RpnTanh() {
|
||||
void Program::RpnTanh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = tanh(stack_.value<Number>(0));
|
||||
|
@ -164,7 +164,7 @@ void program::RpnTanh() {
|
|||
|
||||
/// @brief atanh keyword implementation
|
||||
///
|
||||
void program::RpnAtanh() {
|
||||
void Program::RpnAtanh() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = atanh(stack_.value<Number>(0));
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
/// @return true variable was found
|
||||
/// @return false variable was not found
|
||||
///
|
||||
bool program::FindVariable(string& variable, Object*& obj) {
|
||||
bool Program::FindVariable(string& variable, Object*& obj) {
|
||||
bool found = false;
|
||||
program* parent = parent_;
|
||||
Program* parent = parent_;
|
||||
|
||||
if (local_heap_.get(variable, obj)) {
|
||||
found = true;
|
||||
|
@ -33,9 +33,9 @@ bool program::FindVariable(string& variable, Object*& obj) {
|
|||
|
||||
/// @brief eval keyword implementation
|
||||
///
|
||||
void program::RpnEval(void) {
|
||||
void Program::RpnEval(void) {
|
||||
bool run_prog = false;
|
||||
string prog_text;
|
||||
Program* prog = nullptr;
|
||||
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kSymbol) {
|
||||
|
@ -47,8 +47,8 @@ void program::RpnEval(void) {
|
|||
// if variable holds a program, run this program
|
||||
if (FindVariable(variable, obj)) {
|
||||
if (obj->_type == kProgram) {
|
||||
prog_text = stack_.value<Program>(0);
|
||||
stack_.pop();
|
||||
prog = reinterpret_cast<Program*>(stack_[0]);
|
||||
stack_.erase(0, 1, false);
|
||||
run_prog = true;
|
||||
} else {
|
||||
// else recall this variable (i.e. stack_ its content)
|
||||
|
@ -59,28 +59,23 @@ void program::RpnEval(void) {
|
|||
}
|
||||
} else if (stack_.type(0) == kProgram) {
|
||||
// eval a program
|
||||
prog_text = stack_.value<Program>(0);
|
||||
stack_.pop();
|
||||
prog = reinterpret_cast<Program*>(stack_[0]);
|
||||
stack_.erase(0, 1, false);
|
||||
run_prog = true;
|
||||
} else {
|
||||
ERROR_CONTEXT(kBadOperandType);
|
||||
}
|
||||
|
||||
// run prog if any
|
||||
if (run_prog) {
|
||||
program prog(stack_, heap_, this);
|
||||
|
||||
// make program from entry
|
||||
if (prog.Parse(prog_text) == kOk) {
|
||||
// run it
|
||||
prog.Run();
|
||||
}
|
||||
if (run_prog && prog != nullptr) {
|
||||
prog->Run();
|
||||
delete prog;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief -> keyword (Branch) implementation
|
||||
///
|
||||
int program::RpnInprog(Branch& inprog_obj) {
|
||||
int Program::RpnInprog(Branch& inprog_obj) {
|
||||
string context("->"); // for showing errors
|
||||
size_t count_symbols = 0;
|
||||
bool prog_found = false;
|
||||
|
@ -139,7 +134,7 @@ int program::RpnInprog(Branch& inprog_obj) {
|
|||
|
||||
// run the program
|
||||
string& entry = reinterpret_cast<Program*>(at(inprog_obj.arg1 + count_symbols + 1))->value;
|
||||
program prog(stack_, heap_, this);
|
||||
Program prog(stack_, heap_, this);
|
||||
|
||||
// make the program from entry
|
||||
if (prog.Parse(entry) == kOk) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
/// @brief + keyword implementation
|
||||
///
|
||||
void program::RpnPlus() {
|
||||
void Program::RpnPlus() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kString && stack_.type(1) == kString) {
|
||||
stack_.value<String>(1) += stack_.value<String>(0);
|
||||
|
@ -29,7 +29,7 @@ void program::RpnPlus() {
|
|||
|
||||
/// @brief - keyword implementation
|
||||
///
|
||||
void program::RpnMinus() {
|
||||
void Program::RpnMinus() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.value<Number>(1) -= stack_.value<Number>(0);
|
||||
|
@ -51,7 +51,7 @@ void program::RpnMinus() {
|
|||
|
||||
/// @brief * keyword implementation
|
||||
///
|
||||
void program::RpnMul() {
|
||||
void Program::RpnMul() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.value<Number>(1) *= stack_.value<Number>(0);
|
||||
|
@ -73,7 +73,7 @@ void program::RpnMul() {
|
|||
|
||||
/// @brief / keyword implementation
|
||||
///
|
||||
void program::RpnDiv() {
|
||||
void Program::RpnDiv() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.value<Number>(1) /= stack_.value<Number>(0);
|
||||
|
@ -95,7 +95,7 @@ void program::RpnDiv() {
|
|||
|
||||
/// @brief neg keyword implementation
|
||||
///
|
||||
void program::RpnNeg() {
|
||||
void Program::RpnNeg() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = -stack_.value<Number>(0);
|
||||
|
@ -107,7 +107,7 @@ void program::RpnNeg() {
|
|||
|
||||
/// @brief inv keyword implementation
|
||||
///
|
||||
void program::RpnInv() {
|
||||
void Program::RpnInv() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = 1 / stack_.value<Number>(0);
|
||||
|
@ -119,7 +119,7 @@ void program::RpnInv() {
|
|||
|
||||
/// @brief power keyword implementation
|
||||
///
|
||||
void program::RpnPower() {
|
||||
void Program::RpnPower() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
if (stack_.value<Number>(1) >= 0) {
|
||||
|
@ -148,7 +148,7 @@ void program::RpnPower() {
|
|||
|
||||
/// @brief sqrt keyword implementation
|
||||
///
|
||||
void program::RpnSquareroot() {
|
||||
void Program::RpnSquareroot() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber) {
|
||||
if (stack_.value<Number>(0) >= 0) {
|
||||
|
@ -170,7 +170,7 @@ void program::RpnSquareroot() {
|
|||
|
||||
/// @brief hex keyword implementation
|
||||
///
|
||||
void program::RpnHex() {
|
||||
void Program::RpnHex() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber) {
|
||||
stack_.obj<Number>(0).base = 16;
|
||||
|
@ -184,7 +184,7 @@ void program::RpnHex() {
|
|||
|
||||
/// @brief bin keyword implementation
|
||||
///
|
||||
void program::RpnBin() {
|
||||
void Program::RpnBin() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber) {
|
||||
stack_.obj<Number>(0).base = 2;
|
||||
|
@ -198,7 +198,7 @@ void program::RpnBin() {
|
|||
|
||||
/// @brief dec keyword implementation
|
||||
///
|
||||
void program::RpnDec() {
|
||||
void Program::RpnDec() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber) {
|
||||
stack_.obj<Number>(0).base = 10;
|
||||
|
@ -212,7 +212,7 @@ void program::RpnDec() {
|
|||
|
||||
/// @brief base keyword implementation
|
||||
///
|
||||
void program::RpnBase() {
|
||||
void Program::RpnBase() {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(1) == kNumber || stack_.type(1) == kComplex) {
|
||||
int base = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
|
@ -234,7 +234,7 @@ void program::RpnBase() {
|
|||
|
||||
/// @brief % (purcent) keyword implementation
|
||||
///
|
||||
void program::RpnPurcent() {
|
||||
void Program::RpnPurcent() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -244,7 +244,7 @@ void program::RpnPurcent() {
|
|||
|
||||
/// @brief %CH keyword implementation
|
||||
///
|
||||
void program::RpnPurcentCH() {
|
||||
void Program::RpnPurcentCH() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -254,7 +254,7 @@ void program::RpnPurcentCH() {
|
|||
|
||||
/// @brief sq keyword implementation
|
||||
///
|
||||
void program::RpnSquare() {
|
||||
void Program::RpnSquare() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) *= stack_.value<Number>(0);
|
||||
|
@ -266,7 +266,7 @@ void program::RpnSquare() {
|
|||
|
||||
/// @brief mod keyword implementation
|
||||
///
|
||||
void program::RpnModulo() {
|
||||
void Program::RpnModulo() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -276,7 +276,7 @@ void program::RpnModulo() {
|
|||
|
||||
/// @brief abs keyword implementation
|
||||
///
|
||||
void program::RpnAbs() {
|
||||
void Program::RpnAbs() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber) {
|
||||
stack_.value<Number>(0) = abs(stack_.value<Number>(0));
|
||||
|
@ -290,7 +290,7 @@ void program::RpnAbs() {
|
|||
|
||||
/// @brief fact (factorial) keyword implementation
|
||||
///
|
||||
void program::RpnFact() {
|
||||
void Program::RpnFact() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
// fact(n) = gamma(n+1)
|
||||
|
@ -299,7 +299,7 @@ void program::RpnFact() {
|
|||
|
||||
/// @brief sign keyword implementation
|
||||
///
|
||||
void program::RpnSign() {
|
||||
void Program::RpnSign() {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = sgn(stack_.value<Number>(0));
|
||||
|
@ -311,7 +311,7 @@ void program::RpnSign() {
|
|||
|
||||
/// @brief mant keyword implementation
|
||||
///
|
||||
void program::RpnMant() {
|
||||
void Program::RpnMant() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
if (!isfinite(stack_.value<Number>(0))) {
|
||||
|
@ -324,7 +324,7 @@ void program::RpnMant() {
|
|||
|
||||
/// @brief xpon keyword implementation
|
||||
///
|
||||
void program::RpnXpon() {
|
||||
void Program::RpnXpon() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
if (!isfinite(stack_.value<Number>(0))) {
|
||||
|
@ -338,7 +338,7 @@ void program::RpnXpon() {
|
|||
|
||||
/// @brief floor keyword implementation
|
||||
///
|
||||
void program::RpnFloor() {
|
||||
void Program::RpnFloor() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) = floor(stack_.value<Number>(0));
|
||||
|
@ -346,7 +346,7 @@ void program::RpnFloor() {
|
|||
|
||||
/// @brief ceil keyword implementation
|
||||
///
|
||||
void program::RpnCeil() {
|
||||
void Program::RpnCeil() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) = ceil(stack_.value<Number>(0));
|
||||
|
@ -354,7 +354,7 @@ void program::RpnCeil() {
|
|||
|
||||
/// @brief fp keyword implementation
|
||||
///
|
||||
void program::RpnFp() {
|
||||
void Program::RpnFp() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) = frac(stack_.value<Number>(0));
|
||||
|
@ -362,7 +362,7 @@ void program::RpnFp() {
|
|||
|
||||
/// @brief ip keyword implementation
|
||||
///
|
||||
void program::RpnIp() {
|
||||
void Program::RpnIp() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) = trunc(stack_.value<Number>(0));
|
||||
|
@ -370,7 +370,7 @@ void program::RpnIp() {
|
|||
|
||||
/// @brief min keyword implementation
|
||||
///
|
||||
void program::RpnMin() {
|
||||
void Program::RpnMin() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -380,7 +380,7 @@ void program::RpnMin() {
|
|||
|
||||
/// @brief max keyword implementation
|
||||
///
|
||||
void program::RpnMax() {
|
||||
void Program::RpnMax() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
/// @brief swap keyword implementation
|
||||
///
|
||||
void program::RpnSwap(void) {
|
||||
void Program::RpnSwap(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
Object* tmp = stack_.front();
|
||||
stack_.erase(0, 1, false);
|
||||
|
@ -13,21 +13,21 @@ void program::RpnSwap(void) {
|
|||
|
||||
/// @brief drop keyword implementation
|
||||
///
|
||||
void program::RpnDrop(void) {
|
||||
void Program::RpnDrop(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
stack_.pop();
|
||||
}
|
||||
|
||||
/// @brief drop2 keyword implementation
|
||||
///
|
||||
void program::RpnDrop2(void) {
|
||||
void Program::RpnDrop2(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
stack_.erase(0, 2);
|
||||
}
|
||||
|
||||
/// @brief dropn keyword implementation
|
||||
///
|
||||
void program::RpnDropn(void) {
|
||||
void Program::RpnDropn(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -38,18 +38,18 @@ void program::RpnDropn(void) {
|
|||
|
||||
/// @brief erase / del keyword implementation
|
||||
///
|
||||
void program::RpnErase(void) { stack_.erase(0, stack_.size()); }
|
||||
void Program::RpnErase(void) { stack_.erase(0, stack_.size()); }
|
||||
|
||||
/// @brief dup keyword implementation
|
||||
///
|
||||
void program::RpnDup(void) {
|
||||
void Program::RpnDup(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
stack_.push_front(stack_.at(0)->Clone());
|
||||
}
|
||||
|
||||
/// @brief dupn keyword implementation
|
||||
///
|
||||
void program::RpnDupn(void) {
|
||||
void Program::RpnDupn(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -66,7 +66,7 @@ void program::RpnDupn(void) {
|
|||
|
||||
/// @brief dup2 keyword implementation
|
||||
///
|
||||
void program::RpnDup2(void) {
|
||||
void Program::RpnDup2(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
stack_.push_front(stack_.at(1)->Clone());
|
||||
stack_.push_front(stack_.at(1)->Clone());
|
||||
|
@ -74,7 +74,7 @@ void program::RpnDup2(void) {
|
|||
|
||||
/// @brief pick keyword implementation
|
||||
///
|
||||
void program::RpnPick(void) {
|
||||
void Program::RpnPick(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -92,7 +92,7 @@ void program::RpnPick(void) {
|
|||
|
||||
/// @brief rot keyword implementation
|
||||
///
|
||||
void program::RpnRot(void) {
|
||||
void Program::RpnRot(void) {
|
||||
MIN_ARGUMENTS(3);
|
||||
Object* tmp = stack_.at(2);
|
||||
stack_.erase(2, 1, false);
|
||||
|
@ -101,11 +101,11 @@ void program::RpnRot(void) {
|
|||
|
||||
/// @brief depth keyword implementation
|
||||
///
|
||||
void program::RpnDepth(void) { stack_.push_front(new Number(stack_.size())); }
|
||||
void Program::RpnDepth(void) { stack_.push_front(new Number(stack_.size())); }
|
||||
|
||||
/// @brief roll keyword implementation
|
||||
///
|
||||
void program::RpnRoll(void) {
|
||||
void Program::RpnRoll(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -124,7 +124,7 @@ void program::RpnRoll(void) {
|
|||
|
||||
/// @brief rolld keyword implementation
|
||||
///
|
||||
void program::RpnRolld(void) {
|
||||
void Program::RpnRolld(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -143,7 +143,7 @@ void program::RpnRolld(void) {
|
|||
|
||||
/// @brief over keyword implementation
|
||||
///
|
||||
void program::RpnOver(void) {
|
||||
void Program::RpnOver(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
stack_.push_front(stack_.at(1)->Clone());
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
/// @brief sto keyword implementation
|
||||
///
|
||||
void program::RpnSto(void) {
|
||||
void Program::RpnSto(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
|
||||
|
@ -21,7 +21,7 @@ void program::RpnSto(void) {
|
|||
|
||||
/// @brief sto+ keyword implementation
|
||||
///
|
||||
void program::RpnStoadd(void) {
|
||||
void Program::RpnStoadd(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -38,7 +38,7 @@ void program::RpnStoadd(void) {
|
|||
|
||||
/// @brief sto- keyword implementation
|
||||
///
|
||||
void program::RpnStosub(void) {
|
||||
void Program::RpnStosub(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -55,7 +55,7 @@ void program::RpnStosub(void) {
|
|||
|
||||
/// @brief sto* keyword implementation
|
||||
///
|
||||
void program::RpnStomul(void) {
|
||||
void Program::RpnStomul(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -72,7 +72,7 @@ void program::RpnStomul(void) {
|
|||
|
||||
/// @brief sto/ keyword implementation
|
||||
///
|
||||
void program::RpnStodiv(void) {
|
||||
void Program::RpnStodiv(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -89,7 +89,7 @@ void program::RpnStodiv(void) {
|
|||
|
||||
/// @brief stosneg keyword implementation
|
||||
///
|
||||
void program::RpnStoneg(void) {
|
||||
void Program::RpnStoneg(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -105,7 +105,7 @@ void program::RpnStoneg(void) {
|
|||
|
||||
/// @brief sinv keyword implementation
|
||||
///
|
||||
void program::RpnStoinv(void) {
|
||||
void Program::RpnStoinv(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
if (heap_.find(stack_.value<String>(0)) == heap_.end()) {
|
||||
|
@ -121,7 +121,7 @@ void program::RpnStoinv(void) {
|
|||
|
||||
/// @brief rcl keyword implementation
|
||||
///
|
||||
void program::RpnRcl(void) {
|
||||
void Program::RpnRcl(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
|
||||
|
@ -140,7 +140,7 @@ void program::RpnRcl(void) {
|
|||
|
||||
/// @brief edit keyword implementation
|
||||
///
|
||||
void program::RpnEdit(void) {
|
||||
void Program::RpnEdit(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
ostringstream st;
|
||||
|
@ -157,7 +157,7 @@ void program::RpnEdit(void) {
|
|||
///
|
||||
/// @param symb the smlbol to recall and autoeval
|
||||
///
|
||||
void program::AutoRcl(Symbol* symb) {
|
||||
void Program::AutoRcl(Symbol* symb) {
|
||||
if (symb->auto_eval) {
|
||||
Object* obj;
|
||||
string variable(symb->value);
|
||||
|
@ -167,7 +167,10 @@ void program::AutoRcl(Symbol* symb) {
|
|||
stack_.push_front(obj->Clone());
|
||||
if (obj->_type == kProgram) RpnEval();
|
||||
} else {
|
||||
stack_.push_front(symb->Clone());
|
||||
// not found, keep it as a simple symbol
|
||||
Symbol* s = reinterpret_cast<Symbol*>(symb->Clone());
|
||||
s->auto_eval = false;
|
||||
stack_.push_front(s);
|
||||
}
|
||||
} else {
|
||||
stack_.push_front(symb->Clone());
|
||||
|
@ -176,7 +179,7 @@ void program::AutoRcl(Symbol* symb) {
|
|||
|
||||
/// @brief purge keyword implementation
|
||||
///
|
||||
void program::RpnPurge(void) {
|
||||
void Program::RpnPurge(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kSymbol);
|
||||
|
||||
|
@ -192,8 +195,8 @@ void program::RpnPurge(void) {
|
|||
|
||||
/// @brief vars keyword implementation
|
||||
///
|
||||
void program::RpnVars(void) {
|
||||
program* parent = parent_;
|
||||
void Program::RpnVars(void) {
|
||||
Program* parent = parent_;
|
||||
string name;
|
||||
int index = 1;
|
||||
|
||||
|
@ -221,4 +224,4 @@ void program::RpnVars(void) {
|
|||
|
||||
/// @brief clusr keyword implementation
|
||||
///
|
||||
void program::RpnClusr(void) { heap_.clear(); }
|
||||
void Program::RpnClusr(void) { heap_.clear(); }
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
/// @brief ->str keyword implementation
|
||||
///
|
||||
void program::RpnInstr() {
|
||||
void Program::RpnInstr() {
|
||||
MIN_ARGUMENTS(1);
|
||||
|
||||
// stringify only if not already a string
|
||||
|
@ -20,12 +20,12 @@ void program::RpnInstr() {
|
|||
|
||||
/// @brief str-> keyword implementation
|
||||
///
|
||||
void program::RpnStrout() {
|
||||
void Program::RpnStrout() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
|
||||
string entry(stack_.value<String>(0));
|
||||
program prog(stack_, heap_);
|
||||
Program prog(stack_, heap_);
|
||||
stack_.pop();
|
||||
|
||||
// make program from string in stack_ level 1
|
||||
|
@ -36,7 +36,7 @@ void program::RpnStrout() {
|
|||
|
||||
/// @brief chr keyword implementation
|
||||
///
|
||||
void program::RpnChr() {
|
||||
void Program::RpnChr() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
char the_chr = static_cast<char>(stack_.value<Number>(0).toLong());
|
||||
|
@ -47,7 +47,7 @@ void program::RpnChr() {
|
|||
|
||||
/// @brief num keyword implementation
|
||||
///
|
||||
void program::RpnNum() {
|
||||
void Program::RpnNum() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
if (stack_.value<String>(0).size() > 0)
|
||||
|
@ -59,7 +59,7 @@ void program::RpnNum() {
|
|||
|
||||
/// @brief size keyword implementation
|
||||
///
|
||||
void program::RpnStrsize() {
|
||||
void Program::RpnStrsize() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
stack_.push_front(new Number(stack_.value<String>(0).size()));
|
||||
|
@ -68,7 +68,7 @@ void program::RpnStrsize() {
|
|||
|
||||
/// @brief pos keyword implementation
|
||||
///
|
||||
void program::RpnStrpos() {
|
||||
void Program::RpnStrpos() {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
ARG_MUST_BE_OF_TYPE(1, kString);
|
||||
|
@ -80,7 +80,7 @@ void program::RpnStrpos() {
|
|||
|
||||
/// @brief sub keyword implementation
|
||||
///
|
||||
void program::RpnStrsub() {
|
||||
void Program::RpnStrsub() {
|
||||
MIN_ARGUMENTS(3);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
|
|
@ -67,7 +67,7 @@ static void ShowTestResult(string title, int tests, int tests_failed, int steps,
|
|||
|
||||
/// @brief test keyword implementation
|
||||
///
|
||||
void program::RpnTest() {
|
||||
void Program::RpnTest() {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kString);
|
||||
|
||||
|
@ -97,8 +97,8 @@ void program::RpnTest() {
|
|||
/// @param total_steps the total steps nb
|
||||
/// @param total_steps_failed the total failed steps nb
|
||||
///
|
||||
void program::RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps,
|
||||
int& total_steps_failed) {
|
||||
void Program::RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps,
|
||||
int& total_steps_failed) {
|
||||
const string stack_size("-> stack size should be ");
|
||||
const string stack_value("-> stack should be ");
|
||||
const string cmd_error("-> error should be ");
|
||||
|
@ -244,13 +244,10 @@ void program::RunTestFile(string test_filename, int& total_tests, int& total_tes
|
|||
// parse entry and run line
|
||||
FindAndReplaceAll(entry, "`", "");
|
||||
if (!entry.empty()) {
|
||||
program prog(stk, hp);
|
||||
Program prog(stk, hp);
|
||||
ret = prog.Parse(entry);
|
||||
if (ret == kOk) {
|
||||
// run it
|
||||
(void)prog.Run();
|
||||
last_err = static_cast<int>(prog.GetLastError());
|
||||
}
|
||||
if (ret == kOk) (void)prog.Run();
|
||||
last_err = static_cast<int>(prog.GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ static int CmpStringOnStackTop(rpnstack& stk) {
|
|||
|
||||
/// @brief > keyword implementation
|
||||
///
|
||||
void program::RpnSup(void) {
|
||||
void Program::RpnSup(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.push_front(new Number(stack_.value<Number>(1) > stack_.value<Number>(0)));
|
||||
|
@ -32,7 +32,7 @@ void program::RpnSup(void) {
|
|||
|
||||
/// @brief >= keyword implementation
|
||||
///
|
||||
void program::RpnSupEq(void) {
|
||||
void Program::RpnSupEq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.push_front(new Number(stack_.value<Number>(1) >= stack_.value<Number>(0)));
|
||||
|
@ -47,7 +47,7 @@ void program::RpnSupEq(void) {
|
|||
|
||||
/// @brief < keyword implementation
|
||||
///
|
||||
void program::RpnInf(void) {
|
||||
void Program::RpnInf(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
|
@ -63,7 +63,7 @@ void program::RpnInf(void) {
|
|||
|
||||
/// @brief <= keyword implementation
|
||||
///
|
||||
void program::RpnInfEq(void) {
|
||||
void Program::RpnInfEq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.push_front(new Number(stack_.value<Number>(1) <= stack_.value<Number>(0)));
|
||||
|
@ -78,7 +78,7 @@ void program::RpnInfEq(void) {
|
|||
|
||||
/// @brief != keyword implementation
|
||||
///
|
||||
void program::RpnDiff(void) {
|
||||
void Program::RpnDiff(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.push_front(new Number(stack_.value<Number>(1) != stack_.value<Number>(0)));
|
||||
|
@ -96,7 +96,7 @@ void program::RpnDiff(void) {
|
|||
|
||||
/// @brief == keyword implementation
|
||||
///
|
||||
void program::RpnEq(void) {
|
||||
void Program::RpnEq(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
if (stack_.type(0) == kNumber && stack_.type(1) == kNumber) {
|
||||
stack_.push_front(new Number(stack_.value<Number>(1) == stack_.value<Number>(0)));
|
||||
|
@ -114,7 +114,7 @@ void program::RpnEq(void) {
|
|||
|
||||
/// @brief and keyword implementation
|
||||
///
|
||||
void program::RpnTestAnd(void) {
|
||||
void Program::RpnTestAnd(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -127,7 +127,7 @@ void program::RpnTestAnd(void) {
|
|||
|
||||
/// @brief or keyword implementation
|
||||
///
|
||||
void program::RpnTestOr(void) {
|
||||
void Program::RpnTestOr(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -140,7 +140,7 @@ void program::RpnTestOr(void) {
|
|||
|
||||
/// @brief xor keyword implementation
|
||||
///
|
||||
void program::RpnTestXor(void) {
|
||||
void Program::RpnTestXor(void) {
|
||||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
|
@ -153,7 +153,7 @@ void program::RpnTestXor(void) {
|
|||
|
||||
/// @brief not keyword implementation
|
||||
///
|
||||
void program::RpnTestNot(void) {
|
||||
void Program::RpnTestNot(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
|
@ -163,4 +163,4 @@ void program::RpnTestNot(void) {
|
|||
|
||||
/// @brief test same implementation
|
||||
///
|
||||
void program::RpnSame(void) { RpnEq(); }
|
||||
void Program::RpnSame(void) { RpnEq(); }
|
||||
|
|
|
@ -8,7 +8,7 @@ using namespace std::chrono;
|
|||
|
||||
/// @brief time keyword implementation
|
||||
///
|
||||
void program::RpnTime() {
|
||||
void Program::RpnTime() {
|
||||
std::time_t rawtime = system_clock::to_time_t(system_clock::now());
|
||||
struct tm tm;
|
||||
|
||||
|
@ -26,7 +26,7 @@ void program::RpnTime() {
|
|||
|
||||
/// @brief date keyword implementation
|
||||
///
|
||||
void program::RpnDate() {
|
||||
void Program::RpnDate() {
|
||||
std::time_t rawtime = system_clock::to_time_t(system_clock::now());
|
||||
struct tm tm;
|
||||
|
||||
|
@ -44,7 +44,7 @@ void program::RpnDate() {
|
|||
|
||||
/// @brief ticks keyword implementation
|
||||
///
|
||||
void program::RpnTicks() {
|
||||
void Program::RpnTicks() {
|
||||
uint64_t time_span = (uint64_t)duration_cast<microseconds>(high_resolution_clock::now().time_since_epoch()).count();
|
||||
stack_.push(new Number(time_span));
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
/// @brief pi keyword implementation
|
||||
///
|
||||
void program::RpnPi(void) {
|
||||
void Program::RpnPi(void) {
|
||||
stack_.push_front(new Number(mpfr::const_pi()));
|
||||
}
|
||||
|
||||
/// @brief d->r keyword implementation
|
||||
///
|
||||
void program::RpnD2r(void) {
|
||||
void Program::RpnD2r(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) *= mpfr::const_pi();
|
||||
|
@ -19,7 +19,7 @@ void program::RpnD2r(void) {
|
|||
|
||||
/// @brief r->d keyword implementation
|
||||
///
|
||||
void program::RpnR2d(void) {
|
||||
void Program::RpnR2d(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
stack_.value<Number>(0) /= mpfr::const_pi();
|
||||
|
@ -28,7 +28,7 @@ void program::RpnR2d(void) {
|
|||
|
||||
/// @brief sin keyword implementation
|
||||
///
|
||||
void program::RpnSin(void) {
|
||||
void Program::RpnSin(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = sin(stack_.value<Number>(0));
|
||||
|
@ -40,7 +40,7 @@ void program::RpnSin(void) {
|
|||
|
||||
/// @brief asin keyword implementation
|
||||
///
|
||||
void program::RpnAsin(void) {
|
||||
void Program::RpnAsin(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = asin(stack_.value<Number>(0));
|
||||
|
@ -52,7 +52,7 @@ void program::RpnAsin(void) {
|
|||
|
||||
/// @brief cos keyword implementation
|
||||
///
|
||||
void program::RpnCos(void) {
|
||||
void Program::RpnCos(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = cos(stack_.value<Number>(0));
|
||||
|
@ -64,7 +64,7 @@ void program::RpnCos(void) {
|
|||
|
||||
/// @brief acos keyword implementation
|
||||
///
|
||||
void program::RpnAcos(void) {
|
||||
void Program::RpnAcos(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = acos(stack_.value<Number>(0));
|
||||
|
@ -76,7 +76,7 @@ void program::RpnAcos(void) {
|
|||
|
||||
/// @brief tan keyword implementation
|
||||
///
|
||||
void program::RpnTan(void) {
|
||||
void Program::RpnTan(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = tan(stack_.value<Number>(0));
|
||||
|
@ -88,7 +88,7 @@ void program::RpnTan(void) {
|
|||
|
||||
/// @brief atan keyword implementation
|
||||
///
|
||||
void program::RpnAtan(void) {
|
||||
void Program::RpnAtan(void) {
|
||||
MIN_ARGUMENTS(1);
|
||||
if (stack_.type(0) == kNumber)
|
||||
stack_.value<Number>(0) = atan(stack_.value<Number>(0));
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
`<< I am a program >>`
|
||||
|
||||
-> stack should be «I am a program»
|
||||
-> stack should be « I am a program »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
|
||||
`<<I am a program>>`
|
||||
|
||||
-> stack should be «I am a program»
|
||||
-> stack should be « I am a program »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
|||
|
||||
`<< I am a program >>`
|
||||
|
||||
-> stack should be «I am a program»
|
||||
-> stack should be « I am a program »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
`«I am a program»`
|
||||
|
||||
-> stack should be «I am a program»
|
||||
-> stack should be « I am a program »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
|||
|
||||
`« I am a program »`
|
||||
|
||||
-> stack should be «I am a program»
|
||||
-> stack should be « I am a program »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -54,7 +54,7 @@
|
|||
|
||||
`<< prog`
|
||||
|
||||
-> stack should be «prog»
|
||||
-> stack should be « prog »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
|||
|
||||
`« prog`
|
||||
|
||||
-> stack should be «prog»
|
||||
-> stack should be « prog »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -70,7 +70,7 @@
|
|||
|
||||
`<< prog>`
|
||||
|
||||
-> stack should be «prog>»
|
||||
-> stack should be « prog> »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -81,6 +81,6 @@
|
|||
«
|
||||
```
|
||||
|
||||
-> stack should be «», «»
|
||||
-> stack should be « », « »
|
||||
|
||||
`del`
|
||||
|
|
|
@ -288,7 +288,7 @@
|
|||
|
||||
`1 2 start «ok» next`
|
||||
|
||||
-> stack should be «ok», «ok»
|
||||
-> stack should be « ok », « ok »
|
||||
|
||||
`del`
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@
|
|||
|
||||
`"<< -> n << n >> >>" str->`
|
||||
|
||||
-> stack should be «-> n << n >>»
|
||||
-> stack should be « -> n « n » »
|
||||
|
||||
`del`
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
-> stack size should be 1
|
||||
|
||||
-> stack should be «'one'»
|
||||
-> stack should be « 'one' »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
|||
|
||||
-> stack size should be 1
|
||||
|
||||
-> stack should be «'one' 2»
|
||||
-> stack should be « 'one' 2 »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
|||
|
||||
-> stack size should be 1
|
||||
|
||||
-> stack should be «»
|
||||
-> stack should be « »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
|||
|
||||
-> stack size should be 1
|
||||
|
||||
-> stack should be «<< << <<»
|
||||
-> stack should be « « « « » » » »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -48,7 +48,7 @@
|
|||
|
||||
-> stack size should be 1
|
||||
|
||||
-> stack should be «-> n << n 2 * >>»
|
||||
-> stack should be « -> n « n 2 * » »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -56,7 +56,7 @@
|
|||
|
||||
`<< 1 << 2 >> >>`
|
||||
|
||||
-> stack should be «1 << 2 >>»
|
||||
-> stack should be « 1 « 2 » »
|
||||
|
||||
`del`
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
`<< 1 << 2 >> >> dup eval`
|
||||
|
||||
-> stack should be «1 << 2 >>», 1, «2»
|
||||
-> stack should be « 1 « 2 » », 1, « 2 »
|
||||
|
||||
`del`
|
||||
|
||||
|
|
Loading…
Reference in a new issue