Add program type and eval command

This commit is contained in:
Louis 2015-02-24 14:51:39 +01:00
parent 9a77fb3f18
commit 00c01524b4
8 changed files with 145 additions and 42 deletions

View file

@ -46,6 +46,41 @@ static bool _cut(const string& entry, vector<string>& entries)
tmp.clear();
break;
//program
case '<':
//push prec entry if exists
if (tmp.size()>0)
{
entries.push_back(tmp);
tmp.clear();
}
if (i<(entry.size()-1) && entry.at(i+1)=='<')
{
//get expression
i+=2;
tmp = "<<";
while(i<entry.size())
{
if (i<(entry.size()-1) && entry.at(i) == '>' && entry.at(i+1) == '>')
{
tmp += ">>";
i+=2;
break;
}
else
tmp+=entry.at(i);
i++;
}
entries.push_back(tmp);
tmp.clear();
}
else
{
// reinject < which is not a program begin
tmp = "<";
}
break;
//other
default:
if (entry.at(i)!=' ' && entry.at(i)!='\t')
@ -68,7 +103,6 @@ static bool _cut(const string& entry, vector<string>& entries)
entries.push_back(tmp);
tmp.clear();
}
return entries.size()>0;
}
@ -123,6 +157,23 @@ static bool get_string(const string& entry, object*& obj)
return ret;
}
static bool get_program(const string& entry, object*& obj)
{
bool ret = false;
int len = entry.size();
if (len>=2 && entry[0]=='<' && entry[1]=='<')
{
int last;
if (len>=4 && entry[len-1]=='>' && entry[len-2]=='>')
last = len-4;
else
last = len-2;
obj = new oprogram(entry.substr(2, last).c_str());
ret = true;
}
return ret;
}
static bool get_float(const string& entry, object*& obj)
{
stringstream token;
@ -240,6 +291,12 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
obj_size = sizeof(ostring);
ret = true;
}
else if (get_program(entry, obj))
{
type = cmd_program;
obj_size = sizeof(oprogram);
ret = true;
}
else if (get_keyword(entry, obj, obj_size, type))
{
ret = true;

View file

@ -20,9 +20,9 @@ void plus()
else if (IS_ARG_TYPE(0, cmd_string))
{
ARG_MUST_BE_OF_TYPE(1, cmd_string);
string& second = *((ostring*)_stack->back())->_name;
string& second = *((ostring*)_stack->back())->_value;
_stack->pop_back();
*((ostring*)_stack->back())->_name += second;
*((ostring*)_stack->back())->_value += second;
}
}

View file

@ -71,7 +71,7 @@ int rpn_for(branch& myobj)
// store symbol with first value
number num(myobj.farg1);
_heap->add(*sym->_name, &num, sizeof(number), cmd_number);
_heap->add(*sym->_value, &num, sizeof(number), cmd_number);
return myobj.arg1 + 1;
}
@ -98,7 +98,7 @@ int rpn_next(branch& myobj)
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))
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
((number*)obj)->_value = myobj.farg1;
}
@ -143,7 +143,7 @@ int rpn_step(branch& myobj)
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))
if (_heap->get(*var->_value, obj, size, type) && (type == cmd_number))
((number*)obj)->_value = myobj.farg1;
}

View file

@ -89,6 +89,10 @@ program::keyword_t program::_keywords[] =
{ cmd_keyword, "purge", &program::purge, "delete a variable. ex: 'name' purge" },
{ cmd_keyword, "vars", &program::vars, "list all variables" },
//PROGRAM
{ cmd_undef, "", NULL, "\nPROGRAM"},
{ cmd_keyword, "eval", &program::eval, "evaluate (run) a program, or recall a variable. ex: 'my_prog' eval" },
//TRIG
{ cmd_undef, "", NULL, "\nTRIG"},
{ cmd_keyword, "pi", &program::pi, "PI constant" },

32
src/rpn-program.h Normal file
View file

