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 
11 KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw) {
12  if (argc % 2 != 0) return krk_runtimeError(vm.exceptions->argumentError, "Expected even number of arguments to krk_dict_of");
13  KrkInstance * outDict = krk_newInstance(vm.baseClasses->dictClass);
14  krk_push(OBJECT_VAL(outDict));
15  krk_initTable(&((KrkDict*)outDict)->entries);
16  krk_tableAdjustCapacity(&((KrkDict*)outDict)->entries, argc);
17  for (int ind = 0; ind < argc; ind += 2) {
18  krk_tableSet(&((KrkDict*)outDict)->entries, argv[ind], argv[ind+1]);
19  }
20  return krk_pop();
21 }
22 
23 static void _dict_gcscan(KrkInstance * self) {
24  krk_markTable(&((KrkDict*)self)->entries);
25 }
26 
27 static void _dict_gcsweep(KrkInstance * self) {
28  krk_freeTable(&((KrkDict*)self)->entries);
29 }
30 
31 #define CURRENT_CTYPE KrkDict *
32 #define CURRENT_NAME self
33 
35  KrkDict * self;
36  KrkValue key;
37  int counter;
38 };
39 
40 static int _keyvalue_pair_callback(void * context, const KrkValue * entries, size_t count) {
41  struct _keyvalue_pair_context * _context = context;
42 
43  if (count > 2) {
44  _context->counter = count;
45  return 1;
46  }
47 
48  for (size_t i = 0; i < count; ++i) {
49  if (_context->counter == 0) {
50  _context->counter = 1;
51  _context->key = entries[i];
52  } else if (_context->counter == 1) {
53  _context->counter = 2;
54  krk_tableSet(&_context->self->entries, _context->key, entries[i]);
55  } else {
56  _context->counter = -1;
57  return 1;
58  }
59  }
60 
61  if (unlikely(krk_currentThread.flags & KRK_THREAD_HAS_EXCEPTION)) return 1;
62  return 0;
63 }
64 
65 static int unpackKeyValuePair(void * self, const KrkValue * pairs, size_t count) {
66  struct _keyvalue_pair_context context = { (KrkDict*)self, NONE_VAL(), 0 };
67 
68  for (size_t i = 0; i < count; ++i) {
69  if (krk_unpackIterable(pairs[i], &context, _keyvalue_pair_callback)) return 1;
70  }
71 
72  if (context.counter != 2) {
73  krk_runtimeError(vm.exceptions->valueError, "dictionary update sequence element has invalid length");
74  return 1;
75  }
76  return 0;
77 }
78 
79 KRK_Method(dict,__init__) {
80  METHOD_TAKES_AT_MOST(1);
81  krk_initTable(&self->entries);
82 
83  if (argc > 1) {
84  if (krk_unpackIterable(argv[1], self, unpackKeyValuePair)) return NONE_VAL();
85  }
86 
87  if (hasKw) {
88  krk_tableAddAll(AS_DICT(argv[argc]), &self->entries);
89  }
90 
91  return NONE_VAL();
92 }
93 
94 KRK_Method(dict,__eq__) {
95  METHOD_TAKES_EXACTLY(1);
96  if (!IS_dict(argv[1]))
97  return NOTIMPL_VAL();
98  CHECK_ARG(1,dict,KrkDict*,them);
99  if (self->entries.count != them->entries.count)
100  return BOOLEAN_VAL(0);
101 
102 
103  for (unsigned int i = 0; i < self->entries.capacity; ++i) {
104  if (IS_KWARGS(self->entries.entries[i].key)) continue;
105  KrkValue val;
106  if (!krk_tableGet(&them->entries, self->entries.entries[i].key, &val)) return BOOLEAN_VAL(0);
107  if (!krk_valuesSameOrEqual(self->entries.entries[i].value, val)) return BOOLEAN_VAL(0);
108  }
109 
110  return BOOLEAN_VAL(1);
111 }
112 
113 
114 KRK_Method(dict,__getitem__) {
115  METHOD_TAKES_EXACTLY(1);
116  KrkValue out;
117  if (!krk_tableGet(&self->entries, argv[1], &out)) {
118  if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
119  return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
120  }
121  return out;
122 }
123 
124 KRK_Method(dict,__setitem__) {
125  METHOD_TAKES_EXACTLY(2);
126  krk_tableSet(&self->entries, argv[1], argv[2]);
127  return argv[2];
128 }
129 
130 KRK_Method(dict,__or__) {
131  METHOD_TAKES_EXACTLY(1);
132  CHECK_ARG(1,dict,KrkDict*,them);
133  KrkValue outDict = krk_dict_of(0,NULL,0);
134  krk_push(outDict);
135  krk_tableAddAll(&self->entries, AS_DICT(outDict));
136  krk_tableAddAll(&them->entries, AS_DICT(outDict));
137  return krk_pop();
138 }
139 
140 KRK_Method(dict,__delitem__) {
141  METHOD_TAKES_EXACTLY(1);
142  if (!krk_tableDelete(&self->entries, argv[1])) {
143  if (!IS_NONE(krk_currentThread.currentException)) return NONE_VAL();
144  return krk_runtimeError(vm.exceptions->keyError, "%V", argv[1]);
145  }
146  return NONE_VAL();
147 }
148 
149 KRK_Method(dict,__len__) {
150  METHOD_TAKES_NONE();
151  return INTEGER_VAL(self->entries.count);
152 }
153 
154 KRK_Method(dict,__contains__) {
155  METHOD_TAKES_EXACTLY(1);
156  KrkValue _unused;
157  return BOOLEAN_VAL(krk_tableGet(&self->entries, argv[1], &_unused));
158 }
159 
160 KRK_Method(dict,capacity) {
161  METHOD_TAKES_NONE();
162  return INTEGER_VAL(self->entries.capacity);
163 }
164 
165 KRK_Method(dict,__repr__) {
166  METHOD_TAKES_NONE();
167  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("{...}"));
168  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
169  struct StringBuilder sb = {0};
170  pushStringBuilder(&sb,'{');
171 
172  size_t c = 0;
173  size_t len = self->entries.capacity;
174  for (size_t i = 0; i < len; ++i) {
175  KrkTableEntry * entry = &self->entries.entries[i];
176  if (IS_KWARGS(entry->key)) continue;
177  if (c > 0) {
178  pushStringBuilderStr(&sb, ", ", 2);
179  }
180  c++;
181 
182  {
183  KrkClass * type = krk_getType(entry->key);
184  krk_push(entry->key);
185  KrkValue result = krk_callDirect(type->_reprer, 1);
186  if (IS_STRING(result)) {
187  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
188  }
189  }
190 
191  pushStringBuilderStr(&sb, ": ", 2);
192 
193  {
194  KrkClass * type = krk_getType(entry->value);
195  krk_push(entry->value);
196  KrkValue result = krk_callDirect(type->_reprer, 1);
197  if (IS_STRING(result)) {
198  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
199  }
200  }
201  }
202 
203  pushStringBuilder(&sb,'}');
204  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
205  return finishStringBuilder(&sb);
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)->capacity) 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)->capacity;
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 > 0) {
358  pushStringBuilderStr(&sb, ", ", 2);
359  }
360  c++;
361 
362  pushStringBuilder(&sb,'(');
363 
364  {
365  KrkClass * type = krk_getType(entry->key);
366  krk_push(entry->key);
367  KrkValue result = krk_callDirect(type->_reprer, 1);
368  if (IS_STRING(result)) {
369  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
370  }
371  }
372 
373  pushStringBuilderStr(&sb, ", ", 2);
374 
375  {
376  KrkClass * type = krk_getType(entry->value);
377  krk_push(entry->value);
378  KrkValue result = krk_callDirect(type->_reprer, 1);
379  if (IS_STRING(result)) {
380  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
381  }
382  }
383 
384  pushStringBuilder(&sb,')');
385  }
386 
387  pushStringBuilderStr(&sb,"])",2);
388  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
389  return finishStringBuilder(&sb);
390 }
391 
392 #undef CURRENT_CTYPE
393 #define CURRENT_CTYPE struct DictKeys *
394 
395 static void _dictkeys_gcscan(KrkInstance * self) {
396  krk_markValue(((struct DictKeys*)self)->dict);
397 }
398 
399 KRK_Method(dictkeys,__init__) {
400  METHOD_TAKES_EXACTLY(1);
401  CHECK_ARG(1,dict,KrkDict*,source);
402  self->dict = argv[1];
403  self->i = 0;
404  return NONE_VAL();
405 }
406 
407 KRK_Method(dictkeys,__iter__) {
408  METHOD_TAKES_NONE();
409  self->i = 0;
410  return argv[0];
411 }
412 
413 KRK_Method(dictkeys,__call__) {
414  METHOD_TAKES_NONE();
415  do {
416  if (self->i >= AS_DICT(self->dict)->capacity) return argv[0];
417  if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
418  krk_push(AS_DICT(self->dict)->entries[self->i].key);
419  self->i++;
420  return krk_pop();
421  }
422  self->i++;
423  } while (1);
424 }
425 
426 KRK_Method(dictkeys,__repr__) {
427  METHOD_TAKES_NONE();
428  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("dictkeys([...])"));
429  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
430  struct StringBuilder sb = {0};
431  pushStringBuilderStr(&sb,"dictkeys([",10);
432 
433  size_t c = 0;
434  size_t len = AS_DICT(self->dict)->capacity;
435  for (size_t i = 0; i < len; ++i) {
436  KrkTableEntry * entry = &AS_DICT(self->dict)->entries[i];
437  if (IS_KWARGS(entry->key)) continue;
438  if (c > 0) {
439  pushStringBuilderStr(&sb, ", ", 2);
440  }
441  c++;
442 
443  {
444  KrkClass * type = krk_getType(entry->key);
445  krk_push(entry->key);
446  KrkValue result = krk_callDirect(type->_reprer, 1);
447  if (IS_STRING(result)) {
448  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
449  }
450  }
451  }
452 
453  pushStringBuilderStr(&sb,"])",2);
454  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
455  return finishStringBuilder(&sb);
456 }
457 
458 #undef CURRENT_CTYPE
459 #define CURRENT_CTYPE struct DictValues *
460 
461 static void _dictvalues_gcscan(KrkInstance * self) {
462  krk_markValue(((struct DictValues*)self)->dict);
463 }
464 
465 KRK_Method(dictvalues,__init__) {
466  METHOD_TAKES_EXACTLY(1);
467  CHECK_ARG(1,dict,KrkDict*,source);
468  self->dict = argv[1];
469  self->i = 0;
470  return NONE_VAL();
471 }
472 
473 KRK_Method(dictvalues,__iter__) {
474  METHOD_TAKES_NONE();
475  self->i = 0;
476  return argv[0];
477 }
478 
479 KRK_Method(dictvalues,__call__) {
480  METHOD_TAKES_NONE();
481  do {
482  if (self->i >= AS_DICT(self->dict)->capacity) return argv[0];
483  if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
484  krk_push(AS_DICT(self->dict)->entries[self->i].value);
485  self->i++;
486  return krk_pop();
487  }
488  self->i++;
489  } while (1);
490 }
491 
492 KRK_Method(dictvalues,__repr__) {
493  METHOD_TAKES_NONE();
494  if (((KrkObj*)self)->flags & KRK_OBJ_FLAGS_IN_REPR) return OBJECT_VAL(S("dictvalues([...])"));
495  ((KrkObj*)self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
496  struct StringBuilder sb = {0};
497  pushStringBuilderStr(&sb,"dictvalues([",12);
498 
499  size_t c = 0;
500  size_t len = AS_DICT(self->dict)->capacity;
501  for (size_t i = 0; i < len; ++i) {
502  KrkTableEntry * entry = &AS_DICT(self->dict)->entries[i];
503  if (IS_KWARGS(entry->key)) continue;
504  if (c > 0) {
505  pushStringBuilderStr(&sb, ", ", 2);
506  }
507  c++;
508 
509  {
510  KrkClass * type = krk_getType(entry->value);
511  krk_push(entry->value);
512  KrkValue result = krk_callDirect(type->_reprer, 1);
513  if (IS_STRING(result)) {
514  pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
515  }
516  }
517  }
518 
519  pushStringBuilderStr(&sb,"])",2);
520  ((KrkObj*)self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
521  return finishStringBuilder(&sb);
522 }
523 
524 _noexport
525 void _createAndBind_dictClass(void) {
526  KrkClass * dict = ADD_BASE_CLASS(vm.baseClasses->dictClass, "dict", vm.baseClasses->objectClass);
527  dict->allocSize = sizeof(KrkDict);
528  dict->_ongcscan = _dict_gcscan;
529  dict->_ongcsweep = _dict_gcsweep;
530  BIND_METHOD(dict,__init__);
531  BIND_METHOD(dict,__repr__);
532  BIND_METHOD(dict,__getitem__);
533  BIND_METHOD(dict,__setitem__);
534  BIND_METHOD(dict,__or__);
535  BIND_METHOD(dict,__delitem__);
536  BIND_METHOD(dict,__len__);
537  BIND_METHOD(dict,__contains__);
538  BIND_METHOD(dict,__ior__);
539  BIND_METHOD(dict,__eq__);
540  BIND_METHOD(dict,keys);
541  BIND_METHOD(dict,items);
542  BIND_METHOD(dict,values);
543  BIND_METHOD(dict,capacity);
544  BIND_METHOD(dict,copy);
545  BIND_METHOD(dict,clear);
546  BIND_METHOD(dict,get);
547  BIND_METHOD(dict,setdefault);
548  BIND_METHOD(dict,update);
549  krk_defineNative(&dict->methods, "__iter__", FUNC_NAME(dict,keys));
550  krk_defineNative(&dict->methods, "__str__", FUNC_NAME(dict,__repr__));
551  krk_defineNative(&dict->methods, "__class_getitem__", krk_GenericAlias)->obj.flags |= KRK_OBJ_FLAGS_FUNCTION_IS_CLASS_METHOD;
552  krk_attachNamedValue(&dict->methods, "__hash__", NONE_VAL());
553  krk_finalizeClass(dict);
554  KRK_DOC(dict, "Mapping of arbitrary keys to values.");
555 
556  KrkClass * dictitems = ADD_BASE_CLASS(vm.baseClasses->dictitemsClass, "dictitems", vm.baseClasses->objectClass);
557  dictitems->allocSize = sizeof(struct DictItems);
558  dictitems->_ongcscan = _dictitems_gcscan;
559  BIND_METHOD(dictitems,__init__);
560  BIND_METHOD(dictitems,__iter__);
561  BIND_METHOD(dictitems,__call__);
562  BIND_METHOD(dictitems,__repr__);
563  krk_finalizeClass(dictitems);
564 
565  KrkClass * dictkeys = ADD_BASE_CLASS(vm.baseClasses->dictkeysClass, "dictkeys", vm.baseClasses->objectClass);
566  dictkeys->allocSize = sizeof(struct DictKeys);
567  dictkeys->_ongcscan = _dictkeys_gcscan;
568  BIND_METHOD(dictkeys,__init__);
569  BIND_METHOD(dictkeys,__iter__);
570  BIND_METHOD(dictkeys,__call__);
571  BIND_METHOD(dictkeys,__repr__);
572  krk_finalizeClass(dictkeys);
573 
574  KrkClass * dictvalues = ADD_BASE_CLASS(vm.baseClasses->dictvaluesClass, "dictvalues", vm.baseClasses->objectClass);
575  dictvalues->allocSize = sizeof(struct DictValues);
576  dictvalues->_ongcscan = _dictvalues_gcscan;
577  BIND_METHOD(dictvalues,__init__);
578  BIND_METHOD(dictvalues,__iter__);
579  BIND_METHOD(dictvalues,__call__);
580  BIND_METHOD(dictvalues,__repr__);
581  krk_finalizeClass(dictvalues);
582 }
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Definition: exceptions.c:445
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:329
void krk_markTable(KrkTable *table)
During a GC scan cycle, mark the contents of a table as used.
Definition: memory.c:438
NativeFn krk_GenericAlias
Special value for type hint expressions.
Definition: obj_typing.c:67
Type object.
Definition: object.h:189
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
Definition: object.h:198
KrkCleanupCallback _ongcscan
C function to call when the garbage collector visits an instance of this class in the scan phase.
Definition: object.h:197
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
Definition: object.h:203
size_t allocSize
Size to allocate when creating instances of this class.
Definition: object.h:196
KrkTable methods
General attributes table.
Definition: object.h:192
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
Flexible mapping type.
Definition: object.h:323
KrkTable entries
The actual table of values in the dict.
Definition: object.h:325
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
Definition: obj_dict.c:11
An object of a class.
Definition: object.h:255
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
Definition: object.c:339
KrkObj obj
Base.
Definition: object.h:284
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:14
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
Definition: table.c:178
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
Definition: table.c:208
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
Definition: table.c:145
void krk_tableAdjustCapacity(KrkTable *table, size_t capacity)
Preset the size of a table.
Definition: table.c:116
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
Definition: vm.c:194
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
Definition: vm.c:825
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
Definition: table.c:169
void krk_freeTable(KrkTable *table)
Release resources associated with a hash table.
Definition: table.c:20
KrkValue currentException
Definition: vm.h:173
int flags
Definition: vm.h:174
Immutable sequence of arbitrary values.
Definition: object.h:297
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
Definition: object.h:299
KrkTuple * krk_newTuple(size_t length)
Create a new tuple.
Definition: object.c:353
KrkValue * values
Definition: value.h:73
size_t count
Definition: value.h:72
Stack reference or primative value.
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
Definition: vm.c:275
int krk_valuesSameOrEqual(KrkValue a, KrkValue b)
Compare two values by identity, then by equality.
Inline flexible string array.
Definition: util.h:150
Utilities for creating native bindings.
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
Definition: builtins.c:380
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definition: util.h:292
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
Definition: vm.h:267
KrkValue krk_pop(void)
Pop the top of the stack.
Definition: vm.c:170
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
void krk_push(KrkValue value)
Push a stack value.
Definition: vm.c:157
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
Definition: vm.c:771
KrkValue krk_peek(int distance)
Peek down from the top of the stack.
Definition: vm.c:178