Skip to content

Instantly share code, notes, and snippets.

@johnfredcee
Created January 1, 2014 16:41
Show Gist options
  • Select an option

  • Save johnfredcee/8209392 to your computer and use it in GitHub Desktop.

Select an option

Save johnfredcee/8209392 to your computer and use it in GitHub Desktop.
Sketch of a C based object system that decouples objects and functions
typedef struct
{
unsigned code;
} class;
static int class_count = 0;
class classes[256];
typedef struct
{
void *class;
} object;
typedef object (*methodptr)(object);
typedef struct
{
void *class;
char *data;
} string;
typedef struct
{
unsigned size;
methodptr* functions;
unsigned* codes;
} hashtable;
typedef struct
{
hashtable *hashes;
methodptr *default;
} generic;
unsigned hash(unsigned code, unsigned size)
{
unsigned mask = (1 << size) - 1;
unsigned a = code;
a -= (a<<6);
a ^= (a>>17);
a -= (a<<9);
a ^= (a<<4);
a -= (a<<3);
a ^= (a<<10);
a ^= (a>>15);
return a & mask;
}
hashtable* new_hashtable(unsigned size)
{
hashtable* result;
unsigned slots = 1 << size;
result = malloc(hashtable);
result->functions = malloc(slots * sizeof(methodptr));
memset(result->functions, 0, slots * sizeof(methodptr));
result->codes = malloc(slots * sizeof(unsigned));
memset(result->codes, 0, slots * sizeof(unsigned));
result->size = size;
return result;
}
void delete_hashtable(hashtable* table)
{
free(table->codes);
free(table->functions);
free(table);
}
hashtable* extend_hashtable(hashtable* table)
{
hashtable* result;
unsigned slots = 1 << (table->size + 1);
result = malloc(hashtable);
result->functions = malloc(slots * sizeof(methodptr));
memset(result->functions, 0, slots * sizeof(methodptr));
result->codes = malloc(slots * sizeof(unsigned));
memset(result->codes, 0, slots * sizeof(unsigned));
result->size = table->size + 1;
// rehash
delete(table);
return result;
}
void add_hash(hashtable* table, unsigned code, methodptr* function)
{
unsigned hashcode = hash(code, table->size);
table->codes[hashcode] = code;
table->functions[hashcode] = function;
}
void remove_hash(hashtable* table, unsigned code, methodptr* function)
{
unsigned hashcode = hash(code, table->size);
table->codes[hashcode] = 0;
table->functions[hashcode] = NULL;
}
methodptr* get_fun(hashtable* table, unsigned code)
{
unsigned hashcode = hash(code, table->size);
return table->functions[hashcode];
}
unsigned new_class()
{
unsigned result = class_count;
class *new_class = malloc(sizeof(class));
new_class->code = class_count;
classes[class_count] = new_class;
class_count++;
return result;
}
generic* new_generic(methodptr *defaultfn)
{
generic *result = malloc(sizeof(generic));
result->hashes = new_hashtable(8);
result->defaultfn = defaultfn;
}
void add_method(generic* genericfun, unsigned code, methodptr* function)
{
add_hash(genericfun->hashes, code, function);
}
void remove_method(generic* genericfun, unsigned code)
{
remove_hash(genericfun->hashes, code);
}
object* dispatch(generic* genericfun, object* object)
{
methodptr* method = get_fun(genericfun->hashes, object->class->code);
if (method)
return method(object);
else
return genericfun->defualt(object);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment