mirror of
https://github.com/louisrubet/rpn
synced 2025-02-07 08:45:48 +01:00
Merge pull request #239 from louisrubet/#218/enhanced_gcc_warnings
Add enhanced gcc warnings
This commit is contained in:
commit
db0e7f6ebb
15 changed files with 134 additions and 110 deletions
|
@ -46,16 +46,6 @@ set(RPN_LICENSE "LGPLv3")
|
|||
set(RPN_LICENSE_FILE "${PROJECT_SOURCE_DIR}/LICENSE")
|
||||
set(RPN_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md")
|
||||
|
||||
# compiler options
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
|
||||
# TODO still up to date?
|
||||
set(BASE_COMPILER_OPTIONS "-std=c++17 -Wl,--no-as-needed")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s")
|
||||
endif()
|
||||
|
||||
# custom linenoise-ng
|
||||
if(NOT EXISTS "${PROJECT_SOURCE_DIR}/linenoise-ng/.git")
|
||||
execute_process(command git submodule init ${PROJECT_SOURCE_DIR}/linenoise-ng)
|
||||
|
@ -73,32 +63,47 @@ endif()
|
|||
# includes
|
||||
include_directories(${PROJECT_SOURCE_DIR}/src ${PROJECT_SOURCE_DIR}/linenoise-ng/include ${PROJECT_SOURCE_DIR}/mpreal)
|
||||
|
||||
# build
|
||||
add_executable(
|
||||
rpn
|
||||
${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
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-store.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-string.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-trig.cc
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp
|
||||
)
|
||||
# src
|
||||
set(RPN_SRC_FILES
|
||||
${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
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-complex.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-general.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-logs.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-program.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-real.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-stack.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-store.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-string.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-test-framework.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-time.cc
|
||||
${PROJECT_SOURCE_DIR}/src/rpn-trig.cc)
|
||||
|
||||
set(LINENOISE_NG_SRC_FILES
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/ConvertUTF.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/linenoise.cpp
|
||||
${PROJECT_SOURCE_DIR}/linenoise-ng/src/wcwidth.cpp)
|
||||
|
||||
# compiler options
|
||||
set_source_files_properties(${RPN_SRC_FILES} COMPILE_FLAGS # some harder warnings
|
||||
"-Wall -Wextra -pedantic -Wno-missing-field-initializers")
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
message(STATUS "Compiler type GNU: ${CMAKE_CXX_COMPILER}")
|
||||
# TODO still up to date?
|
||||
set(BASE_COMPILER_OPTIONS "-std=c++17 -Wl,--no-as-needed")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILER_OPTIONS}")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${BASE_COMPILER_OPTIONS} -O0 -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${BASE_COMPILER_OPTIONS} -O3 -s")
|
||||
endif()
|
||||
|
||||
add_executable(rpn ${RPN_SRC_FILES} ${LINENOISE_NG_SRC_FILES})
|
||||
|
||||
target_link_libraries(rpn mpfr)
|
||||
target_link_libraries(rpn gmp)
|
||||
|
|
16
src/lexer.cc
16
src/lexer.cc
|
@ -2,8 +2,11 @@
|
|||
|
||||
#include "lexer.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic" // allow designated initializers
|
||||
|
||||
bool Lexer::Analyse(string& entry, map<string, ReservedWord>& keywords, vector<SynElement>& elements,
|
||||
vector<SynError>& errors) {
|
||||
vector<SynError>& errors) {
|
||||
size_t jump;
|
||||
for (size_t i = 0; i < entry.size(); i++) {
|
||||
if (isspace(entry[i])) continue;
|
||||
|
@ -49,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,
|
||||
bool Lexer::ParseString(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++) {
|
||||
|
@ -66,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,
|
||||
bool Lexer::ParseSymbol(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++) {
|
||||
|
@ -81,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,
|
||||
bool Lexer::ParseProgram(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 "»"
|
||||
|
@ -153,7 +156,6 @@ int Lexer::GetBaseAt(string& entry, size_t& next_idx, bool& positive) {
|
|||
|
||||
bool Lexer::GetNUmberAt(string& entry, size_t idx, size_t& next_idx, int& base, mpreal** r, char delim) {
|
||||
stringstream ss;
|
||||
int idxNumber = 0;
|
||||
string token;
|
||||
bool positive = true;
|
||||
|
||||
|
@ -193,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,
|
||||
bool Lexer::ParseComplex(string& entry, size_t idx, size_t& next_idx, vector<SynError>& errors __attribute__((unused)),
|
||||
vector<SynElement>& elements) {
|
||||
mpreal* re = nullptr;
|
||||
mpreal* im = nullptr;
|
||||
|
@ -253,3 +255,5 @@ bool Lexer::ParseUnknown(string& entry, size_t idx, size_t& next_idx, vector<Syn
|
|||
next_idx = token.size() + idx;
|
||||
return true;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
|
14
src/main.cc
14
src/main.cc
|
@ -52,13 +52,16 @@ static void EnterInteractive() {
|
|||
/// @param siginfo signal info, see POSIX sigaction
|
||||
/// @param context see POSIX sigaction
|
||||
///
|
||||
static void CtrlHandler(int sig, siginfo_t* siginfo, void* context) { ExitInteractive(); }
|
||||
static void CtrlHandler(int sig __attribute__((unused)), siginfo_t* siginfo __attribute__((unused)),
|
||||
void* context __attribute__((unused))) {
|
||||
ExitInteractive();
|
||||
}
|
||||
|
||||
/// @brief setup signals handlers to stop with honours
|
||||
///
|
||||
/// @param prog the prog to catch the signals to, must be checked not nullptr by user
|
||||
///
|
||||
static void CatchSignals(program* prog) {
|
||||
static void CatchSignals() {
|
||||
struct sigaction act = {0};
|
||||
|
||||
act.sa_sigaction = &CtrlHandler;
|
||||
|
@ -85,6 +88,9 @@ int main(int argc, char* argv[]) {
|
|||
// init history
|
||||
EnterInteractive();
|
||||
|
||||
// user could stop prog with CtrlC
|
||||
CatchSignals();
|
||||
|
||||
// entry loop
|
||||
heap heap;
|
||||
rpnstack stack;
|
||||
|
@ -95,8 +101,6 @@ int main(int argc, char* argv[]) {
|
|||
string entry;
|
||||
switch (Input(entry, program::GetAutocompletionWords()).status) {
|
||||
case Input::InputStatus::kOk:
|
||||
// user could stop prog with CtrlC
|
||||
CatchSignals(&prog);
|
||||
// run it
|
||||
if (prog.Parse(entry) == kOk && prog.Run() == kGoodbye)
|
||||
go_on = false;
|
||||
|
@ -127,7 +131,7 @@ int main(int argc, char* argv[]) {
|
|||
ret = prog.Parse(entry);
|
||||
if (ret == kOk) {
|
||||
// user could stop prog with CtrlC
|
||||
CatchSignals(&prog);
|
||||
CatchSignals();
|
||||
|
||||
// run it
|
||||
ret = prog.Run();
|
||||
|
|
|
@ -184,7 +184,7 @@ ostream& _out_number(ostream& out, int base, const mpreal& value) {
|
|||
if (digits > 0) {
|
||||
out << '.';
|
||||
|
||||
int remaining = MIN(strlen(print_from) - nexp - 1, digits) + 1;
|
||||
int remaining = MIN(static_cast<int>(strlen(print_from)) - nexp - 1, digits) + 1;
|
||||
for (int i = nexp; i < remaining + nexp; i++) out << print_from[i];
|
||||
for (int i = 0; i < nexp + digits - len; i++) out << '0';
|
||||
}
|
||||
|
|
|
@ -172,8 +172,8 @@ struct Symbol : Object {
|
|||
virtual Object* Clone() { return new Symbol(value, auto_eval); }
|
||||
virtual string Name() { return string("symbol"); }
|
||||
virtual ostream& Show(ostream& out) { return out << "'" << value << "'"; }
|
||||
bool auto_eval;
|
||||
string value;
|
||||
bool auto_eval;
|
||||
};
|
||||
|
||||
struct Keyword : Object {
|
||||
|
@ -187,19 +187,19 @@ struct Keyword : Object {
|
|||
|
||||
struct Branch : Object {
|
||||
Branch() : Object(kBranch) {}
|
||||
explicit Branch(branch_fn_t fn__, const string& value__) : Object(kBranch) {
|
||||
fn = fn__;
|
||||
explicit Branch(branch_fn_t fn__, const string& value__) : Object(kBranch), fn(fn__), value(value__) {
|
||||
arg1 = static_cast<size_t>(-1);
|
||||
arg2 = static_cast<size_t>(-1);
|
||||
arg3 = static_cast<size_t>(-1);
|
||||
arg_bool = 0;
|
||||
value = value__;
|
||||
}
|
||||
explicit Branch(Branch& other) : Object(kBranch) {
|
||||
fn = other.fn;
|
||||
arg1 = other.arg1;
|
||||
arg2 = other.arg2;
|
||||
arg3 = other.arg3;
|
||||
first_index = other.first_index;
|
||||
last_index = other.last_index;
|
||||
arg_bool = other.arg_bool;
|
||||
value = other.value;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#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
|
||||
vector<program::keyword_t> program::keywords_{
|
||||
// GENERAL
|
||||
{kUndef, "", nullptr, "\nGENERAL"},
|
||||
|
@ -129,8 +131,7 @@ vector<program::keyword_t> program::keywords_{
|
|||
{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, "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"},
|
||||
|
@ -202,6 +203,7 @@ vector<program::keyword_t> program::keywords_{
|
|||
{kKeyword, "date", &program::RpnDate, "date in local format"},
|
||||
{kKeyword, "ticks", &program::RpnTicks, "system tick in µs"},
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
/// autocompletion vector for linenoise autocompletion
|
||||
vector<string>& program::GetAutocompletionWords() {
|
||||
|
@ -219,7 +221,6 @@ vector<string>& program::GetAutocompletionWords() {
|
|||
RetValue program::Run() {
|
||||
bool go_out = false;
|
||||
RetValue ret = kOk;
|
||||
ObjectType type;
|
||||
|
||||
err_ = kOk;
|
||||
err_context_ = "";
|
||||
|
@ -598,7 +599,10 @@ RetValue program::Parse(string& entry) {
|
|||
push_back(new Keyword(element.fn, 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
|
||||
break;
|
||||
default:
|
||||
ShowError(kUnknownError, "error creating program from entry");
|
||||
|
@ -637,8 +641,10 @@ RetValue program::ShowError() {
|
|||
case kInternalError:
|
||||
case kDeadlyError:
|
||||
ret = kDeadlyError;
|
||||
break;
|
||||
default:
|
||||
ret = kOk;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -213,7 +213,7 @@ class program : public deque<Object*>, public Lexer {
|
|||
// test-core
|
||||
void RpnTest();
|
||||
void RunTestFile(string test_filename, int& total_tests, int& total_tests_failed, int& total_steps,
|
||||
int& total_steps_failed);
|
||||
int& total_steps_failed);
|
||||
|
||||
// test
|
||||
void RpnSup(void);
|
||||
|
@ -248,42 +248,42 @@ class program : public deque<Object*>, public Lexer {
|
|||
// convenience macros for rpn_xx function
|
||||
// carefull : some of these macros modify program flow
|
||||
|
||||
#define ERROR_CONTEXT(err) \
|
||||
#define ERROR_CONTEXT(err) \
|
||||
do { \
|
||||
err_ = (err); \
|
||||
err_context_ = __FUNCTION__; \
|
||||
} while (0)
|
||||
|
||||
#define MIN_ARGUMENTS(num) \
|
||||
do { \
|
||||
if ((num) >= 0 && 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 ((num) >= 0 && 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 { \
|
||||
if ((num) >= 0 && stack_.at(num)->_type != (type)) { \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return; \
|
||||
} \
|
||||
#define ARG_MUST_BE_OF_TYPE(num, type) \
|
||||
do { \
|
||||
if (stack_.at(num)->_type != (type)) { \
|
||||
ERROR_CONTEXT(kBadOperandType); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define ARG_MUST_BE_OF_TYPE_RET(num, type, ret) \
|
||||
do { \
|
||||
if ((num) >= 0 && 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_
|
||||
|
|
|
@ -83,7 +83,7 @@ size_t program::RpnEnd(Branch& myobj) {
|
|||
size_t ret = kStepOut;
|
||||
|
||||
// arg1 = index of do+1 in case of do..unti..end
|
||||
if (myobj.arg1 != -1) {
|
||||
if (myobj.arg1 != kStepOut) {
|
||||
// in a template do..until..end
|
||||
MIN_ARGUMENTS_RET(1, kRtError);
|
||||
ARG_MUST_BE_OF_TYPE_RET(0, kNumber, kRtError);
|
||||
|
@ -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) {
|
||||
size_t program::RpnDo(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ size_t program::RpnDo(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::RpnUntil(Branch& myobj) {
|
||||
size_t program::RpnUntil(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -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) {
|
||||
size_t program::RpnWhile(Branch& myobj __attribute__((unused))) {
|
||||
// nothing
|
||||
return kStepOut;
|
||||
}
|
||||
|
@ -298,8 +298,7 @@ size_t program::RpnNext(Branch& myobj) {
|
|||
mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), mpreal(1).mpfr_srcptr(), MPFR_RNDD);
|
||||
|
||||
// for command: increment symbol too
|
||||
if (start_or_for->arg1 != -1) {
|
||||
Object* obj;
|
||||
if (start_or_for->arg1 != kStepOut) {
|
||||
Symbol* var;
|
||||
if (start_or_for->arg1 >= size() || at(start_or_for->arg1)->_type != kSymbol) {
|
||||
ERROR_CONTEXT(kMissingOperand);
|
||||
|
@ -318,7 +317,7 @@ size_t program::RpnNext(Branch& myobj) {
|
|||
return kStepOut;
|
||||
} else {
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1) return start_or_for->arg1 + 1;
|
||||
if (start_or_for->arg1 != kStepOut) return start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
return myobj.arg1 + 1;
|
||||
|
@ -361,8 +360,7 @@ size_t program::RpnStep(Branch& myobj) {
|
|||
// carefull: round toward minus infinity to avoid missing last boundary (because growing step)
|
||||
mpfr_add(myobj.first_index.mpfr_ptr(), myobj.first_index.mpfr_srcptr(), step.mpfr_srcptr(), MPFR_RNDD);
|
||||
|
||||
if (start_or_for->arg1 != -1) {
|
||||
Object* obj;
|
||||
if (start_or_for->arg1 != kStepOut) {
|
||||
Symbol* var;
|
||||
|
||||
// for command: increment symbol too
|
||||
|
@ -382,7 +380,7 @@ size_t program::RpnStep(Branch& myobj) {
|
|||
ret = kStepOut;
|
||||
} else {
|
||||
// for command: next instruction will be after symbol variable
|
||||
if (start_or_for->arg1 != -1) ret = start_or_for->arg1 + 1;
|
||||
if (start_or_for->arg1 != kStepOut) ret = start_or_for->arg1 + 1;
|
||||
// start command: next instruction will be after start command
|
||||
else
|
||||
ret = myobj.arg1 + 1;
|
||||
|
|
|
@ -54,7 +54,6 @@ void program::RpnHelp() {
|
|||
cout << _syntax << endl;
|
||||
|
||||
// keywords
|
||||
unsigned int i = 0;
|
||||
for (auto& kw : keywords_)
|
||||
if (!kw.comment.empty()) {
|
||||
// titles in bold
|
||||
|
|
|
@ -82,10 +82,10 @@ void program::RpnEval(void) {
|
|||
///
|
||||
int program::RpnInprog(Branch& inprog_obj) {
|
||||
string context("->"); // for showing errors
|
||||
int count_symbols = 0;
|
||||
size_t count_symbols = 0;
|
||||
bool prog_found = false;
|
||||
|
||||
if (inprog_obj.arg1 == -1) {
|
||||
if (inprog_obj.arg1 == kStepOut) {
|
||||
ERROR_CONTEXT(kUnknownError);
|
||||
return -1;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ int program::RpnInprog(Branch& inprog_obj) {
|
|||
}
|
||||
|
||||
// load variables
|
||||
for (unsigned int i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) {
|
||||
for (size_t i = inprog_obj.arg1 + count_symbols; i > inprog_obj.arg1; i--) {
|
||||
local_heap_[reinterpret_cast<Symbol*>(at(i))->value] = stack_.at(0)->Clone();
|
||||
stack_.pop();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ void program::RpnDropn(void) {
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
int args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
size_t args = stack_.value<Number>(0).toULong();
|
||||
MIN_ARGUMENTS(args + 1);
|
||||
stack_.erase(0, args + 1);
|
||||
}
|
||||
|
@ -53,11 +53,15 @@ void program::RpnDupn(void) {
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
int args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
size_t args = stack_.value<Number>(0).toULong();
|
||||
stack_.pop();
|
||||
if (args == 0) {
|
||||
ERROR_CONTEXT(kOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
MIN_ARGUMENTS(args);
|
||||
for (int i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->Clone());
|
||||
for (size_t i = 0; i < args; i++) stack_.push_front(stack_.at(args - 1)->Clone());
|
||||
}
|
||||
|
||||
/// @brief dup2 keyword implementation
|
||||
|
@ -74,7 +78,7 @@ void program::RpnPick(void) {
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
int to_pick = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
size_t to_pick = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
stack_.pop();
|
||||
|
||||
// treat stack_ depth errors
|
||||
|
@ -105,9 +109,13 @@ void program::RpnRoll(void) {
|
|||
MIN_ARGUMENTS(1);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
int args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
size_t args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
stack_.pop();
|
||||
MIN_ARGUMENTS(args);
|
||||
if (args == 0) {
|
||||
ERROR_CONTEXT(kOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
Object* tmp = stack_.at(args - 1);
|
||||
stack_.erase(args - 1, 1, false);
|
||||
|
@ -120,9 +128,13 @@ void program::RpnRolld(void) {
|
|||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
|
||||
int args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
size_t args = static_cast<int>(stack_.value<Number>(0).toLong());
|
||||
stack_.pop();
|
||||
MIN_ARGUMENTS(args);
|
||||
if (args == 0) {
|
||||
ERROR_CONTEXT(kOutOfRange);
|
||||
return;
|
||||
}
|
||||
|
||||
Object* tmp = stack_.at(0);
|
||||
stack_.erase(0, 1, false);
|
||||
|
|
|
@ -193,7 +193,6 @@ void program::RpnPurge(void) {
|
|||
/// @brief vars keyword implementation
|
||||
///
|
||||
void program::RpnVars(void) {
|
||||
Object* obj;
|
||||
program* parent = parent_;
|
||||
string name;
|
||||
int index = 1;
|
||||
|
@ -214,7 +213,7 @@ void program::RpnVars(void) {
|
|||
while (parent != nullptr) {
|
||||
for (auto i : parent->local_heap_) {
|
||||
cout << "parent var " << index++ << ": name '" << i.first << "', type " << i.second->Name() << ", value ";
|
||||
obj->Show(cout) << endl;
|
||||
i.second->Show(cout) << endl;
|
||||
}
|
||||
parent = parent->parent_;
|
||||
}
|
||||
|
|
|
@ -117,9 +117,9 @@ void program::RunTestFile(string test_filename, int& total_tests, int& total_tes
|
|||
rpnstack stk;
|
||||
heap hp;
|
||||
bool failed = false;
|
||||
bool is_first_step;
|
||||
bool is_test_error_shown;
|
||||
int last_err;
|
||||
bool is_first_step = true;
|
||||
bool is_test_error_shown = false;
|
||||
int last_err = static_cast<int>(kOk);
|
||||
stringstream cerr_buffer;
|
||||
streambuf* cerr_old_buffer;
|
||||
|
||||
|
|
|
@ -144,7 +144,7 @@ void program::RpnTestXor(void) {
|
|||
MIN_ARGUMENTS(2);
|
||||
ARG_MUST_BE_OF_TYPE(0, kNumber);
|
||||
ARG_MUST_BE_OF_TYPE(1, kNumber);
|
||||
if (stack_.value<Number>(0) != 0 ^ stack_.value<Number>(1) != 0)
|
||||
if ((stack_.value<Number>(0) != 0) ^ (stack_.value<Number>(1) != 0))
|
||||
stack_.push(new Number(1));
|
||||
else
|
||||
stack_.push(new Number(0));
|
||||
|
|
|
@ -44,9 +44,6 @@ void program::RpnDate() {
|
|||
// date format = (M)M.DDYYYY
|
||||
date = static_cast<double>(tm->tm_mon + 1) * 1000000.0 + static_cast<double>(tm->tm_mday) * 10000.0 +
|
||||
static_cast<double>(tm->tm_year + 1900);
|
||||
|
||||
// push it
|
||||
Number* num;
|
||||
// division after push for real precision
|
||||
stack_.push(new Number(date));
|
||||
stack_.value<Number>(0) /= 1000000.0;
|
||||
|
|
Loading…
Add table
Reference in a new issue