@ -0,0 +1,32 @@
//
void eval(void)
{
MIN_ARGUMENTS(1);
if (IS_ARG_TYPE(0, cmd_symbol))
{
// recall a variable
void* obj;
unsigned int size;
int type;
if (_heap->get(getn(), obj, size, type))
_stack->push_back(obj, size, type);
else
ERR_CONTEXT(ret_unknown_variable);
}
else if (IS_ARG_TYPE(0, cmd_program))
{
string& entry = *((oprogram*)_stack->back())->_value;
_stack->pop_back();
program prog;
// make program from string in stack level 1
if (program::parse(entry, prog) == ret_ok)
{
// run it
prog.run(*_stack, *_heap);
}
}
else
ERR_CONTEXT(ret_bad_operand_type);
}

View file

@ -31,7 +31,7 @@ void auto_rcl(symbol* symb)
void* obj;
unsigned int size;
int type;
if (_heap->get(*symb->_name, obj, size, type))
if (_heap->get(*symb->_value, obj, size, type))
_stack->push_back(obj, size, type);
else
_stack->push_back(symb, sizeof(symbol), cmd_symbol);

View file

@ -19,7 +19,7 @@ void strout()
MIN_ARGUMENTS(1);
ARG_MUST_BE_OF_TYPE(0, cmd_string);
string& entry = *((ostring*)_stack->back())->_name;
string& entry = *((ostring*)_stack->back())->_value;
_stack->pop_back();
program prog;

View file

