lu_lu.cc

Go to the documentation of this file.
00001 /*
00002    The lestes compiler suite
00003    Copyright (C) 2002, 2003, 2004, 2005 Miroslav Tichy
00004    Copyright (C) 2002, 2003, 2004, 2005 Petr Zika
00005    Copyright (C) 2002, 2003, 2004, 2005 Vojtech Hala
00006    Copyright (C) 2002, 2003, 2004, 2005 Jiri Kosina
00007    Copyright (C) 2002, 2003, 2004, 2005 Pavel Sanda
00008    Copyright (C) 2002, 2003, 2004, 2005 Jan Zouhar
00009    Copyright (C) 2002, 2003, 2004, 2005 Rudolf Thomas
00010 
00011    This program is free software; you can redistribute it and/or modify
00012    it under the terms of the GNU General Public License as published by
00013    the Free Software Foundation; version 2 of the License.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    See the full text of the GNU General Public License version 2, and
00021    the limitations in the file doc/LICENSE.
00022 
00023    By accepting the license the licensee waives any and all claims
00024    against the copyright holder(s) related in whole or in part to the
00025    work, its use, and/or the inability to use it.
00026  
00027  */
00028 #include <lestes/common.hh>
00029 #include <lestes/lang/cplus/sem/lu_filter.g.hh>
00030 #include <lestes/lang/cplus/sem/lu_logger.hh>
00031 #include <lestes/lang/cplus/sem/lu_lu.g.hh>
00032 #include <lestes/lang/cplus/sem/ss_declaration.g.hh>
00033 #include <lestes/lang/cplus/sem/ss_decl_name.g.hh>
00034 #include <lestes/lang/cplus/sem/ss_misc.g.hh>
00035 #include <lestes/lang/cplus/sem/ss_statement.g.hh>
00036 #include <lestes/lang/cplus/sem/ss_type.g.hh>
00037 #include <lestes/lang/cplus/sem/ss_using_target.g.hh>
00038 #include <lestes/msg/logger.hh>
00039 #include <lestes/std/list.hh>
00040 #include <lestes/std/objectize_macros.hh>
00041 #include <lestes/std/pair.hh>
00042 #include <lestes/std/set.hh>
00043 
00044 #include <algorithm>
00045 #include <iterator>
00046 
00047 package(lestes);
00048 package(lang);
00049 package(cplus);
00050 package(sem);
00051 
00052 declare_logger( lookup_log );
00053 initialize_logger( lookup_log, "lookup", lu_logger );
00054 
00055 #define LOOKUP_ASSERTIONS
00056 
00057 #ifdef LOOKUP_ASSERTIONS
00058 # define lookup_lassert( x )            lassert( x )
00059 # define lookup_lassert2( x, y )        lassert2( x, y )
00060 
00061 static ptr<ss_decl_seq> seq_param;
00062 
00063 #else
00064 # define lookup_lassert( x )            (void)0
00065 # define lookup_lassert2( x, y )        (void)0
00066 #endif
00067 
00068 typedef list< srp<ss_base_specifier> >  bases_type;
00069 end_package(sem);
00070 end_package(cplus);
00071 end_package(lang);
00072 package(std);
00073 specialize_objectize_nodump( ::lestes::lang::cplus::sem::bases_type::const_iterator );
00074 end_package(std);
00075 package(lang);
00076 package(cplus);
00077 package(sem);
00078 
00079 /*!
00080  * Not reentrant!
00081  * Never returns NULL.
00082  */
00083 ptr<declaration_set_type> lu_lookup::main( ptr<ss_decl_seq> seq, ptr<lu_params> params )
00084 {
00085         lassert( !params_get() && !visited_seqs );
00086         lassert2( params, "Lookup parameters must not be NULL." );
00087 
00088         visited_seqs_set( decl_seq_set_type::create() );
00089         params_set( params );
00090 
00091         bool search_parents = params->parent_search_get() == lu_params::SEARCH_PARENTS;
00092         ptr<declaration_set_type> result;
00093         do {
00094                 bool not_yet_visited = visited_seqs_get()->insert(seq).second;
00095                 if (not_yet_visited)
00096                         result = deep_scan( seq );
00097                 lassert2( result, "The very first decl_seq has been marked as already visited!" );
00098                 if (seq == ss_decl_seq::root_instance())
00099                         break;
00100                 seq = seq->parent_get();
00101         } while (result->empty() && search_parents);
00102 
00103         params_set( NULL );
00104         visited_seqs_set( NULL );
00105         return result;
00106 }
00107 
00108 /*!
00109  * \brief  Computes union of two given sets of declarations.
00110  */
00111 static ptr<declaration_set_type> unify(
00112                 const ptr<declaration_set_type> & s1,
00113                 const ptr<declaration_set_type> & s2 )
00114 {
00115         ptr<declaration_set_type> result = declaration_set_type::create();
00116         ::std::set_union( s1->begin(), s1->end(), s2->begin(), s2->end(),
00117                         ::std::inserter( *result, result->end() ) );
00118         return result;
00119 }
00120 
00121 /*!
00122  * Never returns NULL.
00123  */
00124 ptr<declaration_set_type> lu_lookup::deep_scan( ptr<ss_decl_seq> starting_seq )
00125 {
00126         typedef list< srp<ss_decl_seq> > queue_type;
00127         typedef list< srp<ss_using_directive> > directives_type;
00128         
00129         ptr<declaration_set_type> result = declaration_set_type::create();
00130 
00131         ptr<queue_type> queue = queue_type::create();
00132         // starting_seq is already marked as visited in 'main'
00133         queue->push_back( starting_seq );
00134 
00135         while (!queue->empty()) {
00136                 ptr<ss_decl_seq> seq = queue->front();
00137                 queue->pop_front();
00138 #ifdef LOOKUP_ASSERTIONS
00139                 // assertions are in the visit methods called from lookup_by_decl()
00140                 seq_param = seq;
00141 #endif
00142                 ptr<declaration_set_type> local_result = lookup_by_decl( seq->declared_by_get() );
00143 
00144                 result = unify( result, local_result );
00145                 
00146                 switch (params_get()->using_directives_handling_get()) {
00147                 case lu_params::UDIR_IGNORE:
00148                         continue;
00149                 case lu_params::UDIR_FALLBACK:
00150                         if (!local_result->empty())
00151                                 continue;
00152                         /* fall-through */
00153                 case lu_params::UDIR_ALWAYS:
00154                         ;
00155                         /* fall-through */
00156                 }
00157 
00158                 const ptr<directives_type> & directives = seq->using_directives_get();
00159                 for ( directives_type::const_iterator it = directives->begin(); it != directives->end(); ++it ) {
00160                         /*
00161                          * XXX:
00162                          * we assume that all using-directives that follow a late one are late too
00163                          * therefore we can break
00164                          */
00165                         if (!(*it)->decl_time_get()->is_before( params_get()->time_get() ))
00166                                 break;
00167                         const ptr<ss_decl_seq> & used_seq = (*it)->nspace_get()->body_get();
00168                         bool not_yet_visited = visited_seqs_get()->insert(used_seq).second;
00169                         if (not_yet_visited)
00170                                 queue->push_back(used_seq);
00171                 }
00172         }
00173         return result;
00174 }
00175 
00176 ptr<declaration_set_type> lu_lookup::simple_scan( ptr<ss_decl_seq> seq, ptr<lu_params> params )
00177 {
00178         ptr<declaration_set_type> result = declaration_set_type::create();
00179         typedef list< srp<ss_declaration> > contents_type;
00180         const srp<contents_type> & contents = seq->contents_get();
00181         
00182         for ( contents_type::reverse_iterator it = contents->rbegin();
00183                         it != contents->rend(); ++it ) {
00184 
00185                 ptr<ss_declaration> decl = *it;
00186                 ptr<ss_declaration> real_decl;
00187 
00188                 /* skip declarations that are too young */
00189                 if (!decl->decl_time_get()->is_before( params->time_get() ))
00190                         continue;
00191 
00192                 lu_params::using_declarations_handling_type udecl_handling =
00193                         params->using_declarations_handling_get();
00194                 if (udecl_handling != lu_params::UDECL_THROUGH) {
00195                         /* handle using declaration, as requested */
00196                         real_decl = ss_using_target::instance()->process(decl);
00197                         if (decl != real_decl) {
00198                                 /* it was ss_using_declaration */
00199                                 switch (udecl_handling) {
00200                                 case lu_params::UDECL_IGNORE:
00201                                         continue;
00202                                 case lu_params::UDECL_RESOLVE_BEFORE_FILTER:
00203                                         decl = real_decl;
00204                                         break;
00205                                 default:
00206                                         /* udecl_handling == UDECL_RESOLVE_AFTER_FILTER */
00207                                         break;
00208                                 }
00209                         }
00210                 }
00211 
00212                 llog(lookup_log) << "calling filter on decl #" << decl->uid_get() << "\n";
00213 
00214                 lu_filter::result_type filt = params->filter_get()->filter(decl);
00215                 
00216                 llog(lookup_log) << "got result " << lu_filter::result2lstring(filt) << "\n";
00217 
00218                 if (filt == lu_filter::FR_NO)
00219                         continue;
00220                 
00221                 if (udecl_handling == lu_params::UDECL_RESOLVE_AFTER_FILTER) {
00222                         lassert( real_decl );
00223                         decl = real_decl;
00224                 }
00225 
00226                 result->insert( decl );
00227 
00228                 if (filt == lu_filter::FR_YES)
00229                         break;
00230         }
00231         return result;
00232 }
00233 
00234 ptr<declaration_set_type> lu_lookup::internal_simple_scan( ptr<ss_decl_seq> seq )
00235 {
00236         return simple_scan( seq, params_get() );
00237 }
00238 
00239 void lu_lookup::default_action( ptr<ss_declaration> )
00240 {
00241         lassert2( false, "Decl_seq declared by an unknown type of declaration." );
00242 }
00243 
00244 void lu_lookup::visit_ss_namespace_definition( ptr<ss_namespace_definition> nsd )
00245 {
00246         lookup_lassert( nsd->body_get() == seq_param );
00247         lookup_result_set( internal_simple_scan( nsd->body_get() ) );
00248 }
00249 
00250 void lu_lookup::visit_ss_function_declaration( ptr<ss_function_declaration> fd )
00251 {
00252         lookup_lassert( fd->parameters_get() == seq_param );
00253         lookup_result_set( internal_simple_scan( fd->body_get()->decl_seq_get() ) );
00254 }
00255 
00256 void lu_lookup::visit_ss_compound_stmt_declaration( ptr<ss_compound_stmt_declaration> csd )
00257 {
00258         lookup_lassert( csd->compound_stmt_get()->decl_seq_get() == seq_param );
00259         lookup_result_set( internal_simple_scan( csd->compound_stmt_get()->decl_seq_get() ) );
00260 }
00261 
00262 void lu_lookup::visit_ss_structure_declaration( ptr<ss_structure_declaration> td )
00263 {
00264         lookup_result_set( lu_lookup_in_type::instance()->main( td->type_get(), params_get() ) );
00265 }
00266 
00267 ptr<declaration_set_type> lu_lookup_in_type::main( ptr<ss_type> type, ptr<lu_params> params )
00268 {
00269         lassert( !params_get() );
00270         params_set( checked(params) );
00271 
00272         ptr<declaration_set_type> result = lookup_by_type( type );
00273 
00274         params_set( NULL );
00275 
00276         return result;
00277 }
00278 
00279 ptr<declaration_set_type> lu_lookup_in_type::internal_simple_scan( ptr<ss_decl_seq> seq )
00280 {
00281         return lu_lookup::simple_scan( seq, params_get() );
00282 }
00283 
00284 void lu_lookup_in_type::default_action( ptr<ss_type> )
00285 {
00286         lassert2( false, "Trying to run lookup on unknown ss_type." );
00287 }
00288 
00289 void lu_lookup_in_type::visit_ss_class( ptr<ss_class> c )
00290 {
00291         ptr<declaration_set_type> result;
00292 
00293         result = internal_simple_scan( c->members_get() );
00294         if (!result->empty())
00295                 return lookup_result_set( result );
00296 
00297         typedef pair<bases_type::const_iterator,bases_type::const_iterator>
00298                                                 iter_pair_type;
00299         typedef list< srp<iter_pair_type> >     iter_pair_list_type;
00300         // this list is used as a stack
00301         ptr<iter_pair_list_type> st = iter_pair_list_type::create();
00302 
00303         st->push_back( iter_pair_type::create( c->bases_get()->begin(), c->bases_get()->end() ) );
00304         while (!st->empty()) {
00305                 bases_type::const_iterator & it = st->back()->first;
00306                 const bases_type::const_iterator & end_it = st->back()->second;
00307 
00308                 if (it == end_it) {
00309                         st->pop_back();
00310                         continue;
00311                 }
00312 
00313                 ptr<ss_class> base_class = (*it)->base_class_get();
00314                 ++it;   // changes the value in the pair, as it is a reference
00315 
00316                 ptr<declaration_set_type> local_result = internal_simple_scan( base_class->members_get() );
00317                 if (local_result->empty()) {
00318                         // go one level deeper in the lattice
00319                         st->push_back( iter_pair_type::create(
00320                                                 base_class->bases_get()->begin(),
00321                                                 base_class->bases_get()->end() ) );
00322                 } else
00323                         result = unify( result, local_result );
00324         }
00325 
00326         lookup_result_set( result );
00327 }
00328 
00329 void lu_lookup_in_type::visit_ss_union( ptr<ss_union> u )
00330 {
00331         //XXX: maybe something more sophisticated?
00332         lookup_result_set( internal_simple_scan( u->members_get() ) );
00333 }
00334 
00335 end_package(sem);
00336 end_package(cplus);
00337 end_package(lang);
00338 end_package(lestes);

Generated on Mon Feb 12 18:22:39 2007 for lestes by doxygen 1.5.1-20070107