9 int compare_parsedclass(const void *_v1, const void *_v2)
11 parsedclass_t*p1 = *(parsedclass_t**)_v1;
12 parsedclass_t*p2 = *(parsedclass_t**)_v2;
13 if((p1->cls->flags^p2->cls->flags)&FLAG_INTERFACE) {
14 return (int)(p2->cls->flags&FLAG_INTERFACE) - (int)(p1->cls->flags&FLAG_INTERFACE);
16 classinfo_t*c2 = dict_lookup(&p1->parents, p2);
17 classinfo_t*c1 = dict_lookup(&p2->parents, p1);
18 assert(!c1 || !c2); // otherwise we would have a loop
19 assert(!c1 || c1==p1->cls);
20 assert(!c2 || c2==p2->cls);
29 c2 = dict_lookup(&p1->usedclasses_deep, p2);
30 c1 = dict_lookup(&p2->usedclasses_deep, p1);
32 assert(!c1 || c1==p1->cls);
33 assert(!c2 || c2==p2->cls);
44 static void add_parent(parsedclass_t*p, classinfo_t*c, dict_t*s2p, char soft)
46 dict_t*parents = soft?(&p->usedclasses_deep):(&p->parents);
48 if(dict_contains(parents, p)) {
50 as3_warning("circular reference: class %s references self (through static code)", p->cls->name);
53 syntaxerror("circular reference: class %s references self", p->cls->name);
58 parsedclass_t*n = dict_lookup(s2p, c);
59 if(n && !dict_contains(parents, n)) {
61 dict_put(parents, n, c);
67 if(soft && dict_contains(s2p, c)) {
68 parsedclass_t*pp = dict_lookup(s2p, c);
69 DICT_ITERATE_KEY(&pp->usedclasses, classinfo_t*, cc) {
70 add_parent(p, cc, s2p, soft);
74 add_parent(p, c->superclass, s2p, soft);
76 for(t=0;c->interfaces[t];t++) {
77 add_parent(p, c->interfaces[t], s2p, soft);
81 parsedclass_t* parsedclass_new(classinfo_t*cls, abc_class_t*abc)
86 dict_init2(&p->parents, &ptr_type, 1);
87 dict_init2(&p->usedclasses, &ptr_type, 1);
88 dict_init2(&p->usedclasses_deep, &ptr_type, 1);
92 /* sort classes so that
93 (a) interfaces appear before classes
94 (b) base classes always appear before their subclasses
95 (c) classes appear after the classes they use in static code
97 parsedclass_t** initcode_sort_classlist(parsedclass_list_t*classes)
99 dict_t* s2p = dict_new2(&ptr_type);
101 /* create hash tables */
103 parsedclass_list_t*l;
104 for(l=classes;l;l=l->next) {
105 dict_put(s2p, l->parsedclass->cls, l->parsedclass);
108 for(l=classes;l;l=l->next) {
109 add_parent(l->parsedclass, 0, s2p, 0);
110 DICT_ITERATE_KEY(&l->parsedclass->usedclasses, classinfo_t*, c) {
111 add_parent(l->parsedclass, c, s2p, 1);
115 parsedclass_t**list = malloc(sizeof(parsedclass_t*)*count);
117 /* build an array for each class */
119 for(l=classes;l;l=l->next) {
120 list[i++] = l->parsedclass;
124 We unfortunately need to do insertion sort O(n^2) as
125 our dependencies are only partially ordered */
127 for(i=0;i<count;i++) {
128 for(j=i+1;j<count;j++) {
129 int r = compare_parsedclass(list+i,list+j);
131 parsedclass_t*p1 = list[i];
132 parsedclass_t*p2 = list[j];
139 parsedclass_t**list2 = malloc(sizeof(parsedclass_t*)*(count+1));
140 for(i=0;i<count;i++) {
141 list2[i] = (parsedclass_t*)list[i];
143 parsedclass_t*p = list[i];
144 printf("%s\n", p->cls->name);
145 if(p->cls->superclass)
146 printf(" extends %s\n", p->cls->superclass->name);
148 for(t=0;p->cls->interfaces[t];t++)
149 printf(" interface %s\n", p->cls->interfaces[t]->name);
150 DICT_ITERATE_KEY(&p->usedclasses, classinfo_t*, c) {
151 printf(" uses %s\n", c->name);
153 DICT_ITERATE_KEY(&p->parents, parsedclass_t*, pp) {
154 printf(" depends on (deep) %s\n", pp->cls->name);
156 DICT_ITERATE_KEY(&p->usedclasses_deep, parsedclass_t*, px) {
157 printf(" uses (deep) %s\n", px->cls->name);
169 void parsedclass_add_dependency(parsedclass_t*p, classinfo_t*c)
171 if(!dict_contains(&p->usedclasses, c)) {
172 dict_put(&p->usedclasses, c, c);
176 void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*_classes)
180 c = abc_getlocal_0(c);
181 c = abc_pushscope(c);
183 parsedclass_t**classes = initcode_sort_classlist(_classes);
186 for(t=0;classes[t];t++) {
187 abc_class_t*abc = classes[t]->abc;
188 classinfo_t*cls = classes[t]->cls;
190 array_append(init->file->classes, "", abc);
192 /* write the construction code for this class to the global init
194 MULTINAME(classname2,cls);
195 trait_t*trait = abc_initscript_addClassTrait(init, &classname2, abc);
197 c = abc_getglobalscope(c);
198 classinfo_t*s = cls->superclass;
203 //TODO: take a look at the current scope stack, maybe
204 // we can re-use something
209 multiname_t*s2 = sig2mname(s);
210 c = abc_getlex2(c, s2);
211 multiname_destroy(s2);
213 c = abc_pushscope(c); count++;
214 c = c->prev->prev; // invert
216 /* continue appending after last op end */
217 while(c && c->next) c = c->next;
219 multiname_t*extends2 = sig2mname(cls->superclass);
220 /* TODO: if this is one of *our* classes, we can also
221 do a getglobalscope/getslot <nr> (which references
222 the init function's slots) */
224 c = abc_getlex2(c, extends2);
226 /* notice: we get a Verify Error #1107 if the top elemnt on the scope
227 stack is not the superclass */
228 c = abc_pushscope(c);count++;
231 /* notice: we get a verify error #1107 if the top element on the scope
232 stack is not the global object */
233 c = abc_getlocal_0(c);
234 c = abc_pushscope(c);count++;
236 c = abc_newclass(c,abc);
240 c = abc_setslot(c, trait->slot_id);
241 multiname_destroy(extends2);
243 c = abc_returnvoid(c);
247 init->method->body->code = c;