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.