Mercurial > repos > rhope
view runtime/object.c @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -0400 |
parents | 04baa003de5a |
children | a68e6828d896 |
line wrap: on
line source
#include "object.h" #include "builtin.h" #include <stdlib.h> #include <string.h> #include <stdio.h> #include "fixed_alloc.h" blueprint ** registered_types = NULL; uint32_t max_registered_type = 0; uint32_t type_storage = 0; mem_manager * manager = NULL; /* returntype call_method(uint32_t methodid, calldata * params) { int i; blueprint * bp = get_blueprint(params->params[0]); if(methodid >= bp->first_methodid && methodid < bp->last_methodid && bp->method_lookup[methodid - bp->first_methodid]) { params->tail_func = bp->method_lookup[methodid - bp->first_methodid]; return TAIL_RETURN; } else { if(METHOD_MISSING >= bp->first_methodid && METHOD_MISSING < bp->last_methodid && bp->method_lookup[METHOD_MISSING - bp->first_methodid]) { params->tail_func = bp->method_lookup[METHOD_MISSING - bp->first_methodid]; return TAIL_RETURN; } else { //TODO: Add useful info to exception for(i = 0; i < params->num_params; ++i) release_ref(params->params[i]); params->params[0] = new_object(TYPE_METHODMISSINGEXCEPTION); return EXCEPTION_RETURN; } } } returntype set_field(uint32_t setfieldid, calldata * params) { int i; blueprint * bp = get_blueprint(params->params[0]); if(setfieldid >= bp->first_setfieldid && setfieldid < bp->last_setfieldid && bp->setter_lookup[setfieldid - bp->first_setfieldid]) { params->tail_func = bp->setter_lookup[setfieldid - bp->first_setfieldid]; return TAIL_RETURN; } else { if(METHOD_SETFIELDMISSING >= bp->first_setfieldid && METHOD_SETFIELDMISSING < bp->last_setfieldid && bp->method_lookup[METHOD_SETFIELDMISSING - bp->first_methodid]) { params->tail_func = bp->method_lookup[METHOD_SETFIELDMISSING - bp->first_methodid]; params->original_methodid = setfieldid; return TAIL_RETURN; } else { //TODO: Add useful info to exception for(i = 0; i < params->num_params; ++i) release_ref(params->params[i]); params->params[0] = new_object(TYPE_FIELDMISSINGEXCEPTION); return EXCEPTION_RETURN; } } } returntype get_field(uint32_t getfieldid, calldata * params) { int i; blueprint * bp = get_blueprint(params->params[0]); if(getfieldid >= bp->first_getfieldid && getfieldid < bp->last_getfieldid && bp->getter_lookup[getfieldid - bp->first_getfieldid]) { params->tail_func = bp->getter_lookup[getfieldid - bp->first_getfieldid]; return TAIL_RETURN; } else { if(METHOD_GETFIELDMISSING >= bp->first_getfieldid && METHOD_GETFIELDMISSING < bp->last_getfieldid && bp->method_lookup[METHOD_GETFIELDMISSING - bp->first_methodid]) { params->tail_func = bp->method_lookup[METHOD_GETFIELDMISSING - bp->first_methodid]; params->original_methodid = getfieldid; return TAIL_RETURN; } else { //TODO: Add useful info to exception for(i = 0; i < params->num_params; ++i) release_ref(params->params[i]); params->params[0] = new_object(TYPE_FIELDMISSINGEXCEPTION); return EXCEPTION_RETURN; } } } returntype convert_to(uint32_t convertto, calldata * params) { int i; blueprint * bp = get_blueprint(params->params[0]); if(convertto >= bp->first_convertto && convertto < bp->last_convertto && bp->convert_to[convertto]) { params->tail_func = bp->convert_to[convertto - bp->first_convertto]; return TAIL_RETURN; } else { return NO_CONVERSION; } } returntype convert_from(uint32_t convertfrom, calldata * params) { int i; blueprint * bp = registered_types[convertfrom]; if(convertfrom >= bp->first_convertfrom && convertfrom < bp->last_convertfrom && bp->convert_from[convertfrom]) { params->tail_func = bp->convert_from[convertfrom - bp->first_convertfrom]; return TAIL_RETURN; } else { return NO_CONVERSION; } } returntype coerce_value(uint32_t type, calldata * params) { int i; blueprint * bp = get_blueprint(params->params[0]); if(bp == registered_types[type]) return NORMAL_RETURN; if(convert_to(type, params) == TAIL_RETURN) return TAIL_RETURN; if(convert_from(type, params) == TAIL_RETURN) return TAIL_RETURN; //TODO: Add useful info to exception for(i = 0; i < params->num_params; ++i) release_ref(params->params[i]); params->params[0] = new_object(TYPE_WRONGTYPEEXCEPTION); return EXCEPTION_RETURN; }*/ object * alloc_object(blueprint * bp) { return falloc(bp->boxed_size, manager); //return malloc(bp->boxed_size); } void dealloc_object(blueprint * bp, object * obj) { ffree(obj, bp->boxed_size, manager); } object * new_object(uint32_t type) { blueprint * bp; object * ret; if(type >= max_registered_type || !registered_types[type]) return NULL; bp = registered_types[type]; return new_object_bp(bp); } object * new_object_bp(blueprint * bp) { object * ret; ret = alloc_object(bp); if(ret) { ret->bprint = bp; rh_atomic_set(ret, refcount, 1); memset(((char *)ret) + sizeof(object), '\0', bp->size); bp->init(ret); } else { fprintf(stderr, "Could not allocate new object with size %d\n", bp->boxed_size); } return ret; } multisize * new_multisize(uint32_t type, uint32_t size) { blueprint *bp; multisize * ret; if(type >= max_registered_type || !registered_types[type]) return NULL; ret = falloc(sizeof(multisize) + size, manager); if(ret) { bp = registered_types[type]; ret->base.bprint = bp; ret->size = size; rh_atomic_set(&(ret->base), refcount, 1); memset(((char *)ret) + sizeof(multisize), '\0', size); bp->init((object *)ret); } return ret; } object * copy_object(object * tocopy) { object * copy; multisize * mcopy, *mtocopy; blueprint * bp; if(rh_atomic_get(tocopy, refcount) == 1) return tocopy; bp = get_blueprint(tocopy); if(bp->size < 0) { mtocopy = (multisize *)tocopy; mcopy = falloc(sizeof(multisize) + mtocopy->size, manager); mcopy->size = mtocopy->size; memcpy(((char *)mcopy)+sizeof(multisize), ((char *)mtocopy)+sizeof(multisize), mtocopy->size); copy = (object *)mcopy; } else { copy = alloc_object(bp); memcpy(((char *)copy) + sizeof(object), ((char *)tocopy)+sizeof(object), bp->size); } copy->bprint = bp; rh_atomic_set(copy, refcount, 1); bp->copy(copy); release_ref(tocopy); return copy; } object * naked_to_boxed(uint32_t type, void * rawdata) { object * dest; blueprint * bp = get_blueprint_byid(type); if(!bp->boxed_size) return NULL; //We don't know how big a naked multi-size object is so we can't do anything with it dest = alloc_object(bp); memcpy(((char *)dest) + sizeof(object), rawdata, bp->size); dest->bprint = bp; rh_atomic_set(dest, refcount, 1); bp->copy(dest); return dest; } void boxed_to_naked(object * src, void * dest) { blueprint * bp = get_blueprint(src); if(!bp->boxed_size) return; //We don't know how big a naked multi-size object is so we can't do anything with it memcpy(dest, ((char *)src) + sizeof(object), bp->size); bp->copy(src); } void release_ref(object * obj) { if(rh_atomic_sub_testzero(obj, refcount, 1)) get_blueprint(obj)->free(obj); } void check_type_storage(type) { uint32_t type_storage_temp; blueprint ** temp; if(type >= type_storage) if(type_storage) { type_storage_temp = (type + (type_storage >> 1)); temp = realloc(registered_types, type_storage_temp * sizeof(blueprint *)); if(temp) { registered_types = temp; memset(registered_types + type_storage, '\0', (type_storage_temp - type_storage) * sizeof(blueprint *)); type_storage = type_storage_temp; } else { free(registered_types); fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage_temp * sizeof(blueprint *)); exit(-1); } } else { if(type < INITIAL_TYPE_STORAGE) type_storage =INITIAL_TYPE_STORAGE; else type_storage = type + 8; registered_types = malloc(type_storage * sizeof(blueprint *)); if(registered_types) memset(registered_types, '\0', type_storage * sizeof(blueprint *)); else { fprintf(stderr, "Couldn't allocate %d bytes for type storage array\n", type_storage * sizeof(blueprint *)); exit(-1); } } } void default_action(object * obj) { } void normal_free(object * obj) { blueprint * bp = get_blueprint(obj); if(bp->cleanup) bp->cleanup(obj); ffree(obj, bp->boxed_size, manager); } void multi_free(object * obj) { multisize * multi = (multisize *)obj; blueprint * bp = get_blueprint(obj); if(bp->cleanup) bp->cleanup(obj); ffree(multi, sizeof(multisize) + multi->size, manager); } blueprint * new_blueprint(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup) { blueprint * bp = malloc(sizeof(blueprint)); //dirty hack!, move elsewhere if (!manager) { fixed_alloc_init(); manager = new_mem_manager(); } if(bp) { bp->size = size; bp->boxed_size = size >= 0 ? size + sizeof(object) : 0; bp->method_lookup = bp->getter_lookup = bp->setter_lookup = bp->convert_to = bp->convert_from = NULL; bp->type_id = type; bp->init = init ? init : default_action; bp->copy = copy ? copy : default_action; bp->cleanup = cleanup ? cleanup : default_action; bp->free = size >= 0 ? normal_free : multi_free; bp->first_methodid = bp->last_methodid = bp->first_getfieldid = bp->last_getfieldid = bp->first_setfieldid = bp->last_setfieldid = bp->first_convertto = bp->last_convertto = bp->first_convertfrom = bp->last_convertfrom = 0; //TODO: Handle names bp->name = NULL; } return bp; } blueprint * register_type_byid(uint32_t type, int32_t size, special_func init, special_func copy, special_func cleanup) { check_type_storage(type); if(registered_types[type]) return registered_types[type]; registered_types[type] = new_blueprint(type, size, init, copy, cleanup); if(!registered_types[type]) { fputs("Couldn't allocate new object blueprint\n", stderr); exit(-1); } if(type >= max_registered_type) max_registered_type = type + 1; return registered_types[type]; } void add_method(blueprint * bp, uint32_t methodid, rhope_func impl) { rhope_func * temp; if(methodid < 1) { fputs("Attempt to add a method with an ID < 1\n", stderr); exit(-1); } if (!bp->method_lookup) { bp->method_lookup = malloc(sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); if(!bp->method_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for method lookup table\n", sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); exit(-1); } if(BELOW_INITIAL_METHOD > methodid) { bp->first_methodid = 1; bp->last_methodid = 1+INITIAL_METHOD_LOOKUP; } else { bp->first_methodid = methodid - BELOW_INITIAL_METHOD; bp->last_methodid = bp->first_methodid + INITIAL_METHOD_LOOKUP; } memset(bp->method_lookup, '\0', sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); } else { if (methodid < bp->first_methodid) { temp = bp->method_lookup; //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer bp->method_lookup = malloc(sizeof(rhope_func) * (bp->last_methodid-methodid)); if(!bp->method_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for method lookup table\n", sizeof(rhope_func) * (bp->last_methodid-methodid)); exit(-1); } memset(bp->method_lookup, '\0', (bp->first_methodid-methodid) * sizeof(rhope_func)); memcpy(bp->method_lookup + bp->first_methodid-methodid, temp, (bp->last_methodid-bp->first_methodid)*sizeof(rhope_func)); free(temp); bp->first_methodid = methodid; } else if(methodid >= bp->last_methodid) { //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer bp->method_lookup = realloc(bp->method_lookup, (methodid+1-bp->first_methodid) * sizeof(rhope_func)); if(!bp->method_lookup) { fprintf(stderr, "Couldn't resize method lookup table to %d bytes\n", (methodid+1-bp->first_methodid) * sizeof(rhope_func)); exit(-1); } memset(bp->method_lookup+bp->last_methodid, '\0', (methodid+1)-bp->last_methodid); bp->last_methodid = methodid+1; } } bp->method_lookup[methodid-bp->first_methodid] = impl; } void add_getter(blueprint * bp, uint32_t getfieldid, rhope_func impl) { rhope_func * temp; if(getfieldid < 1) { fputs("Attempt to add a method with an ID < 1\n", stderr); exit(-1); } if (!bp->getter_lookup) { bp->getter_lookup = malloc(sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); if(!bp->getter_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for getter lookup table\n", sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); exit(-1); } if(BELOW_INITIAL_METHOD > getfieldid) { bp->first_getfieldid = 1; bp->last_getfieldid = 1+INITIAL_METHOD_LOOKUP; } else { bp->first_getfieldid = getfieldid - BELOW_INITIAL_METHOD; bp->last_getfieldid = bp->first_getfieldid + INITIAL_METHOD_LOOKUP; } memset(bp->getter_lookup, '\0', sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); } else { if (getfieldid < bp->first_getfieldid) { temp = bp->getter_lookup; //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer bp->getter_lookup = malloc(sizeof(rhope_func) * (bp->last_getfieldid-getfieldid)); if(!bp->getter_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for getter lookup table\n", sizeof(rhope_func) * (bp->last_getfieldid-getfieldid)); exit(-1); } memset(bp->getter_lookup, '\0', (bp->first_getfieldid-getfieldid) * sizeof(rhope_func)); memcpy(bp->getter_lookup + bp->first_getfieldid-getfieldid, temp, (bp->last_getfieldid-bp->first_getfieldid)*sizeof(rhope_func)); free(temp); bp->first_getfieldid = getfieldid; } else if(getfieldid >= bp->last_getfieldid) { //Note: if this gets changed to generating an exception on failure, we need to restore the original buffer bp->getter_lookup = realloc(bp->getter_lookup, (getfieldid+1-bp->first_getfieldid) * sizeof(rhope_func)); if(!bp->getter_lookup) { fprintf(stderr, "Couldn't resize getter lookup table to %d bytes\n", (getfieldid+1-bp->first_getfieldid) * sizeof(rhope_func)); exit(-1); } memset(bp->getter_lookup+bp->last_getfieldid, '\0', (getfieldid+1)-bp->last_getfieldid); bp->last_getfieldid = getfieldid+1; } } bp->getter_lookup[getfieldid-bp->first_getfieldid] = impl; } void add_setter(blueprint * bp, uint32_t setfieldid, rhope_func impl) { rhope_func * temp; if(setfieldid < 1) { fputs("Attempt to add a method with an ID < 1\n", stderr); exit(-1); } if (!bp->setter_lookup) { bp->setter_lookup = malloc(sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); if(!bp->setter_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for setter lookup table\n", sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); exit(-1); } if(BELOW_INITIAL_METHOD > setfieldid) { bp->first_setfieldid = 1; bp->last_setfieldid = 1+INITIAL_METHOD_LOOKUP; } else { bp->first_setfieldid = setfieldid - BELOW_INITIAL_METHOD; bp->last_setfieldid = bp->first_setfieldid + INITIAL_METHOD_LOOKUP; } memset(bp->setter_lookup, '\0', sizeof(rhope_func) * INITIAL_METHOD_LOOKUP); } else { if (setfieldid < bp->first_setfieldid) { temp = bp->setter_lookup; //Note: if this sets changed to generating an exception on failure, we need to restore the original buffer bp->setter_lookup = malloc(sizeof(rhope_func) * (bp->last_setfieldid-setfieldid)); if(!bp->setter_lookup) { fprintf(stderr, "Couldn't allocate %d bytes for setter lookup table\n", sizeof(rhope_func) * (bp->last_setfieldid-setfieldid)); exit(-1); } memset(bp->setter_lookup, '\0', (bp->first_setfieldid-setfieldid) * sizeof(rhope_func)); memcpy(bp->setter_lookup + bp->first_setfieldid-setfieldid, temp, (bp->last_setfieldid-bp->first_setfieldid)*sizeof(rhope_func)); free(temp); bp->first_setfieldid = setfieldid; } else if(setfieldid >= bp->last_setfieldid) { //Note: if this sets changed to generating an exception on failure, we need to restore the original buffer bp->setter_lookup = realloc(bp->setter_lookup, (setfieldid+1-bp->first_setfieldid) * sizeof(rhope_func)); if(!bp->setter_lookup) { fprintf(stderr, "Couldn't resize setter lookup table to %d bytes\n", (setfieldid+1-bp->first_setfieldid) * sizeof(rhope_func)); exit(-1); } memset(bp->setter_lookup+bp->last_setfieldid, '\0', (setfieldid+1)-bp->last_setfieldid); bp->last_setfieldid = setfieldid+1; } } bp->setter_lookup[setfieldid-bp->first_setfieldid] = impl; } blueprint * get_blueprint_byid(uint32_t type) { if(type >= max_registered_type) return NULL; return registered_types[type]; }