#5: stack refactoring

This commit is contained in:
Louis Rubet 2017-05-02 10:47:03 +02:00
parent 6fe768006a
commit e63e6f98aa
8 changed files with 119 additions and 223 deletions

View file

@ -24,10 +24,8 @@ void rtob()
ARG_MUST_BE_OF_TYPE(0, cmd_number); ARG_MUST_BE_OF_TYPE(0, cmd_number);
number* left = (number*)_stack->pop_back(); number* left = (number*)_stack->pop_back();
binary* bin = (binary*)_stack->allocate_back(sizeof(binary), cmd_binary);
binary bin; bin->set(mpfr_get_sj(left->_value.mpfr, s_mpfr_rnd));
bin.set(mpfr_get_sj(left->_value.mpfr, s_mpfr_rnd));
_stack->push_back(&bin, bin.size(), cmd_binary);
} }
void btor() void btor()
@ -36,9 +34,6 @@ void btor()
ARG_MUST_BE_OF_TYPE(0, cmd_binary); ARG_MUST_BE_OF_TYPE(0, cmd_binary);
integer_t bin = getb(); integer_t bin = getb();
number* left = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
void* significand;
number* left = (number*)_stack->allocate_back(sizeof(number), cmd_number, MPFR_128BITS_STORING_LENGTH, &significand);
left->init(significand);
left->set(bin); left->set(bin);
} }

View file

@ -56,13 +56,13 @@ int rpn_start(branch& myobj)
// farg1 = first value of start command // farg1 = first value of start command
// farg2 = last value of start command // farg2 = last value of start command
stack::copy_and_push_back(*_stack, 0, _branch_stack); stack::copy_and_push_back(*_stack, 0, _branch_stack);
myobj.farg2 = (number*)_branch_stack.get_obj(0); //myobj.farg2 = (number*)_branch_stack.get_obj(0);
myobj.farg2->init(_branch_stack.get_blob(0)); //myobj.farg2->init(_branch_stack.get_blob(0));
_stack->pop_back(); _stack->pop_back();
stack::copy_and_push_back(*_stack, 0, _branch_stack); stack::copy_and_push_back(*_stack, 0, _branch_stack);
myobj.farg1 = (number*)_branch_stack.get_obj(0); //myobj.farg1 = (number*)_branch_stack.get_obj(0);
myobj.farg1->init(_branch_stack.get_blob(0)); //myobj.farg1->init(_branch_stack.get_blob(0));
_stack->pop_back(); _stack->pop_back();
return -1; return -1;
} }
@ -79,17 +79,16 @@ int rpn_for(branch& myobj)
// farg2 = last value of for command // farg2 = last value of for command
// arg1 = index of symbol to increase // arg1 = index of symbol to increase
stack::copy_and_push_back(*_stack, 0, _branch_stack); stack::copy_and_push_back(*_stack, 0, _branch_stack);
myobj.farg2 = (number*)_branch_stack.back(); //myobj.farg2 = (number*)_branch_stack.back();
myobj.farg2->init(_branch_stack.back_blob()); //myobj.farg2->init(_branch_stack.back_blob());
stack::copy_and_push_back(*_stack, 0, _branch_stack); stack::copy_and_push_back(*_stack, 0, _branch_stack);
myobj.farg1 = (number*)_branch_stack.back(); //myobj.farg1 = (number*)_branch_stack.back();
myobj.farg1->init(_branch_stack.back_blob()); //myobj.farg1->init(_branch_stack.back_blob());
// store symbol with first value // store symbol with first value
//TODO //TODO
//number* num = (number*)_local_heap.add(string(sym->_value), NULL, sizeof(number), cmd_number); //number* num = (number*)_local_heap.add(string(sym->_value), NULL, number::calc_size(), cmd_number);
//num->set(myobj.farg1); //num->set(myobj.farg1);
//num->ensure_significand();
return myobj.arg1 + 1; return myobj.arg1 + 1;
} }
@ -174,7 +173,6 @@ int rpn_step(branch& myobj)
if (_local_heap.get(string(var->_value), obj, size, type) && (type == cmd_number)) if (_local_heap.get(string(var->_value), obj, size, type) && (type == cmd_number))
{ {
((number*)obj)->_value = myobj.farg1; ((number*)obj)->_value = myobj.farg1;
((number*)obj)->ensure_significand();
} }
} }

