ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
StackFrameVector.h
Go to the documentation of this file.
1 // Author: Gergo Barany
2 // $Id: StackFrameVector.h,v 1.1 2008/01/08 02:56:39 dquinlan Exp $
3 
4 /*
5  StackFrameVector is a template container class meant to be used for the
6  stack of SythesizedAttributes in the SgTreeTraversal class; to the concrete
7  traversal classes (Ast*Processing) it is hidden behind the
8  SynthesizedAttributesList typedef, which used to be a std::vector.
9  Therefore StackFrameVector implements much of the interface of std::vector
10  in the hope that this will cause minimal breakage of existing user code.
11 
12  As it was never a useful operation to alter the size of the
13  SynthesizedAttributesList, or to change its contents, and this would be
14  impossible to support efficiently with StackFrameVector, member functions
15  such as push_back(), erase(), resize() etc. are not implemented. Code using
16  these, for whatever strange reason, should make a copy of the container (a
17  conversion to std::vector is provided) to continue working.
18 
19  At the moment we don't provide comparison operators either.
20 
21  StackFrameVector is basically implemented as a pointer to a vector, which
22  contains the stack elements, and a pair of iterators into this vector
23  denoting the start and end of a stack frame. Some special stack operations
24  are provided: push(const T &) to push an element to the top of the stack,
25  and setFrameSize(BufferType::size_type) to define how many elements will
26  comprise the stack's top frame (i.e., how many elements there will be
27  between begin() and end()). A push() always pops off the current frame
28  before the new element is added.
29 
30  The function debugSize() tells you the total size of the stack, and pop()
31  pops and returns the topmost element, which is mainly useful if the stack
32  contains exactly that one element. All these special functions should only
33  be used by code that knows what it's doing.
34 */
35 
36 #ifndef STACKFRAMEVECTOR_H
37 #define STACKFRAMEVECTOR_H
38 
39 #include <vector>
40 #include <ostream>
41 
42 template <class T>
44 {
45 public:
46  // typedef to the underlying container type; this is provided for
47  // generality, but it will probably not make much sense to change it
48  typedef std::vector<T> BufferType;
49 
50  // typedefs required for std::vector, just use those defined for the
51  // buffer type
52  typedef typename BufferType::reference reference;
53  typedef typename BufferType::const_reference const_reference;
54  typedef typename BufferType::iterator iterator;
55  typedef typename BufferType::const_iterator const_iterator;
56  typedef typename BufferType::size_type size_type;
57  typedef typename BufferType::difference_type difference_type;
58  typedef typename BufferType::value_type value_type;
59  typedef typename BufferType::allocator_type allocator_type;
60  typedef typename BufferType::pointer pointer;
61  typedef typename BufferType::const_pointer const_pointer;
62  typedef typename BufferType::reverse_iterator reverse_iterator;
63  typedef typename BufferType::const_reverse_iterator const_reverse_iterator;
64 
65  // constructors required for std::vector are not all implemented
66  // because user code is not supposed to construct a StackFrameVector
71 
73 
74  // deep copy operation, returns a new instance with a copy of this one's
75  // stack up to the stackPtr (the iterators are set correctly in the copy)
76  StackFrameVector *deepCopy() const;
77 
78  // iterator functions required for std::vector
79  iterator begin();
80  const_iterator begin() const;
81  iterator end();
82  const_iterator end() const;
87 
88  // various size-related operations required for std::vector; these do
89  // not return the size of the underlying buffer (stack), but only the
90  // size of the current stack frame
91  // size(), max_size(), capacity() return the same value, no resizing
92  // functions are provided.
93  size_type size() const;
94  size_type max_size() const;
95  size_type capacity() const;
96  bool empty() const;
97 
98  // element access functions required for std::vector
103  reference front();
104  const_reference front() const;
105  reference back();
106  const_reference back() const;
107 
108  // type conversion to underlying type (this results in a copy, so it
109  // will cost you)
110  operator std::vector<T>();
111 
112  // modifiers; these are deliberately different from what std::vector
113  // provides! use at your own risk, and only if you know what you're doing
114  void push(const T &);
116 
117  // function used for debugging, returns the overall number of objects
118  // on the stack, i.e. not just in the current frame
119  size_type debugSize() const;
120 
121  // Clear the stack; deliberately not named clear. This should only be
122  // called by the traversal code at the beginning of a traversal, and in
123  // fact it is only needed to support tutorial/traversalShortCircuit.C
124  // which calls a traversal, exits from it by throwing an exception,
125  // leaving junk on the stack, then uses that traversal object again.
126  void resetStack();
127 
128  // Pops the top element off the stack, returns it, and adjusts the
129  // stack pointer accordingly. Note that this makes sense primarily if
130  // the stack (not just the current frame!) contains exactly one element.
131  value_type pop();
132 
133  // do some debug output; this should not be called
134  void debugDump(std::ostream &s);
135 
136 protected:
137  // the buffer to hold all stack elements
139  // the top stack frame is denoted by these iterators, framePtr plays the
140  // role of begin, stackPtr the role of end
142  // flag to indicate whether the destructor should delete the buffer; this
143  // must be false for shallow copies (shallow copying is the default
144  // behavior)
146 
147 private:
148  explicit StackFrameVector(const BufferType &otherBuffer, difference_type framePtrOffset);
149 };
150 
151 // Author: Gergo Barany
152 // $Id: StackFrameVector.C,v 1.1 2008/01/08 02:56:39 dquinlan Exp $
153 
154 template <class T>
156  : buffer(new BufferType()),
157  framePtr(buffer->begin()),
158  stackPtr(buffer->end()),
159  deleteBufferWhenDone(true)
160 {
161 }
162 
163 template <class T>
165  : buffer(NULL),
166  framePtr(v.framePtr),
167  stackPtr(v.stackPtr),
168  deleteBufferWhenDone(false) // don't delete the pointer, it's not ours
169 {
170 }
171 
172 template <class T>
175  : buffer(new BufferType(n)),
176  framePtr(buffer->begin()),
177  stackPtr(buffer->end()),
178  deleteBufferWhenDone(true)
179 {
180 }
181 
182 template <class T>
185  typename StackFrameVector<T>::value_type initValue)
186  : buffer(new BufferType(n, initValue)),
187  framePtr(buffer->begin()),
188  stackPtr(buffer->end()),
189  deleteBufferWhenDone(true)
190 {
191 }
192 
193 template <class T>
195  const typename StackFrameVector<T>::BufferType &otherBuffer,
196  typename StackFrameVector<T>::difference_type framePtrOffset)
197  : buffer(new BufferType(otherBuffer)),
198  framePtr(buffer->begin() + framePtrOffset),
199  stackPtr(buffer->end()),
200  deleteBufferWhenDone(true)
201 {
202 }
203 
204 template <class T>
206 {
207  ROSE_ASSERT(deleteBufferWhenDone == (buffer != NULL));
208  if (deleteBufferWhenDone)
209  {
210  delete buffer;
211  buffer = NULL;
212  }
213 }
214 
215 template <class T>
218 {
219  // return a pointer to a new instance having a deep copy of all the live
220  // elements on the stack (those up to stackPtr). The second argument is
221  // the offset of the framePtr that needs to be set correctly in the copy
222  // (the stackPtr can just be set to the end of the newly copied buffer).
223  return new StackFrameVector(BufferType(buffer->begin(), stackPtr), framePtr - buffer->begin());
224 }
225 
226 template <class T>
229 {
230  return framePtr;
231 }
232 
233 template <class T>
236 {
237  return framePtr;
238 }
239 
240 template <class T>
243 {
244  return stackPtr;
245 }
246 
247 template <class T>
250 {
251  return stackPtr;
252 }
253 
254 template <class T>
257 {
258  return reverse_iterator(end());
259 }
260 
261 template <class T>
264 {
265  return reverse_iterator(end());
266 }
267 
268 template <class T>
271 {
272  return reverse_iterator(begin());
273 }
274 
275 template <class T>
278 {
279  return reverse_iterator(begin());
280 }
281 
282 template <class T>
285 {
286  return end() - begin();
287 }
288 
289 template <class T>
292 {
293  return size();
294 }
295 
296 template <class T>
299 {
300  return size();
301 }
302 
303 template <class T>
304 bool
306 {
307  return size() == 0;
308 }
309 
310 template <class T>
313 {
314  return framePtr[n];
315 }
316 
317 template <class T>
320 {
321  return framePtr[n];
322 }
323 
324 #include <stdexcept>
325 
326 template <class T>
329 {
330  if (n >= size())
331  throw std::out_of_range("StackFrameVector: index out of range");
332  return (*this)[n];
333 }
334 
335 template <class T>
338 {
339  if (n >= size())
340  throw std::out_of_range("StackFrameVector: index out of range");
341  return (*this)[n];
342 }
343 
344 template <class T>
347 {
348  return *framePtr;
349 }
350 
351 template <class T>
354 {
355  return *framePtr;
356 }
357 
358 template <class T>
361 {
362  return *(stackPtr - 1);
363 }
364 
365 template <class T>
368 {
369  return *(stackPtr - 1);
370 }
371 
372 template <class T>
374 {
375  // return a copy of the objects in the current stack frame
376  return BufferType(begin(), end());
377 }
378 
379 template <class T>
380 void
382 {
383  ROSE_ASSERT(buffer != NULL);
384 
385  if (framePtr == buffer->end())
386  {
387  buffer->push_back(x);
388  // push_back may have caused a resize, invalidating iterators;
389  // compute the new iterator values
390  framePtr = stackPtr = buffer->end();
391  // note that no user should have iterators into our buffer lying
392  // around (push is only called by the traversal code, no user function
393  // is alive at that point), so hopefully we haven't invalidated
394  // anything else
395  }
396  else
397  {
398  *framePtr++ = x;
399  stackPtr = framePtr;
400  }
401 }
402 
403 template <class T>
404 void
406 {
407  // set the frame size to the desired value by adjusting the frame
408  // pointer; the next push() (which writes through the frame pointer)
409  // will in effect pop off this whole frame
410  framePtr = stackPtr - frameSize;
411 }
412 
413 template <class T>
416 {
417  ROSE_ASSERT(buffer != NULL);
418  return stackPtr - buffer->begin();
419 }
420 
421 template <class T>
422 void
424 {
425  ROSE_ASSERT(buffer != NULL);
426  framePtr = stackPtr = buffer->begin();
427 }
428 
429 template <class T>
432 {
433  // pop off a single element, this is intended to be used if the whole
434  // stack contains just this element (the final result of the computation);
435  // if your stack contains more than one element at this point, your
436  // pointers will be messed up
437  --framePtr;
438  return *--stackPtr;
439 }
440 
441 template <class T>
442 void
444 {
445  // this function should only be called for debugging
446  s << "\n"
447  << "framePtr offset: " << framePtr - buffer->begin()
448  << " stackPtr offset: " << stackPtr - buffer->begin()
449  << " size: " << size()
450  << " buffer size: " << buffer->size()
451  << "\n";
452  s << "buffer:" << "\n";
453  const_iterator i;
454  for (i = buffer->begin(); i != buffer->end(); ++i)
455  s << (void *) *i << ' ';
456  s << "\n" << "\n";
457 }
458 
459 #endif