Browse Source

Buiding dependency tree with checking of circular dependencies.

test
Michael Uleysky 9 years ago
parent
commit
973762bfd4
  1. 145
      src/deptree.cpp
  2. 38
      src/deptree.h
  3. 101
      src/globals.cpp
  4. 24
      src/globals.h
  5. 2
      src/init.h
  6. 18
      src/object.h

145
src/deptree.cpp

@ -0,0 +1,145 @@
#include "deptree.h"
#include "globals.h"
int DepTree::CreateNodeFromVar(const std::string& var, std::set<std::string>& used, std::set<DepTree*>& callstack)
{
COUT(DEBUG)<<"DepTree::CreateNodeFromVar "<<var<<std::endl;
if(G_vars.count(var)==0)
{
COUT(ERROR)<<"Definition of variable "<<var<<" not found"<<std::endl;
return 1;
}
std::set<std::string> ids;
used.insert(var);
G_vars[var]->UsedIdents(ids);
type=DepTree::VAR;
name=var;
DepTree* d;
int ret;
callstack.insert(this);
for(auto& i:ids)
{
d=FindNodeByVar(i);
if(d==0)
{
auto n=*childrens.insert(new DepTree).first;
n->parents.insert(this);
ret=n->CreateNodeFromVar(i,used,callstack);
if(ret!=0)
{
COUT(ERROR)<<" in definition of variable "<<name<<std::endl;
return ret;
}
}
else
{
if(callstack.find(d)!=callstack.end())
{
COUT(ERROR)<<"Circular dependency of variable "<<name<<" from variable "<<i<<std::endl;
return 1;
}
childrens.insert(d);
d->parents.insert(this);
}
}
callstack.erase(this);
return 0;
}
int DepTree::CreateNodeFromSP(DepTree::NodeType list, std::vector<ObjectList*>::size_type ind, std::set<std::string>& used)
{
if(list!=DepTree::SAVE && list!=DepTree::PRINT)
{
COUT(ERROR)<<"Internal error, incorrect NodeType in DepTree::CreateNodeFromSP()."<<std::endl;
return 2;
}
COUT(DEBUG)<<"DepTree::CreateNodeFromSP "<<((list==DepTree::SAVE)?G_tosave:G_toprint)[ind]->Dump()<<std::endl;
std::set<std::string> ids;
std::set<DepTree*> callstack;
type=list;
index=ind;
if(type==DepTree::SAVE) G_tosave[index]->UsedIdents(ids);
else if(type==DepTree::PRINT) G_toprint[index]->UsedIdents(ids);
DepTree* d;
int ret;
for(auto& i:ids)
{
d=FindNodeByVar(i);
if(d==0)
{
auto n=*childrens.insert(new DepTree).first;
n->parents.insert(this);
ret=n->CreateNodeFromVar(i,used,callstack);
if(ret!=0)
{
COUT(ERROR)<<" in "<<((type==DepTree::SAVE)?"save":"print")<<" directive "<<((type==DepTree::SAVE)?G_tosave:G_toprint)[index]->Dump()<<"."<<std::endl;
return ret;
}
}
else
{
childrens.insert(d);
d->parents.insert(this);
}
}
return 0;
}
int DepTree::CreateGlobalTree(std::set<std::string>& used)
{
if(parents.size()!=0)
{
COUT(ERROR)<<"Internal error, DepTree::CreateGlobalTree() call for non-root node."<<std::endl;
return 2;
}
type=DepTree::ROOT;
for(int i=0; i<G_tosave.size(); i++)
{
auto n=*childrens.insert(new DepTree).first;
n->parents.insert(this);
auto ret=n->CreateNodeFromSP(DepTree::SAVE,i,used);
if(ret!=0) return ret;
}
for(int i=0; i<G_toprint.size(); i++)
{
auto n=*childrens.insert(new DepTree).first;
n->parents.insert(this);
auto ret=n->CreateNodeFromSP(DepTree::PRINT,i,used);
if(ret!=0) return ret;
}
return 0;
}
DepTree* DepTree::FindNodeByVarFromCurrent(const std::string& var) const
{
if(type==DepTree::VAR && name==var) return const_cast<DepTree*>(this);
DepTree* d;
for(auto& i:childrens)
{
d=i->FindNodeByVarFromCurrent(var);
if(d!=0) return d;
}
return 0;
}
DepTree* DepTree::FindNodeByVar(const std::string& var) const
{
const DepTree* curnode=this;
while(curnode->parents.size()!=0) curnode=*(curnode->parents.begin());
return curnode->FindNodeByVarFromCurrent(var);
}