View file

@ -128,55 +128,25 @@ void sci()
void rpn_version() void rpn_version()
{ {
int naked_entry_len; // allocate and set object
int obj_len; unsigned int naked_entry_len = strlen(version);
ostring* str; ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
// entry length without prefix / postfix
naked_entry_len = (int)strlen(version);
// total object length
obj_len = sizeof(ostring)+naked_entry_len+1;
// allocate object
str = (ostring*)malloc(obj_len);
// set it
str->set(version, naked_entry_len); str->set(version, naked_entry_len);
// push in stack
_stack->push_back(str, str->size(), cmd_string);
free(str);
} }
void rpn_uname() void rpn_uname()
{ {
int naked_entry_len; // allocate and set object
int obj_len; unsigned int naked_entry_len = strlen(uname);
ostring* str; ostring* str = (ostring*)_stack->allocate_back(sizeof(ostring)+naked_entry_len+1, cmd_string);
// entry length without prefix / postfix
naked_entry_len = (int)strlen(uname);
// total object length
obj_len = sizeof(ostring)+naked_entry_len+1;
// allocate object
str = (ostring*)malloc(obj_len);
// set it
str->set(uname, naked_entry_len); str->set(uname, naked_entry_len);
// push in stack
_stack->push_back(str, str->size(), cmd_string);
free(str);
} }
void type() void type()
{ {
MIN_ARGUMENTS(1); MIN_ARGUMENTS(1);
int type = _stack->seq_type(_stack->size()-1); int type = _stack->pop_back()->_type;
if (type < 0 || type >= (int)cmd_max) if (type < 0 || type >= (int)cmd_max)
type = (int)cmd_undef; type = (int)cmd_undef;

View file

@ -8,15 +8,15 @@ void eval(void)
if (IS_ARG_TYPE(0, cmd_symbol)) if (IS_ARG_TYPE(0, cmd_symbol))
{ {
// recall a variable // recall a variable
void* obj; object* obj;
unsigned int size; unsigned int size;
int type; int type;
string variable(((symbol*)_stack->back())->_value); string variable(((symbol*)_stack->back())->_value);
// mind the order of heaps // mind the order of heaps
if (_local_heap.get(variable, obj, size, type) if (_local_heap.get(variable, obj, size)
|| ((_parent_local_heap != NULL) && _parent_local_heap->get(variable, obj, size, type)) || ((_parent_local_heap != NULL) && _parent_local_heap->get(variable, obj, size))
|| _global_heap->get(variable, obj, size, type)) || _global_heap->get(variable, obj, size))
{ {
// if variable holds a program, run this program // if variable holds a program, run this program
if (type == cmd_program) if (type == cmd_program)
@ -27,9 +27,10 @@ void eval(void)
} }
else else
{ {
// else recall variable (i.e. stack its content) // else recall this variable (i.e. stack its content)
(void)_stack->pop_back(); (void)_stack->pop_back();
_stack->push_back(obj, size, type); object* new_obj = _stack->allocate_back(size, obj->_type);
stack::copy_and_push_back(obj, *_stack, size);
} }
} }
else else

View file

@ -82,8 +82,6 @@ void rot(void)
void depth(void) void depth(void)
{ {
unsigned long depth = (unsigned long)_stack->size(); unsigned long depth = (unsigned long)_stack->size();
void* significand; number* num = (number*)_stack->allocate_back(number::calc_size(), cmd_number);
number* num = (number*)_stack->allocate_back(sizeof(number), cmd_number, MPFR_128BITS_STORING_LENGTH, &significand);
num->init(significand);
num->set(depth); num->set(depth);
} }

View file

@ -5,7 +5,7 @@ void sto(void)
ARG_MUST_BE_OF_TYPE(0, cmd_symbol); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
string name(((symbol*)_stack->pop_back())->_value); string name(((symbol*)_stack->pop_back())->_value);
_global_heap->add(name, _stack->get_obj(0), _stack->get_len(0), _stack->get_type(0)); _global_heap->add(name, _stack->get_obj(0), _stack->get_len(0));
(void)_stack->pop_back(); (void)_stack->pop_back();
} }
@ -15,18 +15,19 @@ void rcl(void)
ARG_MUST_BE_OF_TYPE(0, cmd_symbol); ARG_MUST_BE_OF_TYPE(0, cmd_symbol);
// recall a variable // recall a variable
void* obj; object* obj;
unsigned int size; unsigned int size;
int type; int type;
string variable(((symbol*)_stack->back())->_value); string variable(((symbol*)_stack->back())->_value);
// mind the order of heaps // mind the order of heaps
if (_local_heap.get(variable, obj, size, type) if (_local_heap.get(variable, obj, size)
|| ((_parent_local_heap != NULL) && (_parent_local_heap->get(variable, obj, size, type))) || ((_parent_local_heap != NULL) && (_parent_local_heap->get(variable, obj, size)))
|| _global_heap->get(variable, obj, size, type)) || _global_heap->get(variable, obj, size))
{ {
(void)_stack->pop_back(); (void)_stack->pop_back();
_stack->push_back(obj, size, type); object* new_obj = _stack->allocate_back(size, obj->_type);
stack::copy_and_push_back(obj, *_stack, size);
} }
else else
ERR_CONTEXT(ret_unknown_variable); ERR_CONTEXT(ret_unknown_variable);
@ -68,29 +69,31 @@ void edit(void)
// carefull : this is not a langage command // carefull : this is not a langage command
void auto_rcl(symbol* symb) void auto_rcl(symbol* symb)
{ {
if (symb->_auto_eval) if (!symb->_auto_eval)
{ {
void* obj; object* obj;
unsigned int size; unsigned int size;
int type; int type;
string variable(symb->_value); string variable(symb->_value);
// mind the order of heaps // mind the order of heaps
if (_local_heap.get(variable, obj, size, type) if (_local_heap.get(variable, obj, size)
|| ((_parent_local_heap != NULL) && (_parent_local_heap->get(variable, obj, size, type))) || ((_parent_local_heap != NULL) && (_parent_local_heap->get(variable, obj, size)))
|| _global_heap->get(variable, obj, size, type)) || _global_heap->get(variable, obj, size))
{ {
_stack->push_back(obj, size, type); stack::copy_and_push_back(obj, *_stack, size);
if (type == cmd_program) if (type == cmd_program)
eval(); eval();
else if (type == cmd_number)
((number*)_stack->back())->ensure_significand();
} }
else else
_stack->push_back(symb, symb->size(), cmd_symbol); {
stack::copy_and_push_back(symb, *_stack, symb->size());
}
} }
else else
_stack->push_back(symb, symb->size(), cmd_symbol); {
stack::copy_and_push_back(symb, *_stack, symb->size());
}
} }
void purge(void) void purge(void)
@ -125,8 +128,8 @@ void vars(void)
for (int i=0; i<(int)_global_heap->size(); i++) for (int i=0; i<(int)_global_heap->size(); i++)
{ {
(void)_global_heap->get_by_index(i, name, (void*&)obj, size, type); (void)_global_heap->get_by_index(i, name, obj, size);
cout<<"var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[type]<<", value "; cout<<"var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[obj->_type]<<", value ";
obj->show(); obj->show();
cout<<endl; cout<<endl;
} }
@ -134,16 +137,16 @@ void vars(void)
{ {
for (int i=0; i<(int)_parent_local_heap->size(); i++) for (int i=0; i<(int)_parent_local_heap->size(); i++)
{ {
(void)_parent_local_heap->get_by_index(i, name, (void*&)obj, size, type); (void)_parent_local_heap->get_by_index(i, name, obj, size);
cout<<"local var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[type]<<", value "; cout<<"local var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[obj->_type]<<", value ";
obj->show(); obj->show();
cout<<endl; cout<<endl;
} }
} }
for (int i=0; i<(int)_local_heap.size(); i++) for (int i=0; i<(int)_local_heap.size(); i++)
{ {
(void)_local_heap.get_by_index(i, name, (void*&)obj, size, type); (void)_local_heap.get_by_index(i, name, obj, size);
cout<<"local var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[type]<<", value "; cout<<"local var "<<i+1<<": name '"<<name<<"', type "<<cmd_type_string[obj->_type]<<", value ";
obj->show(); obj->show();
cout<<endl; cout<<endl;
} }

