// sobjstack.h see license.txt for copyright and terms of use // stack of objects, *not* owned by the stack #ifndef SOBJSTACK_H #define SOBJSTACK_H #include "sobjlist.h" // SObjList template class SObjStack { public: // data // will implement the stack as a list, with prepend and removeAt(0) SObjList list; public: // funcs SObjStack() : list() {} ~SObjStack() {} int count() const { return list.count(); } bool isEmpty() const { return list.isEmpty(); } bool isNotEmpty() const { return list.isNotEmpty(); } T const *topC() const { return list.firstC(); } T *top() { return list.first(); } T *pop() { return list.removeAt(0); } void push(T *item) { list.prepend(item); } bool contains(T const *item) const { return list.contains((void*)item); } }; // utility class for maintaining a first-class sub-stack of the AST // stack isomorphic to the stackframe stack; Note that the fact that // nothing happens if 'obj' is NULL is a feature: sometimes you can't // map the need to call this class completely onto the control flow, // and so some dataflow is involved; since the dtor for this class is // used as a kind of finally statement, we can't nest its construction // in an 'if' statement! Instead pass in NULL if you want a no-op // effect. template class StackMaintainer { SObjStack &s; T *obj; StackMaintainer(StackMaintainer&); // forbid copying public: explicit StackMaintainer(SObjStack &s0, T *obj0) : s(s0) , obj(obj0) { if (obj) { s.push(obj); } } ~StackMaintainer() { if (obj) { T *obj0 = s.pop(); xassert(obj0 == obj); } } }; #endif // SOBJSTACK_H