38
src/deptree.h

@ -0,0 +1,38 @@
#ifndef DEPTREE_H
#define DEPTREE_H
#include <set>
#include <vector>
#include <string>
#include "object.h"
class DepTree
{
enum NodeType {NOTDEF,ROOT,SAVE,PRINT,VAR};
std::set<DepTree*> parents;
std::set<DepTree*> childrens;
NodeType type;
std::vector<ObjectList*>::size_type index;
std::string name;
int CreateNodeFromVar(const std::string& var, std::set<std::string>& used, std::set<DepTree*>& callstack);
int CreateNodeFromSP(NodeType list, std::vector<ObjectList*>::size_type ind, std::set<std::string>& used);
DepTree* FindNodeByVarFromCurrent(const std::string& var) const;
DepTree* FindNodeByVar(const std::string& var) const;
public:
DepTree():type(DepTree::NOTDEF) {}
DepTree(const DepTree&) = delete;
~DepTree()
{
for(auto& i:parents) i->childrens.erase(this);
for(auto& i:childrens)
{
i->parents.erase(this);
if(i->parents.size()==0) delete i;
}
}
int CreateGlobalTree(std::set<std::string>& used);
};
#endif

101
src/globals.cpp

@ -27,104 +27,3 @@ void RegisterFunction(const std::string& name, Func func)
{
G_funcs.emplace(name,func);
}
int DepTree::CreateNodeFromVar(const std::string& var, std::set<std::string>& used)
{
if(G_vars.count(var)==0)
{
COUT(ERROR)<<"Definition of variable "<<var<<" not found."<<std::endl;
return 1;
}
std::vector<std::string> ids;
used.insert(var);
G_vars[var]->UsedIdents(ids);
type=DepTree::VAR;
name=var;
nchild=ids.size();
COUT(DEBUG)<<ids.size()<<std::endl;
if(nchild!=0)
{
childrens=new DepTree*[nchild];
for(unsigned int i=0;i<nchild;i++) {childrens[i]=new DepTree; childrens[i]->parent=this;}
for(unsigned int i=0;i<nchild;i++)
{
int ret;
ret=childrens[i]->CreateNodeFromVar(ids[i],used);
if(ret!=0)
{
COUT(ERROR)<<" in definition of variable "<<var<<"."<<std::endl;
return ret;
}
}
}
return 0;
}
int DepTree::CreateNodeFromSP(DepTree::NodeType list, std::vector<ObjectList*>::size_type ind, std::set<std::string>& used)
{
if(list!=DepTree::SAVE && list!=DepTree::PRINT)
{
COUT(ERROR)<<"Internal error, incorrect NodeType in DepTree::CreateNodeFromSP()."<<std::endl;
return 2;
}
std::vector<std::string> ids;
type=list;
index=ind;
if(type==DepTree::SAVE) G_tosave[index]->UsedIdents(ids);
else if(type==DepTree::PRINT) G_toprint[index]->UsedIdents(ids);
nchild=ids.size();
if(nchild!=0)
{
childrens=new DepTree*[nchild];
for(unsigned int i=0;i<nchild;i++) {childrens[i]=new DepTree; childrens[i]->parent=this;}
for(unsigned int i=0;i<nchild;i++)
{
int ret;
ret=childrens[i]->CreateNodeFromVar(ids[i],used);
if(ret!=0)
{
COUT(ERROR)<<" in print/save directive "<<G_toprint[index]->Dump()<<"."<<std::endl;
return ret;
}
}
}
return 0;
}
int DepTree::CreateGlobalTree(std::set<std::string>& used)
{
if(parent!=0)
{
COUT(ERROR)<<"Internal error, DepTree::CreateGlobalTree() call for non-root node."<<std::endl;
return 2;
}
unsigned int i,j;
int ret;
type=DepTree::ROOT;
nchild=G_toprint.size()+G_tosave.size();
if(nchild!=0) childrens=new DepTree*[nchild];
for(i=0;i<nchild;i++) {childrens[i]=new DepTree; childrens[i]->parent=this;}
i=0;
for(j=0;j<G_tosave.size();j++)
{
ret=childrens[i++]->CreateNodeFromSP(DepTree::SAVE,j,used);
if(ret!=0) return ret;
}
for(j=0;j<G_toprint.size();j++)
{
ret=childrens[i++]->CreateNodeFromSP(DepTree::PRINT,j,used);
if(ret!=0) return ret;
}
return 0;
}

