stack.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef EXECUTABLE_SEMANTICS_INTERPRETER_STACK_H_
  5. #define EXECUTABLE_SEMANTICS_INTERPRETER_STACK_H_
  6. #include <cassert>
  7. #include <cstddef>
  8. #include <iterator>
  9. namespace Carbon {
  10. /// A persistent stack data structure.
  11. ///
  12. /// - Note: this data structure leaks memory.
  13. template <class T>
  14. struct Stack {
  15. /// A forward iterator over elements of a `Stack`.
  16. struct Iterator {
  17. using value_type = T;
  18. using difference_type = std::ptrdiff_t;
  19. using pointer = const T*;
  20. using reference = const T&;
  21. using iterator_category = std::forward_iterator_tag;
  22. Iterator(Cons<T>* x) : p(x) {}
  23. Iterator(const Iterator& mit) : p(mit.p) {}
  24. Iterator& operator++() {
  25. p = p->next;
  26. return *this;
  27. }
  28. Iterator operator++(int) {
  29. Iterator tmp(*this);
  30. operator++();
  31. return tmp;
  32. }
  33. bool operator==(const Iterator& rhs) const { return p == rhs.p; }
  34. bool operator!=(const Iterator& rhs) const { return p != rhs.p; }
  35. const T& operator*() { return p->curr; }
  36. const T* operator->() { return &p->curr; }
  37. private:
  38. Cons<T>* p;
  39. };
  40. /// The position of the first/`Top()` element, or `end()` if
  41. /// `this->IsEmpty()`.
  42. auto begin() const -> Iterator { return Iterator(head); }
  43. /// The position one past that of the last element.
  44. auto end() const -> Iterator { return Iterator(nullptr); }
  45. /// Creates an empty instance.
  46. Stack() { head = nullptr; }
  47. /// Creates an instance containing just `x`.
  48. Stack(T x) : Stack() { Push(x); }
  49. /// Pushes `x` onto the top of the stack.
  50. void Push(T x) { head = new Cons<T>(x, head); }
  51. /// Returns a copy of `*this`, with `x` pushed onto the top.
  52. auto Pushing(T x) const -> Stack {
  53. auto r = *this;
  54. r.Push(x);
  55. return r;
  56. }
  57. /// Removes and returns the top element of the stack.
  58. ///
  59. /// - Requires: !this->IsEmpty()
  60. auto Pop() -> T {
  61. assert(!IsEmpty() && "Can't pop from empty stack.");
  62. auto r = head->curr;
  63. head = head->next;
  64. return r;
  65. }
  66. /// Removes the top `n` elements of the stack.
  67. ///
  68. /// - Requires: n >= 0 && n <= Count()
  69. void Pop(int n) {
  70. assert(n >= 0 && "Negative pop count disallowed.");
  71. while (n--) {
  72. assert(head != nullptr && "Can only pop as many elements as stack has.");
  73. head = head->next;
  74. }
  75. }
  76. /// Returns a copy of `*this`, sans the top element.
  77. ///
  78. /// - Requires: !this->IsEmpty()
  79. auto Popped() const -> Stack {
  80. auto r = *this;
  81. r.Pop();
  82. return r;
  83. }
  84. /// Returns the top element of the stack.
  85. ///
  86. /// - Requires: !this->IsEmpty()
  87. auto Top() const -> T {
  88. assert(!IsEmpty() && "Empty stack has no Top().");
  89. return head->curr;
  90. }
  91. /// Returns `true` iff `Count() > 0`.
  92. auto IsEmpty() const -> bool { return head == nullptr; }
  93. /// Returns `true` iff `Count() > n`.
  94. ///
  95. /// - Complexity: O(`n`)
  96. auto CountExceeds(int n) const -> bool {
  97. if (n < 0)
  98. return true;
  99. for (auto p = head; p != nullptr; p = p->next) {
  100. if (n-- == 0)
  101. return true;
  102. }
  103. return false;
  104. }
  105. /// Returns the number of elements in `*this`.
  106. auto Count() const -> int { return std::distance(begin(), end()); }
  107. private:
  108. /// An linked list of cells containing the elements of self.
  109. Cons<T>* head;
  110. };
  111. } // namespace Carbon
  112. #endif // EXECUTABLE_SEMANTICS_INTERPRETER_CONS_LIST_H_