dictionary.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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_DICTIONARY_H_
  5. #define EXECUTABLE_SEMANTICS_INTERPRETER_DICTIONARY_H_
  6. #include <iterator>
  7. #include <optional>
  8. #include "executable_semantics/common/arena.h"
  9. namespace Carbon {
  10. // A persistent dictionary with a simple implementation.
  11. // Copying the dictionary is O(1) time.
  12. template <class K, class V>
  13. class Dictionary {
  14. public:
  15. struct Node {
  16. using ValueType = std::pair<K, V>;
  17. Node(ValueType e, std::optional<Nonnull<Node*>> n) : curr(e), next(n) {}
  18. const ValueType curr;
  19. const std::optional<Nonnull<Node*>> next;
  20. // Node cells are part of a "persistent data structure" and are thus
  21. // immutable.
  22. auto operator=(const Node&) -> Node& = delete;
  23. auto operator=(Node&&) -> Node& = delete;
  24. };
  25. // A forward iterator over elements of a `Node` list.
  26. struct Iterator {
  27. // NOLINTNEXTLINE(readability-identifier-naming)
  28. using value_type = typename Node::ValueType;
  29. // NOLINTNEXTLINE(readability-identifier-naming)
  30. using difference_type = std::ptrdiff_t;
  31. // NOLINTNEXTLINE(readability-identifier-naming)
  32. using pointer = const value_type*;
  33. // NOLINTNEXTLINE(readability-identifier-naming)
  34. using reference = const value_type&;
  35. // NOLINTNEXTLINE(readability-identifier-naming)
  36. using iterator_category = std::forward_iterator_tag;
  37. explicit Iterator(std::optional<Nonnull<Node*>> x) : p_(x) {}
  38. Iterator(const Iterator& iter) : p_(iter.p_) {}
  39. auto operator++() -> Iterator& {
  40. p_ = (*p_)->next;
  41. return *this;
  42. }
  43. auto operator++(int) -> Iterator {
  44. Iterator tmp(*this);
  45. operator++();
  46. return tmp;
  47. }
  48. auto operator==(const Iterator& rhs) const -> bool { return p_ == rhs.p_; }
  49. auto operator!=(const Iterator& rhs) const -> bool { return p_ != rhs.p_; }
  50. auto operator*() -> const value_type& { return (*p_)->curr; }
  51. auto operator->() -> const value_type* { return &(*p_)->curr; }
  52. private:
  53. std::optional<Nonnull<Node*>> p_;
  54. };
  55. // Create an empty dictionary.
  56. explicit Dictionary(Nonnull<Arena*> arena) : arena_(arena) {}
  57. // Return the value associated with the given key.
  58. // Time complexity: O(n) where n is the number of times
  59. // any value has been set across all keys.
  60. auto Get(const K& key) -> std::optional<V> {
  61. for (auto kv : *this) {
  62. if (kv.first == key) {
  63. return kv.second;
  64. }
  65. }
  66. return std::nullopt;
  67. }
  68. // Associate the value v with key k in the dictionary.
  69. // Time complexity: O(1).
  70. auto Set(const K& k, const V& v) -> void {
  71. head_ = arena_->New<Node>(std::make_pair(k, v), head_);
  72. }
  73. auto IsEmpty() -> bool { return !head_; }
  74. // The position of the first element of the dictionary
  75. // or `end()` if the dictionary is empty.
  76. auto begin() const -> Iterator { return Iterator(head_); }
  77. // The position one past that of the last element.
  78. auto end() const -> Iterator { return Iterator(std::nullopt); }
  79. private:
  80. std::optional<Nonnull<Node*>> head_;
  81. Nonnull<Arena*> arena_;
  82. };
  83. } // namespace Carbon
  84. #endif // EXECUTABLE_SEMANTICS_INTERPRETER_DICTIONARY_H_