mirror of
https://github.com/louisrubet/rpn
synced 2025-01-17 06:12:09 +01:00
166 lines
3.8 KiB
C
166 lines
3.8 KiB
C
|
//
|
||
|
int rpn_if(branch& myobj)
|
||
|
{
|
||
|
// myobj.arg1 = 'if' condition evaluation value
|
||
|
MIN_ARGUMENTS_RET(1, -1);
|
||
|
ARG_IS_OF_TYPE_RET(0, cmd_number, -1);
|
||
|
myobj.arg1 = ((getf() != 0) ? 1 : 0);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int rpn_then(branch& myobj)
|
||
|
{
|
||
|
// myobj.arg1 = index of then + 1
|
||
|
// myobj.arg2 = index of else + 1 or end + 1
|
||
|
// myobj.arg3 = index of if
|
||
|
// if condition is true -> arg1 (= jump to then + 1)
|
||
|
// else -> arg2 (= jump to else + 1 or end + 1)
|
||
|
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||
|
if (if_cmd->arg1 == 1)
|
||
|
return myobj.arg1;
|
||
|
else
|
||
|
return myobj.arg2;
|
||
|
}
|
||
|
|
||
|
int rpn_else(branch& myobj)
|
||
|
{
|
||
|
// myobj.arg1 = index of else + 1
|
||
|
// myobj.arg2 = index of end + 1
|
||
|
// myobj.arg3 = index of if
|
||
|
// if condition was false -> arg1 (= jump to else + 1)
|
||
|
// if condition was true -> arg2 (= jump to end + 1)
|
||
|
branch* if_cmd = (branch*)seq_obj(myobj.arg3);
|
||
|
if (if_cmd->arg1 == 1)
|
||
|
return myobj.arg2;
|
||
|
else
|
||
|
return myobj.arg1;
|
||
|
}
|
||
|
|
||
|
void rpn_end(void)
|
||
|
{
|
||
|
// nothing
|
||
|
}
|
||
|
|
||
|
int rpn_start(branch& myobj)
|
||
|
{
|
||
|
MIN_ARGUMENTS_RET(2, 1);
|
||
|
ARG_IS_OF_TYPE_RET(0, cmd_number, -1);
|
||
|
ARG_IS_OF_TYPE_RET(1, cmd_number, -1);
|
||
|
|
||
|
// farg1 = first value of start command
|
||
|
// farg2 = last value of start command
|
||
|
myobj.farg2 = getf();
|
||
|
myobj.farg1 = getf();
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int rpn_for(branch& myobj)
|
||
|
{
|
||
|
MIN_ARGUMENTS_RET(2, 1);
|
||
|
ARG_IS_OF_TYPE_RET(0, cmd_number, -1);
|
||
|
ARG_IS_OF_TYPE_RET(1, cmd_number, -1);
|
||
|
|
||
|
symbol* sym = ((symbol*)seq_obj(myobj.arg1));
|
||
|
|
||
|
// farg1 = first value of for command
|
||
|
// farg2 = last value of for command
|
||
|
// arg1 = index of symbol to increase
|
||
|
myobj.farg2 = getf();
|
||
|
myobj.farg1 = getf();
|
||
|
|
||
|
// store symbol with first value
|
||
|
_heap->add(sym->_name, &number(myobj.farg1), sizeof(number), cmd_number);
|
||
|
|
||
|
return myobj.arg1 + 1;
|
||
|
}
|
||
|
|
||
|
int rpn_next(branch& myobj)
|
||
|
{
|
||
|
// 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;
|
||
|
}
|
||
|
|
||
|
// increment then test
|
||
|
myobj.farg1++;
|
||
|
|
||
|
// 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 (_heap->get(var->_name, obj, size, type) && (type == cmd_number))
|
||
|
((number*)obj)->_value = myobj.farg1;
|
||
|
}
|
||
|
|
||
|
//test value
|
||
|
if (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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int rpn_step(branch& myobj)
|
||
|
{
|
||
|
// arg1 = index of start or for command in program
|
||
|
// farg1 = current count
|
||
|
floating_t step = getf();
|
||
|
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
|
||
|
myobj.farg1 += step;
|
||
|
|
||
|
// 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 (_heap->get(var->_name, obj, size, type) && (type == cmd_number))
|
||
|
((number*)obj)->_value = myobj.farg1;
|
||
|
}
|
||
|
|
||
|
//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;
|
||
|
}
|
||
|
}
|