#34, #58, #55: multiple evo (branch and errors refactoring)

This commit is contained in:
Louis Rubet 2017-05-20 22:25:42 +02:00
parent b0d57dd2b4
commit 3b72e9d714
2 changed files with 116 additions and 125 deletions

View file

@ -3,8 +3,8 @@
int rpn_if(branch& myobj) int rpn_if(branch& myobj)
{ {
// myobj.arg1 = 'if' condition evaluation value // myobj.arg1 = 'if' condition evaluation value
MIN_ARGUMENTS_RET(1, -1); MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); 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) if (mpfr_cmp_si(((number*)_stack->get_obj(0))->_value.mpfr, 0UL) != 0)
myobj.arg1 = 1; myobj.arg1 = 1;
@ -51,9 +51,9 @@ int rpn_start(branch& myobj)
{ {
int ret = -1; int ret = -1;
MIN_ARGUMENTS_RET(2, 1); MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -1); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
// farg2 = last value of start command // farg2 = last value of start command
stack::copy_and_push_back(*_stack, _stack->size()-1, _branch_stack); stack::copy_and_push_back(*_stack, _stack->size()-1, _branch_stack);
@ -79,9 +79,9 @@ int rpn_for(branch& myobj)
{ {
int ret; int ret;
MIN_ARGUMENTS_RET(2, 1); MIN_ARGUMENTS_RET(2, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -1); ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -1); ARG_MUST_BE_OF_TYPE_RET(1, cmd_number, -(int)ret_runtime_error);
symbol* sym = ((symbol*)seq_obj(myobj.arg1)); symbol* sym = ((symbol*)seq_obj(myobj.arg1));
@ -96,11 +96,21 @@ int rpn_for(branch& myobj)
myobj.farg1 = (number*)_branch_stack.back(); myobj.farg1 = (number*)_branch_stack.back();
_stack->pop_back(); _stack->pop_back();
// store symbol with first value // test value
_local_heap.add(sym->_value, myobj.farg1, myobj.farg1->size()); if (myobj.farg1->_value > myobj.farg2->_value)
(void)_stack->pop_back(); // 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) int rpn_next(branch& myobj)
@ -150,108 +160,59 @@ int rpn_next(branch& myobj)
int rpn_step(branch& myobj) int rpn_step(branch& myobj)
{ {
static int count = 0; int ret;
// arg1 = index of start or for command in program MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
// farg1 = current count ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
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
number* step = (number*)_stack->pop_back(); 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<<endl; // end of loop if step is negative or zero
return -1; if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0)
ret = -1;
// 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 value
bool step_positive = mpfr_cmp_d(step->_value.mpfr, 0.0)>0;
cout<<"(count="<<count;")\n";
if (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;
}
else else
{ {
// for command: next instruction will be after symbol variable // arg1 = index of start or for command in program
if (start_or_for->arg1 != -1) // farg1 = current count
return start_or_for->arg1 + 1; branch* start_or_for = (branch*)seq_obj(myobj.arg1);
// start command: next instruction will be after start command if (! myobj.arg_bool)
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))
{ {
((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 return ret;
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;
} }

View file

@ -75,12 +75,13 @@ typedef enum {
ret_nop, ret_nop,
ret_syntax, ret_syntax,
ret_div_by_zero, ret_div_by_zero,
ret_runtime_error,
ret_max ret_max
} ret_value; } ret_value;
const char* ret_value_string[ret_max] = { const char* ret_value_string[ret_max] = {
"ok", "unknown command", "missing operand", "bad operand type", "out of range", "unknown variable", "internal error, aborting", "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 { typedef enum {
@ -491,10 +492,20 @@ public:
// call matching function // call matching function
branch* b = (branch*)seq_obj(i); branch* b = (branch*)seq_obj(i);
int next_cmd = (this->*(b->_fn))(*b); int next_cmd = (this->*(b->_fn))(*b);
if (next_cmd == -1) switch (next_cmd)
i++; {
else case -1:
i = next_cmd; 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 // not a command, but a stack entry, manage it
@ -660,8 +671,8 @@ public:
show_syntax_error("missing start or for before next"); show_syntax_error("missing start or for before next");
return ret_syntax; return ret_syntax;
} }
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index k->arg1 = vstartindex[vstartindex.size() - 1]; // 'next' arg1 = 'start' index
((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i;// fill 'for' or 'start' arg2 = 'next' index ((branch*)seq_obj(vstartindex[vstartindex.size() - 1]))->arg2 = i; // 'for' or 'start' arg2 = 'next' index
vstartindex.pop_back(); vstartindex.pop_back();
} }
else if (compare_branch(k, "step", 4)) else if (compare_branch(k, "step", 4))
@ -673,6 +684,7 @@ public:
return ret_syntax; return ret_syntax;
} }
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'step' branch1 = 'start' index 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(); vstartindex.pop_back();
} }
else if (compare_branch(k, "->", 2)) else if (compare_branch(k, "->", 2))
@ -696,28 +708,46 @@ public:
return ret_ok; return ret_ok;
} }
static ret_value show_error(ret_value err, string& context) ret_value show_error()
{ {
cerr<<context<<": "<<ret_value_string[err]<<endl; ret_value ret;
switch(err)
// show last recorded error
cerr<<ret_value_string[_err]<<"("<<_err<<"): "<<_err_context<<endl;
switch(_err)
{ {
case ret_internal: case ret_internal:
case ret_deadly: case ret_deadly:
return ret_deadly; ret = ret_deadly;
default: default:
return ret_ok; ret = ret_ok;
} }
return ret;
} }
static ret_value show_error(ret_value err, char* context) ret_value show_error(ret_value err, string& context)
{ {
string context_string(context); // record error
return show_error(err, context_string); _err = err;
_err_context = context;
return show_error();
} }
static void show_syntax_error(const char* context) ret_value show_error(ret_value err, const char* context)
{ {
cerr<<"syntax error: "<<context<<endl; // record error
_err = err;
_err_context = context;
return show_error();
}
void show_syntax_error(const char* context)
{
// record error
_err = ret_syntax;
_err_context = context;
(void)show_error();
} }
ret_value get_err(void) { return _err; } ret_value get_err(void) { return _err; }