Zen
A cross-platform functional programming language
|
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 }