24
src/globals.h

@ -24,28 +24,4 @@ extern "C" {
EXPORT void RegisterFunction(const std::string& name, Func func);
}
class DepTree
{
enum NodeType {NOTDEF,ROOT,SAVE,PRINT,VAR};
DepTree* parent;
unsigned int nchild;
DepTree** childrens;
NodeType type;
std::vector<ObjectList*>::size_type index;
std::string name;
int CreateNodeFromVar(const std::string& var, std::set<std::string>& used);
int CreateNodeFromSP(NodeType list, std::vector<ObjectList*>::size_type ind, std::set<std::string>& used);
public:
DepTree():parent(0),nchild(0),childrens(0),type(DepTree::NOTDEF) {}
DepTree(const DepTree&) = delete;
~DepTree()
{
if(childrens!=0) for(unsigned int i=0; i<nchild; i++) delete childrens[i];
delete[] childrens;
}
int CreateGlobalTree(std::set<std::string>& used);
};
#endif

2
src/init.h

@ -4,7 +4,7 @@
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif
#include "globals.h"
#include "deptree.h"
int ParseConfigFile(char* config);
int RegisterArifmeticFunctions();

18
src/object.h

@ -65,8 +65,8 @@ public:
return true;
}
virtual std::string Dump() const {return "%"+Type()+"%";}
virtual void UsedFuncs(std::vector<std::string>& funcs) const {}
virtual void UsedIdents(std::vector<std::string>& ids) const {}
virtual void UsedFuncs(std::set<std::string>& funcs) const {}
virtual void UsedIdents(std::set<std::string>& ids) const {}
};
// Template for objects without specific constructor/destructor
@ -151,8 +151,8 @@ public:
const ObjectBase* Value() const {return val;}
void SetPair(const std::string& n, ObjectBase* v) {if(!Exist()) {name=n; val=v;}}
std::string Dump() const override { return Name()+"="+val->Dump(); }
void UsedFuncs(std::vector<std::string>& funcs) const override {return val->UsedFuncs(funcs);}
void UsedIdents(std::vector<std::string>& ids) const override {return val->UsedIdents(ids);}
void UsedFuncs(std::set<std::string>& funcs) const override {return val->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {return val->UsedIdents(ids);}
};
// Class for objects list
@ -189,8 +189,8 @@ public:
if(vals.size()!=0) s.resize(s.length()-2);
return s+")";
}
void UsedFuncs(std::vector<std::string>& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);}
void UsedIdents(std::vector<std::string>& ids) const override {for(auto& i: vals) i->UsedIdents(ids);}
void UsedFuncs(std::set<std::string>& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {for(auto& i: vals) i->UsedIdents(ids);}
};
// Class for storing identifiers
@ -212,7 +212,7 @@ public:
std::string Name() const {return name;}
void SetName(std::string s) {ParseName(s);}
std::string Dump() const override {return fullname;};
void UsedIdents(std::vector<std::string>& ids) const override {ids.push_back(name);}
void UsedIdents(std::set<std::string>& ids) const override {ids.insert(name);}
};
// Class for storing functions
@ -237,8 +237,8 @@ public:
std::string Name() const {return name;}
void SetName(std::string s) {name=s;}
std::string Dump() const override {return Name()+args->Dump();};
void UsedFuncs(std::vector<std::string>& funcs) const override {funcs.push_back(name); args->UsedFuncs(funcs);}
void UsedIdents(std::vector<std::string>& ids) const override {args->UsedIdents(ids);}
void UsedFuncs(std::set<std::string>& funcs) const override {funcs.insert(name); args->UsedFuncs(funcs);}
void UsedIdents(std::set<std::string>& ids) const override {args->UsedIdents(ids);}
};
#endif

Loading…
Cancel
Save