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

classwalk.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 "classwalk.h"
00017 #include "cbodywalk.h"
00018 #include "mop.h"
00019 #include "env.h"
00020 #include "typeinfo.h"
00021 #include "member.h"
00022 #include "encoding.h"
00023 
00024 Class* ClassWalker::GetClassMetaobject(TypeInfo& tinfo)
00025 {
00026     Class* c;
00027     if(tinfo.IsClass(c))
00028         return c;
00029     else if(tinfo.IsReferenceType()){
00030         tinfo.Dereference();
00031         if(tinfo.IsClass(c))
00032             return c;
00033     }
00034 
00035     return nil;
00036 }
00037 
00038 bool ClassWalker::IsClassWalker()
00039 {
00040     return TRUE;
00041 }
00042 
00043 void ClassWalker::InsertBeforeStatement(Ptree* p)
00044 {
00045     before_statement.Append(p);
00046 }
00047 
00048 void ClassWalker::AppendAfterStatement(Ptree* p)
00049 {
00050     after_statement.Append(p);
00051 }
00052 
00053 void ClassWalker::InsertBeforeToplevel(Ptree* p)
00054 {
00055     before_toplevel.Append(p);
00056 }
00057 
00058 void ClassWalker::AppendAfterToplevel(Ptree* p)
00059 {
00060     after_toplevel.Append(p);
00061 }
00062 
00063 bool ClassWalker::InsertDeclaration(Ptree* d, Class* metaobject, Ptree* key,
00064                                     void* data)
00065 {
00066     inserted_declarations.Append(d);
00067     if(metaobject == nil || key == nil)
00068         return TRUE;
00069     else if(LookupClientData(metaobject, key))
00070         return FALSE;
00071     else{
00072         ClientDataLink* entry = new ClientDataLink;
00073         entry->next = client_data;
00074         entry->metaobject = metaobject;
00075         entry->key = key;
00076         entry->data = data;
00077         client_data = entry;
00078         return TRUE;
00079     }
00080 }
00081 
00082 void* ClassWalker::LookupClientData(Class* metaobject, Ptree* key)
00083 {
00084     for(ClientDataLink* c = client_data; c != nil; c = c->next)
00085         if(c->metaobject == metaobject && Ptree::Eq(key, c->key))
00086             return c->data;
00087 
00088     return nil;
00089 }
00090 
00091 Ptree* ClassWalker::GetInsertedPtree()
00092 {
00093     Ptree* result = nil;
00094     if(before_toplevel.Number() > 0)
00095         result = Ptree::Nconc(result, before_toplevel.All());
00096 
00097     if(inserted_declarations.Number() > 0)
00098         result = Ptree::Nconc(result, inserted_declarations.All());
00099 
00100     if(before_statement.Number() > 0)
00101         result = Ptree::Nconc(result, before_statement.All());
00102 
00103     before_statement.Clear();
00104     inserted_declarations.Clear();
00105     client_data = nil;
00106     before_toplevel.Clear();
00107     return result;
00108 }
00109 
00110 Ptree* ClassWalker::GetAppendedPtree()
00111 {
00112     Ptree* result = nil;
00113     if(after_statement.Number() > 0)
00114         result = Ptree::Nconc(result, after_statement.All());
00115 
00116     if(after_toplevel.Number() > 0)
00117         result = Ptree::Nconc(result, after_toplevel.All());
00118 
00119     after_statement.Clear();
00120     after_toplevel.Clear();
00121     return result;
00122 }
00123 
00124 Ptree* ClassWalker::TranslateMetaclassDecl(Ptree* decl)
00125 {
00126     env->RecordMetaclassName(decl);
00127     return nil;
00128 }
00129 
00130 Ptree* ClassWalker::TranslateClassSpec(Ptree* spec, Ptree* userkey,
00131                                        Ptree* class_def, Class* metaobject)
00132 {
00133     if(metaobject != nil){
00134         // the class body is given.
00135         Ptree* bases = class_def->Third();
00136         PtreeArray* tspec_list = RecordMembers(class_def, bases, metaobject);
00137         metaobject->TranslateClass(env);
00138         metaobject->TranslateClassHasFinished();
00139         if(metaobject->removed)
00140             return nil;
00141 
00142         ClassBodyWalker w(this, tspec_list);
00143         Ptree* body = class_def->Nth(3);
00144         Ptree* body2 = w.TranslateClassBody(body, class_def->Third(),
00145                                             metaobject);
00146         Ptree* bases2 = metaobject->GetBaseClasses();
00147         Ptree* cspec = metaobject->GetClassSpecifier();
00148         Ptree* name2 = metaobject->GetNewName();
00149         if(bases != bases2 || body != body2 || cspec != nil || name2 != nil){
00150             if(name2 == nil)
00151                 name2 = class_def->Second();
00152 
00153             Ptree* rest = Ptree::List(name2, bases2, body2);
00154             if(cspec != nil)
00155                 rest = Ptree::Cons(cspec, rest);
00156             return new PtreeClassSpec(class_def->Car(), rest, nil,
00157                                       spec->GetEncodedName());
00158         }
00159     }
00160 
00161     if(userkey == nil)
00162         return spec;
00163     else
00164         return new PtreeClassSpec(class_def->Car(), class_def->Cdr(),
00165                                   nil, spec->GetEncodedName());
00166 }
00167 
00168 Ptree* ClassWalker::TranslateTemplateInstantiation(Ptree* inst_spec,
00169                         Ptree* userkey, Ptree* class_spec, Class* metaobject)
00170 {
00171     Ptree* class_spec2;
00172     if (metaobject != nil && metaobject->AcceptTemplate()) {
00173         TemplateClass* tmetaobj = (TemplateClass*)metaobject;
00174         class_spec2 = tmetaobj->TranslateInstantiation(env, class_spec);
00175         if (class_spec != class_spec2)
00176             return class_spec2;
00177     }
00178     else
00179         class_spec2 = class_spec;
00180 
00181     if(userkey == nil)
00182         return inst_spec;
00183     else if (class_spec == class_spec2)
00184         return inst_spec;
00185     else
00186         return new PtreeTemplateInstantiation(class_spec);
00187 }
00188 
00189 Ptree* ClassWalker::ConstructClass(Class* metaobject)
00190 {
00191     Ptree* def = metaobject->Definition();
00192     Ptree* def2;
00193 
00194     metaobject->TranslateClassHasFinished();
00195     ClassBodyWalker w(this, nil);
00196     Ptree* body = def->Nth(3);
00197     Ptree* body2 = w.TranslateClassBody(body, nil, metaobject);
00198     Ptree* bases2 = metaobject->GetBaseClasses();
00199     Ptree* cspec2 = metaobject->GetClassSpecifier();
00200     Ptree* name2 = metaobject->GetNewName();
00201     if(body == body2 && bases2 == nil && cspec2 == nil && name2 == nil)
00202         def2 = def;
00203     else{
00204         if(name2 == nil)
00205             name2 = def->Second();
00206 
00207         Ptree* rest = Ptree::List(name2, bases2, body2);
00208         if(cspec2 != nil)
00209             rest = Ptree::Cons(cspec2, rest);
00210 
00211         def2 = new PtreeClassSpec(def->Car(), rest,
00212                                   nil, def->GetEncodedName());
00213     }
00214 
00215     return new PtreeDeclaration(nil, Ptree::List(def2, Class::semicolon_t));
00216 }
00217 
00218 PtreeArray* ClassWalker::RecordMembers(Ptree* class_def, Ptree* bases,
00219                                        Class* metaobject)
00220 {
00221     Ptree *tspec, *tspec2;
00222 
00223     NewScope(metaobject);
00224     RecordBaseclassEnv(bases);
00225 
00226     PtreeArray* tspec_list = new PtreeArray();
00227 
00228     Ptree* rest = class_def->Nth(3)->Second();
00229     while(rest != nil){
00230         Ptree* mem = rest->Car();
00231         switch(mem->What()){
00232         case ntTypedef :
00233             tspec = mem->Second();
00234             tspec2 = TranslateTypespecifier(tspec);
00235             env->RecordTypedefName(mem->Third());
00236             if(tspec != tspec2){
00237                 tspec_list->Append(tspec);
00238                 tspec_list->Append(tspec2);
00239             }
00240 
00241             break;
00242         case ntMetaclassDecl :
00243             env->RecordMetaclassName(mem);
00244             break;
00245         case ntDeclaration :
00246             RecordMemberDeclaration(mem, tspec_list);
00247             break;
00248         case ntTemplateDecl :
00249         case ntTemplateInstantiation :
00250         case ntUsing :
00251         default :
00252             break;
00253         }
00254 
00255         rest = rest->Cdr();
00256     }
00257 
00258     if(tspec_list->Number() == 0){
00259         delete tspec_list;
00260         tspec_list = nil;
00261     }
00262         
00263     ExitScope();
00264     return tspec_list;
00265 }
00266 
00267 //  RecordMemberDeclaration() is derived from TranslateDeclaration().
00268 
00269 void ClassWalker::RecordMemberDeclaration(Ptree* mem,
00270                                           PtreeArray* tspec_list)
00271 {
00272     Ptree *tspec, *tspec2, *decls;
00273 
00274     tspec = mem->Second();
00275     tspec2 = TranslateTypespecifier(tspec);
00276     decls = mem->Third();
00277     if(decls->IsA(ntDeclarator))        // if it is a function
00278         env->RecordDeclarator(decls);
00279     else if(!decls->IsLeaf())           // not a null declaration.
00280         while(decls != nil){
00281             Ptree* d = decls->Car();
00282             if(d->IsA(ntDeclarator))
00283                 env->RecordDeclarator(d);
00284 
00285             decls = decls->Cdr();
00286             if(decls != nil)
00287                 decls = decls->Cdr();
00288         }
00289 
00290     if(tspec != tspec2){
00291         tspec_list->Append(tspec);
00292         tspec_list->Append(tspec2);
00293     }
00294 }
00295 
00296 Ptree* ClassWalker::ConstructAccessSpecifier(int access)
00297 {
00298     Ptree* lf;
00299     switch(access){
00300     case Class::Protected :
00301         lf = Class::protected_t;
00302         break;
00303     case Class::Private :
00304         lf = Class::private_t;
00305         break;
00306     case Class::Public :
00307     default :
00308         lf = Class::public_t;
00309         break;
00310      }
00311 
00312      return new PtreeAccessSpec(lf, Ptree::List(Class::colon_t));
00313 }
00314 
00315 Ptree* ClassWalker::ConstructMember(void* ptr)
00316 {
00317     ChangedMemberList::Cmem* m = (ChangedMemberList::Cmem*)ptr;
00318     Ptree* def = m->def;
00319     Ptree* def2;
00320 
00321     if(def->Third()->IsA(ntDeclarator)){
00322         // function implementation
00323         if(m->body == nil){
00324             NameScope old_env;
00325             Environment* fenv = env->DontRecordDeclarator(m->declarator);
00326             if(fenv != nil)
00327                 old_env = ChangeScope(fenv);
00328 
00329             NewScope();
00330             def2 = MakeMemberDeclarator(TRUE, m,
00331                                         (PtreeDeclarator*)m->declarator);
00332             def2 = Ptree::List(def2,
00333                                TranslateFunctionBody(def->Nth(3)));
00334             ExitScope();
00335             if(fenv != nil)
00336                 RestoreScope(old_env);
00337         }
00338         else{
00339             def2 = MakeMemberDeclarator(FALSE, m,
00340                                         (PtreeDeclarator*)m->declarator);
00341             def2 = Ptree::List(def2, m->body);
00342         }
00343     }
00344     else{
00345         // declaration
00346         def2 = MakeMemberDeclarator(FALSE, m,
00347                                     (PtreeDeclarator*)m->declarator);
00348         if(m->body == nil)
00349             def2 = Ptree::List(Ptree::List(def2), Class::semicolon_t);
00350         else
00351             def2 = Ptree::List(def2, m->body);
00352     }
00353 
00354     def2 = new PtreeDeclaration(
00355                         TranslateStorageSpecifiers(def->First()),
00356                         Ptree::Cons(TranslateTypespecifier(def->Second()),
00357                                     def2));
00358     return def2;
00359 }
00360 
00361 Ptree* ClassWalker::TranslateStorageSpecifiers(Ptree* spec)
00362 {
00363     return TranslateStorageSpecifiers2(spec);
00364 }
00365 
00366 Ptree* ClassWalker::TranslateStorageSpecifiers2(Ptree* rest)
00367 {
00368     if(rest == nil)
00369         return nil;
00370     else{
00371         Ptree* h = rest->Car();
00372         Ptree* t = rest->Cdr();
00373         Ptree* t2 = TranslateStorageSpecifiers2(t);
00374         if(h->IsA(ntUserdefKeyword))
00375             return t2;
00376         else if(t == t2)
00377             return rest;
00378         else
00379             return Ptree::Cons(h, t2);
00380     }
00381 }
00382 
00383 Ptree* ClassWalker::TranslateTemplateFunction(Ptree* temp_def, Ptree* impl)
00384 {
00385     Environment* fenv = env->RecordTemplateFunction(temp_def, impl);
00386     if (fenv != nil) {
00387         Class* metaobject = fenv->IsClassEnvironment();
00388         if(metaobject != nil){
00389             NameScope old_env = ChangeScope(fenv);
00390             NewScope();
00391 
00392             ChangedMemberList::Cmem m;
00393             Ptree* decl = impl->Third();
00394             MemberFunction mem(metaobject, impl, decl);
00395             metaobject->TranslateMemberFunction(env, mem);
00396             ChangedMemberList::Copy(&mem, &m, Class::Undefined);
00397             Ptree* decl2
00398                 = MakeMemberDeclarator(TRUE, &m, (PtreeDeclarator*)decl);
00399 
00400             ExitScope();
00401             RestoreScope(old_env);
00402             if(decl != decl2) {
00403                 Ptree* pt = Ptree::List(impl->Second(), decl2, impl->Nth(3));
00404                 pt = new PtreeDeclaration(impl->First(), pt);
00405                 pt = Ptree::List(temp_def->Second(), temp_def->Third(),
00406                                  temp_def->Nth(3), pt);
00407                 return new PtreeTemplateDecl(temp_def->First(), pt);
00408             }
00409         }
00410     }
00411 
00412     return temp_def;
00413 }
00414 
00415 Ptree* ClassWalker::TranslateFunctionImplementation(Ptree* impl)
00416 {
00417     Ptree* sspec = impl->First();
00418     Ptree* sspec2 = TranslateStorageSpecifiers(sspec);
00419     Ptree* tspec = impl->Second();
00420     Ptree* decl = impl->Third();
00421     Ptree* body = impl->Nth(3);
00422     Ptree* decl2;
00423     Ptree *body2;
00424 
00425     Ptree* tspec2 = TranslateTypespecifier(tspec);
00426     Environment* fenv = env->RecordDeclarator(decl);
00427 
00428     if(fenv == nil){
00429         // reach here if resolving the qualified name fails. error?
00430         NewScope();
00431         decl2 = TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00432         body2 = TranslateFunctionBody(body);
00433         ExitScope();
00434     }
00435     else{
00436         Class* metaobject = fenv->IsClassEnvironment();
00437         NameScope old_env = ChangeScope(fenv);
00438         NewScope();
00439 
00440         if (metaobject == nil && Class::metaclass_for_c_functions != nil)
00441             metaobject = MakeMetaobjectForCfunctions();
00442 
00443         if(metaobject == nil){
00444             decl2 = TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00445             body2 = TranslateFunctionBody(body);
00446         }
00447         else{
00448             ChangedMemberList::Cmem m;
00449             MemberFunction mem(metaobject, impl, decl);
00450             metaobject->TranslateMemberFunction(env, mem);
00451             ChangedMemberList::Copy(&mem, &m, Class::Undefined);
00452             decl2 = MakeMemberDeclarator(TRUE, &m, (PtreeDeclarator*)decl);
00453             if(m.body != nil)
00454                 body2 = m.body;
00455             else
00456                 body2 = TranslateFunctionBody(body);
00457         }
00458 
00459         ExitScope();
00460         RestoreScope(old_env);
00461     }
00462 
00463     if(sspec == sspec2 && tspec == tspec2 && decl == decl2 && body == body2)
00464         return impl;
00465     else
00466         return new PtreeDeclaration(sspec2,
00467                                     Ptree::List(tspec2, decl2, body2));
00468 }
00469 
00470 Class* ClassWalker::MakeMetaobjectForCfunctions() {
00471     if (Class::for_c_functions == nil) {
00472         Encoding encode;
00473         Ptree* name = new Leaf("<C>", 3);
00474         encode.SimpleName(name);
00475         Ptree* class_def
00476             = new PtreeClassSpec(Class::class_t,
00477                                  Ptree::List(name, nil,
00478                                              Class::empty_block_t),
00479                                  nil, encode.Get());
00480 
00481         Class* metaobject = opcxx_ListOfMetaclass::New(
00482                         Class::metaclass_for_c_functions,
00483                         class_def, nil);
00484         if(metaobject == nil)
00485             MopErrorMessage2(
00486                 "the metaclass for C functions cannot be loaded: ",
00487                 Class::metaclass_for_c_functions);
00488 
00489         metaobject->SetEnvironment(env);
00490         Class::for_c_functions = metaobject;
00491     }
00492 
00493     return Class::for_c_functions;
00494 }
00495 
00496 Ptree* ClassWalker::MakeMemberDeclarator(bool record, void* ptr,
00497                                          PtreeDeclarator* decl)
00498 {
00499     Ptree *args, *args2, *name, *name2, *init, *init2;
00500 
00501     //  Since g++ cannot parse the nested-class declaration:
00502     //     class ChangedMemberList::Cmem;
00503     //  MakeMemberDeclarator() takes a void* pointer and convert the type
00504     //  into ChangedMemberList::Cmem*.
00505     ChangedMemberList::Cmem* m = (ChangedMemberList::Cmem*)ptr;
00506 
00507     if(m->removed)
00508         return nil;
00509 
00510     if(GetArgDeclList(decl, args))
00511         if(m->args == nil)
00512             args2 = TranslateArgDeclList2(record, env, TRUE,
00513                                           m->arg_name_filled, 0, args);
00514         else{
00515             args2 = m->args;
00516             // we may need to record the arguments.
00517             TranslateArgDeclList2(record, env, FALSE, FALSE, 0, args);
00518         }
00519     else
00520         args = args2 = nil;
00521 
00522     name = decl->Name();
00523     if(m->name != nil)
00524         name2 = m->name;
00525     else
00526         name2 = name;
00527 
00528     if(m->init == nil)
00529         init = init2 = nil;
00530     else{
00531         init2 = m->init;
00532         init = decl->Last()->Car();
00533         if(init->IsLeaf() || !init->Car()->Eq(':'))
00534             init = nil;
00535     }
00536 
00537     if(args == args2 && name == name2 && init == init2)
00538         return decl;
00539     else{
00540         Ptree* rest;
00541         if(init == nil && init2 != nil){
00542             rest = Ptree::Subst(args2, args, name2, name, decl->Cdr());
00543             rest = Ptree::Append(rest, init2);
00544         }
00545         else
00546             rest = Ptree::Subst(args2, args, name2, name,
00547                                 init2, init, decl->Cdr());
00548 
00549         if(decl->Car() == name)
00550             return new PtreeDeclarator(decl, name2, rest);
00551         else
00552             return new PtreeDeclarator(decl, decl->Car(), rest);
00553     }
00554 }
00555 
00556 Ptree* ClassWalker::RecordArgsAndTranslateFbody(Class* c, Ptree* args,
00557                                                 Ptree* body)
00558 {
00559     NameScope old_env;
00560     Environment* fenv = c->GetEnvironment();
00561 
00562     if(fenv != nil)
00563         old_env = ChangeScope(fenv);
00564 
00565     NewScope();
00566     TranslateArgDeclList2(TRUE, env, FALSE, FALSE, 0, args);
00567     Ptree* body2 = TranslateFunctionBody(body);
00568     ExitScope();
00569 
00570     if(fenv != nil)
00571         RestoreScope(old_env);
00572 
00573     return body2;
00574 }
00575 
00576 Ptree* ClassWalker::TranslateFunctionBody(Ptree* body)
00577 {
00578     Ptree* body2;
00579 
00580     inserted_declarations.Clear();
00581     client_data = nil;
00582     body = Translate(body);
00583     if(body == nil || body->IsLeaf() || inserted_declarations.Number() <= 0)
00584         body2 = body;
00585     else{
00586         Ptree* decls = inserted_declarations.All();
00587         body2 = new PtreeBlock(Ptree::First(body),
00588                               Ptree::Nconc(decls, Ptree::Second(body)),
00589                               Ptree::Third(body));
00590     }
00591 
00592     inserted_declarations.Clear();
00593     client_data = nil;
00594     return body2;
00595 }
00596 
00597 Ptree* ClassWalker::TranslateBlock(Ptree* block)
00598 {
00599     Ptree* block2;
00600 
00601     NewScope();
00602 
00603     PtreeArray array;
00604     bool changed = FALSE;
00605     Ptree* body = Ptree::Second(block);
00606     Ptree* rest = body;
00607     while(rest != nil){
00608         uint i, n;
00609         Ptree* p = rest->Car();
00610         Ptree* q = Translate(p);
00611 
00612         n = before_statement.Number();
00613         if(n > 0){
00614             changed = TRUE;
00615             for(i = 0; i < n; ++i)
00616                 array.Append(before_statement[i]);
00617         }
00618 
00619         array.Append(q);
00620         if(p != q)
00621             changed = TRUE;
00622 
00623         n = after_statement.Number();
00624         if(n > 0){
00625             changed = TRUE;
00626             for(i = 0; i < n; ++i)
00627                 array.Append(after_statement[i]);
00628         }
00629 
00630         before_statement.Clear();
00631         after_statement.Clear();
00632         rest = rest->Cdr();
00633     }
00634 
00635     if(changed)
00636         block2 = new PtreeBlock(Ptree::First(block), array.All(),
00637                                 Ptree::Third(block));
00638     else
00639         block2 = block;
00640 
00641     ExitScope();
00642     return block2;
00643 }
00644 
00645 Ptree* ClassWalker::TranslateArgDeclList(bool record, Ptree*, Ptree* args)
00646 {
00647     return TranslateArgDeclList2(record, env, TRUE, FALSE, 0, args);
00648 }
00649 
00650 Ptree* ClassWalker::TranslateInitializeArgs(PtreeDeclarator* decl, Ptree* init)
00651 {
00652     TypeInfo tinfo;
00653     env->Lookup(decl, tinfo);
00654     Class* metaobject = tinfo.ClassMetaobject();
00655     if(metaobject != nil)
00656         return metaobject->TranslateInitializer(env, decl->Name(), init);
00657     else
00658         return TranslateArguments(init);
00659 }
00660 
00661 Ptree* ClassWalker::TranslateAssignInitializer(PtreeDeclarator* decl,
00662                                                Ptree* init)
00663 {
00664     TypeInfo tinfo;
00665     env->Lookup(decl, tinfo);
00666     Class* metaobject = tinfo.ClassMetaobject();
00667     if(metaobject != nil)
00668         return metaobject->TranslateInitializer(env, decl->Name(), init);
00669     else{
00670         Ptree* exp = init->Second();
00671         Ptree* exp2 = Translate(exp);
00672         if(exp == exp2)
00673             return init;
00674         else
00675             return Ptree::List(init->Car(), exp2);
00676     }
00677 }
00678 
00679 Ptree* ClassWalker::TranslateUserAccessSpec(Ptree*)
00680 {
00681     return nil;
00682 }
00683 
00684 Ptree* ClassWalker::TranslateAssign(Ptree* exp)
00685 {
00686     Ptree *left, *left2, *right, *right2, *exp2;
00687     Environment* scope;
00688     Class* metaobject;
00689     TypeInfo type;
00690 
00691     left = exp->First();
00692     right = exp->Third();
00693     if(left->IsA(ntDotMemberExpr, ntArrowMemberExpr)){
00694         Ptree* object = left->First();
00695         Ptree* op = left->Second();
00696         Ptree* member = left->Third();
00697         Ptree* assign_op = exp->Second();
00698         Typeof(object, type);
00699         if(!op->Eq('.'))
00700             type.Dereference();
00701 
00702         metaobject = GetClassMetaobject(type);
00703         if(metaobject != nil){
00704             exp2 = metaobject->TranslateMemberWrite(env, object, op,
00705                                                     member, assign_op, right);
00706             return CheckMemberEquiv(exp, exp2);
00707         }
00708     }
00709     else if((scope = env->IsMember(left)) != nil){
00710         metaobject = scope->IsClassEnvironment();
00711         if(metaobject != nil){
00712             exp2 = metaobject->TranslateMemberWrite(env, left, exp->Second(),
00713                                                     right);
00714             return CheckEquiv(exp, exp2);
00715         }
00716     }
00717     else{
00718         Typeof(left, type);
00719         metaobject = GetClassMetaobject(type);
00720         if(metaobject != nil){
00721             exp2 = metaobject->TranslateAssign(env, left, exp->Second(),
00722                                                right);
00723             return CheckEquiv(exp, exp2);       
00724         }
00725     }
00726 
00727     left2 = Translate(left);
00728     right2 = Translate(right);
00729     if(left == left2 && right == right2)
00730         return exp;
00731     else
00732         return new PtreeAssignExpr(left2, Ptree::List(exp->Second(), right2));
00733 }
00734 
00735 Ptree* ClassWalker::CheckMemberEquiv(Ptree* exp, Ptree* exp2)
00736 {
00737     if(!exp2->IsLeaf()
00738        && Ptree::Equiv(exp->Car(), exp2->Car())
00739        && Ptree::Equiv(exp->Cdr(), exp2->Cdr()))
00740         return exp;
00741     else
00742         return exp2;
00743 }
00744 
00745 Ptree* ClassWalker::TranslateInfix(Ptree* exp)
00746 {
00747     TypeInfo type;
00748 
00749     Ptree* left = exp->First();
00750     Ptree* right = exp->Third();
00751     Typeof(right, type);
00752     Class* metaobject = GetClassMetaobject(type);
00753     if(metaobject == nil){
00754         Typeof(left, type);
00755         metaobject = GetClassMetaobject(type);
00756     }
00757 
00758     if(metaobject != nil){
00759         Ptree* exp2 = metaobject->TranslateBinary(env, left, exp->Second(),
00760                                                   right);
00761         return CheckEquiv(exp, exp2);
00762     }
00763     else{
00764         Ptree* left2 = Translate(left);
00765         Ptree* right2 = Translate(right);
00766         if(left == left2 && right == right2)
00767             return exp;
00768         else
00769             return new PtreeInfixExpr(left2, Ptree::List(exp->Second(),
00770                                                          right2));
00771     }
00772 }
00773 
00774 Ptree* ClassWalker::TranslateUnary(Ptree* exp)
00775 {
00776     TypeInfo type;
00777     Environment* scope;
00778     Class* metaobject;
00779     Ptree* exp2;
00780 
00781     Ptree* unaryop = exp->Car();
00782     Ptree* right = exp->Second();
00783     if(right->IsA(ntDotMemberExpr, ntArrowMemberExpr)){
00784         Ptree* object = right->First();
00785         Ptree* op = right->Second();
00786         Typeof(object, type);
00787         if(!op->Eq('.'))
00788             type.Dereference();
00789 
00790         metaobject = GetClassMetaobject(type);
00791         if(metaobject != nil){
00792             exp2 = metaobject->TranslateUnaryOnMember(env, unaryop, object,
00793                                                       op, right->Third());
00794             if(exp2->Length() == 2 && exp2->Car() == unaryop
00795                && Ptree::Equiv(exp2->Second(), right))
00796                 return exp;
00797             else
00798                 return exp2;
00799         }
00800     }    
00801     else if((scope = env->IsMember(right)) != nil){
00802         metaobject = scope->IsClassEnvironment();
00803         if(metaobject != nil){
00804             exp2 = metaobject->TranslateUnaryOnMember(env, unaryop, right);
00805             return CheckEquiv(exp, exp2);
00806         }
00807     }
00808 
00809     Typeof(right, type);
00810     metaobject = GetClassMetaobject(type);
00811     if(metaobject != nil){
00812         Ptree* exp2 = metaobject->TranslateUnary(env, unaryop, right);
00813         return CheckEquiv(exp, exp2);
00814     }
00815     else{
00816         Ptree* right2 = Translate(right);
00817         if(right == right2)
00818             return exp;
00819         else
00820             return new PtreeUnaryExpr(unaryop, Ptree::List(right2));
00821     }
00822 }
00823 
00824 Ptree* ClassWalker::TranslateArray(Ptree* exp)
00825 {
00826     TypeInfo type;
00827 
00828     Ptree* array = exp->Car();
00829     Typeof(array, type);
00830     Class* metaobject = GetClassMetaobject(type);
00831     if(metaobject != nil){
00832         Ptree* exp2 = metaobject->TranslateSubscript(env, array, exp->Cdr());
00833         return CheckEquiv(exp, exp2);
00834     }
00835     else{
00836         Ptree* index = exp->Third();
00837         Ptree* array2 = Translate(array);
00838         Ptree* index2 = Translate(index);
00839         if(array == array2 && index == index2)
00840             return exp;
00841         else
00842             return new PtreeArrayExpr(array2,
00843                         Ptree::ShallowSubst(index2, index, exp->Cdr()));
00844     }
00845 }
00846 
00847 Ptree* ClassWalker::TranslatePostfix(Ptree* exp)
00848 {
00849     TypeInfo type;
00850     Environment* scope;
00851     Class* metaobject;
00852     Ptree* exp2;
00853 
00854     Ptree* left = exp->Car();
00855     Ptree* postop = exp->Second();
00856     if(left->IsA(ntDotMemberExpr, ntArrowMemberExpr)){
00857         Ptree* object = left->First();
00858         Ptree* op = left->Second();
00859         Typeof(object, type);
00860         if(!op->Eq('.'))
00861             type.Dereference();
00862 
00863         metaobject = GetClassMetaobject(type);
00864         if(metaobject != nil){
00865             exp2 = metaobject->TranslatePostfixOnMember(env, object, op,
00866                                                         left->Third(), postop);
00867             return CheckMemberEquiv(exp, exp2);
00868         }
00869     }    
00870     else if((scope = env->IsMember(left)) != nil){
00871         metaobject = scope->IsClassEnvironment();
00872         if(metaobject != nil){
00873             exp2 = metaobject->TranslatePostfixOnMember(env, left, postop);
00874             return CheckEquiv(exp, exp2);
00875         }
00876     }
00877 
00878     Typeof(left, type);
00879     metaobject = GetClassMetaobject(type);
00880     if(metaobject != nil){
00881         exp2 = metaobject->TranslatePostfix(env, left, postop);
00882         return CheckEquiv(exp, exp2);
00883     }
00884     else{
00885         Ptree* left2 = Translate(left);
00886         if(left == left2)
00887             return exp;
00888         else
00889             return new PtreePostfixExpr(left2, exp->Cdr());
00890     }
00891 }
00892 
00893 Ptree* ClassWalker::TranslateFuncall(Ptree* exp)
00894 {
00895     TypeInfo type;
00896     Environment* scope;
00897     Class* metaobject;
00898     Ptree *fun, *arglist, *exp2;
00899 
00900     fun = exp->Car();
00901     arglist = exp->Cdr();
00902     if(fun->IsA(ntDotMemberExpr, ntArrowMemberExpr)){
00903         Ptree* object = fun->First();
00904         Ptree* op = fun->Second();
00905         Ptree* member = fun->Third();
00906         Typeof(object, type);
00907         if(!op->Eq('.'))
00908             type.Dereference();
00909 
00910         metaobject = GetClassMetaobject(type);
00911         if(metaobject != nil){
00912             exp2 = metaobject->TranslateMemberCall(env, object, op,
00913                                                    member, arglist);
00914             return CheckMemberEquiv(exp, exp2);
00915         }
00916     }
00917     else if((scope = env->IsMember(fun)) != nil){
00918         metaobject = scope->IsClassEnvironment();
00919         if(metaobject != nil){
00920             exp2 = metaobject->TranslateMemberCall(env, fun, arglist);
00921             return CheckEquiv(exp, exp2);
00922         }
00923     }
00924     else{
00925         Typeof(fun, type);
00926         metaobject = GetClassMetaobject(type);
00927         if(metaobject != nil){
00928             exp2 = metaobject->TranslateFunctionCall(env, fun, arglist);
00929             return CheckEquiv(exp, exp2);
00930         }
00931         else if (Class::for_c_functions != nil) {
00932             exp2 = Class::for_c_functions->TranslateFunctionCall(env,
00933                                                         fun, arglist);
00934             return CheckEquiv(exp, exp2);
00935         }
00936     }
00937 
00938     Ptree* fun2 = Translate(fun);
00939     Ptree* arglist2 = TranslateArguments(arglist);
00940     if(fun == fun2 && arglist == arglist2)
00941         return exp;
00942     else
00943         return new PtreeFuncallExpr(fun2, arglist2);
00944 }
00945 
00946 Ptree* ClassWalker::TranslateDotMember(Ptree* exp)
00947 {
00948     TypeInfo type;
00949 
00950     Ptree* left = exp->Car();
00951     Typeof(left, type);
00952     Class* metaobject = GetClassMetaobject(type);
00953     if(metaobject != nil){
00954         Ptree* exp2 = metaobject->TranslateMemberRead(env, left, exp->Second(),
00955                                                       exp->Third());
00956         return CheckEquiv(exp, exp2);
00957     }
00958     else{
00959         Ptree* left2 = Translate(left);
00960         if(left == left2)
00961             return exp;
00962         else
00963             return new PtreeDotMemberExpr(left2, exp->Cdr());
00964     }
00965 }
00966 
00967 Ptree* ClassWalker::TranslateArrowMember(Ptree* exp)
00968 {
00969     TypeInfo type;
00970 
00971     Ptree* left = exp->Car();
00972     Typeof(left, type);
00973     type.Dereference();
00974     Class* metaobject = GetClassMetaobject(type);
00975     if(metaobject != nil){
00976         Ptree* exp2 = metaobject->TranslateMemberRead(env, left, exp->Second(),
00977                                                       exp->Third());
00978         return CheckEquiv(exp, exp2);
00979     }
00980     else{
00981         Ptree* left2 = Translate(left);
00982         if(left == left2)
00983             return exp;
00984         else
00985             return new PtreeArrowMemberExpr(left2, exp->Cdr());
00986     }
00987 }
00988 
00989 Ptree* ClassWalker::TranslateThis(Ptree* exp)
00990 {
00991     TypeInfo type;
00992     Typeof(exp, type);
00993     type.Dereference();
00994     Class* metaobject = GetClassMetaobject(type);
00995     if(metaobject != nil)
00996         return metaobject->TranslatePointer(env, exp);
00997     else
00998         return exp;
00999 }
01000 
01001 Ptree* ClassWalker::TranslateVariable(Ptree* exp)
01002 {
01003     Environment* scope = env->IsMember(exp);
01004     if(scope != nil){
01005         Class* metaobject = scope->IsClassEnvironment();
01006         if(metaobject != nil)
01007             return metaobject->TranslateMemberRead(env, exp);
01008     }
01009 
01010     TypeInfo type;
01011     Typeof(exp, type);
01012     if(type.IsPointerType()){
01013         type.Dereference();
01014         Class* metaobject = GetClassMetaobject(type);
01015         if(metaobject != nil)
01016             return metaobject->TranslatePointer(env, exp);
01017     }
01018 
01019     return exp;
01020 }
01021 
01022 Ptree* ClassWalker::TranslateUserStatement(Ptree* exp)
01023 {
01024     TypeInfo type;
01025     Ptree* object = exp->First();
01026     Ptree* op = exp->Second();
01027     Ptree* keyword = exp->Third();
01028     Ptree* rest = exp->ListTail(3);
01029 
01030     Typeof(object, type);
01031     if(!op->Eq('.'))
01032         type.Dereference();
01033 
01034     Class* metaobject = GetClassMetaobject(type);
01035     if(metaobject != nil){
01036         NewScope();
01037         if(keyword->IsA(UserKeyword2))          // closure style
01038             TranslateArgDeclList2(TRUE, env, FALSE, FALSE, 0, rest->Second());
01039 
01040         Ptree* exp2 = metaobject->TranslateUserStatement(env, object, op,
01041                                                          keyword, rest);
01042         ExitScope();
01043         return exp2;
01044     }
01045 
01046     ErrorMessage("no complete class specification for: ", object, exp);
01047     return nil;
01048 }
01049 
01050 Ptree* ClassWalker::TranslateStaticUserStatement(Ptree* exp)
01051 {
01052     bool is_type_name;
01053     TypeInfo type;
01054     Ptree* qualifier = exp->First();
01055     Ptree* keyword = exp->Third();
01056     Ptree* rest = exp->ListTail(3);
01057 
01058     if(env->Lookup(qualifier, is_type_name, type))
01059         if(is_type_name){
01060             Class* metaobject = GetClassMetaobject(type);
01061             if(metaobject != nil){
01062                 NewScope();
01063                 if(keyword->IsA(UserKeyword2))          // closure style
01064                     TranslateArgDeclList2(TRUE, env, FALSE, FALSE, 0,
01065                                           rest->Second());
01066                 Ptree* exp2 = metaobject->TranslateStaticUserStatement(env,
01067                                                         keyword, rest);
01068                 ExitScope();
01069                 return exp2;
01070             }
01071         }
01072 
01073     ErrorMessage("no complete class specification for: ", qualifier, exp);
01074     return nil;
01075 }
01076 
01077 Ptree* ClassWalker::TranslateNew2(Ptree* exp, Ptree* userkey, Ptree* scope,
01078                                   Ptree* op, Ptree* placement,
01079                                   Ptree* type, Ptree* init)
01080 {
01081     TypeInfo t;
01082 
01083     if(type->Car()->Eq('('))
01084         t.Set(type->Second()->Second()->GetEncodedType(), env);
01085     else
01086         t.Set(type->Second()->GetEncodedType(), env);
01087 
01088     Class* metaobject = GetClassMetaobject(t);
01089     if(metaobject != nil){
01090         if(userkey == nil)
01091             userkey = scope;
01092 
01093         Ptree* exp2 = metaobject->TranslateNew(env, userkey, op,
01094                                                placement, type, init);
01095         return CheckEquiv(exp, exp2);
01096     }
01097     else{
01098         Ptree* placement2 = TranslateArguments(placement);
01099         Ptree* type2 = TranslateNew3(type);
01100         Ptree* init2 = TranslateArguments(init);
01101         if(userkey == nil && placement == placement2
01102            && type == type2 && init == init2)
01103             return exp;
01104         else{
01105             if(userkey == nil)
01106                 return new PtreeNewExpr(exp->Car(),
01107                                 Ptree::ShallowSubst(placement2, placement,
01108                                                     type2, type,
01109                                                     init2, init, exp->Cdr()));
01110             else{
01111                 ErrorMessage("no complete class specification for: ",
01112                              type, exp);
01113                 exp = exp->Cdr();
01114                 if(placement == placement2 && type == type2 && init == init2)
01115                     return exp;
01116                 else
01117                     return new PtreeNewExpr(exp->Car(),
01118                                 Ptree::ShallowSubst(placement2, placement,
01119                                                     type2, type,
01120                                                     init2, init, exp->Cdr()));
01121             }
01122 
01123         }
01124     }
01125 }
01126 
01127 Ptree* ClassWalker::TranslateDelete(Ptree* exp)
01128 {
01129     TypeInfo type;
01130 
01131     Ptree* obj = Ptree::Last(exp)->Car();
01132     if(exp->Length() == 2){     // not ::delete or delete []
01133         Typeof(obj, type);
01134         type.Dereference();
01135         Class* metaobject = GetClassMetaobject(type);
01136         if(metaobject != nil){
01137             Ptree* exp2 = metaobject->TranslateDelete(env, exp->Car(), obj);
01138             return CheckEquiv(exp, exp2);
01139         }
01140     }
01141 
01142     Ptree* obj2 = Translate(obj);
01143     if(obj == obj2)
01144         return exp;
01145     else
01146         return new PtreeDeleteExpr(exp->Car(),
01147                                    Ptree::ShallowSubst(obj2, obj,
01148                                                        exp->Cdr()));
01149 }

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