Zen
A cross-platform functional programming language

/home/renji/Data/projects/zenlang/sources/zbl/GetXRef.hpp

00001 #pragma once
00002 
00003 #include "Ast.hpp"
00004 
00005 namespace zbl {
00008     class ParseContext;
00009 
00012     class RefCollector {
00013     private:
00016         struct StackItem {
00020             inline StackItem(const Ast::Scope::Type& type) : _type(type) {}
00021 
00023             Ast::Scope::Type _type;
00024 
00026             Ast::VariableDefMap _map;
00027         };
00028 
00030         typedef z::stack<StackItem*> DefStack;
00031 
00032     public:
00037         inline RefCollector(ParseContext& pctx, const Ast::Storage::T& storage) : _pctx(pctx), _storage(storage) {}
00038 
00041         inline ~RefCollector() {assert(_defStack.size() == 0);}
00042 
00043     private:
00049         inline RefCollector(const RefCollector& src) : _pctx(src._pctx), _storage(src._storage) {}
00050 
00051     public:
00055         void getInvokerRefList(const Ast::Invoker& invoker);
00056 
00060         void getImplItemRefList(const Ast::ImplItem& item);
00061 
00065         void getExprRefList(const Ast::Expr& expr);
00066 
00070         void getExprListRefList(const Ast::ExprList& list);
00071 
00075         void getSharedDefRefList(const Ast::SharedDef& sdef);
00076 
00081         void getStatementListRefList(const Ast::FunctionDef& fdef, const Ast::StatementList& list);
00082 
00083     public:
00087         inline const Ast::VariableRefList& getRefList() const {return _refList;}
00088 
00089     private:
00093         inline z::string printStack() const {
00094             z::string str;
00095             z::stringstream ss(str);
00096             for(DefStack::iterator it(_defStack); !it.end(); ++it) {
00097                 const StackItem& si = ref(*it);
00098                 ss << ((long)ptr(si._map)) << "{ ";
00099                 for(Ast::VariableDefMap::List::iterator it2(si._map.getList()); !it2.end(); ++it2) {
00100                     const Ast::VariableDef& vd = ref(*it2);
00101                     ss << "{@name:" << vd.getName() << ", @ptr:" << ((long)ptr(vd)) << "}";
00102                 }
00103                 ss << " }";
00104             }
00105             return str;
00106         }
00107     private:
00112         inline StackItem& pushDefItem(const Ast::Scope::Type& type) {
00113             _defStack.push(new StackItem(type));
00114             return ref(_defStack.top());
00115         }
00116 
00120         inline void popDefItem(StackItem& item) {
00121             if(_defStack.top() != ptr(item)) {
00122                 throw z::exception(z::string::creator("Internal error: DefStackItem mismatch").value());
00123             }
00124             StackItem* t = _defStack.top();
00125             _defStack.pop();
00126             delete t;
00127         }
00128 
00129     public:
00133         inline void addDef(const Ast::VariableDef& def) {
00134             ref(_defStack.top())._map.addDef(def);
00135         }
00136 
00137     public:
00142         inline bool hasDefItem(const Ast::VariableDef& vdef) {
00143             zbl::RefCollector::DefStack::iterator it(_defStack);
00144             it.toBack();
00145             while(!it.begin()) {
00146                 const StackItem& si = ref(--it);
00147                 const Ast::VariableDefMap& vdl = si._map;
00148                 const Ast::VariableDefMap::List& list = vdl.getList();
00149                 for(Ast::VariableDefMap::List::iterator it1(list); !it1.end(); ++it1) {
00150                     const Ast::VariableDef* vd = *it1;
00151                     if(vd == ptr(vdef)) {
00152                         return true;
00153                     }
00154                 }
00155             }
00156             return false;
00157         }
00158 
00159     public:
00164         inline void setStorage(const Ast::VariableRef& vref, const Ast::Storage::T& storage) {
00165             // set the xref storage type.
00166             Ast::VariableRef& mref = const_cast<Ast::VariableRef&>(vref); // TODO: eliminate need to make mutable.
00167             mref.setStorage(storage);
00168         }
00169 
00170     public:
00175         inline bool addRef(const Ast::VariableRef& vref) {
00176             // is vref declared in any immediate scopes?
00177             if(hasDefItem(vref.getFirst())) {
00178                 return false;
00179             }
00180 
00181             // If not, it is an xref. Is the xref already present in the xref list?
00182             if(!_refList.hasRef(vref)) {
00183                 // if not, add it.
00184                 _refList.addRef(vref);
00185             }
00186             return true;
00187         }
00188 
00192         inline void addRefWithStorage(const Ast::VariableRef& vref) {
00193             if(!addRef(vref)) {
00194                 return;
00195             }
00196 
00197             // set storage type
00198             setStorage(vref, _storage);
00199         }
00200 
00204         inline void addRefList(const Ast::VariableRefList& xRefList) {
00205             for(Ast::VariableRefList::List::iterator it(xRefList.getList()); !it.end(); ++it) {
00206                 const Ast::VariableRef& vref = ref(*it);
00207                 // it is an external reference of the current continuation
00208                 addRef(vref);
00209             }
00210         }
00211 
00212     public:
00215         struct DefStackItem {
00220             inline DefStackItem(RefCollector& ctx, const Ast::Scope::Type& type) : _ctx(ctx), _stackItem(0) {
00221                 _stackItem = ptr(_ctx.pushDefItem(type));
00222             }
00223 
00226             inline ~DefStackItem() {
00227                 _ctx.popDefItem(ref(_stackItem));
00228             }
00229 
00233             inline void addDef(const Ast::VariableDef& def) {
00234                 _ctx.addDef(def);
00235             }
00236 
00241             inline bool hasRef(const Ast::VariableRef& vref) const {
00242                 return ref(_stackItem)._map.hasDef(vref.getFirst().getName());
00243             }
00244 
00245         private:
00247             RefCollector& _ctx;
00248 
00250             StackItem* _stackItem;
00251         };
00252     private:
00254         ParseContext& _pctx;
00255 
00257         const Ast::Storage::T _storage;
00258 
00260         Ast::VariableRefList _refList;
00261 
00263         DefStack _defStack;
00264     };
00265 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines