#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)
{
// 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<<endl;
return -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;
}
// 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;
}

View file

@ -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<<context<<": "<<ret_value_string[err]<<endl;
switch(err)
ret_value ret;
// show last recorded error
cerr<<ret_value_string[_err]<<"("<<_err<<"): "<<_err_context<<endl;
switch(_err)
{
case ret_internal:
case ret_deadly:
return ret_deadly;
ret = ret_deadly;
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);
return show_error(err, context_string);
// record error
_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; }