obj_dict.c
1 #include <string.h>
2 #include <kuroko/vm.h>
3 #include <kuroko/value.h>
4 #include <kuroko/memory.h>
5 #include <kuroko/util.h>
6 
7 #if defined(__TINYC__) || (defined(_MSC_VER) && !defined(__clang__))
8 static int __builtin_clz(unsigned int x) {
9  int i = 31;
10  while (!(x & (1 << i)) && i >= 0) i--;
11  return 31-i;
12 }
13 #endif
14 
19 KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw) {
20  if (argc % 2 != 0) return krk_runtimeError(vm.exceptions->argumentError, "Expected even number of arguments to krk_dict_of");
21  KrkInstance * outDict = krk_newInstance(vm.baseClasses->dictClass);
22  krk_push(OBJECT_VAL(outDict));
23  krk_initTable(&((KrkDict*)outDict)->entries);
24  if (argc) {
25  size_t capacity = argc;
26  size_t powerOfTwoCapacity = __builtin_clz(1) - __builtin_clz(capacity);
27  if ((1UL << powerOfTwoCapacity) != capacity) powerOfTwoCapacity++;
28  capacity = (1UL << powerOfTwoCapacity);
29  krk_tableAdjustCapacity(&((KrkDict*)outDict)->entries, capacity);
30  for (int ind = 0; ind < argc; ind += 2) {
31  krk_tableSet(&((KrkDict*)outDict)->entries, argv[ind], argv[ind+1]);
32  }
33  }
34  return krk_pop();
35 }
36 
37 static void _dict_gcscan(KrkInstance * self) {
38  krk_markTable(&((KrkDict*)self)->entries);
39 }
40 
41 static void _dict_gcsweep(KrkInstance * self) {
42  krk_freeTable(&((KrkDict*)self)->entries);
43 }
44 
45 #define CURRENT_CTYPE KrkDict *
46 #define CURRENT_NAME self
47 
49  KrkDict * self;
50  KrkValue key;
51  int counter;
52 };
53 
54 static int _keyvalue_pair_callback(void * context, const KrkValue * entries, size_t count) {
55  struct _keyvalue_pair_context * _context = context;
56 
57  if (count > 2) {
58  _context->counter = count;
59  return 1;
60  }
61 
62  for (size_t i = 0; i < count; ++i) {
63  if (_context->counter == 0) {
64  _context->counter = 1;
65  _context->key = entries[i];
66  } else if (_context->counter == 1) {
67  _context->counter = 2;
68  krk_tableSet(&_context->self->entries, _context->key, entries[i]);
69  } else {
70  _context->counter = -1;
71  return 1;
72  }
73  }
74 
75  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
76  return 0;
77 }
78 
79 static int unpackKeyValuePair(void * self, const KrkValue * pairs, size_t count) {
80  struct _keyvalue_pair_context context = { (KrkDict*)self, NONE_VAL(), 0 };
81 
82  for (size_t i = 0; i < count; ++i) {
83  if (krk_unpackIterable(pairs[i], &context, _keyvalue_pair_callback)) return 1;
84  }
85 
86  if (context.counter != 2) {
87  krk_runtimeError(vm.exceptions->valueError, "dictionary update sequence element has invalid length");
88  return 1;
89  }
90  return 0;
91 }
92 
93 KRK_Method(dict,__init__) {
94  METHOD_TAKES_AT_MOST(1);
95  krk_initTable(&self->entries);
96 
97  if (argc > 1) {
98  if (krk_unpackIterable(argv[1], self, unpackKeyValuePair)) return NONE_VAL();
99  }
100 
101  if (hasKw) {
102  krk_tableAddAll(AS_DICT(argv[argc]), &self->entries);
103  }
104 
105  return NONE_VAL();
106 }
107 
108 KRK_Method(dict,__eq__) {
109  METHOD_TAKES_EXACTLY(1);
110  if (!IS_dict(argv[1]))
111  return NOTIMPL_VAL();
112  CHECK_ARG(1,dict,KrkDict*,them);
113  if (self->entries.count != them->entries.count)
114  return BOOLEAN_VAL(0);
115 
116 
117  for (unsigned int i = 0; i < self->entries.capacity; ++i) {
118  if (IS_KWARGS(self->entries.entries[i].key)) continue;
119  KrkValue val;
120  if (!krk_tableGet(&them->entries, self->entries.entries[i].key, &val)) return BOOLEAN_VAL(0);
121  if (!krk_valuesSameOrEqual(self->entries.entries[i].value, val)) return BOOLEAN_VAL(0);
122  }
123 
124  return BOOLEAN_VAL(1);
125 }
126 
127 
128 KRK_Method(dict,__getitem__) {
129  METHOD_TAKES_EXACTLY(1);
130  KrkValue out;
131  if (!krk_tableGet(&self->entries, argv[1], &out)) {
132  if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
133  return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
134  }
135  return out;
136 }
137 
138 KRK_Method(dict,__setitem__) {
139  METHOD_TAKES_EXACTLY(2);
140  krk_tableSet(&self->entries, argv[1], argv[2]);
141  return argv[2];
142 }
143 
144 KRK_Method(dict,__or__) {
145  METHOD_TAKES_EXACTLY(1);
146  CHECK_ARG(1,dict,KrkDict*,them);
147  KrkValue outDict = krk_dict_of(0,NULL,0);
148  krk_push(outDict);
149  krk_tableAddAll(&self->entries, AS_DICT(outDict));
150  krk_tableAddAll(&them->entries, AS_DICT(outDict));
151  return krk_pop();
152 }
153 
154 KRK_Method(dict,__delitem__) {
155  METHOD_TAKES_EXACTLY(1);
156  if (!krk_tableDelete(&self->entries, argv[1])) {
157  if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
158  return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
159  }
160  return NONE_VAL();
161 }
162 
163 KRK_Method(dict,__len__) {
164  METHOD_TAKES_NONE();
165  return INTEGER_VAL(self->entries.count);
166 }
167 
168 KRK_Method(dict,__contains__) {
169  METHOD_TAKES_EXACTLY(1);
170  KrkValue v;
171  return BOOLEAN_VAL(krk_tableGet(&self->entries, argv[1], &v));
172 }
173 
174 KRK_Method(dict,capacity) {
175  METHOD_TAKES_NONE();
176  return INTEGER_VAL(self->entries.capacity);
177 }
178 
179 KRK_Method(dict,__repr__) {
180  METHOD_TAKES_NONE();
181  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("{...}"));
182  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
183  struct StringBuilder sb = {0};
184  pushStringBuilder(&sb,'{');
185 
186  size_t c = 0;
187  size_t len = self->entries.capacity;
188  for (size_t i = 0; i < len; ++i) {
189  KrkTableEntry * entry = &self->entries.entries[i];
190  if (IS_KWARGS(entry->key)) continue;
191  if (c) pushStringBuilderStr(&sb, ", ", 2);
192  c++;
193  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->key)) goto _error;
194  pushStringBuilderStr(&sb, ": ", 2);
195  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->value)) goto _error;
196  }
197 
198  pushStringBuilder(&sb,'}');
199  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
200  return finishStringBuilder(&sb);
201 
202 _error:
203  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
205  return NONE_VAL();
206 }
207 
208 KRK_Method(dict,copy) {
209  METHOD_TAKES_NONE();
210  KrkValue dictOut = krk_dict_of(0,NULL,0);
211  krk_push(dictOut);
212  krk_tableAddAll(&self->entries, AS_DICT(dictOut));
213  return krk_pop();
214 }
215 
216 KRK_Method(dict,clear) {
217  METHOD_TAKES_NONE();
218  krk_freeTable(&self->entries);
219  return NONE_VAL();
220 }
221 
222 KRK_Method(dict,get) {
223  METHOD_TAKES_AT_LEAST(1);
224  METHOD_TAKES_AT_MOST(2);
225  KrkValue out = NONE_VAL();
226  if (argc > 2) out = argv[2];
227  krk_tableGet(&self->entries, argv[1], &out);
228  return out;
229 }
230 
231 KRK_Method(dict,setdefault) {
232  METHOD_TAKES_AT_LEAST(1);
233  METHOD_TAKES_AT_MOST(2);
234  KrkValue out = NONE_VAL();
235  if (argc > 2) out = argv[2];
236 
237  /* TODO this is slow; use findEntry instead! */
238  if (!krk_tableGet(&self->entries, argv[1], &out)) {
239  krk_tableSet(&self->entries, argv[1], out);
240  }
241 
242  return out;
243 }
244 
245 KRK_Method(dict,update) {
246  METHOD_TAKES_AT_MOST(1);
247  if (argc > 1) {
248  /* TODO sequence */
249  CHECK_ARG(1,dict,KrkDict*,other);
250  krk_tableAddAll(&other->entries, &self->entries);
251  }
252  if (hasKw) {
253  krk_tableAddAll(AS_DICT(argv[argc]), &self->entries);
254  }
255  return NONE_VAL();
256 }
257 
258 KRK_Method(dict,__ior__) {
259  METHOD_TAKES_EXACTLY(1);
260  CHECK_ARG(1,dict,KrkDict*,other);
261  krk_tableAddAll(&other->entries, &self->entries);
262  return argv[0];
263 }
264 
265 FUNC_SIG(dictkeys,__init__);
266 
267 KRK_Method(dict,keys) {
268  METHOD_TAKES_NONE();
269  KrkInstance * output = krk_newInstance(vm.baseClasses->dictkeysClass);
270  krk_push(OBJECT_VAL(output));
271  FUNC_NAME(dictkeys,__init__)(2, (KrkValue[]){krk_peek(0), argv[0]},0);
272  krk_pop();
273  return OBJECT_VAL(output);
274 }
275 
276 FUNC_SIG(dictitems,__init__);
277 
278 KRK_Method(dict,items) {
279  METHOD_TAKES_NONE();
280  KrkInstance * output = krk_newInstance(vm.baseClasses->dictitemsClass);
281  krk_push(OBJECT_VAL(output));
282  FUNC_NAME(dictitems,__init__)(2, (KrkValue[]){krk_peek(0), argv[0]},0);
283  krk_pop();
284  return OBJECT_VAL(output);
285 }
286 
287 FUNC_SIG(dictvalues,__init__);
288 
289 KRK_Method(dict,values) {
290  METHOD_TAKES_NONE();
291  KrkInstance * output = krk_newInstance(vm.baseClasses->dictvaluesClass);
292  krk_push(OBJECT_VAL(output));
293  FUNC_NAME(dictvalues,__init__)(2, (KrkValue[]){krk_peek(0), argv[0]},0);
294  krk_pop();
295  return OBJECT_VAL(output);
296 }
297 
298 KrkValue krk_dict_nth_key_fast(size_t capacity, KrkTableEntry * entries, size_t index) {
299  size_t found = 0;
300  for (size_t i = 0; i < capacity; ++i) {
301  if (IS_KWARGS(entries[i].key)) continue;
302  if (found == index) return entries[i].key;
303  found++;
304  }
305  return NONE_VAL();
306 }
307 
308 #undef CURRENT_CTYPE
309 #define CURRENT_CTYPE struct DictItems *
310 
311 static void _dictitems_gcscan(KrkInstance * self) {
312  krk_markValue(((struct DictItems*)self)->dict);
313 }
314 
315 KRK_Method(dictitems,__init__) {
316  METHOD_TAKES_EXACTLY(1);
317  CHECK_ARG(1,dict,KrkDict*,source);
318  self->dict = argv[1];
319  self->i = 0;
320  return NONE_VAL();
321 }
322 
323 KRK_Method(dictitems,__iter__) {
324  METHOD_TAKES_NONE();
325  self->i = 0;
326  return argv[0];
327 }
328 
329 KRK_Method(dictitems,__call__) {
330  do {
331  if (self->i >= AS_DICT(self->dict)->used) return argv[0];
332  if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
333  KrkTuple * outValue = krk_newTuple(2);
334  krk_push(OBJECT_VAL(outValue));
335  outValue->values.values[0] = AS_DICT(self->dict)->entries[self->i].key;
336  outValue->values.values[1] = AS_DICT(self->dict)->entries[self->i].value;
337  outValue->values.count = 2;
338  self->i++;
339  return krk_pop();
340  }
341  self->i++;
342  } while (1);
343 }
344 
345 KRK_Method(dictitems,__repr__) {
346  METHOD_TAKES_NONE();
347  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("dictitems([...])"));
348  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
349  struct StringBuilder sb = {0};
350  pushStringBuilderStr(&sb,"dictitems([",11);
351 
352  size_t c = 0;
353  size_t len = AS_DICT(self->dict)->used;
354  for (size_t i = 0; i < len; ++i) {
355  KrkTableEntry * entry = &AS_DICT(self->dict)->entries[i];
356  if (IS_KWARGS(entry->key)) continue;
357  if (c) pushStringBuilderStr(&sb, ", ", 2);
358  c++;
359  pushStringBuilder(&sb,'(');
360  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->key)) goto _error;
361  pushStringBuilderStr(&sb, ", ", 2);
362  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->value)) goto _error;
363  pushStringBuilder(&sb,')');
364  }
365 
366  pushStringBuilderStr(&sb,"])",2);
367  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
368  return finishStringBuilder(&sb);
369 
370 _error:
371  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
373  return NONE_VAL();
374 }
375 
376 #undef CURRENT_CTYPE
377 #define CURRENT_CTYPE struct DictKeys *
378 
379 static void _dictkeys_gcscan(KrkInstance * self) {
380  krk_markValue(((struct DictKeys*)self)->dict);
381 }
382 
383 KRK_Method(dictkeys,__init__) {
384  METHOD_TAKES_EXACTLY(1);
385  CHECK_ARG(1,dict,KrkDict*,source);
386  self->dict = argv[1];
387  self->i = 0;
388  return NONE_VAL();
389 }
390 
391 KRK_Method(dictkeys,__iter__) {
392  METHOD_TAKES_NONE();
393  self->i = 0;
394  return argv[0];
395 }
396 
397 KRK_Method(dictkeys,__call__) {
398  METHOD_TAKES_NONE();
399  do {
400  if (self->i >= AS_DICT(self->dict)->used) return argv[0];
401  if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
402  krk_push(AS_DICT(self->dict)->entries[self->i].key);
403  self->i++;
404  return krk_pop();
405  }
406  self->i++;
407  } while (1);
408 }
409 
410 KRK_Method(dictkeys,__repr__) {
411  METHOD_TAKES_NONE();
412  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("dictkeys([...])"));
413  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
414  struct StringBuilder sb = {0};
415  pushStringBuilderStr(&sb,"dictkeys([",10);
416 
417  size_t c = 0;
418  size_t len = AS_DICT(self->dict)->used;
419  for (size_t i = 0; i < len; ++i) {
420  KrkTableEntry * entry = &AS_DICT(self->dict)->entries[i];
421  if (IS_KWARGS(entry->key)) continue;
422  if (c) pushStringBuilderStr(&sb, ", ", 2);
423  c++;
424  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->key)) goto _error;
425  }
426 
427  pushStringBuilderStr(&sb,"])",2);
428  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
429  return finishStringBuilder(&sb);
430 
431 _error:
432  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
434  return NONE_VAL();
435 }
436 
437 #undef CURRENT_CTYPE
438 #define CURRENT_CTYPE struct DictValues *
439 
440 static void _dictvalues_gcscan(KrkInstance * self) {
441  krk_markValue(((struct DictValues*)self)->dict);
442 }
443 
444 KRK_Method(dictvalues,__init__) {
445  METHOD_TAKES_EXACTLY(1);
446  CHECK_ARG(1,dict,KrkDict*,source);
447  self->dict = argv[1];
448  self->i = 0;
449  return NONE_VAL();
450 }
451 
452 KRK_Method(dictvalues,__iter__) {
453  METHOD_TAKES_NONE();
454  self->i = 0;
455  return argv[0];
456 }
457 
458 KRK_Method(dictvalues,__call__) {
459  METHOD_TAKES_NONE();
460  do {
461  if (self->i >= AS_DICT(self->dict)->used) return argv[0];
462  if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
463  krk_push(AS_DICT(self->dict)->entries[self->i].value);
464  self->i++;
465  return krk_pop();
466  }
467  self->i++;
468  } while (1);
469 }
470 
471 KRK_Method(dictvalues,__repr__) {
472  METHOD_TAKES_NONE();
473  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("dictvalues([...])"));
474  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
475  struct StringBuilder sb = {0};
476  pushStringBuilderStr(&sb,"dictvalues([",12);
477 
478  size_t c = 0;
479  size_t len = AS_DICT(self->dict)->used;
480  for (size_t i = 0; i < len; ++i) {
481  KrkTableEntry * entry = &AS_DICT(self->dict)->entries[i];
482  if (IS_KWARGS(entry->key)) continue;
483  if (c) pushStringBuilderStr(&sb, ", ", 2);
484  c++;
485  if (!krk_pushStringBuilderFormat(&sb, "%R", entry->value)) goto _error;
486  }
487 
488  pushStringBuilderStr(&sb,"])",2);
489  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
490  return finishStringBuilder(&sb);
491 
492 _error:
493  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
495  return NONE_VAL();
496 }
497 
498 _noexport
499 void _createAndBind_dictClass(void) {
500  KrkClass * dict = ADD_BASE_CLASS(vm.baseClasses->dictClass, "dict", vm.baseClasses->objectClass);
501  dict->allocSize = sizeof(KrkDict);
502  dict->_ongcscan = _dict_gcscan;
503  dict->_ongcsweep = _dict_gcsweep;
504  BIND_METHOD(dict,__init__);
505  BIND_METHOD(dict,__repr__);
506  BIND_METHOD(dict,__getitem__);
507  BIND_METHOD(dict,__setitem__);
508  BIND_METHOD(dict,__or__);
509  BIND_METHOD(dict,__delitem__);
510  BIND_METHOD(dict,__len__);
511  BIND_METHOD(dict,__contains__);
512  BIND_METHOD(dict,__ior__);
513  BIND_METHOD(dict,__eq__);
514  BIND_METHOD(dict,keys);
515  BIND_METHOD(dict,items);
516  BIND_METHOD(dict,values);
517  BIND_METHOD(dict,capacity);
518  BIND_METHOD(dict,copy);
519  BIND_METHOD(dict,clear);
520  BIND_METHOD(dict,get);
521  BIND_METHOD(dict,setdefault);
522  BIND_METHOD(dict,update);
523  krk_defineNative(&dict->methods, "__iter__", FUNC_NAME(dict,keys));
524  krk_defineNative(&dict->methods, "__class_getitem__", krk_GenericAlias)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
525  krk_attachNamedValue(&dict->methods, "__hash__", NONE_VAL());
526  krk_finalizeClass(dict);
527  KRK_DOC(dict, "Mapping of arbitrary keys to values.");
528 
529  KrkClass * dictitems = ADD_BASE_CLASS(vm.baseClasses->dictitemsClass, "dictitems", vm.baseClasses->objectClass);
530  dictitems->allocSize = sizeof(struct DictItems);
531  dictitems->_ongcscan = _dictitems_gcscan;
532  BIND_METHOD(dictitems,__init__);
533  BIND_METHOD(dictitems,__iter__);
534  BIND_METHOD(dictitems,__call__);
535  BIND_METHOD(dictitems,__repr__);
536  krk_finalizeClass(dictitems);
537 
538  KrkClass * dictkeys = ADD_BASE_CLASS(vm.baseClasses->dictkeysClass, "dictkeys", vm.baseClasses->objectClass);
539  dictkeys->allocSize = sizeof(struct DictKeys);
540  dictkeys->_ongcscan = _dictkeys_gcscan;
541  BIND_METHOD(dictkeys,__init__);
542  BIND_METHOD(dictkeys,__iter__);
543  BIND_METHOD(dictkeys,__call__);
544  BIND_METHOD(dictkeys,__repr__);
545  krk_finalizeClass(dictkeys);
546 
547  KrkClass * dictvalues = ADD_BASE_CLASS(vm.baseClasses->dictvaluesClass, "dictvalues", vm.baseClasses->objectClass);
548  dictvalues->allocSize = sizeof(struct DictValues);
549  dictvalues->_ongcscan = _dictvalues_gcscan;
550  BIND_METHOD(dictvalues,__init__);
551  BIND_METHOD(dictvalues,__iter__);
552  BIND_METHOD(dictvalues,__call__);
553  BIND_METHOD(dictvalues,__repr__);
554  krk_finalizeClass(dictvalues);
555 }
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:460
Functions for dealing with garbage collection and memory allocation.
void krk_markValue(KrkValue value)
During a GC scan cycle, mark a value as used.
Definition: memory.c:334
void krk_markTable(KrkTable *table)
During a GC scan cycle, mark the contents of a table as used.
Definition: memory.c:444
NativeFn krk_GenericAlias
Special value for type hint expressions.
Definition: obj_typing.c:67
Type object.
Definition: object.h:215
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
Definition: object.h:224
KrkCleanupCallback _ongcscan
C function to call when the garbage collector visits an instance of this class in the scan phase.
Definition: object.h:223
size_t allocSize
Size to allocate when creating instances of this class.
Definition: object.h:222
KrkTable methods
General attributes table.
Definition: object.h:218
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
Definition: vm.c:189
Flexible mapping type.
Definition: object.h:349
KrkTable entries
The actual table of values in the dict.
Definition: object.h:351
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
Definition: obj_dict.c:19
An object of a class.
Definition: object.h:281
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:343
KrkObj obj
Base.
Definition: object.h:310
The most basic object type.
Definition: object.h:41
uint16_t flags
General object flags, mostly related to garbage collection.
Definition: object.h:43
One (key,value) pair in a table.
Definition: table.h:20
void krk_initTable(KrkTable *table)
Initialize a hash table.
Definition: table.c:33
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
Definition: table.c:211
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
Definition: table.c:238
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
Definition: table.c:148
void krk_tableAdjustCapacity(KrkTable *table, size_t capacity)
Preset the size of a table.
Definition: table.c:115
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:155
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Definition: vm.c:794
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
Definition: table.c:202
void krk_freeTable(KrkTable *table)
Release resources associated with a hash table.
Definition: table.c:41
KrkValue currentException
Definition: vm.h:164
int flags
Definition: vm.h:165
Immutable sequence of arbitrary values.
Definition: object.h:323
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
Definition: object.h:325
KrkTuple * krk_newTuple(size_t length)
Create a new tuple.
Definition: object.c:357
KrkValue * values
Definition: value.h:78
size_t count
Definition: value.h:77
Stack reference or primative value.
int krk_valuesSameOrEqual(KrkValue a, KrkValue b)
Compare two values by identity, then by equality.
Definition: value.c:96
Inline flexible string array.
Definition: util.h:162
Utilities for creating native bindings.
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
Definition: obj_str.c:1123
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
Definition: builtins.c:387
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definition: util.h:304
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
#define vm
Convenience macro for namespacing.
Definition: vm.h:257
KrkValue krk_pop(void)
Pop the top of the stack.
Definition: vm.c:131
void krk_push(KrkValue value)
Push a stack value.
Definition: vm.c:118
KrkValue krk_peek(int distance)
Peek down from the top of the stack.
Definition: vm.c:139