#include "registry.h"
#include "initcode.h"
-void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*classes)
+int compare_lists(const void *_v1, const void *_v2)
+{
+ classinfo_t**v1 = *(classinfo_t***)_v1;
+ classinfo_t**v2 = *(classinfo_t***)_v2;
+ parsedclass_t*p1 = **(parsedclass_t***)_v1;
+ parsedclass_t*p2 = **(parsedclass_t***)_v2;
+ if((p1->cls->flags^p2->cls->flags)&FLAG_INTERFACE) {
+ return (int)(p2->cls->flags&FLAG_INTERFACE) - (int)(p1->cls->flags&FLAG_INTERFACE);
+ }
+ do {
+ v1++;v2++;
+ if(*v1<*v2) return -1;
+ else if(*v1>*v2) return 1;
+ } while(*v1 && *v2);
+ return 0;
+}
+
+/* sort classes so that
+ (a) interfaces appear before classes
+ (b) base classes always appear before their subclasses
+ (c) neighboring elements have similar scope stacks
+
+ Notice: we don't yet handle multiple inheritance (in interfaces) correctly.
+*/
+parsedclass_t** initcode_sort_classlist(parsedclass_list_t*classes)
+{
+ /* count classes */
+ int count = 0;
+ parsedclass_list_t*l;
+ for(l=classes;l;l=l->next) {
+ count++;
+ }
+ void***list = malloc(sizeof(void**)*count);
+
+ /* build an array for each class */
+ int i = 0;
+ for(l=classes;l;l=l->next) {
+ classinfo_t*cls = l->parsedclass->cls;
+ int len=0;
+ classinfo_t*c=cls;
+ while(c) {
+ len ++;
+ c = c->flags&FLAG_INTERFACE?c->interfaces[0]:c->superclass;
+ }
+ void**a = (void**)malloc(sizeof(void*)*(len+2));
+ a[0] = l->parsedclass;
+ a[len+1] = 0;
+ int t=len;
+ c = cls;
+ while(c) {
+ len ++;
+ a[t--] = c;
+ c = c->flags&FLAG_INTERFACE?c->interfaces[0]:c->superclass;
+ }
+ list[i++] = a;
+ }
+
+ /* sort and flatten */
+ qsort(list, count, sizeof(void**), compare_lists);
+
+ parsedclass_t**list2 = malloc(sizeof(parsedclass_t*)*(count+1));
+ for(i=0;i<count;i++) {
+ list2[i] = (parsedclass_t*)list[i][0];
+ free(list[i]);
+ }
+ list2[count]=0;
+ free(list);
+ return list2;
+}
+
+void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*_classes)
{
code_t*c = 0;
c = abc_getlocal_0(c);
c = abc_pushscope(c);
+
+ parsedclass_t**classes = initcode_sort_classlist(_classes);
- for(;classes;classes=classes->next) {
- abc_class_t*abc = classes->parsedclass->abc;
- classinfo_t*cls = classes->parsedclass->cls;
+ int t;
+ for(t=0;classes[t];t++) {
+ abc_class_t*abc = classes[t]->abc;
+ classinfo_t*cls = classes[t]->cls;
+
+ array_append(init->file->classes, "", abc);
/* write the construction code for this class to the global init
function */
}
c = abc_returnvoid(c);
+ free(classes);
+
init->method->body->code = c;
}