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);
28 c2 = dict_lookup(&p1->usedclasses_deep, p2);
29 c1 = dict_lookup(&p2->usedclasses_deep, p1);
31 assert(!c1 || c1==p1->cls);
32 assert(!c2 || c2==p2->cls);
42 void add_parent(parsedclass_t*p, classinfo_t*c, dict_t*s2p, char soft)
44 dict_t*parents = soft?(&p->usedclasses_deep):(&p->parents);
46 if(dict_contains(parents, p)) {
48 as3_warning("circular reference: class %s references self (through static code)", p->cls->name);
51 syntaxerror("circular reference: class %s references self", p->cls->name);
56 parsedclass_t*n = dict_lookup(s2p, c);
57 if(n && !dict_contains(parents, n)) {
59 dict_put(parents, n, c);
65 if(soft && dict_contains(s2p, c)) {
66 parsedclass_t*pp = dict_lookup(s2p, c);
67 DICT_ITERATE_KEY(&pp->usedclasses, classinfo_t*, cc) {
68 add_parent(p, cc, s2p, soft);
72 add_parent(p, c->superclass, s2p, soft);
74 for(t=0;c->interfaces[t];t++) {
75 add_parent(p, c->interfaces[t], s2p, soft);
79 parsedclass_t* parsedclass_new(classinfo_t*cls, abc_class_t*abc)
84 dict_init2(&p->parents, &ptr_type, 1);
85 dict_init2(&p->usedclasses, &ptr_type, 1);
86 dict_init2(&p->usedclasses_deep, &ptr_type, 1);
90 /* sort classes so that
91 (a) interfaces appear before classes
92 (b) base classes always appear before their subclasses
93 (c) classes appear after the classes they use in static code
95 parsedclass_t** initcode_sort_classlist(parsedclass_list_t*classes)
97 dict_t* s2p = dict_new2(&ptr_type);
99 /* create hash tables */
101 parsedclass_list_t*l;
102 for(l=classes;l;l=l->next) {
103 dict_put(s2p, l->parsedclass->cls, l->parsedclass);
106 for(l=classes;l;l=l->next) {
107 add_parent(l->parsedclass, 0, s2p, 0);
108 DICT_ITERATE_KEY(&l->parsedclass->usedclasses, classinfo_t*, c) {
109 add_parent(l->parsedclass, c, s2p, 1);
113 parsedclass_t**list = malloc(sizeof(parsedclass_t*)*count);
115 /* build an array for each class */
117 for(l=classes;l;l=l->next) {
118 list[i++] = l->parsedclass;
121 /* sort and flatten */
122 qsort(list, count, sizeof(void**), compare_parsedclass);
124 parsedclass_t**list2 = malloc(sizeof(parsedclass_t*)*(count+1));
125 for(i=0;i<count;i++) {
126 list2[i] = (parsedclass_t*)list[i];
135 void parsedclass_add_dependency(parsedclass_t*p, classinfo_t*c)
137 if(!dict_contains(&p->usedclasses, c)) {
138 dict_put(&p->usedclasses, c, c);
142 void initcode_add_classlist(abc_script_t*init, parsedclass_list_t*_classes)
146 c = abc_getlocal_0(c);
147 c = abc_pushscope(c);
149 parsedclass_t**classes = initcode_sort_classlist(_classes);
152 for(t=0;classes[t];t++) {
153 abc_class_t*abc = classes[t]->abc;
154 classinfo_t*cls = classes[t]->cls;
156 array_append(init->file->classes, "", abc);
158 /* write the construction code for this class to the global init
160 MULTINAME(classname2,cls);
161 trait_t*trait = abc_initscript_addClassTrait(init, &classname2, abc);
163 c = abc_findpropstrict(c, "trace");
164 c = abc_pushstring(c, allocprintf("initialize class %s", cls->name));
165 c = abc_callpropvoid(c, "trace", 1);
167 c = abc_getglobalscope(c);
168 classinfo_t*s = cls->superclass;
173 //TODO: take a look at the current scope stack, maybe
174 // we can re-use something
179 multiname_t*s2 = sig2mname(s);
180 c = abc_getlex2(c, s2);
181 multiname_destroy(s2);
183 c = abc_pushscope(c); count++;
184 c = c->prev->prev; // invert
186 /* continue appending after last op end */
187 while(c && c->next) c = c->next;
189 multiname_t*extends2 = sig2mname(cls->superclass);
190 /* TODO: if this is one of *our* classes, we can also
191 do a getglobalscope/getslot <nr> (which references
192 the init function's slots) */
194 c = abc_getlex2(c, extends2);
196 /* notice: we get a Verify Error #1107 if the top elemnt on the scope
197 stack is not the superclass */
198 c = abc_pushscope(c);count++;
201 /* notice: we get a verify error #1107 if the top element on the scope
202 stack is not the global object */
203 c = abc_getlocal_0(c);
204 c = abc_pushscope(c);count++;
206 c = abc_newclass(c,abc);
210 c = abc_setslot(c, trait->slot_id);
211 multiname_destroy(extends2);
213 c = abc_returnvoid(c);
217 init->method->body->code = c;