00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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;
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
00181 NewScope();
00182 ClassWalker w(this);
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
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