12 if (argc % 2 != 0)
return krk_runtimeError(
vm.exceptions->argumentError,
"Expected even number of arguments to krk_dict_of");
17 for (
int ind = 0; ind < argc; ind += 2) {
31 #define CURRENT_CTYPE KrkDict *
32 #define CURRENT_NAME self
40 static int _keyvalue_pair_callback(
void * context,
const KrkValue * entries,
size_t count) {
44 _context->counter = count;
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;
56 _context->counter = -1;
65 static int unpackKeyValuePair(
void *
self,
const KrkValue * pairs,
size_t count) {
68 for (
size_t i = 0; i < count; ++i) {
72 if (context.counter != 2) {
73 krk_runtimeError(
vm.exceptions->valueError,
"dictionary update sequence element has invalid length");
79 KRK_Method(dict,__init__) {
80 METHOD_TAKES_AT_MOST(1);
94 KRK_Method(dict,__eq__) {
95 METHOD_TAKES_EXACTLY(1);
96 if (!IS_dict(argv[1]))
98 CHECK_ARG(1,dict,
KrkDict*,them);
99 if (self->entries.count != them->entries.count)
100 return BOOLEAN_VAL(0);
103 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
104 if (IS_KWARGS(self->entries.entries[i].key))
continue;
106 if (!
krk_tableGet(&them->entries, self->entries.entries[i].key, &val))
return BOOLEAN_VAL(0);
110 return BOOLEAN_VAL(1);
114 KRK_Method(dict,__getitem__) {
115 METHOD_TAKES_EXACTLY(1);
124 KRK_Method(dict,__setitem__) {
125 METHOD_TAKES_EXACTLY(2);
130 KRK_Method(dict,__or__) {
131 METHOD_TAKES_EXACTLY(1);
132 CHECK_ARG(1,dict,
KrkDict*,them);
140 KRK_Method(dict,__delitem__) {
141 METHOD_TAKES_EXACTLY(1);
149 KRK_Method(dict,__len__) {
151 return INTEGER_VAL(self->entries.count);
154 KRK_Method(dict,__contains__) {
155 METHOD_TAKES_EXACTLY(1);
157 return BOOLEAN_VAL(
krk_tableGet(&self->entries, argv[1], &_unused));
160 KRK_Method(dict,capacity) {
162 return INTEGER_VAL(self->entries.capacity);
165 KRK_Method(dict,__repr__) {
167 if (((
KrkObj*)
self)->flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(S(
"{...}"));
168 ((
KrkObj*)
self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
170 pushStringBuilder(&sb,
'{');
173 size_t len =
self->entries.capacity;
174 for (
size_t i = 0; i < len; ++i) {
176 if (IS_KWARGS(entry->key))
continue;
178 pushStringBuilderStr(&sb,
", ", 2);
186 if (IS_STRING(result)) {
187 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
191 pushStringBuilderStr(&sb,
": ", 2);
197 if (IS_STRING(result)) {
198 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
203 pushStringBuilder(&sb,
'}');
204 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
205 return finishStringBuilder(&sb);
208 KRK_Method(dict,copy) {
216 KRK_Method(dict,clear) {
222 KRK_Method(dict,get) {
223 METHOD_TAKES_AT_LEAST(1);
224 METHOD_TAKES_AT_MOST(2);
226 if (argc > 2) out = argv[2];
231 KRK_Method(dict,setdefault) {
232 METHOD_TAKES_AT_LEAST(1);
233 METHOD_TAKES_AT_MOST(2);
235 if (argc > 2) out = argv[2];
245 KRK_Method(dict,update) {
246 METHOD_TAKES_AT_MOST(1);
249 CHECK_ARG(1,dict,
KrkDict*,other);
258 KRK_Method(dict,__ior__) {
259 METHOD_TAKES_EXACTLY(1);
260 CHECK_ARG(1,dict,
KrkDict*,other);
265 FUNC_SIG(dictkeys,__init__);
267 KRK_Method(dict,keys) {
273 return OBJECT_VAL(output);
276 FUNC_SIG(dictitems,__init__);
278 KRK_Method(dict,items) {
284 return OBJECT_VAL(output);
287 FUNC_SIG(dictvalues,__init__);
289 KRK_Method(dict,values) {
295 return OBJECT_VAL(output);
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;
309 #define CURRENT_CTYPE struct DictItems *
311 static void _dictitems_gcscan(
KrkInstance *
self) {
315 KRK_Method(dictitems,__init__) {
316 METHOD_TAKES_EXACTLY(1);
317 CHECK_ARG(1,dict,
KrkDict*,source);
318 self->dict = argv[1];
323 KRK_Method(dictitems,__iter__) {
329 KRK_Method(dictitems,__call__) {
331 if (self->i >= AS_DICT(self->dict)->capacity)
return argv[0];
332 if (!IS_KWARGS(AS_DICT(self->dict)->entries[self->i].key)) {
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;
345 KRK_Method(dictitems,__repr__) {
347 if (((
KrkObj*)
self)->flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(S(
"dictitems([...])"));
348 ((
KrkObj*)
self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
350 pushStringBuilderStr(&sb,
"dictitems([",11);
353 size_t len = AS_DICT(self->dict)->capacity;
354 for (
size_t i = 0; i < len; ++i) {
356 if (IS_KWARGS(entry->key))
continue;
358 pushStringBuilderStr(&sb,
", ", 2);
362 pushStringBuilder(&sb,
'(');
368 if (IS_STRING(result)) {
369 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
373 pushStringBuilderStr(&sb,
", ", 2);
379 if (IS_STRING(result)) {
380 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
384 pushStringBuilder(&sb,
')');
387 pushStringBuilderStr(&sb,
"])",2);
388 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
389 return finishStringBuilder(&sb);
393 #define CURRENT_CTYPE struct DictKeys *
399 KRK_Method(dictkeys,__init__) {
400 METHOD_TAKES_EXACTLY(1);
401 CHECK_ARG(1,dict,
KrkDict*,source);
402 self->dict = argv[1];
407 KRK_Method(dictkeys,__iter__) {
413 KRK_Method(dictkeys,__call__) {
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);
426 KRK_Method(dictkeys,__repr__) {
428 if (((
KrkObj*)
self)->flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(S(
"dictkeys([...])"));
429 ((
KrkObj*)
self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
431 pushStringBuilderStr(&sb,
"dictkeys([",10);
434 size_t len = AS_DICT(self->dict)->capacity;
435 for (
size_t i = 0; i < len; ++i) {
437 if (IS_KWARGS(entry->key))
continue;
439 pushStringBuilderStr(&sb,
", ", 2);
447 if (IS_STRING(result)) {
448 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
453 pushStringBuilderStr(&sb,
"])",2);
454 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
455 return finishStringBuilder(&sb);
459 #define CURRENT_CTYPE struct DictValues *
461 static void _dictvalues_gcscan(
KrkInstance *
self) {
465 KRK_Method(dictvalues,__init__) {
466 METHOD_TAKES_EXACTLY(1);
467 CHECK_ARG(1,dict,
KrkDict*,source);
468 self->dict = argv[1];
473 KRK_Method(dictvalues,__iter__) {
479 KRK_Method(dictvalues,__call__) {
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);
492 KRK_Method(dictvalues,__repr__) {
494 if (((
KrkObj*)
self)->flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(S(
"dictvalues([...])"));
495 ((
KrkObj*)
self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
497 pushStringBuilderStr(&sb,
"dictvalues([",12);
500 size_t len = AS_DICT(self->dict)->capacity;
501 for (
size_t i = 0; i < len; ++i) {
503 if (IS_KWARGS(entry->key))
continue;
505 pushStringBuilderStr(&sb,
", ", 2);
513 if (IS_STRING(result)) {
514 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
519 pushStringBuilderStr(&sb,
"])",2);
520 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
521 return finishStringBuilder(&sb);
525 void _createAndBind_dictClass(
void) {
526 KrkClass * dict = ADD_BASE_CLASS(
vm.baseClasses->dictClass,
"dict",
vm.baseClasses->objectClass);
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);
554 KRK_DOC(dict,
"Mapping of arbitrary keys to values.");
556 KrkClass * dictitems = ADD_BASE_CLASS(
vm.baseClasses->dictitemsClass,
"dictitems",
vm.baseClasses->objectClass);
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__);
565 KrkClass * dictkeys = ADD_BASE_CLASS(
vm.baseClasses->dictkeysClass,
"dictkeys",
vm.baseClasses->objectClass);
568 BIND_METHOD(dictkeys,__init__);
569 BIND_METHOD(dictkeys,__iter__);
570 BIND_METHOD(dictkeys,__call__);
571 BIND_METHOD(dictkeys,__repr__);
574 KrkClass * dictvalues = ADD_BASE_CLASS(
vm.baseClasses->dictvaluesClass,
"dictvalues",
vm.baseClasses->objectClass);
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__);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Functions for dealing with garbage collection and memory allocation.
void krk_markValue(KrkValue value)
During a GC scan cycle, mark a value as used.
void krk_markTable(KrkTable *table)
During a GC scan cycle, mark the contents of a table as used.
NativeFn krk_GenericAlias
Special value for type hint expressions.
KrkCleanupCallback _ongcsweep
C function to call when the garbage collector is discarding an instance of this class.
KrkCleanupCallback _ongcscan
C function to call when the garbage collector visits an instance of this class in the scan phase.
KrkObj * _reprer
__repr__ Called to create a reproducible string representation of an instance
size_t allocSize
Size to allocate when creating instances of this class.
KrkTable methods
General attributes table.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
KrkTable entries
The actual table of values in the dict.
KrkValue krk_dict_of(int argc, const KrkValue argv[], int hasKw)
Create a dict object.
KrkInstance * krk_newInstance(KrkClass *_class)
Create a new instance of the given class.
The most basic object type.
uint16_t flags
General object flags, mostly related to garbage collection.
One (key,value) pair in a table.
void krk_initTable(KrkTable *table)
Initialize a hash table.
int krk_tableGet(KrkTable *table, KrkValue key, KrkValue *value)
Obtain the value associated with a key in a table.
int krk_tableDelete(KrkTable *table, KrkValue key)
Remove a key from a hash table.
int krk_tableSet(KrkTable *table, KrkValue key, KrkValue value)
Assign a value to a key in a table.
void krk_tableAdjustCapacity(KrkTable *table, size_t capacity)
Preset the size of a table.
KrkNative * krk_defineNative(KrkTable *table, const char *name, NativeFn function)
Attach a native C function to an attribute table.
void krk_attachNamedValue(KrkTable *table, const char name[], KrkValue obj)
Attach a value to an attribute table.
void krk_tableAddAll(KrkTable *from, KrkTable *to)
Add all key-value pairs from 'from' into 'to'.
void krk_freeTable(KrkTable *table)
Release resources associated with a hash table.
KrkValue currentException
Immutable sequence of arbitrary values.
KrkValueArray values
Stores the length, capacity, and actual values of the tuple.
KrkTuple * krk_newTuple(size_t length)
Create a new tuple.
Stack reference or primative value.
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
int krk_valuesSameOrEqual(KrkValue a, KrkValue b)
Compare two values by identity, then by equality.
Inline flexible string array.
Utilities for creating native bindings.
int krk_unpackIterable(KrkValue iterable, void *context, int callback(void *, const KrkValue *, size_t))
Unpack an iterable.
#define KRK_DOC(thing, text)
Attach documentation to a thing of various types.
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
void krk_push(KrkValue value)
Push a stack value.
KrkValue krk_callDirect(KrkObj *callable, int argCount)
Call a closure or native function with argCount arguments.
KrkValue krk_peek(int distance)
Peek down from the top of the stack.