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 }