symbol.c

00001 /*
00002  * Copyright (c) 2010 Jiri Svoboda
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00031 #include <stdlib.h>
00032 #include <assert.h>
00033 #include "list.h"
00034 #include "mytypes.h"
00035 #include "strtab.h"
00036 #include "stree.h"
00037 
00038 #include "symbol.h"
00039 
00040 static stree_symbol_t *symbol_search_global(stree_program_t *prog,
00041     stree_ident_t *name);
00042 static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
00043     stree_ident_t *name, stree_csi_t *csi);
00044 static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol);
00045 
00058 stree_symbol_t *symbol_xlookup_in_csi(stree_program_t *prog,
00059     stree_csi_t *scope, stree_texpr_t *texpr)
00060 {
00061         stree_symbol_t *a, *b;
00062         stree_csi_t *a_csi;
00063 
00064         switch (texpr->tc) {
00065         case tc_tnameref:
00066                 return symbol_lookup_in_csi(prog, scope, texpr->u.tnameref->name);
00067         case tc_taccess:
00068                 a = symbol_xlookup_in_csi(prog, scope, texpr->u.taccess->arg);
00069                 a_csi = symbol_to_csi(a);
00070                 if (a_csi == NULL) {
00071                         printf("Error: Symbol is not CSI.\n");
00072                         exit(1);
00073                 }
00074                 b = symbol_search_csi(prog, a_csi, texpr->u.taccess->member_name);
00075                 if (b == NULL) {
00076                         printf("Error: CSI '%s' not found\n", strtab_get_str(texpr->u.taccess->member_name->sid));
00077                         exit(1);
00078                 }
00079                 return b;
00080         case tc_tapply:
00081                 return symbol_xlookup_in_csi(prog, scope,
00082                     texpr->u.tapply->gtype);
00083         default:
00084                 assert(b_false);
00085         }
00086 }
00087 
00099 stree_symbol_t *symbol_lookup_in_csi(stree_program_t *prog, stree_csi_t *scope,
00100         stree_ident_t *name)
00101 {
00102         stree_symbol_t *symbol;
00103 
00104         /* This CSI node should have been processed. */
00105         assert(scope == NULL || scope->ancr_state == ws_visited);
00106 
00107         symbol = NULL;
00108         while (scope != NULL && symbol == NULL) {
00109                 symbol = symbol_search_csi(prog, scope, name);
00110                 scope = csi_to_symbol(scope)->outer_csi;
00111         }
00112 
00113         if (symbol == NULL)
00114                 symbol = symbol_search_global(prog, name);
00115 
00116         return symbol;
00117 }
00118 
00130 stree_symbol_t *symbol_search_csi(stree_program_t *prog,
00131     stree_csi_t *scope, stree_ident_t *name)
00132 {
00133         stree_csi_t *base_csi;
00134         stree_symbol_t *symbol;
00135 
00136         /* Look in new members in this class. */
00137         symbol = symbol_search_csi_no_base(prog, scope, name);
00138         if (symbol != NULL)
00139                 return symbol;
00140 
00141         /* Try inherited members. */
00142         base_csi = symbol_get_base_class(prog, scope);
00143         if (base_csi != NULL)
00144                 return symbol_search_csi(prog, base_csi, name);
00145 
00146         /* No match */
00147         return NULL;
00148 }
00149 
00161 stree_symbol_t *symbol_search_csi_no_base(stree_program_t *prog,
00162     stree_csi_t *scope, stree_ident_t *name)
00163 {
00164         list_node_t *node;
00165         stree_csimbr_t *csimbr;
00166         stree_ident_t *mbr_name;
00167 
00168         (void) prog;
00169 
00170         /* Look in new members in this class. */
00171 
00172         node = list_first(&scope->members);
00173         while (node != NULL) {
00174                 csimbr = list_node_data(node, stree_csimbr_t *);
00175                 mbr_name = stree_csimbr_get_name(csimbr);
00176 
00177                 if (name->sid == mbr_name->sid) {
00178                         /* Match */
00179                         return csimbr_to_symbol(csimbr);
00180                 }
00181 
00182                 node = list_next(&scope->members, node);
00183         }
00184         /* No match */
00185         return NULL;
00186 }
00187 
00195 static stree_symbol_t *symbol_search_global(stree_program_t *prog,
00196     stree_ident_t *name)
00197 {
00198         list_node_t *node;
00199         stree_modm_t *modm;
00200         stree_symbol_t *symbol;
00201         stree_ident_t *mbr_name;
00202 
00203         node = list_first(&prog->module->members);
00204         while (node != NULL) {
00205                 modm = list_node_data(node, stree_modm_t *);
00206 
00207                 /* Make compiler happy. */
00208                 mbr_name = NULL;
00209 
00210                 switch (modm->mc) {
00211                 case mc_csi: mbr_name = modm->u.csi->name; break;
00212                 case mc_enum: mbr_name = modm->u.enum_d->name; break;
00213                 }
00214 
00215                 /* The Clang static analyzer is just too picky. */
00216                 assert(mbr_name != NULL);
00217 
00218                 if (name->sid == mbr_name->sid) {
00219                         /* Make compiler happy. */
00220                         symbol = NULL;
00221 
00222                         /* Match */
00223                         switch (modm->mc) {
00224                         case mc_csi:
00225                                 symbol = csi_to_symbol(modm->u.csi);
00226                                 break;
00227                         case mc_enum:
00228                                 symbol = enum_to_symbol(modm->u.enum_d);
00229                                 break;
00230                         }
00231                         return symbol;
00232                 }
00233                 node = list_next(&prog->module->members, node);
00234         }
00235 
00236         return NULL;
00237 }
00238 
00249 stree_csi_t *symbol_get_base_class(stree_program_t *prog, stree_csi_t *csi)
00250 {
00251         list_node_t *pred_n;
00252         stree_texpr_t *pred;
00253         stree_symbol_t *pred_sym;
00254         stree_csi_t *pred_csi;
00255         stree_csi_t *outer_csi;
00256 
00257         outer_csi = csi_to_symbol(csi)->outer_csi;
00258 
00259         pred_n = list_first(&csi->inherit);
00260         if (pred_n == NULL)
00261                 return NULL;
00262 
00263         pred = list_node_data(pred_n, stree_texpr_t *);
00264         pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
00265         pred_csi = symbol_to_csi(pred_sym);
00266         assert(pred_csi != NULL); /* XXX! */
00267 
00268         if (pred_csi->cc == csi_class)
00269                 return pred_csi;
00270 
00271         return NULL;
00272 }
00273 
00284 stree_texpr_t *symbol_get_base_class_ref(stree_program_t *prog,
00285     stree_csi_t *csi)
00286 {
00287         list_node_t *pred_n;
00288         stree_texpr_t *pred;
00289         stree_symbol_t *pred_sym;
00290         stree_csi_t *pred_csi;
00291         stree_csi_t *outer_csi;
00292 
00293         outer_csi = csi_to_symbol(csi)->outer_csi;
00294 
00295         pred_n = list_first(&csi->inherit);
00296         if (pred_n == NULL)
00297                 return NULL;
00298 
00299         pred = list_node_data(pred_n, stree_texpr_t *);
00300         pred_sym = symbol_xlookup_in_csi(prog, outer_csi, pred);
00301         pred_csi = symbol_to_csi(pred_sym);
00302         assert(pred_csi != NULL); /* XXX! */
00303 
00304         if (pred_csi->cc == csi_class)
00305                 return pred;
00306 
00307         return NULL;
00308 }
00309 
00319 stree_symbol_t *symbol_find_epoint(stree_program_t *prog, stree_ident_t *name)
00320 {
00321         list_node_t *node;
00322         stree_modm_t *modm;
00323         stree_symbol_t *entry, *etmp;
00324 
00325         entry = NULL;
00326 
00327         node = list_first(&prog->module->members);
00328         while (node != NULL) {
00329                 modm = list_node_data(node, stree_modm_t *);
00330                 if (modm->mc == mc_csi) {
00331                         etmp = symbol_find_epoint_rec(prog, name, modm->u.csi);
00332                         if (etmp != NULL) {
00333                                 if (entry != NULL) {
00334                                         printf("Error: Duplicate entry point.\n");
00335                                         exit(1);
00336                                 }
00337                                 entry = etmp;
00338                         }
00339                 }
00340                 node = list_next(&prog->module->members, node);
00341         }
00342 
00343         return entry;
00344 }
00345 
00355 static stree_symbol_t *symbol_find_epoint_rec(stree_program_t *prog,
00356     stree_ident_t *name, stree_csi_t *csi)
00357 {
00358         list_node_t *node;
00359         stree_csimbr_t *csimbr;
00360         stree_symbol_t *entry, *etmp;
00361         stree_symbol_t *fun_sym;
00362 
00363         entry = NULL;
00364 
00365         node = list_first(&csi->members);
00366         while (node != NULL) {
00367                 csimbr = list_node_data(node, stree_csimbr_t *);
00368 
00369                 switch (csimbr->cc) {
00370                 case csimbr_csi:
00371                         etmp = symbol_find_epoint_rec(prog, name, csimbr->u.csi);
00372                         if (etmp != NULL) {
00373                                 if (entry != NULL) {
00374                                         printf("Error: Duplicate entry point.\n");
00375                                         exit(1);
00376                                 }
00377                                 entry = etmp;
00378                         }
00379                         break;
00380                 case csimbr_fun:
00381                         fun_sym = fun_to_symbol(csimbr->u.fun);
00382 
00383                         if (csimbr->u.fun->name->sid == name->sid &&
00384                             stree_symbol_has_attr(fun_sym, sac_static)) {
00385                                 if (entry != NULL) {
00386                                         printf("Error: Duplicate entry point.\n");
00387                                         exit(1);
00388                                 }
00389                                 entry = fun_sym;
00390                         }
00391                 default:
00392                         break;
00393                 }
00394 
00395                 node = list_next(&csi->members, node);
00396         }
00397 
00398         return entry;
00399 }
00400 
00401 /*
00402  * The notion of symbol is designed as a common base class for several
00403  * types of declarations with global and CSI scope. Here we simulate
00404  * conversion from this base class (symbol) to derived classes (CSI,
00405  * fun, ..) and vice versa.
00406  */
00407 
00413 stree_deleg_t *symbol_to_deleg(stree_symbol_t *symbol)
00414 {
00415         if (symbol->sc != sc_deleg)
00416                 return NULL;
00417 
00418         return symbol->u.deleg;
00419 }
00420 
00426 stree_symbol_t *deleg_to_symbol(stree_deleg_t *deleg)
00427 {
00428         assert(deleg->symbol);
00429         return deleg->symbol;
00430 }
00431 
00437 stree_enum_t *symbol_to_enum(stree_symbol_t *symbol)
00438 {
00439         if (symbol->sc != sc_enum)
00440                 return NULL;
00441 
00442         return symbol->u.enum_d;
00443 }
00444 
00450 stree_symbol_t *enum_to_symbol(stree_enum_t *enum_d)
00451 {
00452         assert(enum_d->symbol);
00453         return enum_d->symbol;
00454 }
00455 
00461 stree_csi_t *symbol_to_csi(stree_symbol_t *symbol)
00462 {
00463         if (symbol->sc != sc_csi)
00464                 return NULL;
00465 
00466         return symbol->u.csi;
00467 }
00468 
00474 stree_symbol_t *csi_to_symbol(stree_csi_t *csi)
00475 {
00476         assert(csi->symbol);
00477         return csi->symbol;
00478 }
00479 
00485 stree_ctor_t *symbol_to_ctor(stree_symbol_t *symbol)
00486 {
00487         if (symbol->sc != sc_ctor)
00488                 return NULL;
00489 
00490         return symbol->u.ctor;
00491 }
00492 
00498 stree_symbol_t *ctor_to_symbol(stree_ctor_t *ctor)
00499 {
00500         assert(ctor->symbol);
00501         return ctor->symbol;
00502 }
00503 
00504 
00510 stree_fun_t *symbol_to_fun(stree_symbol_t *symbol)
00511 {
00512         if (symbol->sc != sc_fun)
00513                 return NULL;
00514 
00515         return symbol->u.fun;
00516 }
00517 
00523 stree_symbol_t *fun_to_symbol(stree_fun_t *fun)
00524 {
00525         assert(fun->symbol);
00526         return fun->symbol;
00527 }
00528 
00534 stree_var_t *symbol_to_var(stree_symbol_t *symbol)
00535 {
00536         if (symbol->sc != sc_var)
00537                 return NULL;
00538 
00539         return symbol->u.var;
00540 }
00541 
00547 stree_symbol_t *var_to_symbol(stree_var_t *var)
00548 {
00549         assert(var->symbol);
00550         return var->symbol;
00551 }
00552 
00558 stree_prop_t *symbol_to_prop(stree_symbol_t *symbol)
00559 {
00560         if (symbol->sc != sc_prop)
00561                 return NULL;
00562 
00563         return symbol->u.prop;
00564 }
00565 
00573 stree_symbol_t *csimbr_to_symbol(stree_csimbr_t *csimbr)
00574 {
00575         stree_symbol_t *symbol;
00576 
00577         /* Keep compiler happy. */
00578         symbol = NULL;
00579 
00580         /* Match */
00581         switch (csimbr->cc) {
00582         case csimbr_csi:
00583                 symbol = csi_to_symbol(csimbr->u.csi);
00584                 break;
00585         case csimbr_ctor:
00586                 symbol = ctor_to_symbol(csimbr->u.ctor);
00587                 break;
00588         case csimbr_deleg:
00589                 symbol = deleg_to_symbol(csimbr->u.deleg);
00590                 break;
00591         case csimbr_enum:
00592                 symbol = enum_to_symbol(csimbr->u.enum_d);
00593                 break;
00594         case csimbr_fun:
00595                 symbol = fun_to_symbol(csimbr->u.fun);
00596                 break;
00597         case csimbr_var:
00598                 symbol = var_to_symbol(csimbr->u.var);
00599                 break;
00600         case csimbr_prop:
00601                 symbol = prop_to_symbol(csimbr->u.prop);
00602                 break;
00603         }
00604 
00605         return symbol;
00606 }
00607 
00608 
00614 stree_symbol_t *prop_to_symbol(stree_prop_t *prop)
00615 {
00616         assert(prop->symbol);
00617         return prop->symbol;
00618 }
00619 
00624 void symbol_print_fqn(stree_symbol_t *symbol)
00625 {
00626         stree_ident_t *name;
00627         stree_symbol_t *outer_sym;
00628 
00629         if (symbol->outer_csi != NULL) {
00630                 outer_sym = csi_to_symbol(symbol->outer_csi);
00631                 symbol_print_fqn(outer_sym);
00632                 printf(".");
00633         }
00634 
00635         name = symbol_get_ident(symbol);
00636         printf("%s", strtab_get_str(name->sid));
00637 }
00638 
00644 static stree_ident_t *symbol_get_ident(stree_symbol_t *symbol)
00645 {
00646         stree_ident_t *ident;
00647 
00648         /* Make compiler happy. */
00649         ident = NULL;
00650 
00651         switch (symbol->sc) {
00652         case sc_csi: ident = symbol->u.csi->name; break;
00653         case sc_ctor: ident = symbol->u.ctor->name; break;
00654         case sc_deleg: ident = symbol->u.deleg->name; break;
00655         case sc_enum: ident = symbol->u.enum_d->name; break;
00656         case sc_fun: ident = symbol->u.fun->name; break;
00657         case sc_var: ident = symbol->u.var->name; break;
00658         case sc_prop: ident = symbol->u.prop->name; break;
00659         }
00660 
00661         return ident;
00662 }

Generated on Thu Jun 2 07:45:43 2011 for HelenOS/USB by  doxygen 1.4.7