@ -46,7 +46,7 @@ using namespace std;
//TODO faut-il que ces variables soient globales ?
static const char g_cursor[] = "> ";
static const string g_show_stack_separator = ":\t";
static const int g_max_commands = 100;
static const int g_max_commands = 128;
//
static int g_verbose = 0;
@ -82,13 +82,14 @@ typedef enum {
cmd_binary,/* binary (integer) value to put in stack */
cmd_string,/* string value to put in stack */
cmd_symbol,/* symbol value to put in stack */
cmd_program,/* program */
cmd_keyword,/* langage keyword */
cmd_branch,/* langage branch keyword */
cmd_max
} cmd_type_t;
const char* cmd_type_string[cmd_max] = {
"undef", "number", "binary", "symbol", "keyword", "keyword"
"undef", "number", "binary", "symbol", "program", "keyword", "keyword"
};
//
@ -185,46 +186,54 @@ binary::binary_enum binary::s_mode = binary::s_default_mode;
class ostring : public object
{
public:
ostring(string& name, cmd_type_t type = cmd_string) : object(type)
ostring(string& value, cmd_type_t type = cmd_string) : object(type)
{
_name = new string(name);
_value = new string(value);
}
ostring(const char* name, cmd_type_t type = cmd_string) : object(type)
ostring(const char* value, cmd_type_t type = cmd_string) : object(type)
{
_name = new string(name);
_value = new string(value);
}
virtual void show(ostream& stream = cout) { stream << "\"" << *_name << "\""; }
string* _name;
virtual void show(ostream& stream = cout) { stream << "\"" << *_value << "\""; }
string* _value;
};
class oprogram : public ostring
{
public:
oprogram(string& value, cmd_type_t type = cmd_program) : ostring(value, type) { }
oprogram(const char* value, cmd_type_t type = cmd_program) : ostring(value, type) { }
virtual void show(ostream& stream = cout) { stream << "<< " << *_value << " >>"; }
};
class symbol : public object
{
public:
symbol(string& name, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
symbol(string& value, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
{
_name = new string(name);
_value = new string(value);
}
symbol(const char* name, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
symbol(const char* value, cmd_type_t type = cmd_symbol) : object(type), _auto_eval(false)
{
_name = new string(name);
_value = new string(value);
}
virtual void show(ostream& stream = cout) { stream << "'" << *_name << "'"; }
string* _name;
virtual void show(ostream& stream = cout) { stream << "'" << *_value << "'"; }
string* _value;
bool _auto_eval;
};
class keyword : public symbol
{
public:
keyword(program_fn_t fn, string& name, cmd_type_t type = cmd_keyword) : symbol(name, type) { _fn = fn; }
keyword(program_fn_t fn, string& value, cmd_type_t type = cmd_keyword) : symbol(value, type) { _fn = fn; }
program_fn_t _fn;
virtual void show(ostream& stream = cout) { stream << *_name; }
virtual void show(ostream& stream = cout) { stream << *_value; }
};
class branch : public keyword
{
public:
branch(branch_fn_t fn, string& name) : keyword(NULL, name, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
branch(branch_fn_t fn, string& value) : keyword(NULL, value, cmd_branch), arg1(-1), arg2(-1), arg3(-1), arg_bool(false)
{
_type = cmd_branch;
_fn = fn;
@ -281,15 +290,8 @@ public:
cout << endl;
}
// not a command, but a stack entry, manage it
if ((type == cmd_number) || (type == cmd_binary) || (type == cmd_string))
{
stk.push_back(seq_obj(i), seq_len(i), type);
i++;
}
// could be an auto-evaluated symbol
else if (type == cmd_symbol)
if (type == cmd_symbol)
{
auto_rcl((symbol*)seq_obj(i));
i++;
@ -337,6 +339,13 @@ public:
else
i = tmp;
}
// not a command, but a stack entry, manage it
else
{
stk.push_back(seq_obj(i), seq_len(i), type);
i++;
}
}
return ret;
}
@ -357,7 +366,7 @@ public:
if (type == cmd_keyword)
{
keyword* k = (keyword*)seq_obj(i);
if(k->_name->compare("end") == 0)
if(k->_value->compare("end") == 0)
{
int next = i + 1;
if (next >= (int)size())
@ -387,14 +396,14 @@ public:
else if (type == cmd_branch)
{
branch* k = (branch*)seq_obj(i);
if (k->_name->compare("if") == 0)
if (k->_value->compare("if") == 0)
{
if_layout_t layout;
layout.index_if = i;
vlayout.push_back(layout);
layout_index++;
}
else if(k->_name->compare("then") == 0)
else if(k->_value->compare("then") == 0)
{
int next = i + 1;
if (next >= (int)size())
@ -423,7 +432,7 @@ public:
k->arg1 = next;
k->arg3 = vlayout[layout_index].index_if;
}
else if(k->_name->compare("else") == 0)
else if(k->_value->compare("else") == 0)
{
int next = i + 1;
if (next >= (int)size())
@ -459,16 +468,16 @@ public:
k->arg3 = vlayout[layout_index].index_if;
((branch*)seq_obj(vlayout[layout_index].index_then))->arg2 = next;// fill branch2 (if was false) of 'then'
}
else if(k->_name->compare("start") == 0)
else if(k->_value->compare("start") == 0)
{
vstartindex.push_back(i);
}
else if(k->_name->compare("for") == 0)
else if(k->_value->compare("for") == 0)
{
vstartindex.push_back(i);
k->arg1 = i + 1;// arg1 points on symbol variable
}
else if(k->_name->compare("next") == 0)
else if(k->_value->compare("next") == 0)
{
if (vstartindex.size() == 0)
{
@ -479,7 +488,7 @@ public:
k->arg1 = vstartindex[vstartindex.size() - 1];// fill 'next' branch1 = 'start' index
vstartindex.pop_back();
}
else if(k->_name->compare("step") == 0)
else if(k->_value->compare("step") == 0)
{
if (vstartindex.size() == 0)
{
@ -620,7 +629,7 @@ private:
string getn()
{
/* warning, caller must check object type before */
string* a = ((symbol*)_stack->back())->_name;
string* a = ((symbol*)_stack->back())->_value;
_stack->pop_back();
return *a;
}
@ -655,6 +664,7 @@ private:
#include "rpn-string.h"
#include "rpn-branch.h"
#include "rpn-store.h"
#include "rpn-program.h"
#include "rpn-trig.h"
#include "rpn-logs.h"
};