diff --git a/src/rpn-branch.h b/src/rpn-branch.h index fd116a7..e951d30 100644 --- a/src/rpn-branch.h +++ b/src/rpn-branch.h @@ -3,8 +3,8 @@ int rpn_if(branch& myobj) { // myobj.arg1 = 'if' condition evaluation value - MIN_ARGUMENTS_RET(1, -1); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); + MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0) myobj.arg1 = 1; @@ -51,9 +51,9 @@ int rpn_start(branch& myobj) { int ret = -1; - MIN_ARGUMENTS_RET(2, 1); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -1); + MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); // farg2 = last value of start command stack::copy_and_push_back(*_stack, _stack->size()-1, _branch_stack); @@ -79,9 +79,9 @@ int rpn_for(branch& myobj) { int ret; - MIN_ARGUMENTS_RET(2, 1); - ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); - ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -1); + MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error); symbol* sym = ((symbol*)seq_obj(myobj.arg1)); @@ -96,11 +96,21 @@ int rpn_for(branch& myobj) myobj.farg1 = (number*)_branch_stack.back(); _stack->pop_back(); - // store symbol with first value - _local_heap.add(sym->_value, myobj.farg1, myobj.farg1->size()); - (void)_stack->pop_back(); + // test value + if (myobj.farg1->_value > myobj.farg2->_value) + // last boundary lower than first boundary + // -> next command shall be after 'next' + // arg2 holds index of 'next' + ret = myobj.arg2 + 1; + else + { + // store symbol with first value + _local_heap.add(sym->_value, myobj.farg1, myobj.farg1->size()); + (void)_stack->pop_back(); + ret = myobj.arg1 + 1; + } - return myobj.arg1 + 1; + return ret; } int rpn_next(branch& myobj) @@ -150,108 +160,59 @@ int rpn_next(branch& myobj) int rpn_step(branch& myobj) { -static int count = 0; - // arg1 = index of start or for command in program - // farg1 = current count - branch* start_or_for = (branch*)seq_obj(myobj.arg1); - if (! myobj.arg_bool) - { - myobj.arg_bool = true; - myobj.farg1 = start_or_for->farg1; - } + int ret; + MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error); + ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error); - // increment then test number* step = (number*)_stack->pop_back(); - mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEF_RND); -cout<<"step=";step->show(cout);cout<arg1 != -1) - { - object* obj; - unsigned int size; - symbol* var = (symbol*)seq_obj(start_or_for->arg1); - - // increase symbol variable - _local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); - } - - //test value - bool step_positive = mpfr_cmp_d(step->_value.mpfr, 0.0)>0; - -cout<<"(count="<10) -return -1; - - if ((step_positive && (myobj.farg1 > start_or_for->farg2)) - || ((! step_positive) && (myobj.farg1 < start_or_for->farg2))) - { - // end of loop - myobj.arg_bool = false;// init again next time - _branch_stack.pop_back(); - _branch_stack.pop_back(); - return -1; - } + // end of loop if step is negative or zero + if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0) + ret = -1; else { - // for command: next instruction will be after symbol variable - if (start_or_for->arg1 != -1) - return start_or_for->arg1 + 1; - // start command: next instruction will be after start command - else - return myobj.arg1 + 1; - } -//TODO -#if 0 - // arg1 = index of start or for command in program - // farg1 = current count - number* step = _stack.pop_back(); - - branch* start_or_for = (branch*)seq_obj(myobj.arg1); - if (! myobj.arg_bool) - { - myobj.arg_bool = true; - myobj.farg1 = start_or_for->farg1; - } - - // increment then test - mpfr_add(&myobj.farg1.mpfr, &myobj.farg1.mpfr, &step.mpfr, MPFR_DEF_RND); - - // for command: increment symbol too - if (start_or_for->arg1 != -1) - { - void* obj; - unsigned int size; - int type; - symbol* var = (symbol*)seq_obj(start_or_for->arg1); - - // check symbol variable is a number, then increase - if (_local_heap.get(string(var->_value), obj, size, type) && (type == cmd_number)) + // arg1 = index of start or for command in program + // farg1 = current count + branch* start_or_for = (branch*)seq_obj(myobj.arg1); + if (! myobj.arg_bool) { - ((number*)obj)->_value = myobj.farg1; + myobj.arg_bool = true; + myobj.farg1 = start_or_for->farg1; + } + + // increment then test + mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEF_RND); + + // for command: increment symbol too + if (start_or_for->arg1 != -1) + { + object* obj; + unsigned int size; + symbol* var = (symbol*)seq_obj(start_or_for->arg1); + + // increase symbol variable + _local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); + } + + // test loop value is out of range + if (myobj.farg1->_value > start_or_for->farg2->_value) + { + // end of loop + myobj.arg_bool = false;// init again next time + _branch_stack.pop_back(); + _branch_stack.pop_back(); + ret = -1; + } + else + { + // for command: next instruction will be after symbol variable + if (start_or_for->arg1 != -1) + ret = start_or_for->arg1 + 1; + // start command: next instruction will be after start command + else + ret = myobj.arg1 + 1; } } - - //test value - if (((step>0) && (myobj.farg1 > start_or_for->farg2)) - || ((step<0) && (myobj.farg1 < start_or_for->farg2))) - { - // end of loop - myobj.arg_bool = false;// init again next time - return -1; - } - else - { - // for command: next instruction will be after symbol variable - if (start_or_for->arg1 != -1) - return start_or_for->arg1 + 1; - // start command: next instruction will be after start command - else - return myobj.arg1 + 1; - } -#endif - - return -1; + + return ret; } diff --git a/src/rpn.cpp b/src/rpn.cpp index 2ce830f..7570745 100644 --- a/src/rpn.cpp +++ b/src/rpn.cpp @@ -75,12 +75,13 @@ typedef enum { ret_nop, ret_syntax, ret_div_by_zero, + ret_runtime_error, ret_max } ret_value; const char* ret_value_string[ret_max] = { "ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", - "deadly", "goodbye", "not implemented", "no operation", "syntax", "division by zero" + "deadly", "goodbye", "not implemented", "no operation", "syntax error", "division by zero", "runtime error" }; typedef enum { @@ -491,10 +492,20 @@ public: // call matching function branch* b = (branch*)seq_obj(i); int next_cmd = (this->*(b->_fn))(*b); - if (next_cmd == -1) - i++; - else - i = next_cmd; + switch (next_cmd) + { + case -1: + i++; // meaning 'next command' + break; + case -(int)ret_runtime_error: + // error: show it + (void)show_error(_err, _err_context); + go_out = true;// end of run + break; + default: + i = next_cmd;// new direction + break; + } } // not a command, but a stack entry, manage it @@ -660,8 +671,8 @@ public: show_syntax_error("missing start or for before next"); return ret_syntax; } - k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index - ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i;// fill 'for' or 'start' arg2 = 'next' index + k->arg1 = vstartindex[vstartindex.size() - 1]; // 'next' arg1 = 'start' index + ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); } else if (compare_branch(k, "step", 4)) @@ -673,6 +684,7 @@ public: return ret_syntax; } k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index + ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index vstartindex.pop_back(); } else if (compare_branch(k, "->", 2)) @@ -696,28 +708,46 @@ public: return ret_ok; } - static ret_value show_error(ret_value err, string& context) + ret_value show_error() { - cerr<