ss_statement.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 // needed by ss_statement, oh the horror... headers that are not self-contained
00029 #include <lestes/std/list.hh>
00030 #include <lestes/lang/cplus/sem/ss_expression.g.hh>
00031 #include <lestes/lang/cplus/sem/ss_statement.g.hh>
00032 #include <lestes/lang/cplus/sem/ss_misc.g.hh>
00033 #include <lestes/std/source_location.hh>
00034 #include <lestes/std/file_info.hh>
00035 #include <iostream>
00036 
00037 package(lestes);
00038 package(lang);
00039 package(cplus);
00040 package(sem);
00041 
00042 static bool hack_used = false;
00043 
00044 /*!
00045  * As we currently do not have protected setters, a setter for the parent field is not provided.
00046  * However, when constructing the "global" ss_compound_stmt, which is derived from ss_statement,
00047  * the parent field has to be set to point to the instance itself, which is impossible to achieve
00048  * using the factory method.
00049  *
00050  * Therefore, this hack is provided. It exists solely for the purpose above.
00051  * Normal code MUST NOT call it, or it will explode :)
00052  */
00053 void ss_statement::parent_set_once_hack( ptr<ss_compound_stmt> a_parent )
00054 {
00055         lassert2( !hack_used, "This method is not meant to be called twice." );
00056         hack_used = true;
00057         parent = a_parent;
00058 }
00059 
00060 /*!
00061  * When called for the first time, constructs the grandparent of all instances
00062  * of ss_compound_stmt. This means that you can simply recognize it, just
00063  * compare your ptr to the return value of this method.
00064  *
00065  * Note that the instance is its own parent. Also note that when creating it,
00066  * root ss_decl_seq must be created too. This is achieved by calling
00067  * ss_decl_seq::root_instance(), which might in turn call us back. The code is
00068  * prepared for this. You can choose which of the two methods you call first.
00069  *
00070  * \return  Pointer to the instance of root ss_compound_stmt.
00071  */
00072 ptr<ss_compound_stmt> ss_compound_stmt::root_instance()
00073 {
00074         if (!the_root_instance) {
00075                 /* this calls us recursively */
00076                 ptr < ss_decl_seq > root_decl_seq = ss_decl_seq::root_instance();
00077 
00078                 /* It is somewhat complicated to tell when the control flow
00079                  * reaches the following statement.
00080                  *
00081                  * Firstly, someone from the ``outer world'' might call
00082                  * ss_decl_seq::root_instance(). Then the root instance object
00083                  * of the type ss_decl_seq gets constructed and we get called
00084                  * after the ss_decl_seq root object already exists. Therefore
00085                  * it is safe to call ss_decl_seq::root_instance() to get that
00086                  * object, because the function will return immediately with
00087                  * the allready constucted, albeit incompletelly initialized
00088                  * object.
00089                  *
00090                  * Secondly, someone from the ``outer world'' might call us in
00091                  * the first place. Then We would initiate the first ever
00092                  * ss_decl_seq::root_instance() call. The same applies as for
00093                  * the first case.
00094                  *
00095                  * It is perhaps easiest to state the invariants.
00096                  * \invariant If ss_decl_seq::root_instance() is called first,
00097                  * then the ss_decl_seq::the_root_instance is created but not
00098                  * fully initialized before ss_statement::root_instance() is
00099                  * called for the first time.
00100                  * \invariant The ss_decl_seq::root_instance() function will
00101                  * call ss_statement::root_instance() on its first invocation
00102                  * only.
00103                  *
00104                  * Therefore, it can be concluded, that the following statement
00105                  * will be executed only after the second (and not necessarily
00106                  * the first) invocation of ss_decl_seq::root_instance() has
00107                  * finished.
00108                  *
00109                  * The only remaining question is in what state will be the
00110                  * following statement encountered. The
00111                  * ss_decl_seq::root_instance() will return a partially
00112                  * initialized ss_decl_seq instance. If the
00113                  * ss_decl_seq::root_instance() was called in the first place,
00114                  * the statement will be executed only once.  If, however, the
00115                  * ss_statement::root_instance() was called in the first place,
00116                  * then the statement will be encountered twice.  The condition
00117                  * will evaluate to false in the first encounter, so the
00118                  * control flow will proceed to the ss_statement root instance
00119                  * creation.  The condition will evaluate to true on the second
00120                  * encounter, because the root instance was created after the
00121                  * first encounter.
00122                  */
00123                 if (the_root_instance)
00124                         return the_root_instance;
00125 
00126                 /* A non-null location is needed.  We can obtain the location
00127                  * from the ss_decl_seq's root instance */
00128                 ptr < source_location > loc = root_decl_seq->location_get();
00129                 /* create some sequence points */
00130                 ptr < ss_sp > psp = ss_sp::create(loc, NULL, NULL, 0),
00131                         nsp = ss_sp::create(loc, NULL, NULL, 0),
00132                         dsp = ss_sp::create(loc, NULL, NULL, 0);
00133                 /* link them together */
00134                 psp->nsp_set(dsp);
00135                 dsp->nsp_set(nsp);
00136                 dsp->psp_set(psp);
00137                 nsp->psp_set(dsp);
00138                 the_root_instance = new ss_compound_stmt(
00139                                 loc,
00140                                 list< srp<ss_label> >::create(), NULL, psp, nsp,
00141                                 list< srp<ss_sp> >::create(),
00142                                 root_decl_seq,
00143                                 list< srp<ss_statement> >::create(), dsp,
00144                                 NORMAL
00145                                 );
00146                 /* insert sequence points to the list */
00147                 the_root_instance->sequence_points_get()->push_back(psp);
00148                 the_root_instance->sequence_points_get()->push_back(nsp);
00149                 the_root_instance->sequence_points_get()->push_back(dsp);
00150                 /* See documentation for the method above... */
00151                 the_root_instance->parent_set_once_hack( the_root_instance );
00152                 /* we do not set decl_seq when calling new above, as the root decl_seq might not
00153                  * be created yet. it calls us back, so we avoid recursion by setting it here
00154                  */
00155                 //the_root_instance->decl_seq = ss_decl_seq::root_instance();
00156         }
00157         return the_root_instance;
00158 }
00159 
00160 end_package(sem);
00161 end_package(cplus);
00162 end_package(lang);
00163 end_package(lestes);

Generated on Mon Feb 12 18:23:30 2007 for lestes by doxygen 1.5.1-20070107