forked from carbon-language/carbon-lang
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dictionary.h
104 lines (84 loc) · 3.21 KB
/
dictionary.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef CARBON_EXPLORER_INTERPRETER_DICTIONARY_H_
#define CARBON_EXPLORER_INTERPRETER_DICTIONARY_H_
#include <iterator>
#include <optional>
#include "explorer/base/arena.h"
namespace Carbon {
// A persistent dictionary with a simple implementation.
// Copying the dictionary is O(1) time.
template <class K, class V>
class Dictionary {
public:
struct Node {
using ValueType = std::pair<K, V>;
Node(ValueType e, std::optional<Nonnull<Node*>> n) : curr(e), next(n) {}
const ValueType curr;
const std::optional<Nonnull<Node*>> next;
// Node cells are part of a "persistent data structure" and are thus
// immutable.
auto operator=(const Node&) -> Node& = delete;
auto operator=(Node&&) -> Node& = delete;
};
// A forward iterator over elements of a `Node` list.
struct Iterator {
// NOLINTNEXTLINE(readability-identifier-naming)
using value_type = typename Node::ValueType;
// NOLINTNEXTLINE(readability-identifier-naming)
using difference_type = std::ptrdiff_t;
// NOLINTNEXTLINE(readability-identifier-naming)
using pointer = const value_type*;
// NOLINTNEXTLINE(readability-identifier-naming)
using reference = const value_type&;
// NOLINTNEXTLINE(readability-identifier-naming)
using iterator_category = std::forward_iterator_tag;
explicit Iterator(std::optional<Nonnull<Node*>> x) : p_(x) {}
Iterator(const Iterator& iter) : p_(iter.p_) {}
auto operator++() -> Iterator& {
p_ = (*p_)->next;
return *this;
}
auto operator++(int) -> Iterator {
Iterator tmp(*this);
operator++();
return tmp;
}
auto operator==(const Iterator& rhs) const -> bool { return p_ == rhs.p_; }
auto operator!=(const Iterator& rhs) const -> bool { return p_ != rhs.p_; }
auto operator*() -> const value_type& { return (*p_)->curr; }
auto operator->() -> const value_type* { return &(*p_)->curr; }
private:
std::optional<Nonnull<Node*>> p_;
};
// Create an empty dictionary.
explicit Dictionary(Nonnull<Arena*> arena) : arena_(arena) {}
// Return the value associated with the given key.
// Time complexity: O(n) where n is the number of times
// any value has been set across all keys.
auto Get(const K& key) -> std::optional<V> {
for (auto kv : *this) {
if (kv.first == key) {
return kv.second;
}
}
return std::nullopt;
}
// Associate the value v with key k in the dictionary.
// Time complexity: O(1).
auto Set(const K& k, const V& v) -> void {
head_ = arena_->New<Node>(std::make_pair(k, v), head_);
}
auto IsEmpty() -> bool { return !head_; }
// The position of the first element of the dictionary
// or `end()` if the dictionary is empty.
auto begin() const -> Iterator { return Iterator(head_); }
// The position one past that of the last element.
auto end() const -> Iterator { return Iterator(std::nullopt); }
private:
std::optional<Nonnull<Node*>> head_;
Nonnull<Arena*> arena_;
};
} // namespace Carbon
#endif // CARBON_EXPLORER_INTERPRETER_DICTIONARY_H_