void* gc_getref(void** ref) {
return (void*)((uintptr_t)*ref & ~DIRTY_BIT);
}
+
+/*****************************************************************************/
+
+typedef struct hash_entry_t {
+ struct hash_entry_t* next;
+ uintptr_t hash;
+} hash_entry_t;
+
+typedef struct {
+ size_t size;
+ size_t bktid;
+ hash_entry_t** buckets;
+} hash_t;
+
+static void hash_set(hash_t* hash, hash_entry_t* entry);
+
+#define NUM_PRIMES (sizeof(Primes)/sizeof(unsigned int))
+
+static unsigned int Primes[] = {
+ 5, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,
+ 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,
+ 12582917, 25165843, 50331653, 100663319, 201326611, 402653189,
+ 805306457, 1610612741
+};
+
+static void hash_init(hash_t* hash) {
+ hash->size = 0;
+ hash->bktid = 0;
+ hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), Primes[hash->bktid]);
+}
+
+static void find_entry(hash_entry_t** parent, hash_entry_t** current, hash_entry_t* entry) {
+ while(*current != NULL) {
+ if (((*current)->hash == entry->hash) &&
+ ((*current)->object == entry->object))
+ break;
+ *parent = *current;
+ *current = (*current)->next;
+ }
+}
+
+static void rehash(hash_t* hash) {
+ unsigned int oldcount, i;
+ hash_entry_t** oldbuckets;
+ hash_entry_t *node, *entry;
+ if ((hash->bktid + 1) < NUM_PRIMES) {
+ oldcount = hash->bktid++;
+ oldbuckets = hash->buckets;
+ hash->buckets = (hash_entry_t**)calloc(sizeof(hash_entry_t*), Primes[hash->bktid]);
+ hash->size = 0;
+ /* Iterate over all of the old buckets */
+ for (i = 0; i < Primes[oldcount]; i++) {
+ node = oldbuckets[i];
+ /* re-insert all entries in the bucket into the new bucket table */
+ while (node != NULL) {
+ entry = node;
+ node = entry->next;
+ hash_set(hash, entry);
+ }
+ }
+ /* Free the old bucket table */
+ free(oldbuckets);
+ }
+}
+
+static uint64_t hash64(uint64_t key) {
+ key = (~key) + (key << 21);
+ key = key ^ (key >> 24);
+ key = (key + (key << 3)) + (key << 8);
+ key = key ^ (key >> 14);
+ key = (key + (key << 2)) + (key << 4);
+ key = key ^ (key >> 28);
+ key = key + (key << 31);
+ return key;
+}
+
+static void hash_set(hash_t* hash, hash_entry_t* entry) {
+ unsigned int index;
+ hash_entry_t *parent, *node, *deadite;
+ if (hash->size >= Primes[hash->bktid])
+ rehash(hash);
+ entry->hash = hash64((uint64_t)(entry->object));
+ index = (entry->hash % Primes[hash->bktid]);
+ parent = NULL;
+ node = hash->buckets[index];
+ deadite = NULL;
+ find_entry(&parent, &node, entry);
+ if ((parent == NULL) && (node == NULL)) {
+ hash->buckets[index] = entry;
+ entry->next = NULL;
+ hash->size++;
+ } else if (node == NULL) {
+ parent->next = entry;
+ entry->next = NULL;
+ hash->size++;
+ }
+}
+
+static hash_entry_t* hash_del(hash_t* hash, hash_entry_t* entry) {
+ unsigned int index;
+ hash_entry_t *parent, *node, *ret = NULL;
+ entry->hash = hash64((uint64_t)(entry->object));
+ index = (entry->hash % Primes[hash->bktid]);
+ parent = NULL;
+ node = hash->buckets[index];
+ find_entry(&parent, &node, entry);
+ if (node != NULL) {
+ ret = node;
+ node = node->next;
+ if (parent != NULL)
+ parent->next = node;
+ else
+ hash->buckets[index] = node;
+ hash->size--;
+ }
+ return ret;
+}
+
require 'open3'
describe "sclpl grammar" do
-# context "definitions" do
+ context "definitions" do
# it "should parse a value definition with type annotation" do
-# expect(ast('def foo int 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
+# expect(ast('123')).to eq([ ['def', 'foo', 'T_INT:123'] ])
# end
#
# it "should parse a function definition with return type annotation" do
# ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'],
# ["let", ["$:0", "T_INT:123"], "$:0"]]]])
# end
-# end
+ end
#
# context "literals" do
# it "should parse a string" do