first commit

This commit is contained in:
cozis
2021-10-31 04:17:57 +00:00
commit 7a5d0d1dcb
55 changed files with 5204 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include "objects.h"
typedef struct OflowAlloc OflowAlloc;
struct OflowAlloc {
OflowAlloc *prev;
char body[];
};
struct xHeap {
int size;
int used;
void *body;
OflowAlloc *oflow;
};
Heap *Heap_New(int size)
{
if(size < 0)
size = 65536;
Heap *heap = malloc(sizeof(Heap));
if(heap == NULL)
return NULL;
heap->size = size;
heap->used = 0;
heap->body = malloc(size);
heap->oflow = 0;
if(heap->body == NULL)
{
free(heap);
return NULL;
}
return heap;
}
void Heap_Free(Heap *heap)
{
while(heap->oflow)
{
OflowAlloc *prev = heap->oflow->prev;
free(heap->oflow);
heap->oflow = prev;
}
free(heap->body);
free(heap);
}
void *Heap_Malloc(Heap *heap, const Type *type, Error *err)
{
void *addr = Heap_RawMalloc(heap, type->size, err);
if(addr == NULL)
return NULL;
Object *obj = addr;
obj->type = type;
obj->flags = 0;
if(type->init && !type->init(obj, err))
return NULL;
obj->type = type;
obj->flags = 0;
return (Object*) addr;
}
void *Heap_RawMalloc(Heap *heap, int size, Error *err)
{
assert(err);
assert(heap);
assert(size > -1);
void *addr;
if(heap->used + size >= heap->size)
{
OflowAlloc *oflow = malloc(sizeof(OflowAlloc) + size);
if(oflow == 0)
return 0;
oflow->prev = heap->oflow;
heap->oflow = oflow;
addr = oflow->body;
}
else
{
if(heap->used & 7)
heap->used = (heap->used & ~7) + 8;
addr = heap->body + heap->used;
heap->used += size;
}
assert(((intptr_t) addr) % 8 == 0);
return addr;
}
+40
View File
@@ -0,0 +1,40 @@
#include <assert.h>
#include "objects.h"
static double to_float(Object *obj, Error *err);
typedef struct {
Object base;
double val;
} FloatObject;
static const Type t_float = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "float",
.size = sizeof (FloatObject),
.atomic = ATMTP_FLOAT,
.to_float = to_float,
};
static double to_float(Object *obj, Error *err)
{
assert(obj);
assert(err);
assert(Object_GetType(obj) == &t_float);
(void) err;
return ((FloatObject*) obj)->val;
}
Object *Object_FromFloat(double val, Heap *heap, Error *error)
{
FloatObject *obj = (FloatObject*) Heap_Malloc(heap, &t_float, error);
if(obj == 0)
return 0;
obj->val = val;
return (Object*) obj;
}
+41
View File
@@ -0,0 +1,41 @@
#include <assert.h>
#include <string.h>
#include "objects.h"
static long long int to_int(Object *obj, Error *err);
typedef struct {
Object base;
long long int val;
} IntObject;
static const Type t_int = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "int",
.size = sizeof (IntObject),
.atomic = ATMTP_INT,
.to_int = to_int,
};
static long long int to_int(Object *obj, Error *err)
{
assert(obj);
assert(err);
assert(Object_GetType(obj) == &t_int);
(void) err;
return ((IntObject*) obj)->val;
}
Object *Object_FromInt(long long int val, Heap *heap, Error *error)
{
IntObject *obj = (IntObject*) Heap_Malloc(heap, &t_int, error);
if(obj == 0)
return 0;
obj->val = val;
return (Object*) obj;
}
+261
View File
@@ -0,0 +1,261 @@
#include <assert.h>
#include "../utils/defs.h"
#include "objects.h"
typedef struct {
Object base;
int mapper_size, count;
int *mapper;
Object **keys;
Object **vals;
} MapObject;
static Object *select(Object *self, Object *key, Heap *heap, Error *err);
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *err);
static int count(Object *self);
static const Type t_map = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "map",
.size = sizeof (MapObject),
.select = select,
.insert = insert,
.count = count,
};
static inline int calc_capacity(int mapper_size)
{
return mapper_size * 2.0 / 3.0;
}
Object *Object_NewMap(int num, Heap *heap, Error *error)
{
// Handle default args.
if(num < 0)
num = 0;
// Calculate initial mapper size.
int mapper_size, capacity;
{
mapper_size = 8;
while(calc_capacity(mapper_size) < num)
mapper_size <<= 1;
capacity = calc_capacity(mapper_size);
}
// Make the thing.
MapObject *obj = (MapObject*) Heap_Malloc(heap, &t_map, error);
{
if(obj == 0)
return 0;
obj->mapper_size = mapper_size;
obj->count = 0;
obj->mapper = Heap_RawMalloc(heap, sizeof(int) * capacity, error);
obj->keys = Heap_RawMalloc(heap, sizeof(Object*) * capacity, error);
obj->vals = Heap_RawMalloc(heap, sizeof(Object*) * capacity, error);
if(obj->mapper == NULL || obj->keys == NULL || obj->vals == NULL)
return NULL;
}
for(int i = 0; i < mapper_size; i += 1)
obj->mapper[i] = -1;
return (Object*) obj;
}
static Object *select(Object *self, Object *key, Heap *heap, Error *error)
{
assert(self != NULL);
assert(self->type == &t_map);
assert(key != NULL);
assert(heap != NULL);
assert(error != NULL);
MapObject *map = (MapObject*) self;
int mask = map->mapper_size - 1;
int hash = Object_Hash(key, error);
int pert = hash;
if(error->occurred)
// No hash function.
return 0;
int i = hash & mask;
while(1)
{
int k = map->mapper[i];
if(k == -1)
{
// Empty slot.
// This key is not present.
return NULL;
}
else
{
// Found an item.
// Is it the right one?
assert(k >= 0);
if(Object_Compare(key, map->keys[i], error))
// Found it!
return map->vals[i];
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Not the one we wanted.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
}
UNREACHABLE;
return NULL;
}
static _Bool grow(MapObject *map, Heap *heap, Error *error)
{
assert(map != NULL);
int new_mapper_size = map->mapper_size << 1;
int new_capacity = calc_capacity(new_mapper_size);
int *mapper = Heap_RawMalloc(heap, sizeof(int) * new_mapper_size, error);
Object **keys = Heap_RawMalloc(heap, sizeof(Object*) * new_capacity, error);
Object **vals = Heap_RawMalloc(heap, sizeof(Object*) * new_capacity, error);
if(mapper == NULL || keys == NULL || vals == NULL)
return 0;
for(int i = 0; i < map->count; i += 1)
{
keys[i] = map->keys[i];
vals[i] = map->vals[i];
}
for(int i = 0; i < new_mapper_size; i += 1)
mapper[i] = -1;
// Rehash everything.
for(int i = 0; i < map->count; i += 1)
{
// 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 mask = new_mapper_size - 1;
int pert = hash;
int j = hash & mask;
while(1)
{
if(mapper[j] == -1)
{
// No collision.
// Insert here.
mapper[j] = i;
break;
}
// Collided. Find a new place.
pert >>= 5;
j = (j * 5 + pert + 1) & mask;
}
}
// Done.
map->mapper = mapper;
map->mapper_size = new_mapper_size;
map->keys = keys;
map->vals = vals;
return 1;
}
static _Bool insert(Object *self, Object *key, Object *val, Heap *heap, Error *error)
{
assert(error != NULL);
assert(key != NULL);
assert(val != NULL);
assert(heap != NULL);
assert(self != NULL);
assert(self->type == &t_map);
MapObject *map = (MapObject*) self;
if(map->count == calc_capacity(map->mapper_size))
if(!grow(map, heap, error))
return 0;
int mask = map->mapper_size - 1;
int hash = Object_Hash(key, error);
int pert = hash;
if(error->occurred)
// No hash function.
return 0;
int i = hash & mask;
while(1)
{
int k = map->mapper[i];
if(k == -1)
{
// Empty slot. We can insert it here.
Object *key_copy = Object_Copy(key, heap, error);
if(key_copy == NULL)
return NULL;
map->mapper[i] = map->count;
map->keys[map->count] = key_copy;
map->vals[map->count] = val;
map->count += 1;
return 1;
}
else
{
assert(k >= 0);
if(Object_Compare(key, map->keys[i], error))
{
// Already inserted.
// Overwrite the value.
map->vals[i] = val;
return 1;
}
if(error->occurred)
// Key doesn't implement compare.
return 0;
// Collision.
}
pert >>= 5;
i = (i * 5 + pert + 1) & mask;
}
UNREACHABLE;
return 0;
}
static int count(Object *self)
{
MapObject *map = (MapObject*) self;
return map->count;
}
+21
View File
@@ -0,0 +1,21 @@
#include <assert.h>
#include <string.h>
#include "objects.h"
static const Type t_none = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "none",
.size = sizeof (Object),
};
static Object the_none_object = {
.type = &t_none,
.flags = Object_STATIC,
};
Object *Object_NewNone(Heap *heap, Error *error)
{
(void) heap;
(void) error;
return &the_none_object;
}
+69
View File
@@ -0,0 +1,69 @@
#include <string.h>
#include <assert.h>
#include "../utils/defs.h"
#include "../utils/hash.h"
#include "objects.h"
typedef struct {
Object base;
int size;
char *body;
} StringObject;
static int hash(Object *self);
static int count(Object *self);
static const Type t_string = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "string",
.size = sizeof (StringObject),
.hash = hash,
.count = count,
};
Object *Object_FromString(const char *str, int len, Heap *heap, Error *error)
{
assert(str != NULL);
assert(heap != NULL);
assert(error != NULL);
if(len < 0)
len = strlen(str);
StringObject *strobj = Heap_Malloc(heap, &t_string, error);
if(strobj == NULL)
return NULL;
strobj->body = Heap_RawMalloc(heap, len+1, error);
strobj->size = len;
if(strobj->body == NULL)
return NULL;
memcpy(strobj->body, str, len);
strobj->body[len] = '\0';
return (Object*) strobj;
}
static int count(Object *self)
{
assert(self != NULL);
assert(self->type == &t_string);
StringObject *strobj = (StringObject*) self;
return strobj->size;
}
static int hash(Object *self)
{
assert(self != NULL);
assert(self->type == &t_string);
StringObject *strobj = (StringObject*) self;
return hashbytes((unsigned char*) strobj->body, strobj->size);
}
+286
View File
@@ -0,0 +1,286 @@
#include <assert.h>
#include "../utils/defs.h"
#include "objects.h"
const Type t_type = {
.base = (Object) { .type = &t_type, .flags = Object_STATIC },
.name = "type",
.size = sizeof (Type),
};
const char *Object_GetName(const Object *obj)
{
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
const char *name = type->name;
assert(name);
return name;
}
const Type *Object_GetType(const Object *obj)
{
assert(obj);
assert(obj->type);
return obj->type;
}
unsigned int Object_GetSize(const Object *obj, Error *err)
{
assert(err);
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
return type->size;
}
unsigned int Object_GetDeepSize(const Object *obj, Error *err)
{
assert(err);
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
if(type->deepsize == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0;
}
return type->deepsize(obj);
}
int Object_Hash(Object *obj, Error *err)
{
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
if(type->hash == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return -1;
}
return type->hash(obj);
}
Object *Object_Copy(Object *obj, Heap *heap, Error *err)
{
assert(err);
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
if(type->copy == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return NULL;
}
return type->copy(obj, heap, err);
}
Object *Object_Call(Object *obj, Object **argv, unsigned int argc, Heap *heap, Error *err)
{
assert(err);
assert(obj);
const Type *type = Object_GetType(obj);
assert(type);
if(type->call == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return NULL;
}
return type->call(obj, argv, argc, heap, err);
}
Object *Object_Select(Object *coll, Object *key, Heap *heap, Error *err)
{
assert(err);
assert(key);
assert(coll);
const Type *type = Object_GetType(coll);
assert(type);
if(type->select == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return NULL;
}
return type->select(coll, key, heap, err);
}
Object *Object_Delete(Object *coll, Object *key, Heap *heap, Error *err)
{
assert(err);
assert(key);
assert(coll);
const Type *type = Object_GetType(coll);
assert(type);
if(type->delete == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return NULL;
}
return type->delete(coll, key, heap, err);
}
_Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *err)
{
assert(err);
assert(key);
assert(coll);
const Type *type = Object_GetType(coll);
assert(type);
if(type->insert == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return 0;
}
return type->insert(coll, key, val, heap, err);
}
int Object_Count(Object *coll, Error *err)
{
assert(err);
assert(coll);
const Type *type = Object_GetType(coll);
assert(type);
if(type->count == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(coll), __func__);
return -1;
}
return type->count(coll);
}
Object *Object_Next(Object *iter, Heap *heap, Error *err)
{
assert(err);
assert(iter);
const Type *type = Object_GetType(iter);
assert(type);
if(type->next == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
return NULL;
}
return type->next(iter, heap, err);
}
Object *Object_Prev(Object *iter, Heap *heap, Error *err)
{
assert(err);
assert(iter);
const Type *type = Object_GetType(iter);
assert(type);
if(type->prev == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(iter), __func__);
return NULL;
}
return type->prev(iter, heap, err);
}
_Bool Object_IsInt(Object *obj)
{
assert(obj != NULL);
assert(obj->type != NULL);
return obj->type->atomic == ATMTP_INT;
}
_Bool Object_IsFloat(Object *obj)
{
assert(obj != NULL);
assert(obj->type != NULL);
return obj->type->atomic == ATMTP_FLOAT;
}
long long int Object_ToInt(Object *obj, Error *err)
{
assert(err);
assert(obj);
if(!Object_IsInt(obj))
{
Error_Report(err, 0, "Object is not an integer");
return 0;
}
const Type *type = Object_GetType(obj);
assert(type);
if(type->to_int == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0;
}
return type->to_int(obj, err);
}
double Object_ToFloat(Object *obj, Error *err)
{
assert(err);
assert(obj);
if(!Object_IsFloat(obj))
{
Error_Report(err, 0, "Object is not a floating");
return 0;
}
const Type *type = Object_GetType(obj);
assert(type);
if(type->to_float == NULL)
{
Error_Report(err, "Object %s doesn't implement %s", Object_GetName(obj), __func__);
return 0;
}
return type->to_float(obj, err);
}
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error)
{
if(obj1->type != obj2->type)
return 0;
if(obj1->type->op_eql == NULL)
{
Error_Report(error, "Object %s doesn't implement %s", Object_GetName(obj1), __func__);
return 0;
}
return obj1->type->op_eql(obj1, obj2);
}
+96
View File
@@ -0,0 +1,96 @@
#ifndef OBJECT_H
#define OBJECT_H
#include "../utils/error.h"
typedef struct Type Type;
typedef struct Object Object;
typedef struct xHeap Heap;
struct Object {
const Type *type;
unsigned int flags;
};
typedef enum {
ATMTP_NOTATOMIC = 0,
ATMTP_INT,
ATMTP_FLOAT,
} AtomicType;
struct Type {
Object base;
// Any.
const char *name;
unsigned int size;
AtomicType atomic;
_Bool (*init)(Object *self, Error *err);
_Bool (*free)(Object *self, Error *err);
int (*hash)(Object *self);
Object* (*copy)(Object *self, Heap *heap, Error *err);
Object* (*call)(Object *self, Object **argv, unsigned int argc, Heap *heap, Error *err);
unsigned int (*deepsize)(const Object *self);
// Collections.
Object *(*select)(Object *self, Object *key, Heap *heap, Error *err);
Object *(*delete)(Object *self, Object *key, Heap *heap, Error *err);
_Bool (*insert)(Object *self, Object *key, Object *val, Heap *heap, Error *err);
int (*count)(Object *self);
// Iterators.
Object *(*next)(Object *self, Heap *heap, Error *err);
Object *(*prev)(Object *self, Heap *heap, Error *err);
// Some.
union {
long long int (*to_int)(Object *self, Error *err);
double (*to_float)(Object *self, Error *err);
char *(*to_string)(Object *self, int *size, Heap *heap, Error *err);
};
_Bool (*op_eql)(Object *self, Object *other);
};
enum {
Object_STATIC = 1,
};
Heap* Heap_New(int size);
void Heap_Free(Heap *heap);
void* Heap_Malloc (Heap *heap, const Type *type, Error *err);
void* Heap_RawMalloc(Heap *heap, int size, Error *err);
const Type* Object_GetType(const Object *obj);
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);
int Object_Hash (Object *obj, Error *err);
Object* Object_Copy (Object *obj, Heap *heap, Error *err);
Object* Object_Call (Object *obj, Object **argv, unsigned int argc, Heap *heap, Error *err);
Object* Object_Select(Object *coll, Object *key, Heap *heap, Error *err);
Object* Object_Delete(Object *coll, Object *key, Heap *heap, Error *err);
_Bool Object_Insert(Object *coll, Object *key, Object *val, Heap *heap, Error *err);
int Object_Count (Object *coll, Error *err);
Object* Object_Next (Object *iter, Heap *heap, Error *err);
Object* Object_Prev (Object *iter, Heap *heap, Error *err);
Object* Object_NewMap(int num, Heap *heap, Error *error);
Object* Object_NewNone(Heap *heap, Error *error);
Object* Object_FromInt (long long int val, Heap *heap, Error *error);
Object* Object_FromFloat (double val, Heap *heap, Error *error);
Object* Object_FromString(const char *str, int len, Heap *heap, Error *error);
_Bool Object_IsInt (Object *obj);
_Bool Object_IsFloat(Object *obj);
long long int Object_ToInt (Object *obj, Error *err);
double Object_ToFloat(Object *obj, Error *err);
_Bool Object_Compare(Object *obj1, Object *obj2, Error *error);
extern const Type t_type;
#endif