Skip to content

Commit

Permalink
SemiCompiled code is changed to a linear serie of minimal structs in …
Browse files Browse the repository at this point in the history
…memory, to be written as minimally as possible in the save file.

A serie of tricks will be used, noticeably to limit the size of some entries that do not deserve to be int32 or int64 (ex: line number, can it be larger than a ushort = 65535 !)
  • Loading branch information
GillesDuvert committed Dec 13, 2023
1 parent 7742324 commit c7472b0
Show file tree
Hide file tree
Showing 3 changed files with 411 additions and 350 deletions.
125 changes: 124 additions & 1 deletion src/dpro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,116 @@
#endif

CodeListT codeList;
SCCodeListT sccList;

using namespace std;

bool is_nonleaf(RefDNode node) {
bool rslt = (node->getFirstChild() != NULL);
return rslt;
}
void process_top(RefDNode top, SCCStructV &nodes, SCCodeAddresses &addrList);

//write a "Node" : current memory address (serves as identifier), type, text, cdata, down( aka GetFirstChild) , right (aka getNextSibling)

void convertNodeToStruct(RefDNode node, SCCStructV &nodes, SCCodeAddresses &addrList) {
sccstruct savenode;
SCCodeAddressesIterator it;
// address is not that simple to retrieve. The address is what ' std::cout<<this " prints, and it is NOT easy to get it right. 'This is the way'.
DNode* ast=node.get();
if (ast->GetVar() != NULL) std::cerr<<"Var = "<<ast->GetVar()<<std::endl; //TBD: check if var is used.
RefDNode dNode = static_cast<RefDNode> (node);
//write node index
it = addrList.find(ast);
if (it != addrList.end()) savenode.node = (*it).second; else savenode.node =0;
RefDNode right = dNode->GetNextSibling();
ast = right.get();
it = addrList.find(ast);
if (it != addrList.end()) savenode.right = (*it).second; else savenode.right =0;
RefDNode down = dNode->GetFirstChild();
ast = down.get();
it = addrList.find(ast);
if (it != addrList.end()) savenode.down = (*it).second; else savenode.down =0;
savenode.nodeType=dNode->getType();
savenode.ligne = dNode->getLine();
savenode.flags=dNode->GetCompileOpt();
// trick to avoid saving a Text and a CData containing the same text, either as a string or a value converted to the good BaseGDL type.
// if dNode->CData() is non-nil, set savenode.Text to ""
savenode.var=dNode->CData();
if (savenode.var == NULL) savenode.Text = dNode->getText(); else savenode.Text = "";
nodes.push_back(savenode);
}

void process_leaves(RefDNode top, SCCStructV &nodes, SCCodeAddresses &addrList) {
RefDNode t;

for (t = ((top && is_nonleaf(top)) ? top->getFirstChild() : (RefDNode) NULL); t; t = t->getNextSibling()) {
if (is_nonleaf(t))
process_top(t,nodes,addrList);
else
convertNodeToStruct(t,nodes,addrList);
}
}

void process_top(RefDNode top, SCCStructV &nodes, SCCodeAddresses &addrList) {
RefDNode t;
bool first = true;

convertNodeToStruct(top,nodes,addrList);

if (is_nonleaf(top)) {
for (t = ((top && is_nonleaf(top)) ? top->getFirstChild() : (RefDNode) NULL); t; t = t->getNextSibling()) {
if (is_nonleaf(t))
first = false;
}
process_leaves(top,nodes,addrList);
}
}

void process_tree(RefDNode top, SCCStructV &nodes, SCCodeAddresses &addrList) {
RefDNode t;
for (t = top; t != NULL; t = t->getNextSibling()) {
process_top(t,nodes,addrList);
}
}

//walks and associate an integer index with node address.
void index_top(RefDNode top, SCCodeAddresses &addrList, int &i);
void indexNodeAddress(RefDNode node, SCCodeAddresses &addrList, int &i) {
// associate node address to an increasing number starting at 1
DNode* ast = node.get();
addrList.insert(std::pair<DNode*,int>(ast, ++i)); //+1 as address 0 is special for all nodes
}

