mirror of
https://github.com/louisrubet/rpn
synced 2024-12-28 09:58:52 +01:00
parent
b0d57dd2b4
commit
3b72e9d714
2 changed files with 116 additions and 125 deletions
177
src/rpn-branch.h
177
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<<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;
|
||||
}
|
||||
|
|
64
src/rpn.cpp
64
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<<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; }
|
||||
|
|
Loading…
Reference in a new issue