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], &_unused));
70 KRK_Method(set,__repr__) {
72 if (((
KrkObj*)
self)->
flags & KRK_OBJ_FLAGS_IN_REPR)
return OBJECT_VAL(
"{...}");
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;
84 pushStringBuilderStr(&sb,
", ", 2);
91 if (IS_STRING(result)) {
92 pushStringBuilderStr(&sb, AS_CSTRING(result), AS_STRING(result)->length);
96 pushStringBuilder(&sb,
'}');
97 ((
KrkObj*)
self)->flags &= ~(KRK_OBJ_FLAGS_IN_REPR);
98 return finishStringBuilder(&sb);
101 KRK_Method(set,__and__) {
102 METHOD_TAKES_EXACTLY(1);
103 CHECK_ARG(1,set,
struct Set*,them);
107 FUNC_NAME(set,__init__)(1,&outSet,0);
111 return krk_runtimeError(
vm.exceptions->typeError,
"unsupported operand types for %s: '%T' and '%T'",
"&", argv[0], argv[1]);
113 for (
size_t i = 0; i <
self->entries.capacity; ++i) {
115 if (IS_KWARGS(entry->key))
continue;
121 if (IS_BOOLEAN(result) && AS_BOOLEAN(result)) {
122 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
129 KRK_Method(set,__xor__) {
130 METHOD_TAKES_EXACTLY(1);
131 CHECK_ARG(1,set,
struct Set*,them);
135 FUNC_NAME(set,__init__)(1,&outSet,0);
139 return krk_runtimeError(
vm.exceptions->typeError,
"unsupported operand types for %s: '%T' and '%T'",
"&", argv[0], argv[1]);
141 for (
size_t i = 0; i <
self->entries.capacity; ++i) {
143 if (IS_KWARGS(entry->key))
continue;
149 if (IS_BOOLEAN(result) && !AS_BOOLEAN(result)) {
150 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
157 for (
size_t i = 0; i < them->entries.capacity; ++i) {
159 if (IS_KWARGS(entry->key))
continue;
165 if (IS_BOOLEAN(result) && !AS_BOOLEAN(result)) {
166 krk_tableSet(&AS_set(outSet)->entries, entry->key, BOOLEAN_VAL(1));
174 KRK_Method(set,__or__) {
175 METHOD_TAKES_EXACTLY(1);
176 CHECK_ARG(1,set,
struct Set*,them);
180 FUNC_NAME(set,__init__)(1,&outSet,0);
188 KRK_Method(set,__len__) {
190 return INTEGER_VAL(self->entries.count);
193 KRK_Method(set,__eq__) {
194 METHOD_TAKES_EXACTLY(1);
195 if (!IS_set(argv[1]))
196 return NOTIMPL_VAL();
197 CHECK_ARG(1,set,
struct Set*,them);
198 if (self->entries.count != them->entries.count)
199 return BOOLEAN_VAL(0);
203 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
204 if (IS_KWARGS(self->entries.entries[i].key))
continue;
205 if (!
krk_tableGet(&them->entries, self->entries.entries[i].key, &_unused))
return BOOLEAN_VAL(0);
208 return BOOLEAN_VAL(1);
212 KRK_Method(set,__lt__) {
213 METHOD_TAKES_EXACTLY(1);
214 if (!IS_set(argv[1]))
215 return NOTIMPL_VAL();
216 struct Set * them = AS_set(argv[1]);
217 if (self->entries.count == them->entries.count)
218 return BOOLEAN_VAL(0);
220 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
221 if (IS_KWARGS(self->entries.entries[i].key))
continue;
222 if (!
krk_tableGet(&them->entries, self->entries.entries[i].key, &_unused))
return BOOLEAN_VAL(0);
224 return BOOLEAN_VAL(1);
228 KRK_Method(set,__le__) {
229 METHOD_TAKES_EXACTLY(1);
230 if (!IS_set(argv[1]))
231 return NOTIMPL_VAL();
232 struct Set * them = AS_set(argv[1]);
234 for (
unsigned int i = 0; i <
self->entries.capacity; ++i) {
235 if (IS_KWARGS(self->entries.entries[i].key))
continue;
236 if (!
krk_tableGet(&them->entries, self->entries.entries[i].key, &_unused))
return BOOLEAN_VAL(0);
238 return BOOLEAN_VAL(1);
242 KRK_Method(set,__gt__) {
243 METHOD_TAKES_EXACTLY(1);
244 if (!IS_set(argv[1]))
245 return NOTIMPL_VAL();
246 struct Set * them = AS_set(argv[1]);
247 if (self->entries.count == them->entries.count)
248 return BOOLEAN_VAL(0);
250 for (
unsigned int i = 0; i < them->entries.capacity; ++i) {
251 if (IS_KWARGS(them->entries.entries[i].key))
continue;
252 if (!
krk_tableGet(&self->entries, them->entries.entries[i].key, &_unused))
return BOOLEAN_VAL(0);
254 return BOOLEAN_VAL(1);
257 KRK_Method(set,__ge__) {
258 METHOD_TAKES_EXACTLY(1);
259 if (!IS_set(argv[1]))
260 return NOTIMPL_VAL();
261 struct Set * them = AS_set(argv[1]);
263 for (
unsigned int i = 0; i < them->entries.capacity; ++i) {
264 if (IS_KWARGS(them->entries.entries[i].key))
continue;
265 if (!
krk_tableGet(&self->entries, them->entries.entries[i].key, &_unused))
return BOOLEAN_VAL(0);
267 return BOOLEAN_VAL(1);
271 KRK_Method(set,add) {
272 METHOD_TAKES_EXACTLY(1);
277 KRK_Method(set,remove) {
278 METHOD_TAKES_EXACTLY(1);
284 KRK_Method(set,discard) {
285 METHOD_TAKES_EXACTLY(1);
290 KRK_Method(set,clear) {
297 KRK_Method(set,update) {
298 METHOD_TAKES_AT_MOST(1);
300 if (IS_set(argv[1])) {
309 FUNC_SIG(setiterator,__init__);
311 KRK_Method(set,__iter__) {
320 #define CURRENT_CTYPE struct SetIterator *
322 KRK_Method(setiterator,__init__) {
323 METHOD_TAKES_EXACTLY(1);
324 CHECK_ARG(1,set,
void*,source);
330 KRK_Method(setiterator,__call__) {
333 if (unlikely(!IS_set(self->set)))
return argv[0];
336 if (self->i >= AS_set(self->set)->entries.capacity)
return argv[0];
337 if (!IS_KWARGS(AS_set(self->set)->entries.entries[self->i].key)) {
338 krk_push(AS_set(self->set)->entries.entries[self->i].key);
352 krk_tableSet(&AS_set(outSet)->entries, argv[argc-1], BOOLEAN_VAL(1));
360 void _createAndBind_setClass(
void) {
365 BIND_METHOD(set,__init__);
366 BIND_METHOD(set,__repr__);
367 BIND_METHOD(set,__len__);
368 BIND_METHOD(set,__eq__);
369 BIND_METHOD(set,__lt__);
370 BIND_METHOD(set,__gt__);
371 BIND_METHOD(set,__le__);
372 BIND_METHOD(set,__ge__);
373 BIND_METHOD(set,__and__);
374 BIND_METHOD(set,__or__);
375 BIND_METHOD(set,__xor__);
376 BIND_METHOD(set,__contains__);
377 BIND_METHOD(set,__iter__);
379 "@brief Add an element to the set.\n"
380 "@arguments value\n\n"
381 "Adds the given @p value to the set. @p value must be hashable.");
382 KRK_DOC(BIND_METHOD(set,remove),
383 "@brief Remove an element from the set.\n"
384 "@arguments value\n\n"
385 "Removes @p value from the set, raising @ref KeyError if it is not a member of the set.");
386 KRK_DOC(BIND_METHOD(set,discard),
387 "@brief Remove an element from the set, quietly.\n"
388 "@arguments value\n\n"
389 "Removes @p value from the set, without raising an exception if it is not a member.");
390 KRK_DOC(BIND_METHOD(set,clear),
391 "@brief Empty the set.\n\n"
392 "Removes all elements from the set, in-place.");
393 BIND_METHOD(set,update);
398 KrkClass * setiterator =
krk_makeClass(
vm.builtins, &KRK_BASE_CLASS(setiterator),
"setiterator",
vm.baseClasses->objectClass);
399 setiterator->
obj.
flags |= KRK_OBJ_FLAGS_NO_INHERIT;
401 setiterator->
_ongcscan = _setiterator_gcscan;
402 BIND_METHOD(setiterator,__init__);
403 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.
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.
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.
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.
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.
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.
#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.