mirror of
https://github.com/louisrubet/rpn
synced 2024-12-30 10:23:32 +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)
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
64
src/rpn.cpp
64
src/rpn.cpp
|
@ -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; }
|
||||||
|
|
Loading…
Reference in a new issue