From b5c23d33ae4bce352b7b1045dea03d1d175489b7 Mon Sep 17 00:00:00 2001 From: Louis Rubet Date: Thu, 22 Sep 2022 10:28:22 +0200 Subject: [PATCH] Remove c++20 warnings Remove pragmas, modify RpnInprog --- src/lexer.cc | 11 +- src/lexer.h | 4 +- src/main.cc | 3 +- src/object.h | 6 +- src/program.cc | 320 ++++++++++++++++++++++----------------------- src/program.h | 4 +- src/rpn-program.cc | 12 +- 7 files changed, 175 insertions(+), 185 deletions(-) diff --git a/src/lexer.cc b/src/lexer.cc index 4d64c60..a6051fc 100644 --- a/src/lexer.cc +++ b/src/lexer.cc @@ -2,9 +2,6 @@ #include "lexer.h" -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers - bool Lexer::Analyse(const string& entry, map& keywords, vector& elements, vector& errors) { size_t jump; @@ -186,7 +183,7 @@ bool Lexer::ParseNumber(const string& entry, size_t idx, size_t& next_idx, vecto vector& elements) { mpreal* r = nullptr; int base = 10; - if (GetNUmberAt(entry, idx, next_idx, base, &r)) { + if (GetNumberAt(entry, idx, next_idx, base, &r)) { elements.push_back({.type = kNumber, .re = r, .re_base = base}); return true; } else { @@ -205,7 +202,7 @@ bool Lexer::ParseComplex(const string& entry, size_t idx, size_t& next_idx, vect 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({.type = kSymbol, .value = entry.substr(idx, entry.size() - idx)}); next_idx = entry.size(); return true; // complex format error, return a symbol @@ -220,7 +217,7 @@ bool Lexer::ParseComplex(const string& entry, size_t idx, size_t& next_idx, vect 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({.type = kSymbol, .value = entry.substr(idx, entry.size() - idx)}); next_idx = entry.size(); if (re != nullptr) delete re; @@ -255,5 +252,3 @@ bool Lexer::ParseUnknown(const string& entry, size_t idx, size_t& next_idx, vect next_idx = token.size() + idx; return true; } - -#pragma GCC diagnostic pop diff --git a/src/lexer.h b/src/lexer.h index af1b361..06e621d 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -23,7 +23,7 @@ class Lexer { mpreal* im; int re_base; int im_base; - program_fn_t fn; + object_cb_t fn; bool auto_eval; }; @@ -34,7 +34,7 @@ class Lexer { struct ReservedWord { ObjectType type; - program_fn_t fn; + object_cb_t fn; }; Lexer() {} diff --git a/src/main.cc b/src/main.cc index 55301b6..187c4dd 100644 --- a/src/main.cc +++ b/src/main.cc @@ -49,7 +49,8 @@ static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __at } static void CatchCtrlC() { - struct sigaction act = {0}; + struct sigaction act; + memset(&act, 0, sizeof(act)); act.sa_sigaction = &CtrlHandler; act.sa_flags = SA_SIGINFO; if (sigaction(SIGINT, &act, nullptr) < 0) diff --git a/src/object.h b/src/object.h index 52e5be6..26814a0 100644 --- a/src/object.h +++ b/src/object.h @@ -69,9 +69,13 @@ struct Object { }; class Program; -class Branch; +struct Branch; typedef void (Program::*program_fn_t)(void); typedef size_t (Program::*branch_fn_t)(Branch&); +union object_cb_t { + program_fn_t prog; + branch_fn_t branch; +}; /// @brief stack objects derived from Object /// diff --git a/src/program.cc b/src/program.cc index 527fd5a..e932e49 100644 --- a/src/program.cc +++ b/src/program.cc @@ -3,206 +3,199 @@ #include "program.h" //< 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 -#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers for keywords_ -vector Program::keywords_{ +// clang-format off +vector 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", {.prog = &Program::RpnHelp}, "this help message"}, + {kKeyword, "h", {.prog = &Program::RpnHelp}, ""}, + {kKeyword, "?", {.prog = &Program::RpnHelp}, ""}, + {kKeyword, "quit", {.prog = &Program::RpnQuit}, "quit software"}, + {kKeyword, "q", {.prog = &Program::RpnQuit}, ""}, + {kKeyword, "exit", {.prog = &Program::RpnQuit}, ""}, + {kKeyword, "test", {.prog = &Program::RpnTest}, ""}, + {kKeyword, "version", {.prog = &Program::RpnVersion}, "show rpn version"}, + {kKeyword, "uname", {.prog = &Program::RpnUname}, "show rpn complete identification string"}, + {kKeyword, "history", {.prog = &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, "+", {.prog = &Program::RpnPlus}, "addition"}, + {kKeyword, "-", {.prog = &Program::RpnMinus}, "substraction"}, + {kKeyword, "*", {.prog = &Program::RpnMul}, "multiplication"}, + {kKeyword, "/", {.prog = &Program::RpnDiv}, "division"}, + {kKeyword, "inv", {.prog = &Program::RpnInv}, "inverse"}, + {kKeyword, "chs", {.prog = &Program::RpnNeg}, "negation"}, + {kKeyword, "neg", {.prog = &Program::RpnNeg}, ""}, + {kKeyword, "^", {.prog = &Program::RpnPower}, "power"}, + {kKeyword, "pow", {.prog = &Program::RpnPower}, ""}, + {kKeyword, "sqrt", {.prog = &Program::RpnSquareroot}, "RpnSquare root"}, + {kKeyword, "sq", {.prog = &Program::RpnSquare}, "RpnSquare"}, + {kKeyword, "abs", {.prog = &Program::RpnAbs}, "absolute value (norm for a complex)"}, + {kKeyword, "sign", {.prog = &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, "%", {.prog = &Program::RpnPurcent}, "purcent"}, + {kKeyword, "%CH", {.prog = &Program::RpnPurcentCH}, "inverse purcent"}, + {kKeyword, "mod", {.prog = &Program::RpnModulo}, "modulo"}, + {kKeyword, "fact", {.prog = &Program::RpnFact}, "n! for integer n or Gamma(x+1) for fractional x"}, + {kKeyword, "mant", {.prog = &Program::RpnMant}, "mantissa of a real number"}, + {kKeyword, "xpon", {.prog = &Program::RpnXpon}, "exponant of a real number"}, + {kKeyword, "floor", {.prog = &Program::RpnFloor}, "largest number <="}, + {kKeyword, "ceil", {.prog = &Program::RpnCeil}, "smallest number >="}, + {kKeyword, "ip", {.prog = &Program::RpnIp}, "integer part"}, + {kKeyword, "fp", {.prog = &Program::RpnFp}, "fractional part"}, + {kKeyword, "min", {.prog = &Program::RpnMin}, "min of 2 real numbers"}, + {kKeyword, "max", {.prog = &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", {.prog = &Program::RpnReal}, "complex real part"}, + {kKeyword, "im", {.prog = &Program::RpnImag}, "complex imaginary part"}, + {kKeyword, "conj", {.prog = &Program::RpnConj}, "complex conjugate"}, + {kKeyword, "arg", {.prog = &Program::RpnArg}, "complex argument in radians"}, + {kKeyword, "c->r", {.prog = &Program::RpnC2r}, "transform a complex in 2 reals"}, + {kKeyword, "r->c", {.prog = &Program::RpnR2c}, "transform 2 reals in a complex"}, + {kKeyword, "p->r", {.prog = &Program::RpnP2r}, "cartesian to polar"}, + {kKeyword, "r->p", {.prog = &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, - "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, "std", {.prog = &Program::RpnStd}, "standard floating numbers representation. ex: std"}, + {kKeyword, "fix", {.prog = &Program::RpnFix}, "fixed point representation. ex: 6 fix"}, + {kKeyword, "sci", {.prog = &Program::RpnSci}, "scientific floating point representation. ex: 20 sci"}, + {kKeyword, "prec", {.prog = &Program::RpnPrecision}, "set float precision in bits. ex: 256 prec"}, + {kKeyword, "round", {.prog = &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", {.prog = &Program::RpnDefault}, "set float representation and precision to default"}, + {kKeyword, "type", {.prog = &Program::RpnType}, "show type of stack first entry"}, + {kKeyword, "hex", {.prog = &Program::RpnHex}, "hexadecimal representation, applies on stack level 0 only"}, + {kKeyword, "dec", {.prog = &Program::RpnDec}, "decimal representation, applies on stack level 0 only"}, + {kKeyword, "bin", {.prog = &Program::RpnBin}, "binary representation, applies on stack level 0 only"}, + {kKeyword, "base", {.prog = &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, ">", {.prog = &Program::RpnSup}, "binary operator >"}, + {kKeyword, ">=", {.prog = &Program::RpnSupEq}, "binary operator >="}, + {kKeyword, "<", {.prog = &Program::RpnInf}, "binary operator <"}, + {kKeyword, "<=", {.prog = &Program::RpnInfEq}, "binary operator <="}, + {kKeyword, "!=", {.prog = &Program::RpnDiff}, "binary operator != (different)"}, + {kKeyword, "==", {.prog = &Program::RpnEq}, "binary operator == (equal)"}, + {kKeyword, "and", {.prog = &Program::RpnTestAnd}, "boolean operator and"}, + {kKeyword, "or", {.prog = &Program::RpnTestOr}, "boolean operator or"}, + {kKeyword, "xor", {.prog = &Program::RpnTestXor}, "boolean operator xor"}, + {kKeyword, "not", {.prog = &Program::RpnTestNot}, "boolean operator not"}, + {kKeyword, "same", {.prog = &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", {.prog = &Program::RpnSwap}, "swap 2 first stack entries"}, + {kKeyword, "drop", {.prog = &Program::RpnDrop}, "drop first stack entry"}, + {kKeyword, "drop2", {.prog = &Program::RpnDrop2}, "drop 2 first stack entries"}, + {kKeyword, "dropn", {.prog = &Program::RpnDropn}, "drop n first stack entries"}, + {kKeyword, "del", {.prog = &Program::RpnErase}, "drop all stack entries"}, + {kKeyword, "erase", {.prog = &Program::RpnErase}, ""}, + {kKeyword, "rot", {.prog = &Program::RpnRot}, "rotate 3 first stack entries"}, + {kKeyword, "dup", {.prog = &Program::RpnDup}, "duplicate first stack entry"}, + {kKeyword, "dup2", {.prog = &Program::RpnDup2}, "duplicate 2 first stack entries"}, + {kKeyword, "dupn", {.prog = &Program::RpnDupn}, "duplicate n first stack entries"}, + {kKeyword, "pick", {.prog = &Program::RpnPick}, "push a copy of the given stack level onto the stack"}, + {kKeyword, "depth", {.prog = &Program::RpnDepth}, "give stack depth"}, + {kKeyword, "roll", {.prog = &Program::RpnRoll}, "move a stack entry to the top of the stack"}, + {kKeyword, "rolld", {.prog = &Program::RpnRolld}, "move the element on top of the stack to a higher stack position"}, + {kKeyword, "over", {.prog = &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, - "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, "->str", {.prog = &Program::RpnInstr}, "convert an object into a string"}, + {kKeyword, "str->", {.prog = &Program::RpnStrout}, "convert a string into an object"}, + {kKeyword, "chr", {.prog = &Program::RpnChr}, "convert ASCII character code in stack level 1 into a string"}, + {kKeyword, "num", {.prog = &Program::RpnNum}, "return ASCII code of the first character of the string in stack level 1 as a real number"}, + {kKeyword, "size", {.prog = &Program::RpnStrsize}, "return the length of the string"}, + {kKeyword, "pos", {.prog = &Program::RpnStrpos}, "seach for the string in level 1 within the string in level 2"}, + {kKeyword, "sub", {.prog = &Program::RpnStrsub}, "return a substring of the string in level 3"}, // BRANCH {kUndef, "", nullptr, "\nBRANCH"}, - {kBranch, "if", (program_fn_t)&Program::RpnIf, - "if then else " - "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 next| step"}, - {kBranch, "for", (program_fn_t)&Program::RpnFor, " for next| 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, ift"}, - {kKeyword, "ifte", &Program::RpnIfte, - "similar to if-then-else-end, " - " ifte"}, - {kBranch, "do", (program_fn_t)&Program::RpnDo, "do until end"}, - {kBranch, "until", (program_fn_t)&Program::RpnUntil, "used with do"}, - {kBranch, "while", (program_fn_t)&Program::RpnWhile, "while repeat end"}, - {kBranch, "repeat", (program_fn_t)&Program::RpnRepeat, "used with while"}, + {kBranch, "if", {.branch = &Program::RpnIf}, "if then else end"}, + {kBranch, "then", {.branch = &Program::RpnThen}, "used with if"}, + {kBranch, "else", {.branch = &Program::RpnElse}, "used with if"}, + {kBranch, "end", {.branch = &Program::RpnEnd}, "used with various branch instructions"}, + {kBranch, "start", {.branch = &Program::RpnStart}, " start next| step"}, + {kBranch, "for", {.branch = &Program::RpnFor}, " for next| step"}, + {kBranch, "next", {.branch = &Program::RpnNext}, "used with start and for"}, + {kBranch, "step", {.branch = &Program::RpnStep}, "used with start and for"}, + {kKeyword, "ift", {.prog = &Program::RpnIft}, "similar to if-then-end, ift"}, + {kKeyword, "ifte", {.prog = &Program::RpnIfte}, "similar to if-then-else-end, ifte"}, + {kBranch, "do", {.branch = &Program::RpnDo}, "do until end"}, + {kBranch, "until", {.branch = &Program::RpnUntil}, "used with do"}, + {kBranch, "while", {.branch = &Program::RpnWhile}, "while repeat end"}, + {kBranch, "repeat", {.branch = &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", {.prog = &Program::RpnSto}, "store a variable. ex: 1 'name' sto"}, + {kKeyword, "rcl", {.prog = &Program::RpnRcl}, "recall a variable. ex: 'name' rcl"}, + {kKeyword, "purge", {.prog = &Program::RpnPurge}, "delete a variable. ex: 'name' purge"}, + {kKeyword, "vars", {.prog = &Program::RpnVars}, "list all variables"}, + {kKeyword, "clusr", {.prog = &Program::RpnClusr}, "erase all variables"}, + {kKeyword, "edit", {.prog = &Program::RpnEdit}, "edit a variable content"}, + {kKeyword, "sto+", {.prog = &Program::RpnStoadd}, "add to a stored variable. ex: 1 'name' sto+ 'name' 2 sto+"}, + {kKeyword, "sto-", {.prog = &Program::RpnStosub}, "substract to a stored variable. ex: 1 'name' sto- 'name' 2 sto-"}, + {kKeyword, "sto*", {.prog = &Program::RpnStomul}, "multiply a stored variable. ex: 3 'name' sto* 'name' 2 sto*"}, + {kKeyword, "sto/", {.prog = &Program::RpnStodiv}, "divide a stored variable. ex: 3 'name' sto/ 'name' 2 sto/"}, + {kKeyword, "sneg", {.prog = &Program::RpnStoneg}, "negate a variable. ex: 'name' sneg"}, + {kKeyword, "sinv", {.prog = &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, - "load program local variables. ex: << -> n m << 0 n m for i i + next >> " - ">>"}, + {kKeyword, "eval", {.prog = &Program::RpnEval}, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval"}, + {kBranch, "->", {.branch = &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", {.prog = &Program::RpnPi}, "pi constant"}, + {kKeyword, "sin", {.prog = &Program::RpnSin}, "sinus"}, + {kKeyword, "asin", {.prog = &Program::RpnAsin}, "arg sinus"}, + {kKeyword, "cos", {.prog = &Program::RpnCos}, "cosinus"}, + {kKeyword, "acos", {.prog = &Program::RpnAcos}, "arg cosinus"}, + {kKeyword, "tan", {.prog = &Program::RpnTan}, "tangent"}, + {kKeyword, "atan", {.prog = &Program::RpnAtan}, "arg tangent"}, + {kKeyword, "d->r", {.prog = &Program::RpnD2r}, "convert degrees to radians"}, + {kKeyword, "r->d", {.prog = &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", {.prog = &Program::RpnE}, "Euler constant"}, + {kKeyword, "ln", {.prog = &Program::RpnLn}, "logarithm base e"}, + {kKeyword, "log", {.prog = &Program::RpnLn}, ""}, + {kKeyword, "lnp1", {.prog = &Program::RpnLnp1}, "ln(1+x) which is useful when x is close to 0"}, + {kKeyword, "exp", {.prog = &Program::RpnExp}, "exponential"}, + {kKeyword, "expm", {.prog = &Program::RpnExpm}, "exp(x)-1 which is useful when x is close to 0"}, + {kKeyword, "log10", {.prog = &Program::RpnLog10}, "logarithm base 10"}, + {kKeyword, "alog10", {.prog = &Program::RpnAlog10}, "exponential base 10"}, + {kKeyword, "exp10", {.prog = &Program::RpnAlog10}, ""}, + {kKeyword, "log2", {.prog = &Program::RpnLog2}, "logarithm base 2"}, + {kKeyword, "alog2", {.prog = &Program::RpnAlog2}, "exponential base 2"}, + {kKeyword, "exp2", {.prog = &Program::RpnAlog2}, ""}, + {kKeyword, "sinh", {.prog = &Program::RpnSinh}, "hyperbolic sine"}, + {kKeyword, "asinh", {.prog = &Program::RpnAsinh}, "inverse hyperbolic sine"}, + {kKeyword, "cosh", {.prog = &Program::RpnCosh}, "hyperbolic cosine"}, + {kKeyword, "acosh", {.prog = &Program::RpnAcosh}, "inverse hyperbolic cosine"}, + {kKeyword, "tanh", {.prog = &Program::RpnTanh}, "hyperbolic tangent"}, + {kKeyword, "atanh", {.prog = &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"}}; -#pragma GCC diagnostic pop + {kKeyword, "time", {.prog = &Program::RpnTime}, "local time in ISO 8601 format"}, + {kKeyword, "date", {.prog = &Program::RpnDate}, "local date in ISO 8601 format"}, + {kKeyword, "ticks", {.prog = &Program::RpnTicks}, "local date and time in µs"} +}; +// clang-format on /// autocompletion vector for linenoise autocompletion vector& Program::GetAutocompletionWords() { @@ -589,13 +582,10 @@ RetValue Program::Parse(const string& entry) { } } break; case kKeyword: - push_back(new Keyword(element.fn, element.value)); + push_back(new Keyword(element.fn.prog, element.value)); break; case kBranch: -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wcast-function-type" // allow casting kBranch callbacks - push_back(new Branch((branch_fn_t)element.fn, element.value)); -#pragma GCC diagnostic pop + push_back(new Branch(element.fn.branch, element.value)); break; default: ShowError(kUnknownError, "error creating program from entry"); diff --git a/src/program.h b/src/program.h index 9801f8a..54d5fbe 100644 --- a/src/program.h +++ b/src/program.h @@ -84,7 +84,7 @@ class Program : public deque, public Lexer, public Object { struct keyword_t { ObjectType type; string name; - program_fn_t fn; + object_cb_t fn; string comment; }; static vector keywords_; @@ -153,7 +153,7 @@ class Program : public deque, public Lexer, public Object { // program bool FindVariable(string& variable, Object*& obj); void RpnEval(void); - int RpnInprog(Branch& inprog_obj); + size_t RpnInprog(Branch& inprog_obj); // real void RpnPlus(); diff --git a/src/rpn-program.cc b/src/rpn-program.cc index 37761c7..dfdc857 100644 --- a/src/rpn-program.cc +++ b/src/rpn-program.cc @@ -75,14 +75,14 @@ void Program::RpnEval(void) { /// @brief -> keyword (Branch) implementation /// -int Program::RpnInprog(Branch& inprog_obj) { +size_t Program::RpnInprog(Branch& inprog_obj) { string context("->"); // for showing errors size_t count_symbols = 0; bool prog_found = false; if (inprog_obj.arg1 == kStepOut) { ERROR_CONTEXT(kUnknownError); - return -1; + return kStepOut; } // syntax must be @@ -101,7 +101,7 @@ int Program::RpnInprog(Branch& inprog_obj) { // found something other than symbol ERROR_CONTEXT(kBadOperandType); ShowError(err_, context); - return -1; + return kStepOut; } } @@ -109,21 +109,21 @@ int Program::RpnInprog(Branch& inprog_obj) { if (count_symbols == 0) { ERROR_CONTEXT(kSyntaxError); ShowError(err_, context); - return -1; + return kStepOut; } // is missing if (!prog_found) { ERROR_CONTEXT(kSyntaxError); ShowError(err_, context); - return -1; + return kStepOut; } // check symbols Number vs stack_ size if (stack_.size() < count_symbols) { ERROR_CONTEXT(kMissingOperand); ShowError(err_, context); - return -1; + return kStepOut; } // load variables