View file

@ -10,11 +10,11 @@ void instr()
((object*)_stack->pop_back())->show(out); ((object*)_stack->pop_back())->show(out);
// reserve the correct size in stack // reserve the correct size in stack
_stack->push_back(NULL, out.str().size(), cmd_string, true); unsigned int str_size = (unsigned int)out.str().size();
ostring* str = (ostring*)_stack->allocate_back(str_size+1+sizeof(ostring), cmd_string);
// fill the obj // fill the obj
ostring* str = (ostring*)_stack->get_obj(0); str->set(out.str().c_str(), str_size);
str->set(out.str().c_str(), out.str().size());
} }
} }

View file

@ -8,11 +8,8 @@
#include <map> #include <map>
using namespace std; using namespace std;
#include "debug.h"
// allocation base size // allocation base size
#define ALLOC_STACK_CHUNK (64*1024) #define ALLOC_STACK_CHUNK (64*1024)
#define ALLOC_BLOB_CHUNK (64*1024)
// //
class stack class stack
@ -21,9 +18,7 @@ public:
stack() stack()
{ {
_base = NULL; _base = NULL;
_blob = NULL;
_total_size = 0; _total_size = 0;
_total_blob_size = 0;
erase(); erase();
} }
@ -31,51 +26,43 @@ public:
{ {
if (_base != NULL) if (_base != NULL)
free(_base); free(_base);
if (_blob != NULL)
free(_blob);
} }
void erase() void erase()
{ {
_current = _base; _current = _base;
_current_blob = _blob;
_vpointer.clear(); _vpointer.clear();
_vpointer_blob.clear();
_vlen.clear(); _vlen.clear();
_vlen_blob.clear();
_vtype.clear();
_count = 0; _count = 0;
} }
void push_back(void* obj, unsigned int size, int type = 0, bool dont_copy = false, void* blob = NULL, unsigned int blob_size = 0)
{
void* allocated_blob;
void* allocated = allocate_back(size, type, blob_size, &allocated_blob);
if (!dont_copy)
{
if (size > 0)
memcpy(allocated, obj, size);
if (blob != NULL && blob_size > 0)
memcpy(allocated_blob, blob, blob_size);
}
}
// //
static void copy_and_push_back(stack& from, unsigned int index_from, stack& to) static void copy_and_push_back(stack& from, unsigned int index_from, stack& to)
{ {
// copy a whole stack entry (with blob) and push it back to another stack // copy a whole stack entry and push it back to another stack
void* allocated_blob; object* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from));
void* allocated = to.allocate_back(from.seq_len(index_from), from.seq_type(index_from), from.seq_blob_size(index_from), &allocated_blob);
memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from)); memcpy(allocated, from.seq_obj(index_from), from.seq_len(index_from));
memcpy(allocated_blob, from.seq_blob(index_from), from.seq_blob_size(index_from));
if (allocated->_type == cmd_number)
((number*)allocated)->_value.set_significand(((number*)allocated)+1);
} }
void* allocate_back(unsigned int size, int type, unsigned int blob_size = 0, void** blob = NULL) //
static void copy_and_push_back(object* from, stack& to, unsigned int size)
{ {
void* allocated; // copy a whole stack entry and push it back to another stack
object* allocated = to.allocate_back(size, from->_type);
memcpy(allocated, from, size);
if (allocated->_type == cmd_number)
((number*)allocated)->_value.set_significand(((number*)allocated)+1);
}
object* allocate_back(unsigned int size, cmd_type_t type)
{
object* allocated;
// manage memory allocation
if (_current + size > _base + _total_size) if (_current + size > _base + _total_size)
{ {
unsigned long offset = _current - _base; unsigned long offset = _current - _base;
@ -84,49 +71,35 @@ public:
_current = _base + offset; _current = _base + offset;
} }
if (_current_blob + blob_size > _blob + _total_blob_size) // manage stack itself
{
unsigned long offset = _current_blob - _blob;
_total_blob_size += ALLOC_BLOB_CHUNK;
_blob = (char*)realloc(_blob, _total_blob_size);
_current_blob = _blob + offset;
}
_vlen.push_back(size); _vlen.push_back(size);
_vpointer.push_back(_current); _vpointer.push_back((object*)_current);
allocated = _current; allocated = (object*)_current;
_current += size; _current += size;
_vlen_blob.push_back(blob_size);
_vpointer_blob.push_back(_current_blob);
if (blob != NULL)
*blob = _current_blob;
_current_blob += blob_size;
_vtype.push_back(type);
_count++; _count++;
// init object
allocated->_type = type;
allocated->_size = size;
if (type == cmd_number)
((number*)allocated)->_value.init(((number*)allocated)+1);
return allocated; return allocated;
} }
void* pop_back() object* pop_back()
{ {
void* back = NULL; object* back = NULL;
if (_count > 0) if (_count > 0)
{ {
_current = _vpointer[_count - 1]; _current = (char*)_vpointer[_count - 1];
_vlen.pop_back(); _vlen.pop_back();
_vpointer.pop_back(); _vpointer.pop_back();
_current_blob = _vpointer_blob[_count - 1];
_vlen_blob.pop_back();
_vpointer_blob.pop_back();
_vtype.pop_back();
_count--; _count--;
back = _current; back = (object*)_current;
} }
return back; return back;
@ -138,7 +111,7 @@ public:
} }
// stack access (index is counted from back) // stack access (index is counted from back)
void* get_obj(unsigned int index) object* get_obj(unsigned int index)
{ {
if (index<_count) if (index<_count)
return _vpointer[_count-index-1]; return _vpointer[_count-index-1];
@ -146,20 +119,12 @@ public:
return NULL; return NULL;
} }
void* get_blob(unsigned int index) object* operator[](unsigned int index)
{
if (index<_count)
return _vpointer_blob[_count-index-1];
else
return NULL;
}
void* operator[](unsigned int index)
{ {
return get_obj(index); return get_obj(index);
} }
void* back() object* back()
{ {
if (_count>0) if (_count>0)
return _vpointer[_count-1]; return _vpointer[_count-1];
@ -167,14 +132,6 @@ public:
return NULL; return NULL;
} }
void* back_blob()
{
if (_count>0)
return _vpointer_blob[_count-1];
else
return NULL;
}
unsigned int get_len(unsigned int index) unsigned int get_len(unsigned int index)
{ {
if (index<_count) if (index<_count)
@ -183,16 +140,16 @@ public:
return 0; return 0;
} }
int get_type(unsigned int index) cmd_type_t get_type(unsigned int index)
{ {
if (index<_count) if (index<_count)
return _vtype[_count-index-1]; return _vpointer[_count-index-1]->_type;
else else
return 0; return cmd_undef;
} }
// sequential access (index is counted from front) // sequential access (index is counted from front)
void* seq_obj(unsigned int index) object* seq_obj(unsigned int index)
{ {
if (index<_count) if (index<_count)
return _vpointer[index]; return _vpointer[index];
@ -208,44 +165,22 @@ public:
return 0; return 0;
} }
void* seq_blob(unsigned int index) cmd_type_t seq_type(unsigned int index)
{ {
if (index<_count) if (index<_count)
return _vpointer_blob[index]; return _vpointer[index]->_type;
else else
return NULL; return cmd_undef;
}
unsigned int seq_blob_size(unsigned int index)
{
if (index<_count)
return _vlen_blob[index];
else
return 0;
}
int seq_type(unsigned int index)
{
if (index<_count)
return _vtype[index];
else
return 0;
} }
private: private:
char* _base; char* _base;
char* _blob;
char* _current; char* _current;
char* _current_blob;
vector<char*> _vpointer;//pointer on each entry vector<object*> _vpointer;//pointer on each entry
vector<char*> _vpointer_blob;//pointer on each entry blob
vector<unsigned int> _vlen;// size of each entry in bytes vector<unsigned int> _vlen;// size of each entry in bytes
vector<unsigned int> _vlen_blob;// size of each blob entry in bytes unsigned int _count;// =_vlen.size()=_vpointer.size()
vector<int> _vtype;//type of each entry
unsigned int _count;// =_vlen.size()=_vpointer.size()=_vtype.size()
unsigned int _total_size;//total allocated size in bytes unsigned int _total_size;//total allocated size in bytes
unsigned int _total_blob_size;//total allocated blob size in bytes
}; };
// //
@ -255,8 +190,7 @@ private:
struct local_var struct local_var
{ {
unsigned int length; unsigned int length;
int type; object obj[0];
int blob;
}; };
public: public:
@ -267,40 +201,38 @@ public:
free(i->second); free(i->second);
} }
void* add(const string name, void* obj, unsigned int size, int type = 0) object* add(const string name, void* obj, unsigned int size, int type = 0)
{ {
struct local_var* blob = _map[name]; struct local_var* local = _map[name];
if (blob == NULL) if (local == NULL)
{ {
//TODO gerer les pbs de memoire //TODO gerer les pbs de memoire
blob = (struct local_var*)malloc(size + sizeof(local_var)); local = (struct local_var*)malloc(size + sizeof(local_var));
_map[name] = blob; _map[name] = local;
} }
else if (size != blob->length) else if (size != local->length)
{ {
//TODO gerer les pbs de memoire //TODO gerer les pbs de memoire
blob = (struct local_var*)realloc(blob, size + sizeof(local_var)); local = (struct local_var*)realloc(local, size + sizeof(local_var));
_map[name] = blob; _map[name] = local;
} }
blob->length = size; local->length = size;
blob->type= type;
if (obj != NULL) if (obj != NULL)
memcpy(&blob->blob, obj, size); memcpy(local->obj, obj, size);
return (void*)&blob->blob; return (object*)local->obj;
} }
bool get(const string name, void*& obj, unsigned int& size, int& type) bool get(const string name, object*& obj, unsigned int& size)
{ {
map<string, struct local_var*>::iterator i = _map.find(name); map<string, struct local_var*>::iterator i = _map.find(name);
if (i != _map.end()) if (i != _map.end())
{ {
if (i->second != NULL) if (i->second != NULL)
{ {
obj = &i->second->blob; obj = i->second->obj;
size = i->second->length; size = i->second->length;
type = i->second->type;
} }
return true; return true;
} }
@ -313,24 +245,23 @@ public:
return (_map.find(name) != _map.end()); return (_map.find(name) != _map.end());
} }
bool get_by_index(int num, string& name, void*& obj, unsigned int& size, int& type) bool get_by_index(int num, string& name, object*& obj, unsigned int& size)
{ {
if (num>=0 && num<(int)_map.size()) if (num>=0 && num<(int)_map.size())
{ {
struct local_var* blob; struct local_var* local;
map<string, struct local_var*>::iterator i=_map.begin(); map<string, struct local_var*>::iterator i=_map.begin();
//TODO moche moche moche //TODO moche moche moche
for(int j=0;j<num;j++) for(int j=0;j<num;j++)
i++; i++;
blob = (struct local_var*)i->second; local = (struct local_var*)i->second;
assert(blob != NULL); assert(local != NULL);
name = i->first; name = i->first;
obj = &blob->blob; obj = local->obj;
size = blob->length; size = local->length;
type = blob->type;
return true; return true;
} }
else else