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

walker.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 <string.h>
00016 #include "env.h"
00017 #include "ptree.h"
00018 #include "walker.h"
00019 #include "typeinfo.h"
00020 #include "mop.h"
00021 #include "metaclass.h"
00022 #include "parse.h"
00023 #include "encoding.h"
00024 #include "member.h"
00025 
00026 Parser* Walker::default_parser = nil;
00027 char* Walker::argument_name = "_arg_%d_";
00028 char* Walker::default_metaclass = nil;
00029 
00030 Walker::Walker(Parser* p)
00031 {
00032     env = new Environment(this);
00033     parser = p;
00034     if(default_parser == nil)
00035         default_parser = p;
00036 }
00037 
00038 Walker::Walker(Parser* p, Environment* e)
00039 {
00040     env = new Environment(e, this);
00041     parser = p;
00042     if(default_parser == nil)
00043         default_parser = p;
00044 }
00045 
00046 Walker::Walker(Environment* e)
00047 {
00048     env = new Environment(e, this);
00049     if(default_parser == nil)
00050         MopErrorMessage("Walker::Walker()", "no default parser");
00051 
00052     parser = default_parser;
00053 }
00054 
00055 Walker::Walker(Walker* w)
00056 {
00057     env = w->env;
00058     parser = w->parser;
00059 }
00060 
00061 void Walker::NewScope()
00062 {
00063     env = new Environment(env);
00064 }
00065 
00066 void Walker::NewScope(Environment* e)
00067 {
00068     if (e != nil)
00069         env = e;
00070     else
00071         env = new Environment(env);
00072 }
00073 
00074 void Walker::NewScope(Class* metaobject)
00075 {
00076     env = new Environment(env);
00077     if(metaobject != nil)
00078         metaobject->SetEnvironment(env);
00079 }
00080 
00081 Environment* Walker::ExitScope()
00082 {
00083     Environment* old_env = env;
00084     env = old_env->GetOuterEnvironment();
00085     return old_env;
00086 }
00087 
00088 void Walker::RecordBaseclassEnv(Ptree* bases)
00089 {
00090     while(bases != nil){
00091         bases = bases->Cdr();           // skip : or ,
00092         Ptree* base_class = bases->Car()->Last()->Car();
00093         Class* metaobject = env->LookupClassMetaobject(base_class);
00094         if(metaobject != nil){
00095             Environment* e = metaobject->GetEnvironment();
00096             if(e != nil)
00097                 env->AddBaseclassEnv(e);
00098         }
00099 
00100         bases = bases->Cdr();
00101     }
00102 }
00103 
00104 Walker::NameScope Walker::ChangeScope(Environment* e)
00105 {
00106     NameScope scope;
00107     scope.walker = e->GetWalker();
00108     e->SetWalker(this);
00109     scope.env = env;
00110     env = e;
00111     return scope;
00112 }
00113 
00114 void Walker::RestoreScope(Walker::NameScope& scope)
00115 {
00116     env->SetWalker(scope.walker);
00117     env = scope.env;
00118 }
00119 
00120 bool Walker::IsClassWalker()
00121 {
00122     return FALSE;
00123 }
00124 
00125 Ptree* Walker::Translate(Ptree* p)
00126 {
00127     if(p == nil)
00128         return p;
00129     else
00130         return p->Translate(this);
00131 }
00132 
00133 void Walker::Typeof(Ptree* p, TypeInfo& t)
00134 {
00135     if(p != nil)
00136         p->Typeof(this, t);
00137 }
00138 
00139 // default translation
00140 
00141 Ptree* Walker::TranslatePtree(Ptree* p)
00142 {
00143     return p;
00144 }
00145 
00146 void Walker::TypeofPtree(Ptree*, TypeInfo& t)
00147 {
00148     t.Unknown();
00149 }
00150 
00151 // translation for each class of node
00152 
00153 Ptree* Walker::TranslateTypedef(Ptree* def)
00154 {
00155     Ptree *tspec, *tspec2;
00156 
00157     tspec = Ptree::Second(def);
00158     tspec2 = TranslateTypespecifier(tspec);
00159     env->RecordTypedefName(Ptree::Third(def));
00160     if(tspec == tspec2)
00161         return def;
00162     else
00163         return new PtreeTypedef(Ptree::First(def),
00164                                 Ptree::List(tspec2,
00165                                             Ptree::ListTail(def, 2)));
00166 }
00167 
00168 Ptree* Walker::TranslateTemplateDecl(Ptree* def)
00169 {
00170     Ptree* body = Ptree::Nth(def, 4);
00171     Ptree* class_spec = GetClassTemplateSpec(body);
00172     if(class_spec->IsA(ntClassSpec))
00173         return TranslateTemplateClass(def, class_spec);
00174     else
00175         return TranslateTemplateFunction(def, body);
00176 }
00177 
00178 Ptree* Walker::TranslateExternTemplate(Ptree* def)
00179 {
00180     return def;
00181 }
00182 
00183 Ptree* Walker::TranslateTemplateClass(Ptree* temp_def, Ptree* class_spec)
00184 {
00185     Ptree* userkey;
00186     Ptree* class_def;
00187 
00188     if(class_spec->Car()->IsLeaf()){
00189         userkey = nil;
00190         class_def = class_spec;
00191     }
00192     else{
00193         userkey = class_spec->Car();
00194         class_def = class_spec->Cdr();
00195     }
00196 
00197     Class* metaobject = nil;
00198     if(Ptree::Length(class_def) == 4)
00199         metaobject = MakeTemplateClassMetaobject(temp_def, userkey, class_def);
00200 
00201     env->RecordTemplateClass(class_spec, metaobject);
00202     Ptree* class_spec2 = TranslateClassSpec(class_spec, userkey, class_def,
00203                                             metaobject);
00204     if(class_spec == class_spec2)
00205         return temp_def;
00206     else
00207         return new PtreeTemplateDecl(temp_def->Car(),
00208                                      Ptree::Subst(class_spec2, class_spec,
00209                                                   temp_def->Cdr()));
00210 }
00211 
00212 Class* Walker::MakeTemplateClassMetaobject(Ptree* def, Ptree* userkey,
00213                                            Ptree* class_def)
00214 {
00215     Class* metaobject = LookupMetaclass(def, userkey, class_def, TRUE);
00216     if(metaobject == nil)
00217         metaobject = new TemplateClass;
00218     else
00219         if(metaobject->AcceptTemplate())
00220             return metaobject;
00221         else{
00222 
00223             ErrorMessage("the specified metaclass is not for templates.",
00224                          nil, def);
00225             metaobject = new TemplateClass;
00226         }
00227 
00228     metaobject->InitializeInstance(def, nil);
00229     return metaobject;
00230 }
00231 
00232 Ptree* Walker::TranslateTemplateFunction(Ptree* temp_def, Ptree* fun)
00233 {
00234     env->RecordTemplateFunction(temp_def, fun);
00235     return temp_def;
00236 }
00237 
00238 Ptree* Walker::TranslateTemplateInstantiation(Ptree *inst_spec)
00239 {
00240     Ptree* userkey;
00241     Ptree* class_spec;
00242     Ptree* full_class_spec = Ptree::First(inst_spec);
00243 
00244     if(full_class_spec->Car()->IsLeaf()){
00245         userkey = nil;
00246         class_spec = full_class_spec;
00247     }
00248     else{
00249         userkey = full_class_spec->Car();
00250         class_spec = full_class_spec->Cdr();
00251     }
00252 
00253     Class* metaobject = nil;
00254     metaobject = MakeTemplateInstantiationMetaobject(full_class_spec,
00255                                                      userkey, class_spec);
00256     return TranslateTemplateInstantiation(inst_spec, userkey, 
00257                                           class_spec, metaobject);
00258 }
00259 
00260 Class* Walker::MakeTemplateInstantiationMetaobject(
00261     Ptree* full_class_spec, Ptree* userkey, Ptree* class_spec)
00262 {
00263     // [class [foo [< ... >]]] -> [class foo]
00264     Ptree* class_name = Ptree::First(Ptree::Second(class_spec));
00265     Bind* binding = nil;
00266     if (!env->Lookup(class_name,binding))
00267         return nil;
00268 
00269     Class* metaobject = nil;
00270     if (binding->What() != Bind::isTemplateClass) {
00271         ErrorMessage("not declarated as a template class?!?",
00272                      nil, full_class_spec);
00273         metaobject = nil;
00274     }
00275     else
00276         metaobject = binding->ClassMetaobject();
00277 
00278     if (metaobject == nil)
00279         metaobject = new TemplateClass;
00280     else
00281         if(metaobject->AcceptTemplate())
00282             return metaobject;
00283         else{
00284             ErrorMessage("the specified metaclass is not for templates.",
00285                          nil, full_class_spec);
00286             metaobject = new TemplateClass;
00287         }
00288 
00289     return metaobject;
00290 }
00291 
00292 Ptree* Walker::TranslateTemplateInstantiation(Ptree* inst_spec,
00293                 Ptree* userkey, Ptree* class_spec, Class* metaobject)
00294 {
00295     if (metaobject == nil)
00296         return inst_spec;
00297     else {
00298         Ptree *class_spec2 = TranslateClassSpec(class_spec);
00299         if (class_spec == class_spec2)
00300             return inst_spec;
00301         else
00302             return class_spec2;
00303     }
00304 }
00305 
00306 Ptree* Walker::TranslateMetaclassDecl(Ptree* decl)
00307 {
00308     env->RecordMetaclassName(decl);
00309     return decl;
00310 }
00311 
00312 Ptree* Walker::TranslateLinkageSpec(Ptree* def)
00313 {
00314     Ptree* body = Ptree::Third(def);
00315     Ptree* body2 = Translate(body);
00316     if(body == body2)
00317         return def;
00318     else
00319         return new PtreeLinkageSpec(Ptree::First(def),
00320                                     Ptree::List(Ptree::Second(def),
00321                                                 body2));
00322 }
00323 
00324 Ptree* Walker::TranslateNamespaceSpec(Ptree* def)
00325 {
00326     Ptree* name = Ptree::Second(def);
00327     Ptree* body = Ptree::Third(def);
00328 
00329     Environment* name_space = env->LookupNamespace0(name);
00330     NewScope(name_space);
00331     Ptree* body2 = Translate(body);
00332     Environment* name_space2 = ExitScope();
00333 
00334     if (name_space == nil)      // if this is the first time
00335         env->RecordNamespace(name_space2, name);
00336 
00337     if(body == body2)
00338         return def;
00339     else
00340         return new PtreeNamespaceSpec(Ptree::First(def),
00341                                       Ptree::List(name, body2));
00342 }
00343 
00344 Ptree* Walker::TranslateUsing(Ptree* def)
00345 {
00346     if (((PtreeUsing*)def)->isNamespace())
00347         env->RecordUsingNamespace(def);
00348     else
00349         env->RecordUsing(def);
00350 
00351     return def;
00352 }
00353 
00354 Ptree* Walker::TranslateDeclaration(Ptree* def)
00355 {
00356     Ptree* decls = Ptree::Third(def);
00357     if(decls->IsA(ntDeclarator))        // if it is a function
00358         return TranslateFunctionImplementation(def);
00359     else{
00360         // if it is a function prototype or a variable declaration.
00361         Ptree* decls2;
00362         Ptree* sspec = Ptree::First(def);
00363         Ptree* sspec2 = TranslateStorageSpecifiers(sspec);
00364         Ptree* tspec = Ptree::Second(def);
00365         Ptree* tspec2 = TranslateTypespecifier(tspec);
00366         if(decls->IsLeaf())     // if it is ";"
00367             decls2 = decls;
00368         else
00369             decls2 = TranslateDeclarators(decls);
00370 
00371         if(sspec == sspec2 && tspec == tspec2 && decls == decls2)
00372             return def;
00373         else if(decls2 == nil)
00374             return new PtreeDeclaration(nil, Ptree::List(nil,
00375                                                          Class::semicolon_t));
00376         else
00377             return new PtreeDeclaration(sspec2,
00378                                         Ptree::ShallowSubst(tspec2, tspec,
00379                                                             decls2, decls,
00380                                                             def->Cdr()));
00381     }
00382 }
00383 
00384 // TranslateStorageSpecifiers() also deals with inline, virtual, etc.
00385 
00386 Ptree* Walker::TranslateStorageSpecifiers(Ptree* spec)
00387 {
00388     return spec;
00389 }
00390 
00391 Ptree* Walker::TranslateDeclarators(Ptree* decls)
00392 {
00393     return TranslateDeclarators(decls, TRUE);
00394 }
00395 
00396 Ptree* Walker::TranslateDeclarators(Ptree* decls, bool record)
00397 {
00398     PtreeArray array;
00399     bool changed = FALSE;
00400     Ptree* rest = decls;
00401     while(rest != nil){
00402         Ptree *p, *q;
00403         int len;
00404         p = q = rest->Car();
00405         if(p->IsA(ntDeclarator)){
00406             Ptree *exp, *exp2;
00407 
00408             if(record)
00409                 env->RecordDeclarator(p);
00410 
00411             len = p->Length();
00412             exp = exp2 = nil;
00413             if(len >= 2 && p->Nth(len - 2)->Eq('=')){
00414                 exp = p->ListTail(len - 2);
00415                 exp2 = TranslateAssignInitializer((PtreeDeclarator*)p, exp);
00416             }
00417             else{
00418                 Ptree* last = p->Last()->Car();
00419                 if(last != nil && !last->IsLeaf() && last->Car()->Eq('(')){
00420                     exp = last;
00421                     exp2 = TranslateInitializeArgs((PtreeDeclarator*)p, last);
00422                 }
00423             }
00424 
00425             q = TranslateDeclarator(FALSE, (PtreeDeclarator*)p);
00426             if(exp != exp2){
00427                 // exp2 should be a list, but...
00428                 if(exp2 != nil && exp2->IsLeaf())
00429                     exp2 = Ptree::List(exp2);
00430 
00431                 if(p == q){
00432                     q = Ptree::SubstSublist(exp2, exp, p->Cdr());
00433                     q = new PtreeDeclarator((PtreeDeclarator*)p, p->Car(), q);
00434                 }
00435                 else if(q != nil && !q->IsLeaf())
00436                     q = new PtreeDeclarator((PtreeDeclarator*)p, q->Car(),
00437                                             Ptree::Subst(exp2, exp, q->Cdr()));
00438             }
00439         }
00440 
00441         if(q == nil){
00442             changed = TRUE;
00443             rest = rest->Cdr();
00444             if(rest != nil)
00445                 rest = rest->Cdr();
00446         }
00447         else{
00448             array.Append(q);
00449             if(p != q)
00450                 changed = TRUE;
00451 
00452             rest = rest->Cdr();
00453             if(rest != nil){
00454                 array.Append(rest->Car());
00455                 rest = rest->Cdr();
00456             }
00457         }
00458     }
00459 
00460     if(changed)
00461         return array.All();
00462     else
00463         return decls;
00464 }
00465 
00466 Ptree* Walker::TranslateDeclarator(bool record, PtreeDeclarator* decl)
00467 {
00468     // if record is true, the formal arguments are recorded in the
00469     // current environment.
00470 
00471     Ptree* args;
00472     if(GetArgDeclList(decl, args)){
00473         Ptree* args2 = TranslateArgDeclList(record, decl, args);
00474         if(args == args2)
00475             return decl;
00476         else
00477             return new PtreeDeclarator(decl, decl->Car(),
00478                                        Ptree::Subst(args2, args,
00479                                                     decl->Cdr()));
00480     }
00481     else
00482         return decl;
00483 }
00484 
00485 bool Walker::GetArgDeclList(PtreeDeclarator* decl, Ptree*& args)
00486 {
00487     Ptree* p = decl;
00488     while(p != nil){
00489         Ptree* q = p->Car();
00490         if(q != nil)
00491             if(q->IsLeaf()){
00492                 if(q->Eq('(')){
00493                     args = p->Cadr();
00494                     return TRUE;
00495                 }
00496             }
00497             else if(q->Car()->Eq('('))  // e.g. int (*p)[];
00498                 p = q->Cadr();
00499 
00500         p = p->Cdr();
00501     }
00502 
00503     args = nil;
00504     return FALSE;
00505 }
00506 
00507 Ptree* Walker::TranslateArgDeclList(bool record, Ptree*, Ptree* args)
00508 {
00509     return TranslateArgDeclList2(record, env, FALSE, FALSE, 0, args);
00510 }
00511 
00512 // If translate is TRUE, this function eliminates a user-defined keyword.
00513 
00514 Ptree* Walker::TranslateArgDeclList2(bool record, Environment* e,
00515                                      bool translate,
00516                                      bool fill_args, int arg_name,
00517                                      Ptree* args)
00518 {
00519     Ptree* rest;
00520     Ptree* rest2;
00521 
00522     if(args == nil)
00523         return args;
00524     else{
00525         Ptree *a, *a2;
00526         a = a2 = args->Car();
00527         if(args->Cdr() == nil)
00528             rest = rest2 = nil;
00529         else{
00530             rest = args->Cddr();        // skip ","
00531             rest2 = TranslateArgDeclList2(record, e, translate, fill_args,
00532                                           arg_name + 1, rest);
00533             if(rest == rest2)
00534                 rest = rest2 = args->Cdr();
00535             else
00536                 rest2 = Ptree::Cons(args->Cadr(), rest2);
00537         }
00538 
00539         bool is_ellipsis = a->IsLeaf();         // a may be "..."
00540         if(is_ellipsis)
00541             /* do nothing */;
00542         else if(a->Car()->IsA(ntUserdefKeyword)){
00543             if(record)
00544                 e->RecordDeclarator(a->Third());
00545 
00546             if(translate){
00547                 a2 = a->Cdr();
00548                 if(fill_args)
00549                     a2 = FillArgumentName(a2, a2->Second(), arg_name);
00550             }
00551         }
00552         else if(a->Car()->IsA(REGISTER)){
00553             if(record)
00554                 e->RecordDeclarator(a->Third());
00555 
00556             if(translate && fill_args){
00557                 a2 = FillArgumentName(a, a->Third(), arg_name);
00558                 if(a != a2)
00559                     a2 = Ptree::Cons(a->First(), a2);
00560             }
00561         }
00562         else{
00563             if(record)
00564                 e->RecordDeclarator(a->Second());
00565 
00566             if(translate && fill_args)
00567                 a2 = FillArgumentName(a, a->Second(), arg_name);
00568         }
00569 
00570         if(a != a2 || rest != rest2)
00571             return Ptree::Cons(a2, rest2);
00572         else
00573             return args;
00574     }
00575 }
00576 
00577 Ptree* Walker::FillArgumentName(Ptree* arg, Ptree* d, int arg_name)
00578 {
00579     PtreeDeclarator* decl = (PtreeDeclarator*)d;
00580     if(decl->Name() != nil)
00581         return arg;
00582     else{
00583         unsigned char* type = (unsigned char*)decl->GetEncodedType();
00584         return Encoding::MakePtree(type,
00585                                    Ptree::Make(argument_name, arg_name));
00586     }
00587 }
00588 
00589 Ptree* Walker::TranslateAssignInitializer(PtreeDeclarator*, Ptree* init)
00590 {
00591     Ptree* exp = init->Second();
00592     Ptree* exp2 = Translate(exp);
00593     if(exp == exp2)
00594         return init;
00595     else
00596         return Ptree::List(init->Car(), exp2);
00597 }
00598 
00599 Ptree* Walker::TranslateInitializeArgs(PtreeDeclarator*, Ptree* init)
00600 {
00601     return TranslateArguments(init);
00602 }
00603 
00604 Ptree* Walker::TranslateFunctionImplementation(Ptree* impl)
00605 {
00606     Ptree* sspec = Ptree::First(impl);
00607     Ptree* sspec2 = TranslateStorageSpecifiers(sspec);
00608     Ptree* tspec = Ptree::Second(impl);
00609     Ptree* decl = Ptree::Third(impl);
00610     Ptree* body = Ptree::Nth(impl, 3);
00611     Ptree* decl2;
00612     Ptree* body2;
00613 
00614     Ptree* tspec2 = TranslateTypespecifier(tspec);
00615     Environment* fenv = env->RecordDeclarator(decl);
00616     if(fenv == nil){
00617         // reach here if resolving the qualified name fails. error?
00618         NewScope();
00619         decl2 = TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00620         body2 = Translate(body);
00621         ExitScope();
00622     }
00623     else{
00624         NameScope old_env = ChangeScope(fenv);
00625         NewScope();
00626         decl2 = TranslateDeclarator(TRUE, (PtreeDeclarator*)decl);
00627         body2 = Translate(body);
00628         ExitScope();
00629         RestoreScope(old_env);
00630     }
00631 
00632     if(sspec == sspec2 && tspec == tspec2 && decl == decl2 && body == body2)
00633         return impl;
00634     else
00635         return new PtreeDeclaration(sspec2,
00636                                     Ptree::List(tspec2, decl2, body2));
00637 }
00638 
00639 Ptree* Walker::RecordArgsAndTranslateFbody(Class*, Ptree* args, Ptree* body)
00640 {
00641     NewScope();
00642     TranslateArgDeclList2(TRUE, env, FALSE, FALSE, 0, args);
00643     Ptree* body2 = TranslateFunctionBody(body);
00644     ExitScope();
00645     return body2;
00646 }
00647 
00648 Ptree* Walker::TranslateFunctionBody(Ptree* body)
00649 {
00650     return Translate(body);
00651 }
00652 
00653 Ptree* Walker::TranslateBrace(Ptree* block)
00654 {
00655     PtreeArray array;
00656     bool changed = FALSE;
00657     Ptree* body = Ptree::Second(block);
00658     Ptree* rest = body;
00659     while(rest != nil){
00660         Ptree* p = rest->Car();
00661         Ptree* q = Translate(p);
00662         array.Append(q);
00663         if(p != q)
00664             changed = TRUE;
00665 
00666         rest = rest->Cdr();
00667     }
00668 
00669     if(changed)
00670         return new PtreeBrace(Ptree::First(block), array.All(),
00671                               Ptree::Third(block));
00672     else
00673         return block;
00674 }
00675 
00676 Ptree* Walker::TranslateBlock(Ptree* block)
00677 {
00678     Ptree* block2;
00679 
00680     NewScope();
00681 
00682     PtreeArray array;
00683     bool changed = FALSE;
00684     Ptree* body = Ptree::Second(block);
00685     Ptree* rest = body;
00686     while(rest != nil){
00687         Ptree* p = rest->Car();
00688         Ptree* q = Translate(p);
00689         array.Append(q);
00690         if(p != q)
00691             changed = TRUE;
00692 
00693         rest = rest->Cdr();
00694     }
00695 
00696     if(changed)
00697         block2 = new PtreeBlock(Ptree::First(block), array.All(),
00698                                 Ptree::Third(block));
00699     else
00700         block2 = block;
00701 
00702     ExitScope();
00703     return block2;
00704 }
00705 
00706 Ptree* Walker::TranslateClassBody(Ptree* block, Ptree* bases,
00707                                   Class* metaobject)
00708 {
00709     Ptree* block2;
00710 
00711     NewScope(metaobject);
00712     RecordBaseclassEnv(bases);
00713 
00714     PtreeArray array;
00715     bool changed = FALSE;
00716     Ptree* body = Ptree::Second(block);
00717     Ptree* rest = body;
00718     while(rest != nil){
00719         Ptree* p = rest->Car();
00720         Ptree* q = Translate(p);
00721         array.Append(q);
00722         if(p != q)
00723             changed = TRUE;
00724 
00725         rest = rest->Cdr();
00726     }
00727 
00728     if(changed)
00729         block2 = new PtreeClassBody(Ptree::First(block), array.All(),
00730                                     Ptree::Third(block));
00731     else
00732         block2 = block;
00733 
00734     ExitScope();
00735     return block2;
00736 }
00737 
00738 Ptree* Walker::TranslateClassSpec(Ptree* spec)
00739 {
00740     Ptree* userkey;
00741     Ptree* class_def;
00742 
00743     if(spec->Car()->IsLeaf()){
00744         userkey = nil;
00745         class_def = spec;
00746     }
00747     else{
00748         userkey = spec->Car();
00749         class_def = spec->Cdr();
00750     }
00751 
00752     Class* metaobject = nil;
00753     if(Ptree::Length(class_def) == 4)
00754         metaobject = MakeClassMetaobject(spec, userkey, class_def);
00755 
00756     env->RecordClassName(spec->GetEncodedName(), metaobject);
00757     return TranslateClassSpec(spec, userkey, class_def, metaobject);
00758 }
00759 
00760 Class* Walker::MakeClassMetaobject(Ptree* def, Ptree* userkey,
00761                                    Ptree* class_def)
00762 {
00763     Class* metaobject = LookupMetaclass(def, userkey, class_def, FALSE);
00764     if(metaobject == nil && default_metaclass != nil){
00765         metaobject = opcxx_ListOfMetaclass::New(default_metaclass, class_def,
00766                                                 nil);
00767         if(metaobject == nil)
00768             MopErrorMessage2("the default metaclass cannot be loaded: ",
00769                              default_metaclass);
00770     }
00771 
00772     if(metaobject == nil)
00773         metaobject = new Class;
00774     else{
00775         if(!metaobject->AcceptTemplate())
00776             return metaobject;
00777         else{
00778             ErrorMessage("the specified metaclass is for templates.",
00779                          nil, def);
00780             metaobject = new Class;
00781         }
00782     }
00783 
00784     metaobject->InitializeInstance(class_def, nil);
00785     return metaobject;
00786 }
00787 
00788 void Walker::ChangeDefaultMetaclass(char* name)
00789 {
00790     default_metaclass = name;
00791 }
00792 
00793 // LookupMetaclass() returns nil if no metaclass is found.
00794 
00795 Class* Walker::LookupMetaclass(Ptree* def, Ptree* userkey, Ptree* class_def,
00796                                bool is_template)
00797 {
00798     Ptree *mclass, *margs;
00799     Class* metaobject;
00800 
00801     Ptree* class_name = class_def->Second();
00802 
00803     // for bootstrapping
00804     if(Metaclass::IsBuiltinMetaclass(class_name)){
00805         metaobject = new Metaclass;
00806         metaobject->InitializeInstance(def, nil);
00807         return metaobject;
00808     }
00809 
00810     Ptree* mdecl = env->LookupMetaclass(class_name);
00811     if(mdecl != nil){
00812         mclass = mdecl->Second();
00813         margs = mdecl->Nth(4);
00814         metaobject = opcxx_ListOfMetaclass::New(mclass, def, margs);
00815         if(metaobject == nil)
00816             ErrorMessage("the metaclass is not loaded: ", mclass, class_def);
00817         else if(userkey != nil)
00818             ErrorMessage("the metaclass declaration conflicts"
00819                          " with the keyword: ", mclass, class_def);
00820 
00821         return metaobject;
00822     }
00823 
00824     if(userkey != nil){
00825         mclass = env->LookupClasskeyword(userkey->Car());
00826         if(mclass == nil)
00827             ErrorMessage("invalid keyword: ", userkey, class_def);
00828         else{
00829             metaobject = opcxx_ListOfMetaclass::New(mclass, class_def,
00830                                                     userkey->Third());
00831             if(metaobject == nil)
00832                 ErrorMessage("the metaclass associated with the"
00833                              " keyword is not loaded: ", userkey, class_def);
00834 
00835             return metaobject;
00836         }
00837     }
00838 
00839     return LookupBaseMetaclass(def, class_def, is_template);
00840 }
00841 
00842 Class* Walker::LookupBaseMetaclass(Ptree* def, Ptree* class_def,
00843                                    bool is_template)
00844 {
00845     Class* metaobject = nil;
00846     Ptree* bases = class_def->Third();
00847     while(bases != nil){
00848         bases = bases->Cdr();
00849         Ptree* base = bases->Car()->Last()->Car();
00850         bases = bases->Cdr();
00851         Class* m = env->LookupClassMetaobject(base);
00852         if(m != nil){
00853             if(metaobject == nil)
00854                 metaobject = m;
00855             else if(m == nil || strcmp(metaobject->MetaclassName(),
00856                                        m->MetaclassName()) != 0){
00857                 ErrorMessage("inherited metaclasses conflict: ",
00858                              class_def->Second(), class_def);
00859                 return nil;
00860             }
00861         }
00862     }
00863 
00864     if(metaobject == nil)
00865         return nil;
00866 
00867     bool accept_template = metaobject->AcceptTemplate();
00868     if((is_template && accept_template) || (!is_template && !accept_template))
00869         return opcxx_ListOfMetaclass::New(metaobject->MetaclassName(),
00870                                           def, nil);
00871     else
00872         return nil;
00873 }
00874 
00875 Ptree* Walker::TranslateClassSpec(Ptree* spec, Ptree*,
00876                                   Ptree* class_def, Class* metaobject)
00877 {
00878     if(metaobject == nil)
00879         return spec;
00880     else{
00881         // a class body is specified.
00882         Ptree* body = class_def->Nth(3);
00883         Ptree* body2 = TranslateClassBody(body, class_def->Third(),
00884                                           metaobject);
00885         if(body == body2)
00886             return spec;
00887         else
00888             return new PtreeClassSpec(spec->Car(),
00889                                       Ptree::ShallowSubst(body2, body,
00890                                                           spec->Cdr()),
00891                                       nil, spec->GetEncodedName());
00892     }
00893 }
00894 
00895 
00896 Ptree* Walker::TranslateEnumSpec(Ptree* spec)
00897 {
00898     env->RecordEnumName(spec);
00899     return spec;
00900 }
00901 
00902 Ptree* Walker::TranslateAccessSpec(Ptree* p)
00903 {
00904     return p;
00905 }
00906 
00907 Ptree* Walker::TranslateAccessDecl(Ptree* p)
00908 {
00909     return p;
00910 }
00911 
00912 Ptree* Walker::TranslateUserAccessSpec(Ptree* p)
00913 {
00914     return p;
00915 }
00916 
00917 Ptree* Walker::TranslateIf(Ptree* s)
00918 {
00919     Ptree* cond = s->Third();
00920     Ptree* cond2 = Translate(cond);
00921     Ptree* then_part = s->Nth(4);
00922     Ptree* then_part2 = Translate(then_part);
00923     Ptree* else_part = s->Nth(6);
00924     Ptree* else_part2 = Translate(else_part);
00925 
00926     if(cond == cond2 && then_part == then_part2 && else_part == else_part2)
00927         return s;
00928     else{
00929         Ptree* rest = Ptree::ShallowSubst(cond2, cond, then_part2, then_part,
00930                                           else_part2, else_part, s->Cdr());
00931         return new PtreeIfStatement(s->Car(), rest);
00932     }
00933 }
00934 
00935 Ptree* Walker::TranslateSwitch(Ptree* s)
00936 {
00937     Ptree* cond = s->Third();
00938     Ptree* cond2 = Translate(cond);
00939     Ptree* body = s->Nth(4);
00940     Ptree* body2 = Translate(body);
00941     if(cond == cond2 && body == body2)
00942         return s;
00943     else{
00944         Ptree* rest = Ptree::ShallowSubst(cond2, cond, body2, body, s->Cdr());
00945         return new PtreeSwitchStatement(s->Car(), rest);
00946     }
00947 }
00948 
00949 Ptree* Walker::TranslateWhile(Ptree* s)
00950 {
00951     Ptree* cond = s->Third();
00952     Ptree* cond2 = Translate(cond);
00953     Ptree* body = s->Nth(4);
00954     Ptree* body2 = Translate(body);
00955     if(cond == cond2 && body == body2)
00956         return s;
00957     else{
00958         Ptree* rest = Ptree::ShallowSubst(cond2, cond, body2, body, s->Cdr());
00959         return new PtreeWhileStatement(s->Car(), rest);
00960     }
00961 }
00962 
00963 Ptree* Walker::TranslateDo(Ptree* s)
00964 {
00965     Ptree* body = s->Second();
00966     Ptree* body2 = Translate(body);
00967     Ptree* cond = s->Nth(4);
00968     Ptree* cond2 = Translate(cond);
00969     if(cond == cond2 && body == body2)
00970         return s;
00971     else{
00972         Ptree* rest = Ptree::ShallowSubst(body2, body, cond2, cond, s->Cdr());
00973         return new PtreeDoStatement(s->Car(), rest);
00974     }
00975 }
00976 
00977 Ptree* Walker::TranslateFor(Ptree* s)
00978 {
00979     NewScope();
00980     Ptree* exp1 = s->Third();
00981     Ptree* exp1t = Translate(exp1);
00982     Ptree* exp2 = s->Nth(3);
00983     Ptree* exp2t = Translate(exp2);
00984     Ptree* exp3 = s->Nth(5);
00985     Ptree* exp3t = Translate(exp3);
00986     Ptree* body = s->Nth(7);
00987     Ptree* body2 = Translate(body);
00988     ExitScope();
00989 
00990     if(exp1 == exp1t && exp2 == exp2t && exp3 == exp3t && body == body2)
00991         return s;
00992     else{
00993         Ptree* rest = Ptree::ShallowSubst(exp1t, exp1, exp2t, exp2,
00994                                           exp3t, exp3, body2, body, s->Cdr());
00995         return new PtreeForStatement(s->Car(), rest);
00996     }
00997 }
00998 
00999 Ptree* Walker::TranslateTry(Ptree* s)
01000 {
01001     Ptree* try_block = s->Second();
01002     Ptree* try_block2 = Translate(try_block);
01003 
01004     PtreeArray array;
01005     Ptree* handlers = s->Cddr();
01006     bool changed = FALSE;
01007 
01008     while(handlers != nil){
01009         Ptree* handle = handlers->Car();
01010         Ptree* body = handle->Nth(4);
01011         Ptree* body2 = Translate(body);
01012         if(body == body2)
01013             array.Append(handle);
01014         else{
01015             array.Append(Ptree::ShallowSubst(body2, body, handle));
01016             changed = TRUE;
01017         }
01018 
01019         handlers = handlers->Cdr();
01020     }
01021 
01022     if(try_block == try_block2 && !changed)
01023         return s;
01024     else
01025         return new PtreeTryStatement(s->Car(),
01026                                      Ptree::Cons(try_block2, array.All()));
01027 }
01028 
01029 Ptree* Walker::TranslateBreak(Ptree* s)
01030 {
01031     return s;
01032 }
01033 
01034 Ptree* Walker::TranslateContinue(Ptree* s)
01035 {
01036     return s;
01037 }
01038 
01039 Ptree* Walker::TranslateReturn(Ptree* s)
01040 {
01041     if(s->Length() == 2)
01042         return s;
01043     else{
01044         Ptree* exp = s->Second();
01045         Ptree* exp2 = Translate(exp);
01046         if(exp == exp2)
01047             return s;
01048         else
01049             return new PtreeReturnStatement(s->Car(),
01050                                             Ptree::ShallowSubst(exp2, exp,
01051                                                                 s->Cdr()));
01052     }
01053 }
01054 
01055 Ptree* Walker::TranslateGoto(Ptree* s)
01056 {
01057     return s;
01058 }
01059 
01060 Ptree* Walker::TranslateCase(Ptree* s)
01061 {
01062     Ptree* st = s->Nth(3);
01063     Ptree* st2 = Translate(st);
01064     if(st == st2)
01065         return s;
01066     else
01067         return new PtreeCaseStatement(s->Car(),
01068                                       Ptree::ShallowSubst(st2, st, s->Cdr()));
01069 }
01070 
01071 Ptree* Walker::TranslateDefault(Ptree* s)
01072 {
01073     Ptree* st = s->Third();
01074     Ptree* st2 = Translate(st);
01075     if(st == st2)
01076         return s;
01077     else
01078         return new PtreeDefaultStatement(s->Car(),
01079                                          Ptree::List(s->Cadr(), st2));
01080 }
01081 
01082 Ptree* Walker::TranslateLabel(Ptree* s)
01083 {
01084     Ptree* st = s->Third();
01085     Ptree* st2 = Translate(st);
01086     if(st == st2)
01087         return s;
01088     else
01089         return new PtreeLabelStatement(s->Car(),
01090                                        Ptree::List(s->Cadr(), st2));
01091 }
01092 
01093 Ptree* Walker::TranslateExprStatement(Ptree* s)
01094 {
01095     Ptree* exp = s->First();
01096     Ptree* exp2 = Translate(exp);
01097     if(exp == exp2)
01098         return s;
01099     else
01100         return new PtreeExprStatement(exp2, s->Cdr());
01101 }
01102 
01103 Ptree* Walker::TranslateTypespecifier(Ptree* tspec)
01104 {
01105     Ptree *class_spec, *class_spec2;
01106 
01107     class_spec = GetClassOrEnumSpec(tspec);
01108     if(class_spec == nil)
01109         class_spec2 = nil;
01110     else
01111         class_spec2 = Translate(class_spec);
01112 
01113     if(class_spec == class_spec2)
01114         return tspec;
01115     else
01116         return Ptree::ShallowSubst(class_spec2, class_spec, tspec);
01117 }
01118 
01119 Ptree* Walker::GetClassOrEnumSpec(Ptree* typespec)
01120 {
01121     Ptree* spec = StripCvFromIntegralType(typespec);
01122     if(spec->IsA(ntClassSpec, ntEnumSpec))
01123         return spec;
01124 
01125     return nil;
01126 }
01127 
01128 Ptree* Walker::GetClassTemplateSpec(Ptree* body)
01129 {
01130     if(Ptree::Eq(Ptree::Third(body), ';')){
01131         Ptree* spec = StripCvFromIntegralType(Ptree::Second(body));
01132         if(spec->IsA(ntClassSpec))
01133             return spec;
01134     }
01135 
01136     return nil;
01137 }
01138 
01139 Ptree* Walker::StripCvFromIntegralType(Ptree* integral)
01140 {
01141     if(integral == nil)
01142         return nil;
01143 
01144     if(!integral->IsLeaf())
01145         if(integral->Car()->IsA(CONST, VOLATILE))
01146             return Ptree::Second(integral);
01147         else if(Ptree::Second(integral)->IsA(CONST, VOLATILE))
01148             return integral->Car();
01149 
01150     return integral;
01151 }
01152 
01153 Ptree* Walker::TranslateComma(Ptree* exp)
01154 {
01155     Ptree* left = exp->First();
01156     Ptree* left2 = Translate(left);
01157     Ptree* right = exp->Third();
01158     Ptree* right2 = Translate(right);
01159     if(left == left2 && right == right2)
01160         return exp;
01161     else
01162         return new PtreeCommaExpr(left2, Ptree::List(exp->Second(), right2));
01163 }
01164 
01165 void Walker::TypeofComma(Ptree* exp, TypeInfo& t)
01166 {
01167     Typeof(exp->Third(), t);
01168 }
01169 
01170 Ptree* Walker::TranslateAssign(Ptree* exp)
01171 {
01172     Ptree* left = exp->First();
01173     Ptree* left2 = Translate(left);
01174     Ptree* right = exp->Third();
01175     Ptree* right2 = Translate(right);
01176     if(left == left2 && right == right2)
01177         return exp;
01178     else
01179         return new PtreeAssignExpr(left2, Ptree::List(exp->Second(), right2));
01180 }
01181 
01182 void Walker::TypeofAssign(Ptree* exp, TypeInfo& t)
01183 {
01184     Typeof(exp->First(), t);
01185 }
01186 
01187 Ptree* Walker::TranslateCond(Ptree* exp)
01188 {
01189     Ptree* c = exp->First();
01190     Ptree* c2 = Translate(c);
01191     Ptree* t = exp->Third();
01192     Ptree* t2 = Translate(t);
01193     Ptree* e = exp->Nth(4);
01194     Ptree* e2 = Translate(e);
01195     if(c == c2 && t == t2 && e == e2)
01196         return exp;
01197     else
01198         return new PtreeCondExpr(c2, Ptree::List(exp->Second(), t2,
01199                                                  exp->Nth(3), e2));
01200 }
01201 
01202 void Walker::TypeofCond(Ptree* exp, TypeInfo& t)
01203 {
01204     Typeof(exp->Third(), t);
01205 }
01206 
01207 Ptree* Walker::TranslateInfix(Ptree* exp)
01208 {
01209     Ptree* left = exp->First();
01210     Ptree* left2 = Translate(left);
01211     Ptree* right = exp->Third();
01212     Ptree* right2 = Translate(right);
01213     if(left == left2 && right == right2)
01214         return exp;
01215     else
01216         return new PtreeInfixExpr(left2, Ptree::List(exp->Second(), right2));
01217 }
01218 
01219 void Walker::TypeofInfix(Ptree* exp, TypeInfo& t)
01220 {
01221     Typeof(exp->First(), t);
01222 }
01223 
01224 Ptree* Walker::TranslatePm(Ptree* exp)
01225 {
01226     Ptree* left = exp->First();
01227     Ptree* left2 = Translate(left);
01228     Ptree* right = exp->Third();
01229     Ptree* right2 = Translate(right);
01230     if(left == left2 && right == right2)
01231         return exp;
01232     else
01233         return new PtreePmExpr(left2, Ptree::List(exp->Second(), right2));
01234 }
01235 
01236 void Walker::TypeofPm(Ptree* exp, TypeInfo& t)
01237 {
01238     Typeof(exp->Third(), t);
01239     t.Dereference();
01240 }
01241 
01242 Ptree* Walker::TranslateCast(Ptree* exp)
01243 {
01244     Ptree* e = exp->Nth(3);
01245     Ptree* e2 = Translate(e);
01246     if(e == e2)
01247         return exp;
01248     else
01249         return new PtreeCastExpr(exp->First(),
01250                                  Ptree::ShallowSubst(e2, e, exp->Cdr()));
01251 }
01252 
01253 void Walker::TypeofCast(Ptree* exp, TypeInfo& t)
01254 {
01255     t.Set(exp->Second()->Second()->GetEncodedType(), env);
01256 }
01257 
01258 Ptree* Walker::TranslateUnary(Ptree* exp)
01259 {
01260     Ptree* oprnd = exp->Second();
01261     Ptree* oprnd2 = Translate(oprnd);
01262     if(oprnd == oprnd2)
01263         return exp;
01264     else
01265         return new PtreeUnaryExpr(exp->First(), Ptree::List(oprnd2));
01266 }
01267 
01268 void Walker::TypeofUnary(Ptree* exp, TypeInfo& t)
01269 {
01270     Typeof(exp->Second(), t);
01271 
01272     Ptree* op = exp->First();
01273     if(op->Eq('*'))
01274         t.Dereference();
01275     else if(op->Eq('&'))
01276         t.Reference();
01277 }
01278 
01279 Ptree* Walker::TranslateThrow(Ptree* exp)
01280 {
01281     Ptree* oprnd = exp->Second();
01282     Ptree* oprnd2 = Translate(oprnd);
01283     if(oprnd == oprnd2)
01284         return exp;
01285     else
01286         return new PtreeThrowExpr(exp->First(), Ptree::List(oprnd2));
01287 }
01288 
01289 void Walker::TypeofThrow(Ptree*, TypeInfo& t)
01290 {
01291     t.SetVoid();
01292 }
01293 
01294 Ptree* Walker::TranslateSizeof(Ptree* exp)
01295 {
01296     Ptree* e = exp->Second();
01297     if(e->Eq('('))
01298         e = exp->Third();
01299 
01300     Ptree* e2 = Translate(e);
01301     if(e == e2)
01302         return exp;
01303     else
01304         return new PtreeSizeofExpr(exp->First(),
01305                                    Ptree::ShallowSubst(e2, e, exp->Cdr()));
01306 }
01307 
01308 void Walker::TypeofSizeof(Ptree*, TypeInfo& t)
01309 {
01310     t.SetInt();
01311 }
01312 
01313 Ptree* Walker::TranslateNew(Ptree* exp)
01314 {
01315     Ptree *p;
01316     Ptree *userkey, *scope, *op, *placement, *type, *init;
01317 
01318     p = exp;
01319     userkey = p->Car();
01320     if(userkey == nil || !userkey->IsLeaf())
01321         p = exp->Cdr();         // user keyword
01322     else
01323         userkey = nil;
01324 
01325     if(p->Car()->Eq("::")){
01326         scope = p->Car();
01327         p = p->Cdr();
01328     }
01329     else
01330         scope = nil;
01331 
01332     op = p->Car();
01333     placement = p->Cadr();
01334     type = p->Third();
01335     init = p->Nth(3);
01336     return TranslateNew2(exp, userkey, scope, op, placement, type, init);
01337 }
01338 
01339 Ptree* Walker::TranslateNew2(Ptree* exp, Ptree*, Ptree*,
01340                              Ptree*, Ptree* placement,
01341                              Ptree* type, Ptree* init)
01342 {
01343     Ptree* placement2 = TranslateArguments(placement);
01344     Ptree* type2 = TranslateNew3(type);
01345     Ptree* init2 = TranslateArguments(init);
01346     if(placement == placement2 && init == init2)
01347         return exp;
01348     else
01349         return new PtreeNewExpr(exp->Car(),
01350                                 Ptree::ShallowSubst(placement2, placement,
01351                                                     type2, type,
01352                                                     init2, init,
01353                                                     exp->Cdr()));
01354 }
01355 
01356 Ptree* Walker::TranslateNew3(Ptree* type)
01357 {
01358     Ptree* p = type;
01359     if(p->Car()->Eq('('))
01360         p = p->Second();
01361 
01362     Ptree* decl = p->Second();
01363     Ptree* decl2 = TranslateNewDeclarator(decl);
01364     if(decl == decl2)
01365         return type;
01366     else
01367         return Ptree::Subst(decl2, decl, type);
01368 }
01369 
01370 void Walker::TypeofNew(Ptree* exp, TypeInfo& t)
01371 {
01372     Ptree *p, *userkey, *type;
01373 
01374     p = exp;
01375     userkey = p->Car();
01376     if(userkey == nil || !userkey->IsLeaf())
01377         p = exp->Cdr();         // user keyword
01378 
01379     if(p->Car()->Eq("::"))
01380         p = p->Cdr();
01381 
01382     type = p->Third();
01383 
01384     if(type->Car()->Eq('('))
01385         t.Set(type->Second()->Second()->GetEncodedType(), env);
01386     else
01387         t.Set(type->Second()->GetEncodedType(), env);
01388 
01389     t.Reference();
01390 }
01391 
01392 Ptree* Walker::TranslateDelete(Ptree* exp)
01393 {
01394     Ptree* obj = Ptree::Last(exp)->Car();
01395     Ptree* obj2 = Translate(obj);
01396     if(obj == obj2)
01397         return exp;
01398     else
01399         return new PtreeDeleteExpr(exp->Car(),
01400                                    Ptree::ShallowSubst(obj2, obj,
01401                                                        exp->Cdr()));
01402 }
01403 
01404 void Walker::TypeofDelete(Ptree*, TypeInfo& t)
01405 {
01406     t.SetVoid();
01407 }
01408 
01409 Ptree* Walker::TranslateThis(Ptree* exp)
01410 {
01411     return exp;
01412 }
01413 
01414 void Walker::TypeofThis(Ptree*, TypeInfo& t)
01415 {
01416     t.Set(env->LookupThis());
01417 }
01418 
01419 Ptree* Walker::TranslateVariable(Ptree* exp)
01420 {
01421     return exp;
01422 }
01423 
01424 /*
01425   This may be a class name if the expression is a function-style cast.
01426 */
01427 void Walker::TypeofVariable(Ptree* exp, TypeInfo& t)
01428 {
01429     bool is_type_name;
01430 
01431     if(env->Lookup(exp, is_type_name, t))
01432         if(is_type_name)        // if exp is a class name
01433             t.Reference();      // see TypeofFuncall
01434 }
01435 
01436 /*
01437   TranslateFstyleCast() deals with function-style casts
01438   to an integral type
01439 */
01440 Ptree* Walker::TranslateFstyleCast(Ptree* exp)
01441 {
01442     Ptree* args = exp->Cdr();
01443     Ptree* args2 = TranslateArguments(args);
01444     if(args == args2)
01445         return exp;
01446     else
01447         return new PtreeFstyleCastExpr(exp->GetEncodedType(), exp->Car(),
01448                                        args2);
01449 }
01450 
01451 void Walker::TypeofFstyleCast(Ptree* exp, TypeInfo& t)
01452 {
01453     t.Set(exp->GetEncodedType(), env);
01454 }
01455 
01456 Ptree* Walker::TranslateArray(Ptree* exp)
01457 {
01458     Ptree* array = exp->Car();
01459     Ptree* array2 = Translate(array);
01460     Ptree* index = exp->Third();
01461     Ptree* index2 = Translate(index);
01462     if(array == array2 && index == index2)
01463         return exp;
01464     else
01465         return new PtreeArrayExpr(array2, Ptree::Subst(index2, index,
01466                                                        exp->Cdr()));
01467 }
01468 
01469 void Walker::TypeofArray(Ptree* exp, TypeInfo& t)
01470 {
01471     Typeof(exp->Car(), t);
01472     t.Dereference();
01473 }
01474 
01475 /*
01476   TranslateFuncall() also deals with function-style casts to a class.
01477 */
01478 Ptree* Walker::TranslateFuncall(Ptree* exp)
01479 {
01480     Ptree* fun = exp->Car();
01481     Ptree* fun2 = Translate(fun);
01482     Ptree* args = exp->Cdr();
01483     Ptree* args2 = TranslateArguments(args);
01484     if(fun == fun2 && args == args2)
01485         return exp;
01486     else
01487         return new PtreeFuncallExpr(fun2, args2);
01488 }
01489 
01490 void Walker::TypeofFuncall(Ptree* exp, TypeInfo& t)
01491 {
01492     Typeof(exp->Car(), t);
01493     if(!t.IsFunction())
01494         t.Dereference();        // maybe a pointer to a function
01495 
01496     t.Dereference();
01497 }
01498 
01499 Ptree* Walker::TranslatePostfix(Ptree* exp)
01500 {
01501     Ptree* left = exp->Car();
01502     Ptree* left2 = Translate(left);
01503     if(left == left2)
01504         return exp;
01505     else
01506         return new PtreePostfixExpr(left2, exp->Cdr());
01507 }
01508 
01509 void Walker::TypeofPostfix(Ptree* exp, TypeInfo& t)
01510 {
01511     Typeof(exp->Car(), t);
01512 }
01513 
01514 Ptree* Walker::TranslateUserStatement(Ptree* exp)
01515 {
01516     return exp;
01517 }
01518 
01519 void Walker::TypeofUserStatement(Ptree*, TypeInfo& t)
01520 {
01521     t.Unknown();
01522 }
01523 
01524 Ptree* Walker::TranslateDotMember(Ptree* exp)
01525 {
01526     Ptree* left = exp->Car();
01527     Ptree* left2 = Translate(left);
01528     if(left == left2)
01529         return exp;
01530     else
01531         return new PtreeDotMemberExpr(left2, exp->Cdr());
01532 }
01533 
01534 void Walker::TypeofDotMember(Ptree* exp, TypeInfo& t)
01535 {
01536     Typeof(exp->Car(), t);
01537     t.SetMember(exp->Third());
01538 }
01539 
01540 Ptree* Walker::TranslateArrowMember(Ptree* exp)
01541 {
01542     Ptree* left = exp->Car();
01543     Ptree* left2 = Translate(left);
01544     if(left == left2)
01545         return exp;
01546     else
01547         return new PtreeArrowMemberExpr(left2, exp->Cdr());
01548 }
01549 
01550 void Walker::TypeofArrowMember(Ptree* exp, TypeInfo& t)
01551 {
01552     Typeof(exp->Car(), t);
01553     t.Dereference();
01554     t.SetMember(exp->Third());
01555 }
01556 
01557 Ptree* Walker::TranslateParen(Ptree* exp)
01558 {
01559     Ptree* e = exp->Second();
01560     Ptree* e2 = Translate(e);
01561     if(e == e2)
01562         return exp;
01563     else
01564         return new PtreeParenExpr(exp->Car(), Ptree::List(e2, exp->Third()));
01565 }
01566 
01567 void Walker::TypeofParen(Ptree* exp, TypeInfo& t)
01568 {
01569     Typeof(exp->Second(), t);
01570 }
01571 
01572 Ptree* Walker::TranslateStaticUserStatement(Ptree* exp)
01573 {
01574     return exp;
01575 }
01576 
01577 void Walker::TypeofStaticUserStatement(Ptree*, TypeInfo& t)
01578 {
01579     t.Unknown();
01580 }
01581 
01582 Ptree* Walker::TranslateNewDeclarator(Ptree* decl)
01583 {
01584     Ptree* decl2 = decl;
01585     Ptree* p = decl;
01586     while(p != nil){
01587         Ptree* head = p->Car();
01588         if(head == nil)
01589             return decl;
01590         else if(head->Eq('[')){
01591             Ptree* p2 = TranslateNewDeclarator2(p);
01592             if(p == p2)
01593                 return decl;
01594             else{
01595                 decl2 = Ptree::ShallowSubst(p2, p, decl);
01596                 break;
01597             }
01598         }
01599         else if(!head->IsLeaf() && head->Car()->Eq('(')){
01600             Ptree* d = head->Cadr();
01601             Ptree* d2 = TranslateNewDeclarator(d);
01602             decl2 = Ptree::ShallowSubst(d2, d, decl);
01603             break;
01604         }
01605 
01606         p = p->Cdr();
01607     }
01608 
01609     if(p == nil)
01610         return decl;
01611     else if(decl->IsA(ntDeclarator))
01612         return new PtreeDeclarator((PtreeDeclarator*)decl,
01613                                    decl2->Car(), decl2->Cdr());
01614     else
01615         return decl2;
01616 }
01617 
01618 Ptree* Walker::TranslateNewDeclarator2(Ptree* decl)
01619 {
01620     for(Ptree* p = decl; p != nil; p = p->Cdr()){
01621         Ptree* head = p->Car();
01622         if(head->Eq('[')){
01623             Ptree* size = p->Cadr();
01624             Ptree* size2 = Translate(size);
01625             if(size != size2){
01626                 Ptree* q = TranslateNewDeclarator2(Ptree::ListTail(p, 3));
01627                 return Ptree::Nconc(Ptree::List(p->Car(), size2, p->Third()),
01628                                     q);
01629             }
01630         }
01631         else if(head->Eq('('))
01632             break;
01633     }
01634 
01635     return decl;
01636 }
01637 
01638 Ptree* Walker::TranslateArguments(Ptree* arglist)
01639 {
01640     if(arglist == nil)
01641         return arglist;
01642 
01643     PtreeArray array;
01644     bool changed = FALSE;
01645     Ptree* body = Ptree::Second(arglist);
01646     Ptree* args = body;
01647     while(args != nil){
01648         Ptree* p = args->Car();
01649         Ptree* q = Translate(p);
01650         array.Append(q);
01651         if(p != q)
01652             changed = TRUE;
01653 
01654         args = args->Cdr();
01655         if(args != nil){
01656             array.Append(args->Car());
01657             args = args->Cdr();
01658         }
01659     }
01660 
01661     if(changed)
01662         return Ptree::ShallowSubst(array.All(), body, arglist);
01663     else
01664         return arglist;
01665 }
01666 
01667 void Walker::SetDeclaratorComments(Ptree* def, Ptree* comments)
01668 {
01669     if (def == nil || !def->IsA(ntDeclaration))
01670         return;
01671 
01672     Ptree* decl;
01673     int n = 0;
01674     for (;;) {
01675         int i = n++;
01676         decl = NthDeclarator(def, i);
01677         if (decl == nil)
01678             break;
01679         else if (decl->IsA(ntDeclarator))
01680             ((PtreeDeclarator*)decl)->SetComments(comments);
01681     }
01682 }
01683 
01684 Ptree* Walker::NthDeclarator(Ptree* def, int& nth)
01685 {
01686     Ptree* decls = def->Third();
01687     if(decls == nil || decls->IsLeaf())
01688         return nil;
01689 
01690     if(decls->IsA(ntDeclarator)){       // if it is a function
01691         if(nth-- == 0)
01692             return decls;
01693     }
01694     else
01695         while(decls != nil && !decls->IsLeaf()){
01696             if(nth-- == 0)
01697                 return decls->Car();
01698 
01699             if((decls = decls->Cdr()) != nil)
01700                 decls = decls->Cdr();           // skip ,
01701         }
01702 
01703     return nil;
01704 }
01705 
01706 Ptree* Walker::FindDeclarator(Ptree* def, char* name, int len,
01707                               char* signature, int& nth, Environment* e)
01708 {
01709     Ptree* decls = def->Third();
01710     if(decls == nil || decls->IsLeaf())
01711         return nil;
01712 
01713     if(decls->IsA(ntDeclarator)){       // if it is a function
01714         if(MatchedDeclarator(decls, name, len, signature, e))
01715             return decls;
01716 
01717         ++nth;
01718     }
01719     else
01720         while(decls != nil){
01721             Ptree* d = decls->Car();
01722             if(MatchedDeclarator(d, name, len, signature, e))
01723                 return d;
01724 
01725             ++nth;
01726             if((decls = decls->Cdr()) != nil)
01727                 decls = decls->Cdr();           // skip ,
01728         }
01729 
01730     return nil;
01731 }
01732 
01733 bool Walker::MatchedDeclarator(Ptree* decl, char* name, int len,
01734                                char* signature, Environment* e)
01735 {
01736     char* str;
01737     int strlen;
01738     char* sig;
01739 
01740     str = decl->GetEncodedName();
01741     sig = decl->GetEncodedType();
01742     if(str == nil || sig == nil)
01743         return FALSE;
01744 
01745     str = Encoding::GetBaseName(str, strlen, e);
01746     return bool(len == strlen && memcmp(name, str, len) == 0
01747                 && strcmp(signature, sig) == 0);
01748 }
01749 
01750 bool Walker::WhichDeclarator(Ptree* def, Ptree* name, int& nth,
01751                              Environment* env)
01752 {
01753     char* str;
01754     int len;
01755     Environment* e;
01756     Ptree* decls = def->Third();
01757     if(decls == nil || decls->IsLeaf())
01758         return FALSE;
01759 
01760     if(decls->IsA(ntDeclarator)){       // if it is a function
01761         str = decls->GetEncodedName();
01762         e = env;
01763         str = Encoding::GetBaseName(str, len, e);
01764         if(name->Eq(str, len))
01765             return TRUE;
01766 
01767         ++nth;
01768     }
01769     else
01770         while(decls != nil){
01771             str = decls->Car()->GetEncodedName();
01772             e = env;
01773             str = Encoding::GetBaseName(str, len, e);
01774             if(name->Eq(str, len))
01775                 return TRUE;
01776 
01777             ++nth;
01778             if((decls = decls->Cdr()) != nil)
01779                 decls = decls->Cdr();
01780         }
01781 
01782     return FALSE;
01783 }
01784 
01785 void Walker::ErrorMessage(char* msg, Ptree* name, Ptree* where)
01786 {
01787     parser->ErrorMessage(msg, name, where);
01788 }
01789 
01790 void Walker::WarningMessage(char* msg, Ptree* name, Ptree* where)
01791 {
01792     parser->WarningMessage(msg, name, where);
01793 }
01794 
01795 // InaccurateErrorMessage() may report a wrong line number.
01796 
01797 void Walker::InaccurateErrorMessage(char* msg, Ptree* name, Ptree* where)
01798 {
01799     if(default_parser == nil)
01800         MopErrorMessage("Walker::InaccurateErrorMessage()",
01801                         "no default parser");
01802     else
01803         default_parser->ErrorMessage(msg, name, where);
01804 }
01805 
01806 void Walker::InaccurateWarningMessage(char* msg, Ptree* name, Ptree* where)
01807 {
01808     if(default_parser == nil)
01809         MopErrorMessage("Walker::InaccurateWarningMessage()",
01810                         "no default parser");
01811     else
01812         default_parser->WarningMessage(msg, name, where);
01813 }

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