12 #define TABLE_MAX_LOAD 3 / 4
17 table->entries = NULL;
26 switch (KRK_VAL_TYPE(value)) {
32 *hashOut = (uint32_t)AS_INTEGER(value);
35 if (AS_OBJECT(value)->flags & KRK_OBJ_FLAGS_VALID_HASH) {
36 *hashOut = AS_OBJECT(value)->hash;
42 *hashOut = (uint32_t)AS_FLOATING(value);
49 if (type && type->
_hash) {
52 if (!IS_INTEGER(result))
goto _unhashable;
53 *hashOut = (uint32_t)AS_INTEGER(result);
56 if (IS_CLASS(value)) {
57 *hashOut = INTEGER_VAL((
int)(intptr_t)AS_OBJECT(value));
71 index &= (capacity-1);
75 if (entry->key == KWARGS_VAL(0)) {
76 return tombstone != NULL ? tombstone : entry;
77 }
else if (entry->key == KWARGS_VAL(1)) {
78 if (tombstone == entry)
return tombstone;
79 if (tombstone == NULL) tombstone = entry;
83 index = (index + 1) & (capacity-1);
92 index &= (capacity-1);
96 if (entry->key == KWARGS_VAL(0)) {
97 return tombstone != NULL ? tombstone : entry;
98 }
else if (entry->key == KWARGS_VAL(1)) {
99 if (tombstone == entry)
return tombstone;
100 if (tombstone == NULL) tombstone = entry;
104 index = (index + 1) & (capacity-1);
109 int __builtin_clz(
unsigned int x) {
111 while (!(x & (1 << i)) && i >= 0) i--;
119 size_t powerOfTwoCapacity = __builtin_clz(1) - __builtin_clz(capacity);
120 if ((1UL << powerOfTwoCapacity) != capacity) powerOfTwoCapacity++;
121 capacity = (1UL << powerOfTwoCapacity);
125 for (
size_t i = 0; i < capacity; ++i) {
126 entries[i].key = KWARGS_VAL(0);
127 entries[i].value = KWARGS_VAL(0);
131 for (
size_t i = 0; i < table->capacity; ++i) {
133 if (IS_KWARGS(entry->key))
continue;
135 dest->key = entry->key;
136 dest->value = entry->value;
141 table->entries = entries;
142 table->capacity = capacity;
146 if (table->count + 1 > table->capacity * TABLE_MAX_LOAD) {
147 size_t capacity = GROW_CAPACITY(table->capacity);
151 if (!entry)
return 0;
152 int isNewKey = IS_KWARGS(entry->key);
153 if (isNewKey) table->count++;
155 entry->value = value;
160 if (table->count == 0)
return 0;
162 if (!entry)
return 0;
163 if (IS_KWARGS(entry->key))
return 0;
165 entry->value = value;
170 for (
size_t i = 0; i < from->capacity; ++i) {
172 if (!IS_KWARGS(entry->key)) {
179 if (table->count == 0)
return 0;
181 if (!entry || IS_KWARGS(entry->key)) {
184 *value = entry->value;
190 if (unlikely(table->count == 0))
return 0;
191 uint32_t index = str->
obj.
hash & (table->capacity-1);
195 if (entry->key == KWARGS_VAL(0)) {
197 }
else if (entry->key == KWARGS_VAL(1)) {
198 if (tombstone == entry)
return 0;
199 if (tombstone == NULL) tombstone = entry;
200 }
else if (entry->key == OBJECT_VAL(str)) {
201 *value = entry->value;
204 index = (index + 1) & (table->capacity-1);
209 if (table->count == 0)
return 0;
211 if (!entry || IS_KWARGS(entry->key)) {
215 entry->key = KWARGS_VAL(1);
216 entry->value = KWARGS_VAL(0);
221 if (table->count == 0)
return 0;
222 KrkTableEntry * entry = krk_findEntryExact(table->entries, table->capacity, key);
223 if (!entry || IS_KWARGS(entry->key)) {
227 entry->key = KWARGS_VAL(1);
228 entry->value = KWARGS_VAL(0);
233 if (table->count == 0)
return NULL;
235 uint32_t index = hash & (table->capacity-1);
239 if (entry->key == KWARGS_VAL(0)) {
241 }
else if (entry->key == KWARGS_VAL(1)) {
242 if (tombstone == entry)
return NULL;
243 if (tombstone == NULL) tombstone = entry;
244 }
else if (AS_STRING(entry->key)->length == length &&
245 AS_OBJECT(entry->key)->hash == hash &&
246 memcmp(AS_STRING(entry->key)->chars, chars, length) == 0) {
247 return AS_STRING(entry->key);
249 index = (index + 1) & (table->capacity-1);
KrkValue krk_runtimeError(KrkClass *type, const char *fmt,...)
Produce and raise an exception with a formatted message.
Top-level header with configuration macros.
Functions for dealing with garbage collection and memory allocation.
Struct definitions for core object types.
KrkObj * _hash
__hash__ Called when an instance is a key in a dict or an entry in a set
uint32_t hash
Cached hash value for table keys.
Immutable sequence of Unicode codepoints.
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_tableDeleteExact(KrkTable *table, KrkValue key)
Remove a key from a hash table, with identity lookup.
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.
struct KrkString * krk_tableFindString(KrkTable *table, const char *chars, size_t length, uint32_t hash)
Find a character sequence in the string interning 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.
int krk_tableGet_fast(KrkTable *table, struct KrkString *str, KrkValue *value)
Obtain the value associated with a string key in a table.
KrkTableEntry * krk_findEntry(KrkTableEntry *entries, size_t capacity, KrkValue key)
Internal table scan function.
int krk_tableSetIfExists(KrkTable *table, KrkValue key, KrkValue value)
Update the value of a table entry only if it is found.
KrkValue currentException
Stack reference or primative value.
int krk_valuesSame(KrkValue a, KrkValue b)
Compare two values by identity.
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.
int krk_hashValue(KrkValue value, uint32_t *hashOut)
Calculate the hash for a value.
Implementation of a generic hash table.
Convience header for providing atomic operations to threads.
Utilities for creating native bindings.
Definitions for primitive stack references.
Core API for the bytecode virtual machine.
#define vm
Convenience macro for namespacing.
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.