From 973762bfd48f466e5f610be605f94bffca3e7dc9 Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Thu, 3 Sep 2015 14:42:13 +1000 Subject: [PATCH] Buiding dependency tree with checking of circular dependencies. --- src/deptree.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++++++++ src/deptree.h | 38 +++++++++++++ src/globals.cpp | 101 --------------------------------- src/globals.h | 24 -------- src/init.h | 2 +- src/object.h | 18 +++--- 6 files changed, 193 insertions(+), 135 deletions(-) create mode 100644 src/deptree.cpp create mode 100644 src/deptree.h diff --git a/src/deptree.cpp b/src/deptree.cpp new file mode 100644 index 0000000..56ca8f4 --- /dev/null +++ b/src/deptree.cpp @@ -0,0 +1,145 @@ +#include "deptree.h" +#include "globals.h" + +int DepTree::CreateNodeFromVar(const std::string& var, std::set& used, std::set& callstack) +{ + COUT(DEBUG)<<"DepTree::CreateNodeFromVar "< 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 "<parents.insert(this); + } + } + callstack.erase(this); + + return 0; +} + + +int DepTree::CreateNodeFromSP(DepTree::NodeType list, std::vector::size_type ind, std::set& used) +{ + if(list!=DepTree::SAVE && list!=DepTree::PRINT) + { + COUT(ERROR)<<"Internal error, incorrect NodeType in DepTree::CreateNodeFromSP()."<Dump()< ids; + std::set 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()<<"."<parents.insert(this); + } + } + + return 0; +} + + +int DepTree::CreateGlobalTree(std::set& used) +{ + if(parents.size()!=0) + { + COUT(ERROR)<<"Internal error, DepTree::CreateGlobalTree() call for non-root node."<parents.insert(this); + auto ret=n->CreateNodeFromSP(DepTree::SAVE,i,used); + if(ret!=0) return ret; + } + for(int i=0; iparents.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(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); +} diff --git a/src/deptree.h b/src/deptree.h new file mode 100644 index 0000000..99718f8 --- /dev/null +++ b/src/deptree.h @@ -0,0 +1,38 @@ +#ifndef DEPTREE_H +#define DEPTREE_H +#include +#include +#include +#include "object.h" + +class DepTree +{ + enum NodeType {NOTDEF,ROOT,SAVE,PRINT,VAR}; + + std::set parents; + std::set childrens; + NodeType type; + std::vector::size_type index; + std::string name; + + int CreateNodeFromVar(const std::string& var, std::set& used, std::set& callstack); + int CreateNodeFromSP(NodeType list, std::vector::size_type ind, std::set& 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& used); +}; + +#endif diff --git a/src/globals.cpp b/src/globals.cpp index 6962fbc..226861a 100644 --- a/src/globals.cpp +++ b/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& used) -{ - if(G_vars.count(var)==0) - { - COUT(ERROR)<<"Definition of variable "< ids; - - used.insert(var); - G_vars[var]->UsedIdents(ids); - type=DepTree::VAR; - name=var; - nchild=ids.size(); - COUT(DEBUG)<parent=this;} - for(unsigned int i=0;iCreateNodeFromVar(ids[i],used); - if(ret!=0) - { - COUT(ERROR)<<" in definition of variable "<::size_type ind, std::set& used) -{ - if(list!=DepTree::SAVE && list!=DepTree::PRINT) - { - COUT(ERROR)<<"Internal error, incorrect NodeType in DepTree::CreateNodeFromSP()."< 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;iparent=this;} - for(unsigned int i=0;iCreateNodeFromVar(ids[i],used); - if(ret!=0) - { - COUT(ERROR)<<" in print/save directive "<Dump()<<"."<& used) -{ - if(parent!=0) - { - COUT(ERROR)<<"Internal error, DepTree::CreateGlobalTree() call for non-root node."<parent=this;} - i=0; - for(j=0;jCreateNodeFromSP(DepTree::SAVE,j,used); - if(ret!=0) return ret; - } - for(j=0;jCreateNodeFromSP(DepTree::PRINT,j,used); - if(ret!=0) return ret; - } - - return 0; -} diff --git a/src/globals.h b/src/globals.h index 395fd81..6bd37cd 100644 --- a/src/globals.h +++ b/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::size_type index; - std::string name; - - int CreateNodeFromVar(const std::string& var, std::set& used); - int CreateNodeFromSP(NodeType list, std::vector::size_type ind, std::set& 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& used); -}; #endif diff --git a/src/init.h b/src/init.h index df124d2..4a1daf7 100644 --- a/src/init.h +++ b/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(); diff --git a/src/object.h b/src/object.h index 270f746..6d09ecd 100644 --- a/src/object.h +++ b/src/object.h @@ -65,8 +65,8 @@ public: return true; } virtual std::string Dump() const {return "%"+Type()+"%";} - virtual void UsedFuncs(std::vector& funcs) const {} - virtual void UsedIdents(std::vector& ids) const {} + virtual void UsedFuncs(std::set& funcs) const {} + virtual void UsedIdents(std::set& 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& funcs) const override {return val->UsedFuncs(funcs);} - void UsedIdents(std::vector& ids) const override {return val->UsedIdents(ids);} + void UsedFuncs(std::set& funcs) const override {return val->UsedFuncs(funcs);} + void UsedIdents(std::set& 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& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);} - void UsedIdents(std::vector& ids) const override {for(auto& i: vals) i->UsedIdents(ids);} + void UsedFuncs(std::set& funcs) const override {for(auto& i: vals) i->UsedFuncs(funcs);} + void UsedIdents(std::set& 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& ids) const override {ids.push_back(name);} + void UsedIdents(std::set& 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& funcs) const override {funcs.push_back(name); args->UsedFuncs(funcs);} - void UsedIdents(std::vector& ids) const override {args->UsedIdents(ids);} + void UsedFuncs(std::set& funcs) const override {funcs.insert(name); args->UsedFuncs(funcs);} + void UsedIdents(std::set& ids) const override {args->UsedIdents(ids);} }; #endif