-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
base_persistent_map.hpp
138 lines (119 loc) · 3.86 KB
/
base_persistent_map.hpp
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#pragma once
namespace jank::runtime
{
native_bool is_map(object_ptr o);
namespace behavior::detail
{
object_ptr validate_meta(object_ptr const m);
}
}
namespace jank::runtime::obj::detail
{
/* Array maps and hash maps share a lot of common code, so we have a common base.
* No virtual fns are used, so this structure won't survive release optimizations. */
template <object_type OT, object_type ST, typename V>
struct base_persistent_map : gc
{
using value_type = V;
using parent_type = static_object<OT>;
using sequence_type = static_object<ST>;
static constexpr native_bool pointer_free{ false };
base_persistent_map() = default;
base_persistent_map(native_box<obj::persistent_array_map> const meta)
: meta{ meta }
{
}
/* behavior::objectable */
native_bool equal(object const &o) const
{
object_ptr p{ const_cast<object *>(&o) };
if(!is_map(p))
{
return false;
}
/* TODO: Is this enough? Value comparison may be needed. */
return to_hash() == hash::visit(p);
}
static void to_string_impl(typename V::const_iterator const &begin,
typename V::const_iterator const &end,
fmt::memory_buffer &buff)
{
auto inserter(std::back_inserter(buff));
inserter = '{';
for(auto i(begin); i != end; ++i)
{
auto const pair(*i);
runtime::detail::to_string(pair.first, buff);
inserter = ' ';
runtime::detail::to_string(pair.second, buff);
auto n(i);
if(++n != end)
{
inserter = ',';
inserter = ' ';
}
}
inserter = '}';
}
void to_string(fmt::memory_buffer &buff) const
{
to_string_impl(static_cast<parent_type const *>(this)->data.begin(),
static_cast<parent_type const *>(this)->data.end(),
buff);
}
native_persistent_string to_string() const
{
fmt::memory_buffer buff;
to_string_impl(static_cast<parent_type const *>(this)->data.begin(),
static_cast<parent_type const *>(this)->data.end(),
buff);
return native_persistent_string{ buff.data(), buff.size() };
}
native_hash to_hash() const
{
if(hash)
{
return hash;
}
return hash = hash::unordered(static_cast<parent_type const *>(this)->data.begin(),
static_cast<parent_type const *>(this)->data.end());
}
/* behavior::seqable */
native_box<sequence_type> seq() const
{
if(static_cast<parent_type const *>(this)->data.empty())
{
return nullptr;
}
return make_box<sequence_type>(static_cast<parent_type const *>(this),
static_cast<parent_type const *>(this)->data.begin(),
static_cast<parent_type const *>(this)->data.end());
}
native_box<sequence_type> fresh_seq() const
{
if(static_cast<parent_type const *>(this)->data.empty())
{
return nullptr;
}
return make_box<sequence_type>(static_cast<parent_type const *>(this),
static_cast<parent_type const *>(this)->data.begin(),
static_cast<parent_type const *>(this)->data.end());
}
/* behavior::countable */
size_t count() const
{
return static_cast<parent_type const *>(this)->data.size();
}
/* behavior::metadatable */
object_ptr with_meta(object_ptr const m) const
{
auto const meta(behavior::detail::validate_meta(m));
auto ret(make_box<parent_type>(static_cast<parent_type const *>(this)->data));
ret->meta = meta;
return ret;
}
object base{ OT };
option<object_ptr> meta;
mutable native_hash hash{};
};
}