/home/uke/oil/mycpp/my_runtime.h
Line | Count | Source (jump to first uncovered line) |
1 | | // my_runtime.h: Statically typed Python builtins. |
2 | | // |
3 | | // Builtin types: tuples, NotImplementedError, AssertionError |
4 | | // Builtin functions: print(), repr(), ord() |
5 | | // Builtin operators: str_concat(), str_repeat(), list_repeat() |
6 | | // Builtin methods: Str::join, etc. Note that Str is declared in gc_heap.h. |
7 | | // |
8 | | // TODO: Rename this file to my_builtins.{h,cc}? |
9 | | |
10 | | #ifndef MY_RUNTIME_H |
11 | | #define MY_RUNTIME_H |
12 | | |
13 | | #include <algorithm> // min(), sort() |
14 | | #include <climits> // CHAR_BIT |
15 | | |
16 | | #include "gc_heap.h" |
17 | | |
18 | | // TODO: Don't use 'using' in header |
19 | | using gc_heap::AllocStr; |
20 | | using gc_heap::CopyStr; |
21 | | using gc_heap::Dict; |
22 | | using gc_heap::List; |
23 | | using gc_heap::StackRoots; |
24 | | using gc_heap::Str; |
25 | | |
26 | | class IndexError {}; |
27 | | class ValueError {}; |
28 | | class KeyError {}; |
29 | | |
30 | | class EOFError {}; |
31 | | |
32 | | class NotImplementedError { |
33 | | public: |
34 | 0 | NotImplementedError() { |
35 | 0 | } |
36 | 0 | explicit NotImplementedError(int i) { // e.g. in expr_to_ast |
37 | 0 | } |
38 | 0 | explicit NotImplementedError(const char* s) { |
39 | 0 | } |
40 | 0 | explicit NotImplementedError(Str* s) { |
41 | 0 | } |
42 | | }; |
43 | | |
44 | | class AssertionError { |
45 | | public: |
46 | 0 | AssertionError() { |
47 | 0 | } |
48 | 0 | explicit AssertionError(int i) { // e.g. in expr_to_ast |
49 | 0 | } |
50 | 0 | explicit AssertionError(const char* s) { |
51 | 0 | } |
52 | 0 | explicit AssertionError(Str* s) { |
53 | 0 | } |
54 | | }; |
55 | | |
56 | | template <class A, class B> |
57 | | class Tuple2 { |
58 | | public: |
59 | 113 | Tuple2(A a, B b) : a_(a), b_(b) { |
60 | 113 | } _ZN6Tuple2IPN7gc_heap3StrES2_EC2ES2_S2_ Line | Count | Source | 59 | 1 | Tuple2(A a, B b) : a_(a), b_(b) { | 60 | 1 | } |
_ZN6Tuple2IiPN7gc_heap3StrEEC2EiS2_ Line | Count | Source | 59 | 6 | Tuple2(A a, B b) : a_(a), b_(b) { | 60 | 6 | } |
_ZN6Tuple2IPN7gc_heap3StrEiEC2ES2_i Line | Count | Source | 59 | 48 | Tuple2(A a, B b) : a_(a), b_(b) { | 60 | 48 | } |
_ZN6Tuple2IN9expr_asdl5tok_eEPN7gc_heap3StrEEC2ES1_S4_ Line | Count | Source | 59 | 58 | Tuple2(A a, B b) : a_(a), b_(b) { | 60 | 58 | } |
|
61 | 116 | A at0() { |
62 | 116 | return a_; |
63 | 116 | } _ZN6Tuple2IPN7gc_heap3StrES2_E3at0Ev Line | Count | Source | 61 | 1 | A at0() { | 62 | 1 | return a_; | 63 | 1 | } |
_ZN6Tuple2IiPN7gc_heap3StrEE3at0Ev Line | Count | Source | 61 | 9 | A at0() { | 62 | 9 | return a_; | 63 | 9 | } |
_ZN6Tuple2IPN7gc_heap3StrEiE3at0Ev Line | Count | Source | 61 | 48 | A at0() { | 62 | 48 | return a_; | 63 | 48 | } |
_ZN6Tuple2IN9expr_asdl5tok_eEPN7gc_heap3StrEE3at0Ev Line | Count | Source | 61 | 58 | A at0() { | 62 | 58 | return a_; | 63 | 58 | } |
|
64 | 114 | B at1() { |
65 | 114 | return b_; |
66 | 114 | } _ZN6Tuple2IPN7gc_heap3StrES2_E3at1Ev Line | Count | Source | 64 | 1 | B at1() { | 65 | 1 | return b_; | 66 | 1 | } |
_ZN6Tuple2IiPN7gc_heap3StrEE3at1Ev Line | Count | Source | 64 | 9 | B at1() { | 65 | 9 | return b_; | 66 | 9 | } |
_ZN6Tuple2IPN7gc_heap3StrEiE3at1Ev Line | Count | Source | 64 | 46 | B at1() { | 65 | 46 | return b_; | 66 | 46 | } |
_ZN6Tuple2IN9expr_asdl5tok_eEPN7gc_heap3StrEE3at1Ev Line | Count | Source | 64 | 58 | B at1() { | 65 | 58 | return b_; | 66 | 58 | } |
|
67 | | |
68 | | private: |
69 | | A a_; |
70 | | B b_; |
71 | | }; |
72 | | |
73 | | template <class A, class B, class C> |
74 | | class Tuple3 { |
75 | | public: |
76 | | Tuple3(A a, B b, C c) : a_(a), b_(b), c_(c) { |
77 | | } |
78 | | A at0() { |
79 | | return a_; |
80 | | } |
81 | | B at1() { |
82 | | return b_; |
83 | | } |
84 | | C at2() { |
85 | | return c_; |
86 | | } |
87 | | |
88 | | private: |
89 | | A a_; |
90 | | B b_; |
91 | | C c_; |
92 | | }; |
93 | | |
94 | | template <class A, class B, class C, class D> |
95 | | class Tuple4 { |
96 | | public: |
97 | | Tuple4(A a, B b, C c, D d) : a_(a), b_(b), c_(c), d_(d) { |
98 | | } |
99 | | A at0() { |
100 | | return a_; |
101 | | } |
102 | | B at1() { |
103 | | return b_; |
104 | | } |
105 | | C at2() { |
106 | | return c_; |
107 | | } |
108 | | D at3() { |
109 | | return d_; |
110 | | } |
111 | | |
112 | | private: |
113 | | A a_; |
114 | | B b_; |
115 | | C c_; |
116 | | D d_; |
117 | | }; |
118 | | |
119 | | void println_stderr(Str* s); |
120 | | |
121 | | void print(Str* s); |
122 | | |
123 | | Str* repr(Str* s); |
124 | | |
125 | | // |
126 | | // Conversion Functions |
127 | | // |
128 | | |
129 | | bool _str_to_int(Str* s, int* result, int base); // for testing only |
130 | | int to_int(Str* s); |
131 | | int to_int(Str* s, int base); |
132 | | |
133 | | // int(a == b) used in arithmetic evaluator |
134 | 0 | inline int to_int(bool b) { |
135 | 0 | return b; |
136 | 0 | } |
137 | | |
138 | 1 | inline bool to_bool(int i) { |
139 | 1 | return i != 0; |
140 | 1 | } |
141 | | |
142 | 0 | inline bool to_bool(Str* s) { |
143 | 0 | return len(s) != 0; |
144 | 0 | } |
145 | | |
146 | 0 | inline double to_float(Str* s) { |
147 | 0 | NotImplemented(); // Uncalled |
148 | 0 | } |
149 | | |
150 | | // https://stackoverflow.com/questions/3919995/determining-sprintf-buffer-size-whats-the-standard/11092994#11092994 |
151 | | // Notes: |
152 | | // - Python 2.7's intobject.c has an erroneous +6 |
153 | | // - This is 13, but len('-2147483648') is 11, which means we only need 12? |
154 | | // - This formula is valid for octal(), because 2^(3 bits) = 8 |
155 | | const int kIntBufSize = CHAR_BIT * sizeof(int) / 3 + 3; |
156 | | |
157 | 14 | inline Str* str(int i) { |
158 | | // Use a static buffer first because we don't know what n is until we call |
159 | | // snprintf(). |
160 | 14 | char buf[kIntBufSize]; |
161 | 14 | int length = snprintf(buf, kIntBufSize, "%d", i); |
162 | 14 | return CopyStr(buf, length); |
163 | 14 | } |
164 | | |
165 | 0 | inline Str* str(double f) { // TODO: should be double |
166 | 0 | NotImplemented(); // Uncalled |
167 | 0 | } |
168 | | |
169 | 433 | inline int ord(Str* s) { |
170 | 433 | assert(len(s) == 1); |
171 | | // signed to unsigned conversion, so we don't get values like -127 |
172 | 0 | uint8_t c = static_cast<uint8_t>(s->data_[0]); |
173 | 433 | return c; |
174 | 433 | } |
175 | | |
176 | 430 | inline Str* chr(int i) { |
177 | 430 | auto result = AllocStr(1); |
178 | 430 | result->data_[0] = i; |
179 | 430 | return result; |
180 | 430 | } |
181 | | |
182 | | // |
183 | | // Comparison and Sorting |
184 | | // |
185 | | |
186 | 8 | inline int int_cmp(int a, int b) { |
187 | 8 | if (a == b) { |
188 | 2 | return 0; |
189 | 2 | } |
190 | 6 | return a < b ? -1 : 1; |
191 | 8 | } |
192 | | |
193 | | // Used by [[ a > b ]] and so forth |
194 | 0 | inline int str_cmp(gc_heap::Str* a, gc_heap::Str* b) { |
195 | 0 | int len_a = len(a); |
196 | 0 | int len_b = len(b); |
197 | 0 |
|
198 | 0 | int min = std::min(len_a, len_b); |
199 | 0 | if (min == 0) { |
200 | 0 | return int_cmp(len_a, len_b); |
201 | 0 | } |
202 | 0 | int comp = memcmp(a->data_, b->data_, min); |
203 | 0 | if (comp == 0) { |
204 | 0 | return int_cmp(len_a, len_b); // tiebreaker |
205 | 0 | } |
206 | 0 | return comp; |
207 | 0 | } |
208 | | |
209 | 0 | inline bool _cmp(gc_heap::Str* a, gc_heap::Str* b) { |
210 | 0 | return str_cmp(a, b) < 0; |
211 | 0 | } |
212 | | |
213 | | // This is a METHOD definition. It's in my_runtime.h so that gc_heap.h doesn't |
214 | | // need to #include <algorithm>. I think that would bloat all the ASDL types. |
215 | | template <typename T> |
216 | 0 | void gc_heap::List<T>::sort() { |
217 | 0 | std::sort(slab_->items_, slab_->items_ + len_, _cmp); |
218 | 0 | } |
219 | | |
220 | | template <typename V> |
221 | 0 | List<Str*>* sorted(Dict<Str*, V>* d) { |
222 | 0 | auto keys = d->keys(); |
223 | 0 | keys->sort(); |
224 | 0 | return keys; |
225 | 0 | } |
226 | | |
227 | | // Is this only used by unit tests? |
228 | 7 | inline bool str_equals0(const char* c_string, Str* s) { |
229 | 7 | int n = strlen(c_string); |
230 | 7 | if (len(s) == n) { |
231 | 7 | return memcmp(s->data_, c_string, n) == 0; |
232 | 7 | } else { |
233 | 0 | return false; |
234 | 0 | } |
235 | 7 | } |
236 | | |
237 | | // |
238 | | // Free Standing Str, List, and Dict Functions |
239 | | // |
240 | | |
241 | | Str* str_concat(Str* a, Str* b); // a + b when a and b are strings |
242 | | Str* str_concat3(Str* a, Str* b, Str* c); // for os_path::join() |
243 | | |
244 | | Str* str_repeat(Str* s, int times); // e.g. ' ' * 3 |
245 | | |
246 | | // e.g. ('a' in 'abc') |
247 | 60 | inline bool str_contains(Str* haystack, Str* needle) { |
248 | 60 | if (len(needle) == 1) { |
249 | 60 | return memchr(haystack->data_, needle->data_[0], len(haystack)); |
250 | 60 | } |
251 | | |
252 | | // NOTE(Jesse): Not sure what this TODO means. Remove strstr and do it |
253 | | // ourselves maybe? |
254 | | // TODO: Implement substring |
255 | 0 | assert(0); |
256 | | |
257 | | // cstring-TODO: this not rely on NUL termination |
258 | 0 | const char* p = strstr(haystack->data_, needle->data_); |
259 | 0 | return p != nullptr; |
260 | 60 | } |
261 | | |
262 | | // ints, floats, enums like Kind |
263 | | // e.g. 1 in [1, 2, 3] |
264 | | template <typename T> |
265 | 2 | inline bool list_contains(List<T>* haystack, T needle) { |
266 | | // StackRoots _roots({&haystack}); // doesn't allocate |
267 | | |
268 | 2 | int n = len(haystack); |
269 | 3 | for (int i = 0; i < n; ++i) { |
270 | 3 | if (haystack->index_(i) == needle) { |
271 | 2 | return true; |
272 | 2 | } |
273 | 3 | } |
274 | 0 | return false; |
275 | 2 | } _Z13list_containsIiEbPN7gc_heap4ListIT_EES2_ Line | Count | Source | 265 | 2 | inline bool list_contains(List<T>* haystack, T needle) { | 266 | | // StackRoots _roots({&haystack}); // doesn't allocate | 267 | | | 268 | 2 | int n = len(haystack); | 269 | 3 | for (int i = 0; i < n; ++i) { | 270 | 3 | if (haystack->index_(i) == needle) { | 271 | 2 | return true; | 272 | 2 | } | 273 | 3 | } | 274 | 0 | return false; | 275 | 2 | } |
Unexecuted instantiation: _Z13list_containsIdEbPN7gc_heap4ListIT_EES2_ |
276 | | |
277 | | // e.g. 'a' in ['a', 'b', 'c'] |
278 | 2 | inline bool list_contains(List<Str*>* haystack, Str* needle) { |
279 | | // StackRoots _roots({&haystack, &needle}); // doesn't allocate |
280 | | |
281 | 2 | int n = len(haystack); |
282 | 4 | for (int i = 0; i < n; ++i) { |
283 | 3 | if (str_equals(haystack->index_(i), needle)) { |
284 | 1 | return true; |
285 | 1 | } |
286 | 3 | } |
287 | 1 | return false; |
288 | 2 | } |
289 | | |
290 | | // TODO: mycpp can just generate the constructor instead? |
291 | | // e.g. [None] * 3 |
292 | | template <typename T> |
293 | 1 | List<T>* list_repeat(T item, int times) { |
294 | 1 | return gc_heap::NewList<T>(item, times); |
295 | 1 | } _Z11list_repeatIPN7gc_heap3StrEEPNS0_4ListIT_EES4_i Line | Count | Source | 293 | 1 | List<T>* list_repeat(T item, int times) { | 294 | 1 | return gc_heap::NewList<T>(item, times); | 295 | 1 | } |
Unexecuted instantiation: _Z11list_repeatIbEPN7gc_heap4ListIT_EES2_i |
296 | | |
297 | | template <typename K, typename V> |
298 | 0 | inline bool dict_contains(Dict<K, V>* haystack, K needle) { |
299 | 0 | return haystack->position_of_key(needle) != -1; |
300 | 0 | } Unexecuted instantiation: _Z13dict_containsIiPN7gc_heap3StrEEbPNS0_4DictIT_T0_EES4_ Unexecuted instantiation: _Z13dict_containsIPN7gc_heap3StrEiEbPNS0_4DictIT_T0_EES4_ |
301 | | |
302 | | // NOTE: This iterates over bytes. |
303 | | class StrIter { |
304 | | public: |
305 | 120 | explicit StrIter(Str* s) : s_(s), i_(0), len_(len(s)) { |
306 | | // We need this because StrIter is directly on the stack, and s_ could be |
307 | | // moved during iteration. |
308 | 120 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&s_)); |
309 | 120 | } |
310 | 120 | ~StrIter() { |
311 | 120 | gc_heap::gHeap.PopRoot(); |
312 | 120 | } |
313 | 146 | void Next() { |
314 | 146 | i_++; |
315 | 146 | } |
316 | 266 | bool Done() { |
317 | 266 | return i_ >= len_; |
318 | 266 | } |
319 | 147 | Str* Value() { // similar to index_() |
320 | 147 | Str* result = AllocStr(1); |
321 | 147 | result->data_[0] = s_->data_[i_]; |
322 | | // assert(result->data_[1] == '\0'); |
323 | 147 | return result; |
324 | 147 | } |
325 | | |
326 | | private: |
327 | | Str* s_; |
328 | | int i_; |
329 | | int len_; |
330 | | |
331 | | DISALLOW_COPY_AND_ASSIGN(StrIter) |
332 | | }; |
333 | | |
334 | | template <class T> |
335 | | class ListIter { |
336 | | public: |
337 | 103 | explicit ListIter(List<T>* L) : L_(L), i_(0) { |
338 | | // We need this because ListIter is directly on the stack, and L_ could be |
339 | | // moved during iteration. |
340 | 103 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); |
341 | 103 | } _ZN8ListIterIiEC2EPN7gc_heap4ListIiEE Line | Count | Source | 337 | 4 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 4 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 4 | } |
_ZN8ListIterIPN7gc_heap3StrEEC2EPNS0_4ListIS2_EE Line | Count | Source | 337 | 16 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 16 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 16 | } |
_ZN8ListIterIP6Tuple2IPN7gc_heap3StrEiEEC2EPNS1_4ListIS5_EE Line | Count | Source | 337 | 1 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 1 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 1 | } |
_ZN8ListIterIP6Tuple2IiPN7gc_heap3StrEEEC2EPNS1_4ListIS5_EE Line | Count | Source | 337 | 2 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 2 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 2 | } |
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEEC2EPN7gc_heap4ListIS2_EE _ZN8ListIterIPN10hnode_asdl5fieldEEC2EPN7gc_heap4ListIS2_EE Line | Count | Source | 337 | 79 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 79 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 79 | } |
_ZN8ListIterIbEC2EPN7gc_heap4ListIbEE Line | Count | Source | 337 | 1 | explicit ListIter(List<T>* L) : L_(L), i_(0) { | 338 | | // We need this because ListIter is directly on the stack, and L_ could be | 339 | | // moved during iteration. | 340 | 1 | gc_heap::gHeap.PushRoot(reinterpret_cast<gc_heap::Obj**>(&L_)); | 341 | 1 | } |
|
342 | 103 | ~ListIter() { |
343 | 103 | gc_heap::gHeap.PopRoot(); |
344 | 103 | } Line | Count | Source | 342 | 4 | ~ListIter() { | 343 | 4 | gc_heap::gHeap.PopRoot(); | 344 | 4 | } |
_ZN8ListIterIPN7gc_heap3StrEED2Ev Line | Count | Source | 342 | 16 | ~ListIter() { | 343 | 16 | gc_heap::gHeap.PopRoot(); | 344 | 16 | } |
_ZN8ListIterIP6Tuple2IPN7gc_heap3StrEiEED2Ev Line | Count | Source | 342 | 1 | ~ListIter() { | 343 | 1 | gc_heap::gHeap.PopRoot(); | 344 | 1 | } |
_ZN8ListIterIP6Tuple2IiPN7gc_heap3StrEEED2Ev Line | Count | Source | 342 | 2 | ~ListIter() { | 343 | 2 | gc_heap::gHeap.PopRoot(); | 344 | 2 | } |
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEED2Ev _ZN8ListIterIPN10hnode_asdl5fieldEED2Ev Line | Count | Source | 342 | 79 | ~ListIter() { | 343 | 79 | gc_heap::gHeap.PopRoot(); | 344 | 79 | } |
Line | Count | Source | 342 | 1 | ~ListIter() { | 343 | 1 | gc_heap::gHeap.PopRoot(); | 344 | 1 | } |
|
345 | 220 | void Next() { |
346 | 220 | i_++; |
347 | 220 | } Line | Count | Source | 345 | 16 | void Next() { | 346 | 16 | i_++; | 347 | 16 | } |
_ZN8ListIterIPN7gc_heap3StrEE4NextEv Line | Count | Source | 345 | 78 | void Next() { | 346 | 78 | i_++; | 347 | 78 | } |
_ZN8ListIterIP6Tuple2IPN7gc_heap3StrEiEE4NextEv Line | Count | Source | 345 | 2 | void Next() { | 346 | 2 | i_++; | 347 | 2 | } |
_ZN8ListIterIP6Tuple2IiPN7gc_heap3StrEEE4NextEv Line | Count | Source | 345 | 4 | void Next() { | 346 | 4 | i_++; | 347 | 4 | } |
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE4NextEv _ZN8ListIterIPN10hnode_asdl5fieldEE4NextEv Line | Count | Source | 345 | 118 | void Next() { | 346 | 118 | i_++; | 347 | 118 | } |
Line | Count | Source | 345 | 2 | void Next() { | 346 | 2 | i_++; | 347 | 2 | } |
|
348 | 324 | bool Done() { |
349 | | // "unsigned size_t was a mistake" |
350 | 324 | return i_ >= static_cast<int>(L_->len_); |
351 | 324 | } Line | Count | Source | 348 | 21 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 21 | return i_ >= static_cast<int>(L_->len_); | 351 | 21 | } |
_ZN8ListIterIPN7gc_heap3StrEE4DoneEv Line | Count | Source | 348 | 94 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 94 | return i_ >= static_cast<int>(L_->len_); | 351 | 94 | } |
_ZN8ListIterIP6Tuple2IPN7gc_heap3StrEiEE4DoneEv Line | Count | Source | 348 | 3 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 3 | return i_ >= static_cast<int>(L_->len_); | 351 | 3 | } |
_ZN8ListIterIP6Tuple2IiPN7gc_heap3StrEEE4DoneEv Line | Count | Source | 348 | 6 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 6 | return i_ >= static_cast<int>(L_->len_); | 351 | 6 | } |
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE4DoneEv _ZN8ListIterIPN10hnode_asdl5fieldEE4DoneEv Line | Count | Source | 348 | 197 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 197 | return i_ >= static_cast<int>(L_->len_); | 351 | 197 | } |
Line | Count | Source | 348 | 3 | bool Done() { | 349 | | // "unsigned size_t was a mistake" | 350 | 3 | return i_ >= static_cast<int>(L_->len_); | 351 | 3 | } |
|
352 | 244 | T Value() { |
353 | 244 | return L_->slab_->items_[i_]; |
354 | 244 | } Line | Count | Source | 352 | 16 | T Value() { | 353 | 16 | return L_->slab_->items_[i_]; | 354 | 16 | } |
_ZN8ListIterIPN7gc_heap3StrEE5ValueEv Line | Count | Source | 352 | 79 | T Value() { | 353 | 79 | return L_->slab_->items_[i_]; | 354 | 79 | } |
_ZN8ListIterIP6Tuple2IPN7gc_heap3StrEiEE5ValueEv Line | Count | Source | 352 | 2 | T Value() { | 353 | 2 | return L_->slab_->items_[i_]; | 354 | 2 | } |
_ZN8ListIterIP6Tuple2IiPN7gc_heap3StrEEE5ValueEv Line | Count | Source | 352 | 4 | T Value() { | 353 | 4 | return L_->slab_->items_[i_]; | 354 | 4 | } |
Unexecuted instantiation: _ZN8ListIterIPN10hnode_asdl7hnode_tEE5ValueEv _ZN8ListIterIPN10hnode_asdl5fieldEE5ValueEv Line | Count | Source | 352 | 141 | T Value() { | 353 | 141 | return L_->slab_->items_[i_]; | 354 | 141 | } |
Line | Count | Source | 352 | 2 | T Value() { | 353 | 2 | return L_->slab_->items_[i_]; | 354 | 2 | } |
|
355 | | |
356 | | private: |
357 | | List<T>* L_; |
358 | | int i_; |
359 | | }; |
360 | | |
361 | | // TODO: Does using pointers rather than indices make this more efficient? |
362 | | template <class T> |
363 | | class ReverseListIter { |
364 | | public: |
365 | 2 | explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) { |
366 | 2 | } Unexecuted instantiation: _ZN15ReverseListIterIiEC2EPN7gc_heap4ListIiEE _ZN15ReverseListIterIPN7gc_heap3StrEEC2EPNS0_4ListIS2_EE Line | Count | Source | 365 | 1 | explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) { | 366 | 1 | } |
_ZN15ReverseListIterIP6Tuple2IiPN7gc_heap3StrEEEC2EPNS1_4ListIS5_EE Line | Count | Source | 365 | 1 | explicit ReverseListIter(List<T>* L) : L_(L), i_(L_->len_ - 1) { | 366 | 1 | } |
|
367 | 7 | void Next() { |
368 | 7 | i_--; |
369 | 7 | } _ZN15ReverseListIterIiE4NextEv Line | Count | Source | 367 | 3 | void Next() { | 368 | 3 | i_--; | 369 | 3 | } |
_ZN15ReverseListIterIPN7gc_heap3StrEE4NextEv Line | Count | Source | 367 | 2 | void Next() { | 368 | 2 | i_--; | 369 | 2 | } |
_ZN15ReverseListIterIP6Tuple2IiPN7gc_heap3StrEEE4NextEv Line | Count | Source | 367 | 2 | void Next() { | 368 | 2 | i_--; | 369 | 2 | } |
|
370 | 10 | bool Done() { |
371 | 10 | return i_ < 0; |
372 | 10 | } _ZN15ReverseListIterIiE4DoneEv Line | Count | Source | 370 | 4 | bool Done() { | 371 | 4 | return i_ < 0; | 372 | 4 | } |
_ZN15ReverseListIterIPN7gc_heap3StrEE4DoneEv Line | Count | Source | 370 | 3 | bool Done() { | 371 | 3 | return i_ < 0; | 372 | 3 | } |
_ZN15ReverseListIterIP6Tuple2IiPN7gc_heap3StrEEE4DoneEv Line | Count | Source | 370 | 3 | bool Done() { | 371 | 3 | return i_ < 0; | 372 | 3 | } |
|
373 | 7 | T Value() { |
374 | 7 | return L_->slab_->items_[i_]; |
375 | 7 | } _ZN15ReverseListIterIiE5ValueEv Line | Count | Source | 373 | 3 | T Value() { | 374 | 3 | return L_->slab_->items_[i_]; | 375 | 3 | } |
_ZN15ReverseListIterIPN7gc_heap3StrEE5ValueEv Line | Count | Source | 373 | 2 | T Value() { | 374 | 2 | return L_->slab_->items_[i_]; | 375 | 2 | } |
_ZN15ReverseListIterIP6Tuple2IiPN7gc_heap3StrEEE5ValueEv Line | Count | Source | 373 | 2 | T Value() { | 374 | 2 | return L_->slab_->items_[i_]; | 375 | 2 | } |
|
376 | | |
377 | | private: |
378 | | List<T>* L_; |
379 | | int i_; |
380 | | }; |
381 | | |
382 | | // TODO: |
383 | | // - Look at entry_ to see if an item is deleted (or is a tombstone once we |
384 | | // have hash chaining) |
385 | | |
386 | | template <class K, class V> |
387 | | class DictIter { |
388 | | public: |
389 | 3 | explicit DictIter(Dict<K, V>* D) : D_(D), pos_(ValidPosAfter(0)) { |
390 | 3 | } _ZN8DictIterIPN7gc_heap3StrEiEC2EPNS0_4DictIS2_iEE Line | Count | Source | 389 | 3 | explicit DictIter(Dict<K, V>* D) : D_(D), pos_(ValidPosAfter(0)) { | 390 | 3 | } |
Unexecuted instantiation: _ZN8DictIterIPN7gc_heap3StrES2_EC2EPNS0_4DictIS2_S2_EE |
391 | 9 | void Next() { |
392 | 9 | pos_ = ValidPosAfter(pos_ + 1); |
393 | 9 | } _ZN8DictIterIPN7gc_heap3StrEiE4NextEv Line | Count | Source | 391 | 9 | void Next() { | 392 | 9 | pos_ = ValidPosAfter(pos_ + 1); | 393 | 9 | } |
Unexecuted instantiation: _ZN8DictIterIPN7gc_heap3StrES2_E4NextEv |
394 | 12 | bool Done() { |
395 | 12 | return pos_ == -1; |
396 | 12 | } _ZN8DictIterIPN7gc_heap3StrEiE4DoneEv Line | Count | Source | 394 | 12 | bool Done() { | 395 | 12 | return pos_ == -1; | 396 | 12 | } |
Unexecuted instantiation: _ZN8DictIterIPN7gc_heap3StrES2_E4DoneEv |
397 | 9 | K Key() { |
398 | 9 | return D_->keys_->items_[pos_]; |
399 | 9 | } _ZN8DictIterIPN7gc_heap3StrEiE3KeyEv Line | Count | Source | 397 | 9 | K Key() { | 398 | 9 | return D_->keys_->items_[pos_]; | 399 | 9 | } |
Unexecuted instantiation: _ZN8DictIterIPN7gc_heap3StrES2_E3KeyEv |
400 | 6 | V Value() { |
401 | 6 | return D_->values_->items_[pos_]; |
402 | 6 | } |
403 | | |
404 | | private: |
405 | 12 | int ValidPosAfter(int pos) { |
406 | | // Returns the position of a valid entry at or after index i_. Or -1 if |
407 | | // there isn't one. Advances i_ too. |
408 | 12 | while (true) { |
409 | 12 | if (pos >= D_->capacity_) { |
410 | 0 | return -1; |
411 | 0 | } |
412 | 12 | int index = D_->entry_->items_[pos]; |
413 | 12 | if (index == gc_heap::kDeletedEntry) { |
414 | 0 | ++pos; |
415 | 0 | continue; // increment again |
416 | 0 | } |
417 | 12 | if (index == gc_heap::kEmptyEntry) { |
418 | 3 | return -1; |
419 | 3 | } |
420 | 9 | break; |
421 | 12 | } |
422 | 9 | return pos; |
423 | 12 | } _ZN8DictIterIPN7gc_heap3StrEiE13ValidPosAfterEi Line | Count | Source | 405 | 12 | int ValidPosAfter(int pos) { | 406 | | // Returns the position of a valid entry at or after index i_. Or -1 if | 407 | | // there isn't one. Advances i_ too. | 408 | 12 | while (true) { | 409 | 12 | if (pos >= D_->capacity_) { | 410 | 0 | return -1; | 411 | 0 | } | 412 | 12 | int index = D_->entry_->items_[pos]; | 413 | 12 | if (index == gc_heap::kDeletedEntry) { | 414 | 0 | ++pos; | 415 | 0 | continue; // increment again | 416 | 0 | } | 417 | 12 | if (index == gc_heap::kEmptyEntry) { | 418 | 3 | return -1; | 419 | 3 | } | 420 | 9 | break; | 421 | 12 | } | 422 | 9 | return pos; | 423 | 12 | } |
Unexecuted instantiation: _ZN8DictIterIPN7gc_heap3StrES2_E13ValidPosAfterEi |
424 | | |
425 | | Dict<K, V>* D_; |
426 | | int pos_; |
427 | | }; |
428 | | |
429 | | #endif // MY_RUNTIME_H |