00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00050 #include <stdlib.h>
00051 #include <assert.h>
00052 #include "builtin.h"
00053 #include "cspan.h"
00054 #include "list.h"
00055 #include "mytypes.h"
00056 #include "stree.h"
00057 #include "strtab.h"
00058 #include "symbol.h"
00059 
00060 #include "ancr.h"
00061 
00062 static void ancr_csi_dfs(stree_program_t *prog, stree_csi_t *csi);
00063 static void ancr_csi_process(stree_program_t *prog, stree_csi_t *node);
00064 static stree_csi_t *ancr_csi_get_pred(stree_program_t *prog, stree_csi_t *csi,
00065     stree_texpr_t *pred_ref);
00066 static void ancr_csi_print_cycle(stree_program_t *prog, stree_csi_t *node);
00067 
00076 void ancr_module_process(stree_program_t *prog, stree_module_t *module)
00077 {
00078         list_node_t *node;
00079         stree_modm_t *modm;
00080 
00081         (void) module;
00082         node = list_first(&prog->module->members);
00083 
00084         while (node != NULL) {
00085                 modm = list_node_data(node, stree_modm_t *);
00086 
00087                 switch (modm->mc) {
00088                 case mc_csi:
00089                         ancr_csi_dfs(prog, modm->u.csi);
00090                         break;
00091                 case mc_enum:
00092                         break;
00093                 }
00094 
00095                 node = list_next(&prog->module->members, node);
00096         }
00097 }
00098 
00108 static void ancr_csi_dfs(stree_program_t *prog, stree_csi_t *csi)
00109 {
00110         list_node_t *node;
00111         stree_csimbr_t *csimbr;
00112 
00113         
00114         ancr_csi_process(prog, csi);
00115 
00116         
00117         node = list_first(&csi->members);
00118         while (node != NULL) {
00119                 csimbr = list_node_data(node, stree_csimbr_t *);
00120                 if (csimbr->cc == csimbr_csi)
00121                         ancr_csi_dfs(prog, csimbr->u.csi);
00122 
00123                 node = list_next(&csi->members, node);
00124         }
00125 }
00126 
00135 static void ancr_csi_process(stree_program_t *prog, stree_csi_t *csi)
00136 {
00137         stree_csi_t *base_csi, *outer_csi;
00138         stree_csi_t *gf_class;
00139 
00140         list_node_t *pred_n;
00141         stree_texpr_t *pred;
00142         stree_csi_t *pred_csi;
00143 
00144         if (csi->ancr_state == ws_visited) {
00145                 
00146                 return;
00147         }
00148 
00149         if (csi->ancr_state == ws_active) {
00150                 
00151                 printf("Error: Circular class, struct or interface chain: ");
00152                 ancr_csi_print_cycle(prog, csi);
00153                 printf(".\n");
00154                 exit(1);
00155         }
00156 
00157         csi->ancr_state = ws_active;
00158 
00159         outer_csi = csi_to_symbol(csi)->outer_csi;
00160         gf_class = builtin_get_gf_class(prog->builtin);
00161 
00162         if (csi != gf_class){
00163                 
00164                 base_csi = gf_class;
00165         } else {
00166                 
00167                 base_csi = NULL;
00168         }
00169 
00170         
00171         if (outer_csi != NULL)
00172                 ancr_csi_process(prog, outer_csi);
00173 
00174         
00175 
00176 
00177         pred_n = list_first(&csi->inherit);
00178 
00179         
00180         if (csi->cc == csi_class && pred_n != NULL) {
00181                 pred = list_node_data(pred_n, stree_texpr_t *);
00182                 pred_csi = ancr_csi_get_pred(prog, csi, pred);
00183                 assert(pred_csi != NULL);
00184 
00185                 if (pred_csi->cc == csi_class) {
00186                         
00187                         base_csi = pred_csi;
00188                         ancr_csi_process(prog, pred_csi);
00189 
00190                         pred_n = list_next(&csi->inherit, pred_n);
00191                 }
00192         }
00193 
00194         
00195         while (pred_n != NULL) {
00196                 pred = list_node_data(pred_n, stree_texpr_t *);
00197                 pred_csi = ancr_csi_get_pred(prog, csi, pred);
00198                 assert(pred_csi != NULL);
00199 
00200                 
00201                 ancr_csi_process(prog, pred_csi);
00202 
00203                 switch (pred_csi->cc) {
00204                 case csi_class:
00205                         switch (csi->cc) {
00206                         case csi_class:
00207                                 cspan_print(csi->name->cspan);
00208                                 printf(" Error: Only the first predecessor "
00209                                     "can be a class. ('");
00210                                 symbol_print_fqn(csi_to_symbol(csi));
00211                                 printf("' deriving from '");
00212                                 symbol_print_fqn(csi_to_symbol(pred_csi));
00213                                 printf("').\n");
00214                                 exit(1);
00215                                 break;
00216                         case csi_struct:
00217                                 assert(b_false); 
00218                         case csi_interface:
00219                                 cspan_print(csi->name->cspan);
00220                                 printf(" Error: Interface predecessor must be "
00221                                     "an interface ('");
00222                                 symbol_print_fqn(csi_to_symbol(csi));
00223                                 printf("' deriving from '");
00224                                 symbol_print_fqn(csi_to_symbol(pred_csi));
00225                                 printf("').\n");
00226                                 exit(1);
00227                                 break;
00228                         }
00229                 case csi_struct:
00230                         assert(b_false); 
00231                 case csi_interface:
00232                         break;
00233                 }
00234 
00235                 pred_n = list_next(&csi->inherit, pred_n);
00236         }
00237 
00238         
00239         csi->ancr_state = ws_visited;
00240         csi->base_csi = base_csi;
00241 }
00242 
00253 static stree_csi_t *ancr_csi_get_pred(stree_program_t *prog, stree_csi_t *csi,
00254     stree_texpr_t *pred_ref)
00255 {
00256         stree_csi_t *outer_csi;
00257         stree_symbol_t *pred_sym;
00258         stree_csi_t *pred_csi;
00259 
00260         outer_csi = csi_to_symbol(csi)->outer_csi;
00261         pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred_ref);
00262         pred_csi = symbol_to_csi(pred_sym);
00263         assert(pred_csi != NULL); 
00264 
00265         return pred_csi;
00266 }
00267 
00276 static void ancr_csi_print_cycle(stree_program_t *prog, stree_csi_t *node)
00277 {
00278         stree_csi_t *n;
00279         stree_symbol_t *pred_sym, *node_sym;
00280         stree_csi_t *pred_csi, *outer_csi;
00281         stree_texpr_t *pred;
00282         list_node_t *pred_n;
00283 
00284         n = node;
00285         do {
00286                 node_sym = csi_to_symbol(node);
00287                 symbol_print_fqn(node_sym);
00288                 printf(", ");
00289 
00290                 outer_csi = node_sym->outer_csi;
00291 
00292                 if (outer_csi != NULL && outer_csi->ancr_state == ws_active) {
00293                         node = outer_csi;
00294                 } else {
00295                         node = NULL;
00296 
00297                         pred_n = list_first(&node->inherit);
00298                         while (pred_n != NULL) {
00299                                 pred = list_node_data(pred_n, stree_texpr_t *);
00300                                 pred_sym = symbol_xlookup_in_csi(prog,
00301                                     outer_csi, pred);
00302                                 pred_csi = symbol_to_csi(pred_sym);
00303                                 assert(pred_csi != NULL);
00304 
00305                                 if (pred_csi->ancr_state == ws_active) {
00306                                         node = pred_csi;
00307                                         break;
00308                                 }
00309                         }
00310 
00311                         assert(node != NULL);
00312                 }
00313         } while (n != node);
00314 
00315         node_sym = csi_to_symbol(node);
00316         symbol_print_fqn(node_sym);
00317 }