void index_leaves(RefDNode top, SCCodeAddresses &addrList, int &i) {
RefDNode t;
for (t = ((top && is_nonleaf(top)) ? top->getFirstChild() : (RefDNode) NULL); t; t = t->getNextSibling()) {
if (is_nonleaf(t))
index_top(t,addrList, i);
else
indexNodeAddress(t,addrList, i);
}
}

void index_top(RefDNode top, SCCodeAddresses &addrList, int &i) {
RefDNode t;
bool first = true;
indexNodeAddress(top,addrList, i);
if (is_nonleaf(top)) {
for (t = ((top && is_nonleaf(top)) ? top->getFirstChild() : (RefDNode) NULL); t; t = t->getNextSibling()) {
if (is_nonleaf(t))
first = false;
}
index_leaves(top,addrList, i);
}
}

void index_tree(RefDNode top, SCCodeAddresses &addrList, int &i) {
RefDNode t;
for (t = top; t != NULL; t = t->getNextSibling()) {
index_top(t, addrList, i);
}
}
// vtable
DSub::~DSub() {}

Expand Down Expand Up @@ -416,7 +523,23 @@ void DSubUD::SetTree( RefDNode n)
#endif

}

//converts a SemiCompiledCode (chained list of DNodes) to a 'flat' vector of sccstruct and insert the vector in the map pointed by "sccList"

void DSubUD::SetAstTree(RefDNode n) {
//first, walk RefDnode tree to associate right,down, and self addresses with a number in the list:
SCCodeAddresses addrList;
int i=0;
index_tree(n, addrList, i);
SCCStructV sccv;
process_tree(n, sccv, addrList);
//PRO or FUNCTION top node may contain a 'wrong' right pointer in the first node, due to the way the whole .pro file is compiled at once.
//Remove it:
sccv[0].right=0;
sccList.insert(std::pair<DSubUD*,SCCStructV >(this, sccv));

//to be removed
codeList.insert(std::pair<DSubUD*, RefDNode>(this, n));
}
bool DSubUD::GetCommonVarName(const BaseGDL* p, std::string& varName)
{
CommonBaseListT::iterator it;
Expand Down
31 changes: 28 additions & 3 deletions src/dpro.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,26 @@
extern bool posixpaths;
}
#endif
typedef struct _SCC_STRUCT_ { //semicompiled code, small memory imprint (instead of a copy of the DNodes)
uint nodeType = 0;
uint ligne = 0;
uint flags = 0;
uint node = 0;
uint right = 0L;
uint down = 0;
BaseGDL* var = NULL;
std::string Text;
} sccstruct;

class DSubUD;
typedef std::vector<sccstruct> SCCStructV;
typedef std::map<DSubUD*, SCCStructV> SCCodeListT;
typedef std::map<DSubUD*, SCCStructV>::iterator SCCodeListIterator;
extern SCCodeListT sccList;

typedef std::map<DNode*,int> SCCodeAddresses;
typedef std::map<DNode*,int>::iterator SCCodeAddressesIterator;

typedef std::map<DSubUD*, RefDNode> CodeListT;
typedef std::map<DSubUD*, RefDNode>::iterator CodeListIterator;
extern CodeListT codeList;
Expand Down Expand Up @@ -354,9 +372,9 @@ class DSubUD: public DSub
void Reset();
void DelTree();
void SetTree( ProgNodeP t) { tree = t;}
void SetAstTree( RefDNode n) {
codeList.insert(std::pair<DSubUD*, RefDNode>(this, n));
}

//converts a SemiCompiledCode (chained list of DNodes) to a 'flat' vector of sccstruct and insert the vector in the map pointed by "sccList"
void SetAstTree( RefDNode n);

void AddCommon(DCommonBase* c) { common.push_back(c);}
void DeleteLastAddedCommon(bool kill=true)
Expand Down Expand Up @@ -557,6 +575,13 @@ void ReName( SizeT ix, const std::string& s)
if (i!=codeList.end()) return (*i).second;
return NULL;
}
SCCStructV* GetSCC()
{
//find Semicompiled code saved in codeList
SCCodeListIterator i = sccList.find(this);
if (i!=sccList.end()) return &((*i).second);
return NULL;
}
unsigned int GetCompileOpt() { return compileOpt; }
void SetCompileOpt(const unsigned int n) { compileOpt = n; }
void AddHiddenToCompileOpt();
Expand Down
Loading

0 comments on commit c7472b0

Please sign in to comment.