-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathconst_map.c3
More file actions
156 lines (135 loc) · 3.32 KB
/
const_map.c3
File metadata and controls
156 lines (135 loc) · 3.32 KB
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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
module const_map {Key, Value};
import const_map::internal @public;
struct Temp @private {Key key; Value val;}
<*
@require $defined((Key){}.@const_hash) &&& $defined((Key){}.rt_hash) : "The key must support both compile-time and runtime hashing, and both must use the same algorithm"
*>
macro @new_hashed(...) @const
{
Entry {Key, Value, $vacount, true}[$vacount] $temp;
$for var $i = 0; $i < $vacount; $i++:
Temp $t = $vaexpr[$i];
$temp[$i] = {$t.key.@const_hash(), $t.key, $t.val};
$endfor
ConstMap {Key, Value, $vacount, true} $new = {$temp};
return $new;
}
<*
@require $defined(((Key){}) == ((Key){})) : "They key must support the equality operator, but compile-time methods may not work unless it's a builtin type"
*>
macro @new_equal(...) @const
{
Entry {Key, Value, $vacount, false}[$vacount] $temp;
$for var $i = 0; $i < $vacount; $i++:
Temp $t = $vaexpr[$i];
$temp[$i] = {$t.key, $t.val};
$endfor
ConstMap {Key, Value, $vacount, false} $new = {$temp};
return $new;
}
module const_map::internal {Key, Value, SIZE, USE_HASHING} @private;
struct Entry
{
uint hash @if(USE_HASHING);
Key key;
Value val;
}
struct ConstMap
{
Entry[SIZE] data;
}
macro usz ConstMap.len(#self) @const @safemacro @operator(len) => SIZE;
macro ConstMap.@each($self; @body($entry))
{
$for var $i = 0; $i < $self.len(); $i ++:
@body($self.data[$i]);
$endfor
}
macro ConstMap.@each_key($self; @body($key)) => $self.@each(; $entry)
{
$body($entry.key);
}
macro ConstMap.@each_value(&self; @body($value)) => $self.@each(; $entry)
{
$body($entry.value);
}
// Methods using hashing
fn bool ConstMap.has_key(&self, Key key) @if(USE_HASHING)
{
uint hash = key.rt_hash();
foreach (&entry : self.data)
{
if (entry.hash == hash) return true;
}
return false;
}
fn Value? ConstMap.get(&self, Key key) @operator([]) @if(USE_HASHING)
{
uint hash = key.rt_hash();
foreach (&entry : self.data)
{
if (entry.hash == hash) return entry.val;
}
return NOT_FOUND?;
}
macro bool ConstMap.@has_key($self, Key $key) @const @if(USE_HASHING)
{
$for var $i = 0; $i < $self.len(); $i ++:
$if $self.data[$i].hash == $key.@const_hash():
return true;
$endif
$endfor
return false;
}
macro Value ConstMap.@get($self, Key $key) @const @if(USE_HASHING)
{
bool $found;
$for var $i = 0; $i < $self.len(); $i ++:
$if $self.data[$i].hash == $key.@const_hash():
$found = true;
return $self.data[$i].val;
$endif
$endfor
$if !$found:
$error @sprintf("Key '%s' does not exist in the map", $key);
$endif
}
// Methods using equality
fn bool ConstMap.has_key(&self, Key key) @if(!USE_HASHING)
{
foreach (&entry : self.data)
{
if (entry.key == key) return true;
}
return false;
}
fn Value? ConstMap.get(&self, Key key) @operator([]) @if(!USE_HASHING)
{
foreach (&entry : self.data)
{
if (entry.key == key) return entry.val;
}
return NOT_FOUND?;
}
macro bool ConstMap.@has_key($self, Key $key) @const @if(!USE_HASHING)
{
$for var $i = 0; $i < $self.len(); $i ++:
$if $self.data[$i].key == $key:
return true;
$endif
$endfor
return false;
}
macro Value ConstMap.@get($self, Key $key) @const @if(!USE_HASHING)
{
bool $found;
$for var $i = 0; $i < $self.len(); $i ++:
$if $self.data[$i].key == $key:
$found = true;
return $self.data[$i].val;
$endif
$endfor
$if !$found:
$error @sprintf("Key '%s' does not exist in the map", $key);
$endif
}