16 #define IS_set(o) krk_isInstanceOf(o,KRK_BASE_CLASS(set))
17 #define AS_set(o) ((struct Set*)AS_OBJECT(o))
36 #define IS_setiterator(o) krk_isInstanceOf(o,KRK_BASE_CLASS(setiterator))
37 #define AS_setiterator(o) ((struct SetIterator*)AS_OBJECT(o))
39 static void _setiterator_gcscan(
KrkInstance *
self) {
43 #define CURRENT_CTYPE struct Set *
44 #define CURRENT_NAME self
46 static int _set_init_callback(
void * context,
const KrkValue * values,
size_t count) {
47 struct Set *
self = context;
48 for (
size_t i = 0; i < count; ++i) {
55 KRK_Method(set,__init__) {
56 METHOD_TAKES_AT_MOST(1);
64 KRK_Method(set,__contains__) {
65 METHOD_TAKES_EXACTLY(1);
67 return BOOLEAN_VAL(
krk_tableGet(&self->entries, argv[1], &v));
70 KRK_Method(set,__repr__) {
72 if (((
KrkObj*)
self)->
flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(S(
"{...}"));
73 if (!self->entries.capacity)
return OBJECT_VAL(S(
"set()"));
74 ((
KrkObj*)
self)->flags |= KRK_OBJ_FLAGS_IN_REPR;
76 pushStringBuilder(&sb,
'{');
79 size_t len =
self->entries.capacity;
80 for (
size_t i = 0; i < len; ++i) {
82 if (IS_KWARGS(entry->key))
continue;
83 if (c) pushStringBuilderStr(&sb,
", ", 2);
85 if (!krk_pushStringBuilderFormat(&sb,
"%R", entry->key))
goto _error;
88 pushStringBuilder(&sb,
'}');
89 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
90 return finishStringBuilder(&sb);
93 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
98 KRK_Method(set,__and__) {
99 METHOD_TAKES_EXACTLY(1);
100 CHECK_ARG(1,set,
struct Set*,them);
104 FUNC_NAME(set,__init__)(1,&outSet,0);
108 return krk_runtimeError(
vm.exceptions->typeError,
"unsupported operand types for %s: '%T' and '%T'",
"&", argv[0], argv[1]);
110 for (
size_t i = 0; i <
self->entries.capacity; ++i) {
112 if (IS_KWARGS(entry->key))
continue;
118 if (IS_BOOLEAN(result) && AS_BOOLEAN(result)) {
119 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
126 KRK_Method(set,__xor__) {
127 METHOD_TAKES_EXACTLY(1);
128 CHECK_ARG(1,set,
struct Set*,them);
132 FUNC_NAME(set,__init__)(1,&outSet,0);
136 return krk_runtimeError(
vm.exceptions->typeError,
"unsupported operand types for %s: '%T' and '%T'",
"&", argv[0], argv[1]);
138 for (
size_t i = 0; i <
self->entries.capacity; ++i) {
140 if (IS_KWARGS(entry->key))
continue;
146 if (IS_BOOLEAN(result) && !AS_BOOLEAN(result)) {
147 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
154 for (
size_t i = 0; i < them->entries.capacity; ++i) {
156 if (IS_KWARGS(entry->key))
continue;
162 if (IS_BOOLEAN(result) && !AS_BOOLEAN(result)) {
163 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
171 KRK_Method(set,__or__) {
172 METHOD_TAKES_EXACTLY(1);
173 CHECK_ARG(1,set,
struct Set*,them);
177 FUNC_NAME(set,__init__)(1,&outSet,0);
185 KRK_Method(set,__len__) {
187 return INTEGER_VAL(self->entries.count);
190 KRK_Method(set,__eq__) {
191 METHOD_TAKES_EXACTLY(1);
192 if (!IS_set(argv[1]))
193 return NOTIMPL_VAL();
194 CHECK_ARG(1,set,
struct Set*,them);
195 if (self->entries.count != them->entries.count)
196 return BOOLEAN_VAL(0);
200 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
201 if (IS_KWARGS(self->entries.entries[i].key))
continue;
202 if (!
krk_tableGet(&them->entries, self->entries.entries[i].key, &v))
return BOOLEAN_VAL(0);
205 return BOOLEAN_VAL(1);
209 KRK_Method(set,__lt__) {
210 METHOD_TAKES_EXACTLY(1);
211 if (!IS_set(argv[1]))
212 return NOTIMPL_VAL();
213 struct Set * them = AS_set(argv[1]);
214 if (self->entries.count == them->entries.
count)
215 return BOOLEAN_VAL(0);
217 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
218 if (IS_KWARGS(self->entries.entries[i].key))
continue;
219 if (!
krk_tableGet(&them->entries, self->
entries.entries[i].key, &v))
return BOOLEAN_VAL(0);
221 return BOOLEAN_VAL(1);
225 KRK_Method(set,__le__) {
226 METHOD_TAKES_EXACTLY(1);
227 if (!IS_set(argv[1]))
228 return NOTIMPL_VAL();
229 struct Set * them = AS_set(argv[1]);
231 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
232 if (IS_KWARGS(self->entries.entries[i].key))
continue;
233 if (!
krk_tableGet(&them->entries, self->
entries.entries[i].key, &v))
return BOOLEAN_VAL(0);
235 return BOOLEAN_VAL(1);
239 KRK_Method(set,__gt__) {
240 METHOD_TAKES_EXACTLY(1);
241 if (!IS_set(argv[1]))
242 return NOTIMPL_VAL();
243 struct Set * them = AS_set(argv[1]);
244 if (self->entries.count == them->entries.
count)
245 return BOOLEAN_VAL(0);
247 for (
unsigned int i = 0; i < them->entries.
capacity; ++i) {
248 if (IS_KWARGS(them->entries.
entries[i].key))
continue;
249 if (!
krk_tableGet(&self->entries, them->entries.
entries[i].key, &v))
return BOOLEAN_VAL(0);
251 return BOOLEAN_VAL(1);
254 KRK_Method(set,__ge__) {
255 METHOD_TAKES_EXACTLY(1);
256 if (!IS_set(argv[1]))
257 return NOTIMPL_VAL();
258 struct Set * them = AS_set(argv[1]);
260 for (
unsigned int i = 0; i < them->entries.
capacity; ++i) {
261 if (IS_KWARGS(them->entries.
entries[i].key))
continue;
262 if (!
krk_tableGet(&self->entries, them->entries.
entries[i].key, &v))
return BOOLEAN_VAL(0);
264 return BOOLEAN_VAL(1);
268 KRK_Method(set,add) {
269 METHOD_TAKES_EXACTLY(1);
274 KRK_Method(set,remove) {
275 METHOD_TAKES_EXACTLY(1);
281 KRK_Method(set,discard) {
282 METHOD_TAKES_EXACTLY(1);
287 KRK_Method(set,clear) {
294 KRK_Method(set,update) {
295 METHOD_TAKES_AT_MOST(1);
297 if (IS_set(argv[1])) {
306 FUNC_SIG(setiterator,__init__);
308 KRK_Method(set,__iter__) {
317 #define CURRENT_CTYPE struct SetIterator *
319 KRK_Method(setiterator,__init__) {
320 METHOD_TAKES_EXACTLY(1);
321 CHECK_ARG(1,set,
void*,source);
327 KRK_Method(setiterator,__call__) {
330 if (unlikely(!IS_set(self->set)))
return argv[0];
333 if (self->i >= AS_set(self->set)->entries.capacity)
return argv[0];
334 if (!IS_KWARGS(AS_set(self->set)->entries.entries[self->i].key)) {
335 krk_push(AS_set(self->set)->entries.entries[self->i].key);
349 krk_tableSet(&AS_set(outSet)->entries, argv[argc-1], BOOLEAN_VAL(1));
357 void _createAndBind_setClass(
void) {
362 BIND_METHOD(set,__init__);
363 BIND_METHOD(set,__repr__);
364 BIND_METHOD(set,__len__);
365 BIND_METHOD(set,__eq__);
366 BIND_METHOD(set,__lt__);
367 BIND_METHOD(set,__gt__);
368 BIND_METHOD(set,__le__);
369 BIND_METHOD(set,__ge__);
370 BIND_METHOD(set,__and__);
371 BIND_METHOD(set,__or__);
372 BIND_METHOD(set,__xor__);
373 BIND_METHOD(set,__contains__);
374 BIND_METHOD(set,__iter__);
376 "@brief Add an element to the set.\n"
377 "@arguments value\n\n"
378 "Adds the given @p value to the set. @p value must be hashable.");
379 KRK_DOC(BIND_METHOD(set,remove),
380 "@brief Remove an element from the set.\n"
381 "@arguments value\n\n"
382 "Removes @p value from the set, raising @ref KeyError if it is not a member of the set.");
383 KRK_DOC(BIND_METHOD(set,discard),
384 "@brief Remove an element from the set, quietly.\n"
385 "@arguments value\n\n"
386 "Removes @p value from the set, without raising an exception if it is not a member.");
387 KRK_DOC(BIND_METHOD(set,clear),
388 "@brief Empty the set.\n\n"
389 "Removes all elements from the set, in-place.");
390 BIND_METHOD(set,update);
394 KrkClass * setiterator =
krk_makeClass(
vm.builtins, &KRK_BASE_CLASS(setiterator),
"setiterator",
vm.baseClasses->objectClass);
395 setiterator->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
397 setiterator->
_ongcscan = _setiterator_gcscan;
398 BIND_METHOD(setiterator,__init__);
399 BIND_METHOD(setiterator,__call__);
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.
Struct definitions for core object types.
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.
size_t allocSize
Size to allocate when creating instances of this class.
KrkClass * krk_makeClass(KrkInstance *module, KrkClass **_class, const char *name, KrkClass *base)
Convenience function for creating new types.
KrkTable methods
General attributes table.
void krk_finalizeClass(KrkClass *_class)
Finalize a class by collecting pointers to core methods.
KrkObj * _contains
__contains__ Called to resolve in (as a binary operator)
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.
Simple hash table of arbitrary keys to values.
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_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.
Stack reference or primative value.
KrkClass * krk_getType(KrkValue value)
Get the class representing a value.
Iterator over the values in a set.
Mutable unordered set of values.
KrkValue krk_set_of(int argc, const KrkValue argv[], int hasKw)
Create a set object.
Inline flexible string array.
Utilities for creating native bindings.
KrkValue krk_discardStringBuilder(struct StringBuilder *sb)
Discard the contents of a string builder.
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.
Core API for the bytecode virtual machine.
krk_threadLocal KrkThreadState krk_currentThread
Thread-local VM state.
#define vm
Convenience macro for namespacing.
KrkValue krk_pop(void)
Pop the top of the stack.
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.