added hash,copy methods for lists and maps. The hash method is now obligatory

This commit is contained in:
cozis
2022-03-09 13:05:05 +01:00
parent 0e9075bdbc
commit 7412f91d7d
6 changed files with 110 additions and 24 deletions
+41
View File
@@ -15,11 +15,15 @@ static int count(Object *self);
static void print(Object *obj, FILE *fp);
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static Object *copy(Object *self, Heap *heap, Error *err);
static int hash(Object *self);
static TypeObject t_list = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "list",
.size = sizeof (ListObject),
.copy = copy,
.hash = hash,
.select = select,
.insert = insert,
.count = count,
@@ -28,6 +32,43 @@ static TypeObject t_list = {
.walkexts = walkexts,
};
static int hash(Object *self)
{
assert(self != NULL);
assert(self->type == &t_list);
ListObject *ls = (ListObject*) self;
int h = 0;
// The hash is the sum of the nested
// hashes. It's not a smart solution
// but it works for now.
for(int i = 0; i < ls->count; i += 1)
h += Object_Hash(ls->vals[i]);
return h;
}
static Object *copy(Object *self, Heap *heap, Error *err)
{
(void) heap;
(void) err;
ListObject *ls = (ListObject*) self;
ListObject *ls2 = (ListObject*) Object_NewList(ls->count, heap, err);
if(ls2 == NULL) return NULL;
for(int i = 0; i < ls->count; i += 1)
{
ls2->vals[i] = Object_Copy(ls->vals[i], heap, err);
if(err->occurred) return NULL;
}
ls2->count = ls->count;
return (Object*) ls2;
}
static inline int calc_capacity(int mapper_size)
{
return mapper_size * 2.0 / 3.0;
+47 -12
View File
@@ -16,11 +16,15 @@ static int count(Object *self);
static void print(Object *self, FILE *fp);
static void walk(Object *self, void (*callback)(Object **referer, void *userp), void *userp);
static void walkexts(Object *self, void (*callback)(void **referer, unsigned int size, void *userp), void *userp);
static Object *copy(Object *self, Heap *heap, Error *err);
static int hash(Object *self);
static TypeObject t_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "map",
.size = sizeof (MapObject),
.copy = copy,
.hash = hash,
.select = select,
.insert = insert,
.count = count,
@@ -34,6 +38,46 @@ static inline int calc_capacity(int mapper_size)
return mapper_size * 2.0 / 3.0;
}
static Object *copy(Object *self, Heap *heap, Error *err)
{
MapObject *m1 = (MapObject*) self;
Object *m2 = Object_NewMap(m1->count, heap, err);
if(m2 == NULL) return NULL;
for(int i = 0; i < m1->count; i += 1)
{
Object *key, *key_cpy;
Object *val, *val_cpy;
key = m1->keys[i];
val = m1->vals[i];
key_cpy = Object_Copy(key, heap, err);
if(key_cpy == NULL) return NULL;
val_cpy = Object_Copy(val, heap, err);
if(val_cpy == NULL) return NULL;
if(!Object_Insert(m2, key_cpy, val_cpy, heap, err))
return NULL;
}
return (Object*) m2;
}
static int hash(Object *self)
{
MapObject *m = (MapObject*) self;
int h = 0;
// The hash of the map is the sum of the
// hashes of each key and each item.
for(int i = 0; i < m->count; i += 1)
h += Object_Hash(m->keys[i])
+ Object_Hash(m->vals[i]);
return h;
}
Object *Object_NewMap(int num, Heap *heap, Error *error)
{
// Handle default args.
@@ -107,13 +151,9 @@ static Object *select(Object *self, Object *key, Heap *heap, Error *error)
MapObject *map = (MapObject*) self;
unsigned int mask = map->mapper_size - 1;
unsigned int hash = Object_Hash(key, error);
unsigned int hash = Object_Hash(key);
unsigned int pert = hash;
if(error->occurred)
// No hash function.
return 0;
int i = hash & mask;
while(1)
@@ -181,8 +221,7 @@ static _Bool grow(MapObject *map, Heap *heap, Error *error)
// This won't trigger an error because the key
// surely has a hash method since we already
// hashed it once.
int hash = Object_Hash(keys[i], error);
assert(error->occurred == 0);
int hash = Object_Hash(keys[i]);
int mask = new_mapper_size - 1;
int pert = hash;
@@ -229,13 +268,9 @@ static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *e
return 0;
unsigned int mask = map->mapper_size - 1;
unsigned int hash = Object_Hash(key, error);
unsigned int hash = Object_Hash(key);
unsigned int pert = hash;
if(error->occurred)
// No hash function.
return 0;
int i = hash & mask;
while(1)
+18 -2
View File
@@ -3,12 +3,16 @@
#include "objects.h"
static _Bool op_eql(Object *self, Object *other);
static void print(Object *obj, FILE *fp);
static void print(Object *obj, FILE *fp);
static int hash(Object *self);
static Object *copy(Object *self, Heap *heap, Error *err);
static TypeObject t_none = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "none",
.size = sizeof (Object),
.hash = hash,
.copy = copy,
.print = print,
.op_eql = op_eql,
};
@@ -18,6 +22,19 @@ static Object the_none_object = {
.flags = Object_STATIC,
};
static int hash(Object *self)
{
assert(self == &the_none_object);
return 0;
}
static Object *copy(Object *self, Heap *heap, Error *err)
{
(void) heap;
(void) err;
return self;
}
Object *Object_NewNone(Heap *heap, Error *error)
{
(void) heap;
@@ -25,7 +42,6 @@ Object *Object_NewNone(Heap *heap, Error *error)
return &the_none_object;
}
static void print(Object *obj, FILE *fp)
{
assert(fp != NULL);
+2 -9
View File
@@ -64,19 +64,12 @@ unsigned int Object_GetDeepSize(const Object *obj, Error *err)
return type->deepsize(obj);
}
int Object_Hash(Object *obj, Error *err)
int Object_Hash(Object *obj)
{
assert(obj != NULL);
const TypeObject *type = Object_GetType(obj);
assert(type != NULL);
if(type->hash == NULL)
{
Error_Report(err, 0, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return -1;
}
assert(type->hash != NULL);
return type->hash(obj);
}
+1 -1
View File
@@ -90,7 +90,7 @@ const char* Object_GetName(const Object *obj);
unsigned int Object_GetSize(const Object *obj, Error *err);
unsigned int Object_GetDeepSize(const Object *obj, Error *err);
void *Object_GetBufferAddrAndSize(Object *obj, int *size, Error *error);
int Object_Hash (Object *obj, Error *err);
int Object_Hash (Object *obj);
Object* Object_Copy (Object *obj, Heap *heap, Error *err);
Object* Object_Call (Object *obj, Object **argv, unsigned int argc, Heap *heap, Error *err);
void Object_Print (Object *obj, FILE *fp);
+1
View File
@@ -80,6 +80,7 @@
({'': none});
({1: none});
({1.0: none});
({none: none});
({true: none});
({false: none});
({[]: none});