Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

cbodywalk.cc

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 1997-2001 Shigeru Chiba, Tokyo Institute of Technology.
00003 
00004   Permission to use, copy, distribute and modify this software and   
00005   its documentation for any purpose is hereby granted without fee,        
00006   provided that the above copyright notice appear in all copies and that 
00007   both that copyright notice and this permission notice appear in 
00008   supporting documentation.
00009 
00010   Shigeru Chiba makes no representations about the suitability of this 
00011   software for any purpose.  It is provided "as is" without express or
00012   implied warranty.
00013 */
00014 
00015 #include "ptree.h"
00016 #include "cbodywalk.h"
00017 #include "mop.h"
00018 #include "env.h"
00019 #include "member.h"
00020 
00021 Ptree* ClassBodyWalker::TranslateClassBody(Ptree* block, Ptree*,
00022                                            Class* metaobject)
00023 {
00024     Ptree* block2;
00025 
00026     Environment* fenv = metaobject->GetEnvironment();
00027     if(fenv == nil)
00028         fenv = env;     // should not reach here.
00029 
00030     NameScope old_env = ChangeScope(fenv);
00031 
00032     PtreeArray array;
00033     bool changed = FALSE;
00034     Ptree* body = Ptree::Second(block);
00035     Ptree* rest = body;
00036     while(rest != nil){
00037         Ptree* p = rest->Car();
00038         Ptree* q = Translate(p);
00039         array.Append(q);
00040         if(p != q)
00041             changed = TRUE;
00042 
00043         rest = rest->Cdr();
00044     }
00045 
00046     AppendNewMembers(metaobject, array, changed);
00047 
00048     Ptree* appended = metaobject->GetAppendedCode();
00049     if(appended != nil){
00050         changed = TRUE;
00051         while(appended != nil){
00052             array.Append(appended->Car());
00053             appended = appended->Cdr();
00054         }
00055     }
00056 
00057     if(changed)
00058         block2 = new PtreeClassBody(Ptree::First(block), array.All(),
00059                                     Ptree::Third(block));
00060     else
00061         block2 = block;
00062 
00063     RestoreScope(old_env);
00064     return block2;
00065 }
00066 
00067 void ClassBodyWalker::AppendNewMembers(Class* metaobject, PtreeArray& array,
00068                                        bool& changed)
00069 {
00070     ChangedMemberList::Cmem* m;
00071     ChangedMemberList* appended_list = metaobject->GetAppendedMembers();
00072     if(appended_list == nil)
00073         return;
00074 
00075     int i = 0;
00076     while((m = appended_list->Get(i++)) != nil)
00077         if(m->def != nil){
00078             changed = TRUE;
00079             ClassWalker w(this);
00080             array.Append(w.ConstructAccessSpecifier(m->access));
00081             array.Append(w.ConstructMember(m));
00082         }
00083 }
00084 
00085 Ptree* ClassBodyWalker::TranslateTypespecifier(Ptree* tspec)
00086 {
00087     if(tspec_list == nil)
00088         return tspec;
00089 
00090     int n = tspec_list->Number();
00091     for(int i =  0; i < n; i += 2)
00092         if(tspec_list->Ref(i) == tspec)
00093             return tspec_list->Ref(i + 1);
00094 
00095     return tspec;
00096 }
00097 
00098 Ptree* ClassBodyWalker::TranslateTypedef(Ptree* def)
00099 {
00100     Ptree *tspec, *tspec2;
00101 
00102     tspec = Ptree::Second(def);
00103     tspec2 = TranslateTypespecifier(tspec);
00104 
00105     if(tspec == tspec2)
00106         return def;
00107     else
00108         return new PtreeTypedef(Ptree::First(def),
00109                                 Ptree::List(tspec2,
00110                                             Ptree::ListTail(def, 2)));
00111 }
00112 
00113 Ptree* ClassBodyWalker::TranslateMetaclassDecl(Ptree*)
00114 {
00115     return nil;
00116 }
00117 
00118 Ptree* ClassBodyWalker::TranslateDeclarators(Ptree* decls)
00119 {
00120     return ClassWalker::TranslateDeclarators(decls, FALSE);
00121 }
00122 
00123 Ptree* ClassBodyWalker::TranslateAssignInitializer(PtreeDeclarator* decl,
00124                                                    Ptree* init)
00125 {
00126     ClassWalker w(this);
00127 
00128     return w.TranslateAssignInitializer(decl, init);
00129 }
00130 
00131 Ptree* ClassBodyWalker::TranslateInitializeArgs(PtreeDeclarator* decl,
00132                                                 Ptree* init)
00133 {
00134     ClassWalker w(this);
00135 
00136     return w.TranslateInitializeArgs(decl, init);
00137 }
00138 
00139 Ptree* ClassBodyWalker::TranslateDeclarator(bool record,
00140                                             PtreeDeclarator* decl)
00141 {
00142     return TranslateDeclarator(record, decl, TRUE);
00143 }
00144 
00145 Ptree* ClassBodyWalker::TranslateDeclarator(bool record,
00146                                             PtreeDeclarator* decl,
00147                                             bool append_body)
00148 {
00149     ClassWalker w(this);
00150 
00151     Class* metaobject = env->LookupThis();
00152     if(metaobject != nil){
00153         ChangedMemberList::Cmem* m = metaobject->GetChangedMember(decl);
00154         if(m != nil){
00155             Ptree* decl2 = w.MakeMemberDeclarator(record, m, decl);
00156             if(m->removed || m->body == nil || !append_body)
00157                 return decl2;
00158             else
00159                 return Ptree::List(decl2, m->body);
00160         }
00161     }
00162 
00163     return w.TranslateDeclarator(record, decl);
00164 }
00165 
00166 Ptree* ClassBodyWalker::TranslateFunctionImplementation(Ptree* impl)
00167 {
00168     Ptree* sspec = impl->First();
00169     Ptree* sspec2 = TranslateStorageSpecifiers(sspec);
00170     Ptree* tspec = impl->Second();
00171     Ptree* decl = impl->Third();
00172     Ptree* body = impl->Nth(3);
00173     Ptree* decl2;
00174     Ptree* body2;
00175 
00176     Ptree* tspec2 = TranslateTypespecifier(tspec);
00177     Environment* fenv = env->DontRecordDeclarator(decl);
00178 
00179     if(fenv == nil){
00180         // shouldn't reach here.
00181         NewScope();
00182         ClassWalker w(this);    // this should be after NewScope().
00183         decl2 = w.TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00184         body2 = w.TranslateFunctionBody(body);
00185         ExitScope();
00186     }
00187     else{
00188         bool is_nested_class = bool(env != fenv);
00189         NameScope old_env = ChangeScope(fenv);
00190         NewScope();
00191         ClassWalker w(this);
00192         if(is_nested_class){
00193             // if it's a member function of a nested class
00194             decl2 = w.TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00195             body2 = w.TranslateFunctionBody(body);
00196         }
00197         else{
00198             decl2 = TranslateDeclarator(TRUE, (PtreeDeclarator*)decl, FALSE);
00199             Class* metaobject = fenv->IsClassEnvironment();
00200             ChangedMemberList::Cmem* m = nil;
00201             if(metaobject != nil)
00202                 m = metaobject->GetChangedMember(decl);
00203 
00204             if(m != nil && m->body != nil)
00205                 body2 = m->body;
00206             else
00207                 body2 = w.TranslateFunctionBody(body);
00208         }
00209 
00210         ExitScope();
00211         RestoreScope(old_env);
00212     }
00213 
00214     if(sspec == sspec2 && tspec == tspec2 && decl == decl2 && body == body2)
00215         return impl;
00216     else if(decl2 == nil)
00217         return new PtreeDeclaration(nil, Ptree::List(nil,
00218                                                      Class::semicolon_t));
00219     else
00220         return new PtreeDeclaration(sspec2,
00221                                     Ptree::List(tspec2, decl2, body2));
00222 }
00223 
00224 

Generated on Mon Feb 10 17:32:44 2003 for VFiasco Semantics Compiler by doxygen1.2.15