#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();
// 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 // store symbol with first value
_local_heap.add(sym->_value, myobj.farg1, myobj.farg1->size()); _local_heap.add(sym->_value, myobj.farg1, myobj.farg1->size());
(void)_stack->pop_back(); (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,7 +160,17 @@ int rpn_next(branch& myobj)
int rpn_step(branch& myobj) int rpn_step(branch& myobj)
{ {
static int count = 0; int ret;
MIN_ARGUMENTS_RET(1, -(int)ret_runtime_error);
ARG_MUST_BE_OF_TYPE_RET(0, cmd_number, -(int)ret_runtime_error);
number* step = (number*)_stack->pop_back();
// end of loop if step is negative or zero
if (mpfr_cmp_d(step->_value.mpfr, 0.0)<=0)
ret = -1;
else
{
// arg1 = index of start or for command in program // arg1 = index of start or for command in program
// farg1 = current count // farg1 = current count
branch* start_or_for = (branch*)seq_obj(myobj.arg1); branch* start_or_for = (branch*)seq_obj(myobj.arg1);
@ -161,12 +181,8 @@ static int count = 0;
} }
// increment then test // 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); mpfr_add(myobj.farg1->_value.mpfr, myobj.farg1->_value.mpfr, step->_value.mpfr, MPFR_DEF_RND);
cout<<"step=";step->show(cout);cout<<endl;
return -1;
// for command: increment symbol too // for command: increment symbol too
if (start_or_for->arg1 != -1) if (start_or_for->arg1 != -1)
{ {
@ -178,80 +194,25 @@ return -1;
_local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size()); _local_heap.replace_value(string(var->_value), myobj.farg1, myobj.farg1->size());
} }
//test value // test loop value is out of range
bool step_positive = mpfr_cmp_d(step->_value.mpfr, 0.0)>0; if (myobj.farg1->_value > start_or_for->farg2->_value)
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 // end of loop
myobj.arg_bool = false;// init again next time myobj.arg_bool = false;// init again next time
_branch_stack.pop_back(); _branch_stack.pop_back();
_branch_stack.pop_back(); _branch_stack.pop_back();
return -1; ret = -1;
} }
else else
{ {
// for command: next instruction will be after symbol variable // for command: next instruction will be after symbol variable
if (start_or_for->arg1 != -1) if (start_or_for->arg1 != -1)
return start_or_for->arg1 + 1; ret = start_or_for->arg1 + 1;
// start command: next instruction will be after start command // start command: next instruction will be after start command
else else
return myobj.arg1 + 1; ret = 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;
} }
} }
//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;
}
} }
static ret_value show_error(ret_value err, char* context) return ret;
{
string context_string(context);
return show_error(err, context_string);
} }
static void show_syntax_error(const char* context) ret_value show_error(ret_value err, string& context)
{ {
cerr<<"syntax error: "<<context<<endl; // record error
_err = err;
_err_context = context;
return show_error();
}
ret_value show_error(ret_value err, const char* context)
{
// 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; }