rpn/src/rpn-program.hpp

169 lines
4 KiB
C++
Raw Normal View History

2015-02-24 14:51:39 +01:00
//
2017-05-25 12:36:30 +02:00
bool find_variable(string& variable, object*& obj, unsigned int& size)
{
bool found = false;
program* parent = _parent_prog;
// find variable in local heap, parens heaps, global heap
if (_local_heap.get(variable, obj, size))
found = true;
else
{
while(parent != NULL)
{
if (parent->_local_heap.get(variable, obj, size))
{
found = true;
break;
}
parent = parent->_parent_prog;
}
if (!found)
{
if (_heap->get(variable, obj, size))
found = true;
}
}
return found;
}
2015-02-24 14:51:39 +01:00
void eval(void)
{
bool run_prog = false;
string prog_text;
MIN_ARGUMENTS(1);
2015-05-19 17:51:03 +02:00
if (IS_ARG_TYPE(0, cmd_symbol))
{
// recall a variable
2017-05-02 10:47:03 +02:00
object* obj;
2015-05-19 17:51:03 +02:00
unsigned int size;
2015-02-26 22:33:28 +01:00
string variable(((symbol*)_stack->back())->_value);
2017-05-25 12:36:30 +02:00
// if variable holds a program, run this program
if (find_variable(variable, obj, size))
2015-05-19 17:51:03 +02:00
{
2017-05-25 12:36:30 +02:00
if (obj->_type == cmd_program)
{
prog_text = ((oprogram*)obj)->_value;
(void)_stack->pop_back();
run_prog = true;
}
else
{
2017-05-02 10:47:03 +02:00
// else recall this variable (i.e. stack its content)
(void)_stack->pop_back();
2017-05-02 10:47:03 +02:00
stack::copy_and_push_back(obj, *_stack, size);
}
2015-05-19 17:51:03 +02:00
}
else
ERR_CONTEXT(ret_unknown_variable);
}
else if (IS_ARG_TYPE(0, cmd_program))
{
// eval a program
prog_text = ((oprogram*)_stack->pop_back())->_value;
run_prog = true;
2015-05-19 17:51:03 +02:00
}
else
ERR_CONTEXT(ret_bad_operand_type);
// run prog if any
if (run_prog)
{
2017-05-25 12:36:30 +02:00
program prog(this);
// make program from entry
if (program::parse(prog_text.c_str(), prog) == ret_ok)
{
// run it
2017-05-25 12:36:30 +02:00
prog.run(*_stack, *_heap, &_local_heap);
}
}
2015-02-24 14:51:39 +01:00
}
2015-02-25 15:39:27 +01:00
// carefull, this not a command but a branch
int inprog(branch& myobj)
{
string context("->");// for showing errors
int count_symbols = 0;
bool prog_found = false;
if (myobj.arg1 == -1)
{
ERR_CONTEXT(ret_unknown_err);
return -1;
}
// syntax must be
// -> <auto evaluated symbol #1> ... <auto evaluated symbol #n> <oprogram>
// find next oprogram object
for (unsigned int i = myobj.arg1 + 1; i < size(); i++)
{
// count symbol
if (seq_type(i) == cmd_symbol)
count_symbols++;
// stop if prog
else if (seq_type(i) == cmd_program)
{
prog_found = true;
break;
}
// found something other than symbol
else
{
ERR_CONTEXT(ret_bad_operand_type);
show_error(_err, context);
return -1;
}
}
// found 0 symbols
if (count_symbols == 0)
{
ERR_CONTEXT(ret_syntax);
show_error(_err, context);
return -1;
}
// <oprogram> is missing
if (! prog_found)
{
ERR_CONTEXT(ret_syntax);
show_error(_err, context);
return -1;
}
// check symbols number vs stack size
if (stack_size() < count_symbols)
{
ERR_CONTEXT(ret_missing_operand);
show_error(_err, context);
return -1;
}
// load variables
heap local_heap;
2015-02-25 15:39:27 +01:00
for (unsigned int i = myobj.arg1 + count_symbols; i > myobj.arg1; i--)
{
2017-05-22 18:22:15 +02:00
local_heap.add(string(((symbol*)seq_obj(i))->_value), _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back();
2015-02-25 15:39:27 +01:00
}
// run the program
2015-02-26 22:33:28 +01:00
string entry(((oprogram*)seq_obj(myobj.arg1 + count_symbols + 1))->_value);
2015-02-25 15:39:27 +01:00
program prog;
// make the program from entry
2015-02-26 22:33:28 +01:00
if (program::parse(entry.c_str(), prog) == ret_ok)
2015-02-25 15:39:27 +01:00
{
// run it
2017-05-25 12:36:30 +02:00
prog.run(*_stack, *_heap, &local_heap);
2015-02-25 15:39:27 +01:00
}
// point on next command
return myobj.arg1 + count_symbols + 2;
}