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(); tmp.clear();
break; 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 //other
default: default:
if (entry.at(i)!=' ' && entry.at(i)!='\t') 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); entries.push_back(tmp);
tmp.clear(); tmp.clear();
} }
return entries.size()>0; return entries.size()>0;
} }
@ -123,6 +157,23 @@ static bool get_string(const string& entry, object*& obj)
return ret; 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) static bool get_float(const string& entry, object*& obj)
{ {
stringstream token; stringstream token;
@ -240,6 +291,12 @@ static bool _obj_from_string(const string& entry, object*& obj, unsigned int& ob
obj_size = sizeof(ostring); obj_size = sizeof(ostring);
ret = true; 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)) else if (get_keyword(entry, obj, obj_size, type))
{ {
ret = true; ret = true;

View file

@ -20,9 +20,9 @@ void plus()
else if (IS_ARG_TYPE(0, cmd_string)) else if (IS_ARG_TYPE(0, cmd_string))
{ {
ARG_MUST_BE_OF_TYPE(1, 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(); _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 // store symbol with first value
number num(myobj.farg1); 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; return myobj.arg1 + 1;
} }
@ -98,7 +98,7 @@ int rpn_next(branch& myobj)
int type; int type;
symbol* var = (symbol*)seq_obj(start_or_for->arg1); symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// check symbol variable is a number, then increase // 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; ((number*)obj)->_value = myobj.farg1;
} }
@ -143,7 +143,7 @@ int rpn_step(branch& myobj)
int type; int type;
symbol* var = (symbol*)seq_obj(start_or_for->arg1); symbol* var = (symbol*)seq_obj(start_or_for->arg1);
// check symbol variable is a number, then increase // 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; ((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, "purge", &program::purge, "delete a variable. ex: 'name' purge" },
{ cmd_keyword, "vars", &program::vars, "list all variables" }, { 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 //TRIG
{ cmd_undef, "", NULL, "\nTRIG"}, { cmd_undef, "", NULL, "\nTRIG"},
{ cmd_keyword, "pi", &program::pi, "PI constant" }, { 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; void* obj;
unsigned int size; unsigned int size;
int type; int type;
if (_heap->get(*symb->_name, obj, size, type)) if (_heap->get(*symb->_value, obj, size, type))
_stack->push_back(obj, size, type); _stack->push_back(obj, size, type);
else else
_stack->push_back(symb, sizeof(symbol), cmd_symbol); _stack->push_back(symb, sizeof(symbol), cmd_symbol);

View file

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

View file

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