dictionary.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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, Node* n) : curr(e), next(n) {}
  18. const ValueType curr;
  19. Node* const next;
  20. // Node cells are part of a "persistent data structure" and are thus
  21. // immutable.
  22. Node& operator=(const Node&) = delete;
  23. Node& operator=(Node&&) = delete;
  24. };
  25. // A forward iterator over elements of a `Node` list.
  26. struct Iterator {
  27. using value_type = typename Node::ValueType;
  28. using difference_type = std::ptrdiff_t;
  29. using pointer = const value_type*;
  30. using reference = const value_type&;
  31. using iterator_category = std::forward_iterator_tag;
  32. Iterator(Node* x) : p(x) {}
  33. Iterator(const Iterator& iter) : p(iter.p) {}
  34. Iterator& operator++() {
  35. p = p->next;
  36. return *this;
  37. }
  38. Iterator operator++(int) {
  39. Iterator tmp(*this);
  40. operator++();
  41. return tmp;
  42. }
  43. bool operator==(const Iterator& rhs) const { return p == rhs.p; }
  44. bool operator!=(const Iterator& rhs) const { return p != rhs.p; }
  45. const value_type& operator*() { return p->curr; }
  46. const value_type* operator->() { return &p->curr; }
  47. private:
  48. Node* p;
  49. };
  50. // Create an empty dictionary.
  51. Dictionary() { head = nullptr; }
  52. // Return the value associated with the given key.
  53. // Time complexity: O(n) where n is the number of times
  54. // any value has been set across all keys.
  55. auto Get(const K& key) -> std::optional<V> {
  56. for (auto kv : *this) {
  57. if (kv.first == key) {
  58. return kv.second;
  59. }
  60. }
  61. return std::nullopt;
  62. }
  63. // Associate the value v with key k in the dictionary.
  64. // Time complexity: O(1).
  65. auto Set(const K& k, const V& v) -> void {
  66. head = global_arena->RawNew<Node>(std::make_pair(k, v), head);
  67. }
  68. // The position of the first element of the dictionary
  69. // or `end()` if the dictionary is empty.
  70. auto begin() const -> Iterator { return Iterator(head); }
  71. // The position one past that of the last element.
  72. auto end() const -> Iterator { return Iterator(nullptr); }
  73. private:
  74. Node* head;
  75. };
  76. } // namespace Carbon
  77. #endif // EXECUTABLE_SEMANTICS_INTERPRETER_DICTIONARY_H_