diff --git a/example.c b/example.c index 9882ba9..f1c18c0 100644 --- a/example.c +++ b/example.c @@ -23,7 +23,10 @@ int main(void) { } printf("\nremoving index %lu\n", list->length(list)); - list->remove(list, list->length(list)); + //list->remove(list, list->length(list)); + //List_t* list2 = new List(); + + Object_t* obj = new Object(); return 0; } diff --git a/exceptions/stdex.c b/exceptions/stdex.c index 52f0a1f..8e242f8 100644 --- a/exceptions/stdex.c +++ b/exceptions/stdex.c @@ -1,7 +1,6 @@ #include "stdex.h" #include "../memory.h" #include "../try.h" - #include #include #include @@ -18,7 +17,7 @@ void method(Exception, populate)(Exception_t* obj, class_t c) { Exception_t* method(Exception, construct)(const char* msg) { throws(OutOfMemoryException_t); - sr_(Exception_t* obj = allocate_object(Exception_t), NULL); + sr_(Exception_t* obj = allocate_object(Exception), NULL); populate(Exception)(obj, Exception_class); obj->msg = msg; @@ -39,7 +38,7 @@ void method(NullPointerException, populate)(NullPointerException_t* obj, class_t NullPointerException_t* method(NullPointerException, construct)() { throws(OutOfMemoryException_t); - sr_(NullPointerException_t* obj = allocate_object(NullPointerException_t), NULL); + sr_(NullPointerException_t* obj = allocate_object(NullPointerException), NULL); populate(NullPointerException)(obj, NullPointerException_class); obj->super.msg = "Unexpected Null-pointer."; @@ -84,7 +83,7 @@ void method(IndexOutOfBoundsException, populate)(IndexOutOfBoundsException_t* ob IndexOutOfBoundsException_t* method(IndexOutOfBoundsException, construct)(size_t index, size_t length) { throws(OutOfMemoryException_t); - sr_(IndexOutOfBoundsException_t* obj = allocate_object(IndexOutOfBoundsException_t), NULL); + sr_(IndexOutOfBoundsException_t* obj = allocate_object(IndexOutOfBoundsException), NULL); populate(IndexOutOfBoundsException)(obj, IndexOutOfBoundsException_class); const char* format = "Requested index %i is out of bounds (%i)."; @@ -102,3 +101,52 @@ IndexOutOfBoundsException_t* method(IndexOutOfBoundsException, construct)(size_t return obj; } + +class_t IllegalArgumentException_class; +void method(IllegalArgumentException, destruct)(IllegalArgumentException_t* this) { + this->super.destruct((Exception_t*) this); +} +void method(IllegalArgumentException, populate)(IllegalArgumentException_t* obj, class_t c) { + populate(Exception)((Exception_t*) obj, c); + + add_method(obj, IllegalArgumentException, destruct); +} +IllegalArgumentException_t* method(IllegalArgumentException, construct)(const char* msg) { + throws(OutOfMemoryException_t); + + sr_(IllegalArgumentException_t* obj = allocate_object(IllegalArgumentException), NULL); + populate(IllegalArgumentException)(obj, IllegalArgumentException_class); + + obj->super.msg = msg; + + return obj; +} + +class_t ClassNotInstanceableException_class; +void method(ClassNotInstanceableException, destruct)(ClassNotInstanceableException_t* this) { + free((void*) this->super.msg); + + this->super.destruct((Exception_t*) this); +} +void method(ClassNotInstanceableException, populate)(ClassNotInstanceableException_t* obj, class_t c) { + populate(Exception)((Exception_t*) obj, c); + + add_method(obj, ClassNotInstanceableException, destruct); +} +ClassNotInstanceableException_t* method(ClassNotInstanceableException, construct)(const char* c) { + throws(OutOfMemoryException_t); + + sr_(ClassNotInstanceableException_t* obj = allocate_object(ClassNotInstanceableException), NULL); + populate(ClassNotInstanceableException)(obj, ClassNotInstanceableException_class); + + const char* format = "Class %s is not instanceable."; + size_t size = strlen(format) - 2 + strlen(c); + + sr_(char* msg = allocate(size + 1), NULL); + + snprintf(msg, size + 1, format, c); + + obj->super.msg = msg; + + return obj; +} diff --git a/exceptions/stdex.h b/exceptions/stdex.h index 40cd7c5..676cb1e 100644 --- a/exceptions/stdex.h +++ b/exceptions/stdex.h @@ -45,4 +45,24 @@ extern class(IndexOutOfBoundsException, Exception_class, NO_INTERFACES, true) { void method(IndexOutOfBoundsException, populate)(IndexOutOfBoundsException_t*, class_t); IndexOutOfBoundsException_t* method(IndexOutOfBoundsException, construct)(size_t, size_t); +#define IllegalArgumentException construct(IllegalArgumentException) +extern class(IllegalArgumentException, Exception_class, NO_INTERFACES, true) { + extends(Exception_t); + + void (*destruct)(defclass IllegalArgumentException*); +} IllegalArgumentException_t; + +void method(IllegalArgumentException, populate)(IllegalArgumentException_t*, class_t); +IllegalArgumentException_t* method(IllegalArgumentException, construct)(const char*); + +#define ClassNotInstanceableException construct(ClassNotInstanceableException) +extern class(ClassNotInstanceableException, Exception_class, NO_INTERFACES, true) { + extends(Exception_t); + + void (*destruct)(defclass ClassNotInstanceableException*); +} ClassNotInstanceableException_t; + +void method(ClassNotInstanceableException, populate)(ClassNotInstanceableException_t*, class_t); +ClassNotInstanceableException_t* method(ClassNotInstanceableException, construct)(const char*); + #endif diff --git a/lists/arraylist.c b/lists/arraylist.c index bd03c79..b201efe 100644 --- a/lists/arraylist.c +++ b/lists/arraylist.c @@ -16,7 +16,7 @@ class_t ArrayList_class; ArrayList_t* method(ArrayList, construct)(void) { throws(OutOfMemoryException_t); - sr_(ArrayList_t* list = allocate_object(ArrayList_t), NULL); + sr_(ArrayList_t* list = allocate_object(ArrayList), NULL); populate(ArrayList)(list, ArrayList_class); return list; diff --git a/lists/lists.c b/lists/lists.c index 75f3d15..a27adc2 100644 --- a/lists/lists.c +++ b/lists/lists.c @@ -3,3 +3,4 @@ class_t Countable_class; class_t List_class; class_t Stack_class; +class_t Iterateable_class; diff --git a/lists/lists.h b/lists/lists.h index 4129aac..20f79a0 100644 --- a/lists/lists.h +++ b/lists/lists.h @@ -3,11 +3,33 @@ #include "../oop.h" +typedef Object_t Countable_t; extern interface(Countable) #define Countable_interface size_t (*length)(void*); +#define Countable(...) NULL; _Pragma("GCC error \"Cannot make instance of interface Countable.\""); + +typedef Object_t List_t; extern interface(List) #define List_interface void (*add)(void*, void*); void* (*get)(void*, size_t); void (*remove)(void*, size_t); +#define List(...) NULL; _Pragma("GCC error \"Cannot make instance of interface List.\""); + +typedef Object_t Stack_t; extern interface(Stack) #define Stack_interface void (*push)(void*, void*); void* (*pop)(void*); +#define Stack(...) NULL; _Pragma("GCC error \"Cannot make instance of interface Stack.\""); + +typedef struct iterator_args { + void* list; + void* parameter; + void* obj; + int num; // -1 if no id +} iterator_args; + +typedef bool (*iterator)(iterator_args); + +typedef Object_t Iterateable_t; +extern interface(Iterateable) +#define Iterateable_interface bool (*iterate)(void*, iterator, void*) +#define Iterateable(...) NULL; _Pragma("GCC error \"Cannot make instance of interface Iterateable.\""); #endif diff --git a/memory.c b/memory.c index 1f00183..ae91017 100644 --- a/memory.c +++ b/memory.c @@ -5,33 +5,41 @@ #include #include -void allocate_sub(size_t size, void** ptr) { throws(Exception_t); +void allocate_sub(size_t size, void** ptr) { throws(OutOfMemoryException_t); *ptr = malloc(size); if (*ptr == NULL) { - throw(new Exception(strerror(errno))); + throw(new OutOfMemoryException()); } } -void* allocate(size_t size) { throws(Exception_t); +void* allocate_o(class_t c, size_t size) { throws(OutOfMemoryException_t, ClassNotInstanceableException_t); + if (!oop_is_instanceable(c)) + throwr(new ClassNotInstanceableException(oop_get_class_name(c)), NULL); void* ptr; sr_(allocate_sub(size, &ptr), NULL); return ptr; } -void reallocate_sub(size_t size, void** ptr, void* old) { throws(Exception_t); +void* allocate(size_t size) { throws(OutOfMemoryException_t); + void* ptr; + sr_(allocate_sub(size, &ptr), NULL); + return ptr; +} + +void reallocate_sub(size_t size, void** ptr, void* old) { throws(OutOfMemoryException_t); *ptr = realloc(old, size); if (*ptr == NULL) { - throw(new Exception(strerror(errno))); + throw(new OutOfMemoryException()); } } -void* reallocate(void* old, size_t size) { throws(Exception_t); +void* reallocate(void* old, size_t size) { throws(OutOfMemoryException_t); void* ptr; sr_(reallocate_sub(size, &ptr, old), NULL); return ptr; } -void* clone(const void* org, size_t size) { throws(Exception_t); +void* clone(const void* org, size_t size) { throws(OutOfMemoryException_t); void* ptr; sr_(allocate_sub(size, &ptr), NULL); memcpy(ptr, org, size); diff --git a/memory.h b/memory.h index a7eac45..5add55f 100644 --- a/memory.h +++ b/memory.h @@ -4,11 +4,16 @@ #include #include -#define allocate_object(type) allocate(sizeof(type)); +#include "oop.h" +#include "try.h" +#include "exceptions/stdex.h" + +#define allocate_object(type) allocate_o(type##_class, sizeof(type##_t)); #define clone_string(s) clone((void*) s, strlen(s) + 1) #define clone_obj(obj, class) clone((void*) obj, sizeof(class)) +void* allocate_o(class_t, size_t); void* allocate(size_t); void* reallocate(void*, size_t); void* clone(const void*, size_t); diff --git a/oop.c b/oop.c index dfdfbd6..6940560 100644 --- a/oop.c +++ b/oop.c @@ -78,6 +78,10 @@ bool oop_class_exists(const char* class_name) { return oop_id_from_name(class_name) != NO_CLASS_ID; } +bool oop_is_instanceable(class_t c) { + return classes[c.id].instanceable; +} + class_t oop_class_from_id(class_id_t id) { return (class_t) {.id = id}; } @@ -90,12 +94,20 @@ class_t oop_get_class_from_obj(Object_t* obj) { return oop_class_from_id(((Object_t*) obj)->meta_obj.type.id); } +void oop_check_interface(class_t c, Object_t* obj) { + throws(IllegalArgumentException_t); + + if (!instanceof(obj, c)) + throw(new IllegalArgumentException("Object is not instance of interface.")); +} + // defined by class macro in h-file class_t Object_class; // defined by interface macro in h-file class_t Cloneable_class; +class_t Compareable_class; void method(Object, destruct)(Object_t* obj) { @@ -103,7 +115,7 @@ void method(Object, destruct)(Object_t* obj) { } Object_t* method(Object, construct)() { throws(OutOfMemoryException_t); - sr_(Object_t* obj = allocate_object(Object_t), NULL); + sr_(Object_t* obj = allocate_object(Object), NULL); populate(Object)(obj, Object_class); return obj; } diff --git a/oop.h b/oop.h index 15da679..e06fec6 100644 --- a/oop.h +++ b/oop.h @@ -59,13 +59,18 @@ typedef struct meta_object { class_id_t oop_add_class(const char*, bool, class_t, iflist_t, bool); #define Object construct(Object) -extern class(Object, NO_SUPER_CLASS, NO_INTERFACES, true) { +extern class(Object, NO_SUPER_CLASS, NO_INTERFACES, false) { meta_object_t meta_obj; void (*destruct)(defclass Object*); } Object_t; extern interface(Cloneable) #define Cloneable_interface void*(*clone)(void*) +#define Cloneable(...) NULL; _Pragma("GCC error \"Cannot make instance of interface Cloneable.\""); + +extern interface(Compareable) +#define Compareable_interface int(*compare)(void*) +#define Compareable(...) NULL; _Pragma("GCC error \"Cannot make instance of interface Compareable.\""); bool oop_instance_of_id(void*, class_id_t); bool oop_instance_of(void*, class_t); @@ -74,7 +79,9 @@ class_id_t oop_id_from_name(const char*); bool oop_class_exists(const char*); class_t oop_class_from_id(class_id_t); class_t oop_get_super_class(class_t); +bool oop_is_instanceable(class_t); class_t oop_get_class_from_obj(Object_t*); +void oop_check_interface(class_t, Object_t*); Object_t* method(Object, construct)(void); void method(Object, populate)(Object_t* obj, class_t); diff --git a/tools/strbuilder.c b/tools/strbuilder.c index 3c9b5c0..7333d9b 100644 --- a/tools/strbuilder.c +++ b/tools/strbuilder.c @@ -91,7 +91,7 @@ const char* method(Strbuilder, get)(Strbuilder_t* this) { Strbuilder_t* method(Strbuilder, construct)(const char* string) { throws(OutOfMemoryException_t); - sr_(Strbuilder_t* obj = allocate_object(Strbuilder_t), NULL); + sr_(Strbuilder_t* obj = allocate_object(Strbuilder), NULL); populate(Strbuilder)(obj, Strbuilder_class); diff --git a/try.c b/try.c index 6ee89d3..641d246 100644 --- a/try.c +++ b/try.c @@ -109,6 +109,8 @@ void try_throw(try_t id, void* exception) { e->msg); #endif + e->destruct(); // destruct of exception (not sub classes), because we don't know what this is + _print_backtrace(stderr, 2); } else { trys[id].exception = exception;