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

env.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 <iostream.h>
00016 #include <string.h>
00017 #include "env.h"
00018 #include "hash.h"
00019 #include "ptree-core.h"
00020 #include "ptree.h"
00021 #include "token.h"
00022 #include "encoding.h"
00023 #include "walker.h"
00024 #include "typeinfo.h"
00025 #include "mop.h"
00026 #include "parse.h"
00027 
00028 // class Environment
00029 
00030 PtreeArray* Environment::classkeywords = nil;
00031 
00032 Environment::Environment(Walker* w)
00033 : baseclasses_or_using(0), namespaces(0)
00034 {
00035     htable = new BigHashTable;          // base environment
00036     next = nil;
00037     metaobject = nil;
00038     walker = w;
00039     namespace_name = nil;
00040 }
00041 
00042 Environment::Environment(Environment* e)
00043 : baseclasses_or_using(0), namespaces(0)
00044 {
00045     htable = new HashTable;
00046     next = e;
00047     metaobject = nil;
00048     walker = e->walker;
00049     namespace_name = nil;
00050 }
00051 
00052 Environment::Environment(Environment* e, Walker* w)
00053 : baseclasses_or_using(0), namespaces(0)
00054 {
00055     htable = new HashTable;
00056     next = e;
00057     metaobject = nil;
00058     walker = w;
00059     namespace_name = nil;
00060 }
00061 
00062 bool Environment::IsEmpty()
00063 {
00064     return bool(htable->IsEmpty());
00065 }
00066 
00067 Environment* Environment::GetBottom()
00068 {
00069     Environment* p;
00070     for(p = this; p->next != nil; p = p->next)
00071         ;
00072 
00073     return p;
00074 }
00075 
00076 Class* Environment::LookupClassMetaobject(Ptree* name)
00077 {
00078     TypeInfo tinfo;
00079     Bind* bind = nil;
00080 
00081     if(this == nil){
00082         MopErrorMessage("Environment::LookupClassMetaobject()",
00083                         "nil enviornment");
00084         return nil;
00085     }
00086 
00087     if(name == nil)
00088         return nil;
00089     else if(name->IsLeaf()){
00090         if(LookupType(name->GetPosition(), name->GetLength(), bind))
00091             if(bind != nil){
00092                 bind->GetType(tinfo, this);
00093                 return tinfo.ClassMetaobject();
00094             }
00095 
00096         return nil;
00097     }
00098     else{
00099         int len;
00100         Environment* e = this;
00101         char* base = Encoding::GetBaseName(name->GetEncodedName(), len, e);
00102         if(base != nil && e != nil)
00103             if(LookupType(base, len, bind))
00104                 if(bind != nil){
00105                     bind->GetType(tinfo, this);
00106                     return tinfo.ClassMetaobject();
00107                 }
00108 
00109         return nil;
00110     }
00111 }
00112 
00113 bool Environment::LookupType(const char* name, int len, Bind*& t)
00114 {
00115     Environment* p;
00116 
00117     for(p = this; p != nil; p = p->next){
00118         int count = 0;
00119         while(p->htable->LookupEntries((char*)name, len, (HashValue*)&t,
00120                                        count))
00121             if(t != nil)
00122                 switch(t->What()){
00123                 case Bind::isVarName :
00124                 case Bind::isTemplateFunction :
00125                     break;
00126                 default :
00127                     return TRUE;
00128                 }
00129 
00130         if (SearchBaseOrUsing(p, &Environment::LookupType, name, len, t))
00131             return TRUE;
00132     }
00133 
00134     return FALSE;
00135 }
00136 
00137 bool Environment::SearchBaseOrUsing(Environment* this_env,
00138                         bool (Environment::*func)(const char*, int, Bind*&),
00139                         const char* name, int len, Bind*& t)
00140 {
00141     uint n = this_env->baseclasses_or_using.Number();
00142     for(uint i = 0; i < n; ++i) {
00143         Environment* e = this_env->baseclasses_or_using.Ref(i);
00144         Environment* e0 = e->next;
00145         e->next = nil;
00146         bool result = (e->*func)(name, len, t);
00147         e->next = e0;
00148         if (result)
00149             return TRUE;
00150     }
00151 
00152     return FALSE;
00153 }
00154 
00155 bool Environment::Lookup(Ptree* name, TypeInfo& t)
00156 {
00157     Bind* bind;
00158 
00159     if(Lookup(name, bind) && bind != nil){
00160         bind->GetType(t, this);
00161         return TRUE;
00162     }
00163     else{
00164         t.Unknown();
00165         return FALSE;
00166     }
00167 }
00168 
00169 bool Environment::Lookup(Ptree* name, bool& is_type_name, TypeInfo& t)
00170 {
00171     Bind* bind;
00172 
00173     if(Lookup(name, bind) && bind != nil){
00174         is_type_name = bind->IsType();
00175         bind->GetType(t, this);
00176         return TRUE;
00177     }
00178     else{
00179         t.Unknown();
00180         return FALSE;
00181     }
00182 }
00183 
00184 bool Environment::Lookup(Ptree* name, Bind*& bind)
00185 {
00186     bind = nil;
00187     if(this == nil){
00188         MopErrorMessage("Environment::Lookup()", "nil enviornment");
00189         return FALSE;
00190     }
00191 
00192     if(name == nil)
00193         return FALSE;
00194     else if(name->IsLeaf())
00195         return LookupAll(name->GetPosition(), name->GetLength(), bind);
00196     else{
00197         char* encode = name->GetEncodedName();
00198         if(encode == nil)
00199             return FALSE;
00200         else{
00201             int len;
00202             Environment* e = this;
00203             char* base = Encoding::GetBaseName(encode, len, e);
00204             if(base != nil && e != nil)
00205                 return e->LookupAll(base, len, bind);
00206             else
00207                 return FALSE;
00208         }
00209     }
00210 }
00211 
00212 bool Environment::LookupTop(Ptree* name, Bind*& bind)
00213 {
00214     bind = nil;
00215     if(this == nil){
00216         MopErrorMessage("Environment::LookupTop()", "nil enviornment");
00217         return FALSE;
00218     }
00219 
00220     if(name == nil)
00221         return FALSE;
00222     else if(name->IsLeaf())
00223         return LookupTop(name->GetPosition(), name->GetLength(), bind);
00224     else{
00225         char* encode = name->GetEncodedName();
00226         if(encode == nil)
00227             return FALSE;
00228         else{
00229             int len;
00230             Environment* e = this;
00231             char* base = Encoding::GetBaseName(encode, len, e);
00232             if(base != nil && e != nil)
00233                 return e->LookupTop(base, len, bind);
00234             else
00235                 return FALSE;
00236         }
00237     }
00238 }
00239 
00240 /* Search only this environment.
00241  */
00242 bool Environment::LookupTop(const char* name, int len, Bind*& t)
00243 {
00244     if(htable->Lookup((char*)name, len, (HashValue*)&t))
00245         return TRUE;
00246     else
00247         return SearchBaseOrUsing(this, &Environment::LookupTop, name, len, t);
00248 }
00249 
00250 /* Search all environments.
00251  */
00252 bool Environment::LookupAll(const char* name, int len, Bind*& t)
00253 {
00254     Environment* p;
00255 
00256     for(p = this; p != nil; p = p->next)
00257         if(p->htable->Lookup((char*)name, len, (HashValue*)&t))
00258             return TRUE;
00259         else
00260             if (SearchBaseOrUsing(p, &Environment::LookupAll, name, len, t))
00261                 return TRUE;
00262 
00263     return FALSE;
00264 }
00265 
00266 bool Environment::RecordVariable(char* name, Class* c)
00267 {
00268     Encoding encode;
00269     encode.SimpleName(c->Name());
00270     return htable->AddEntry(name, new BindVarName(encode.Get())) >= 0;
00271 }
00272 
00273 bool Environment::RecordPointerVariable(char* name, Class* c)
00274 {
00275     Encoding encode;
00276     encode.SimpleName(c->Name());
00277     encode.PtrOperator('*');
00278     return htable->AddEntry(name, new BindVarName(encode.Get())) >= 0;
00279 }
00280 
00281 int Environment::AddEntry(char* key, int len, Bind* b) {
00282     return htable->AddEntry(key, len, b);
00283 }
00284 
00285 int Environment::AddDupEntry(char* key, int len, Bind* b) {
00286     return htable->AddDupEntry(key, len, b);
00287 }
00288 
00289 void Environment::RecordNamespace(Environment* name_space, Ptree* name)
00290 {
00291     if (name_space != nil) {
00292         name_space->namespace_name = name;
00293         namespaces.Append(name_space);
00294     }
00295 }
00296 
00297 Environment* Environment::LookupNamespace(const char* name, int len)
00298 {
00299     Environment* e = this;
00300     while (e != nil) {
00301         Environment* ns = e->LookupNamespace0(name, len);
00302         if (ns != nil)
00303             return ns;
00304 
00305         uint n = e->baseclasses_or_using.Number();
00306         for(uint i = 0; i < n; ++i) {
00307             Environment* p = e->baseclasses_or_using.Ref(i);
00308             Environment* p0 = p->next;
00309             p->next = nil;
00310             ns = p->LookupNamespace(name, len);
00311             p->next = p0;
00312             if (ns != nil)
00313                 return ns;
00314         }
00315 
00316         e = e->next;
00317     }
00318 
00319     return nil;
00320 }
00321 
00322 Environment* Environment::LookupNamespace0(Ptree* name)
00323 {
00324     if (name == nil)
00325         return LookupNamespace0(nil, 0);
00326     else
00327         return LookupNamespace0(name->GetPosition(), name->GetLength());
00328 }
00329 
00330 Environment* Environment::LookupNamespace0(const char* name, int len)
00331 {
00332     int n = namespaces.Number();
00333     for (int i = 0; i < n; ++i) {
00334         Environment* ns = namespaces.Ref(i);
00335         Ptree* n = ns->namespace_name;
00336         if (name == nil) {
00337             if (n == nil)
00338                 return ns;
00339         }
00340         else if (n != nil && n->Eq(name, len))
00341             return ns;
00342     }
00343 
00344     return nil;
00345 }
00346 
00347 void Environment::RecordUsing(Ptree* name)
00348 {
00349     char* encode = name->GetEncodedName();
00350     if(encode == nil)
00351         return;
00352 
00353     int len;
00354     Environment* e = this;
00355     char* base = Encoding::GetBaseName(encode, len, e);
00356     if(base == nil || e == nil)
00357         return;
00358 
00359     Bind* bind;
00360     if (!e->LookupAll(base, len, bind))
00361         return;
00362 
00363     htable->AddEntry(base, len, bind);
00364 }
00365 
00366 void Environment::RecordUsingNamespace(Ptree* name)
00367 {
00368     char* encode = name->GetEncodedName();
00369     if(encode == nil)
00370         return;
00371 
00372     int len;
00373     Environment* e = this;
00374     char* base = Encoding::GetBaseName(encode, len, e);
00375     if(base == nil || e == nil)
00376         return;
00377 
00378     Environment* ns = e->LookupNamespace(base, len);
00379     if (ns != nil && !IsClassEnvironment())
00380         AddBaseclassEnv(ns);
00381 }
00382 
00383 void Environment::RecordTypedefName(Ptree* decls)
00384 {
00385     while(decls != nil){
00386         Ptree* d = decls->Car();
00387         if(d->What() == ntDeclarator){
00388             char* name = d->GetEncodedName();
00389             char* type = d->GetEncodedType();
00390             if(name != nil && type != nil){
00391                 int len;
00392                 Environment* e = this;
00393                 name = Encoding::GetBaseName(name, len, e);
00394                 if(name != nil)
00395                     AddEntry(name, len, new BindTypedefName(type));
00396             }
00397         }
00398 
00399         decls = Ptree::ListTail(decls, 2);
00400     }
00401 }
00402 
00403 void Environment::RecordEnumName(Ptree* spec)
00404 {
00405     Ptree* tag = Ptree::Second(spec);
00406     char* encoded_name = spec->GetEncodedName();
00407     if(tag != nil && tag->IsLeaf())
00408         AddEntry(tag->GetPosition(), tag->GetLength(),
00409                  new BindEnumName(encoded_name, spec));
00410     else{
00411         int n;
00412         Environment* e = this;
00413         char* name = Encoding::GetBaseName(encoded_name, n, e);
00414         if(name != nil && e != nil)
00415             e->AddEntry(name, n, new BindEnumName(encoded_name, spec));
00416     }
00417 }
00418 
00419 void Environment::RecordClassName(char* encoded_name, Class* metaobject)
00420 {
00421     int n;
00422     Environment* e;
00423     Bind* bind;
00424 
00425     e = this;
00426     char* name = Encoding::GetBaseName(encoded_name, n, e);
00427     if(name == nil || e == nil)
00428         return;         // error?
00429 
00430     if(e->LookupAll(name, n, bind))
00431         if(bind != nil && bind->What() == Bind::isClassName){
00432             if(metaobject != nil)
00433                 bind->SetClassMetaobject(metaobject);
00434 
00435             return;
00436         }
00437 
00438     e->AddEntry(name, n, new BindClassName(metaobject));
00439 }
00440 
00441 void Environment::RecordTemplateClass(Ptree* spec, Class* metaobject)
00442 {
00443     int n;
00444     Environment* e;
00445     Bind* bind;
00446 
00447     e = this;
00448     char* name = Encoding::GetBaseName(spec->GetEncodedName(), n, e);
00449     if(name == nil || e == nil)
00450         return;         // error?
00451 
00452     if(e->LookupAll(name, n, bind))
00453         if(bind != nil && bind->What() == Bind::isTemplateClass){
00454             if(metaobject != nil)
00455                 bind->SetClassMetaobject(metaobject);
00456 
00457             return;
00458         }
00459 
00460     e->AddEntry(name, n, new BindTemplateClass(metaobject));
00461 }
00462 
00463 Environment* Environment::RecordTemplateFunction(Ptree* def, Ptree* body)
00464 {
00465     int n;
00466     Ptree* decl = Ptree::Third(body);
00467     if(decl->IsA(ntDeclarator)){
00468         char* name = decl->GetEncodedName();
00469         if(name != nil){
00470             Environment* e = this;
00471             name = Encoding::GetBaseName(name, n, e);
00472             if(name != nil && e != nil)
00473                 e->AddEntry(name, n, new BindTemplateFunction(def));
00474 
00475             return e;
00476         }
00477     }
00478 
00479     return this;
00480 }
00481 
00482 Environment* Environment::RecordDeclarator(Ptree* decl)
00483 {
00484     if(decl->What() == ntDeclarator){
00485         char* name = decl->GetEncodedName();
00486         char* type = decl->GetEncodedType();
00487         if(name != nil && type != nil){
00488             int len;
00489             Environment* e = this;
00490             name = Encoding::GetBaseName(name, len, e);
00491 
00492             // allow a duplicated entry because of overloaded functions
00493             if(name != nil && e != nil)
00494                 e->AddDupEntry(name, len, new BindVarName(type));
00495 
00496             return e;
00497         }
00498     }
00499 
00500     return this;
00501 }
00502 
00503 Environment* Environment::DontRecordDeclarator(Ptree* decl)
00504 {
00505     if(decl->What() == ntDeclarator){
00506         char* name = decl->GetEncodedName();
00507         if(name != nil){
00508             int len;
00509             Environment* e = this;
00510             Encoding::GetBaseName(name, len, e);
00511             return e;
00512         }
00513     }
00514 
00515     return this;
00516 }
00517 
00518 void Environment::RecordMetaclassName(Ptree* decl)
00519 {
00520     if(decl->Third() != nil)
00521         metaclasses.Append(decl);
00522 }
00523 
00524 Ptree* Environment::LookupMetaclass(Ptree* name)
00525 {
00526     uint n = metaclasses.Number();
00527     for(uint i = 0; i < n; ++i){
00528         Ptree* d = metaclasses[i];
00529         if(d->Third()->Eq(name))
00530             return d;
00531     }
00532 
00533     return nil;
00534 }
00535 
00536 bool Environment::RecordClasskeyword(char* keyword, char* metaclass_name)
00537 {
00538     Ptree* keywordp = new Leaf(keyword, strlen(keyword));
00539     Ptree* metaclassp = new Leaf(metaclass_name, strlen(metaclass_name));
00540 
00541     if(LookupClasskeyword(keywordp) == nil){
00542         classkeywords->Append(keywordp);
00543         classkeywords->Append(metaclassp);
00544         return TRUE;
00545     }
00546     else
00547         return FALSE;
00548 }
00549 
00550 Ptree* Environment::LookupClasskeyword(Ptree* keyword)
00551 {
00552     if(classkeywords == nil)
00553         classkeywords = new PtreeArray;
00554 
00555     uint n = classkeywords->Number();
00556     for(uint i = 0; i < n; i += 2){
00557         Ptree* d = classkeywords->Ref(i);
00558         if(d->Eq(keyword))
00559             return classkeywords->Ref(i + 1);
00560     }
00561 
00562     return nil;
00563 }
00564 
00565 Class* Environment::LookupThis()
00566 {
00567     Environment* p;
00568     for(p = this; p != nil; p = p->next)
00569         if(p->metaobject != nil)
00570             return p->metaobject;
00571 
00572     return nil;
00573 }
00574 
00575 // IsMember() returns the class environment that the member belongs to.
00576 // If the member is not valid, IsMember() returns nil.
00577 
00578 Environment* Environment::IsMember(Ptree* member)
00579 {
00580     Bind* bind;
00581     Environment* e;
00582 
00583     if(!member->IsLeaf()){
00584         char* encode = member->GetEncodedName();
00585         if(encode != nil){
00586             int len;
00587             e = this;
00588             char* base = Encoding::GetBaseName(encode, len, e);
00589             if(base != nil && e != nil && e->metaobject != nil)
00590                 return e;
00591         }
00592     }
00593 
00594     for(e = this; e != nil; e = e->next)
00595         if(e->metaobject != nil)
00596             break;
00597         else if(e->LookupTop(member, bind))
00598             if(bind != nil && !bind->IsType())
00599                 return nil;     // the member is overridden.
00600 
00601     if(e != nil && e->LookupTop(member, bind))
00602        if(bind != nil && !bind->IsType())
00603            return e;
00604 
00605     return nil;
00606 }
00607 
00608 void Environment::Dump()
00609 {
00610     htable->Dump(cerr);
00611     cerr << '\n';
00612 }
00613 
00614 void Environment::Dump(int level)
00615 {
00616     Environment* e = this;
00617     while(level-- > 0)
00618         if(e->next != nil)
00619             e = e->next;
00620         else{
00621             cerr << "Environment::Dump(): the bottom is reached.\n";
00622             return;
00623         }
00624 
00625     e->Dump();
00626 }
00627 
00628 Ptree* Environment::GetLineNumber(Ptree* p, int& number)
00629 {
00630     if (walker == nil) {
00631         number = 0;
00632         return nil;
00633     }
00634 
00635     char* fname;
00636     int fname_len;
00637     number = (int)walker->GetParser()->LineNumber(p->GetPosition(),
00638                                                   fname, fname_len);
00639     return new Leaf(fname, fname_len);
00640 }
00641 
00642 
00643 // class Environment::Array
00644 
00645 Environment::Array::Array(int s)
00646 {
00647     num = 0;
00648     size = s;
00649     if(s > 0)
00650         array = new (GC) Environment*[s];
00651     else
00652         array = nil;
00653 }
00654 
00655 void Environment::Array::Append(Environment* p)
00656 {
00657     if(num >= size){
00658         size += 8;
00659         Environment** a = new (GC) Environment*[size];
00660         memmove(a, array, size_t(num * sizeof(Environment*)));
00661         delete [] array;
00662         array = a;
00663     }
00664 
00665     array[num++] = p;
00666 }
00667 
00668 Environment* Environment::Array::Ref(uint i)
00669 {
00670     if(i < num)
00671         return array[i];
00672     else
00673         return nil;
00674 }
00675 
00676 
00677 // class Bind
00678 
00679 char* Bind::GetEncodedType()
00680 {
00681     return nil;
00682 }
00683 
00684 bool Bind::IsType()
00685 {
00686     return TRUE;
00687 }
00688 
00689 Class* Bind::ClassMetaobject()
00690 {
00691     return nil;
00692 }
00693 
00694 void Bind::SetClassMetaobject(Class*) {}
00695 
00696 Bind::Kind BindVarName::What()
00697 {
00698     return isVarName;
00699 }
00700 
00701 void BindVarName::GetType(TypeInfo& t, Environment* e)
00702 {
00703     t.Set(type, e);
00704 }
00705 
00706 char* BindVarName::GetEncodedType()
00707 {
00708     return type;
00709 }
00710 
00711 bool BindVarName::IsType()
00712 {
00713     return FALSE;
00714 }
00715 
00716 Bind::Kind BindTypedefName::What()
00717 {
00718     return isTypedefName;
00719 }
00720 
00721 void BindTypedefName::GetType(TypeInfo& t, Environment* e)
00722 {
00723     t.Set(type, e);
00724 }
00725 
00726 char* BindTypedefName::GetEncodedType()
00727 {
00728     return type;
00729 }
00730 
00731 Bind::Kind BindClassName::What()
00732 {
00733     return isClassName;
00734 }
00735 
00736 void BindClassName::GetType(TypeInfo& t, Environment*)
00737 {
00738     t.Set(metaobject);
00739 }
00740 
00741 Class* BindClassName::ClassMetaobject()
00742 {
00743     return metaobject;
00744 }
00745 
00746 void BindClassName::SetClassMetaobject(Class* c)
00747 {
00748     metaobject = c;
00749 }
00750 
00751 BindEnumName::BindEnumName(char* encoded_type, Ptree* spec)
00752 {
00753     type = encoded_type;
00754     specification = spec;
00755 }
00756 
00757 Bind::Kind BindEnumName::What()
00758 {
00759     return isEnumName;
00760 }
00761 
00762 void BindEnumName::GetType(TypeInfo& t, Environment* e)
00763 {
00764     t.Set(type, e);
00765 }
00766 
00767 Bind::Kind BindTemplateClass::What()
00768 {
00769     return isTemplateClass;
00770 }
00771 
00772 void BindTemplateClass::GetType(TypeInfo& t, Environment*)
00773 {
00774     t.Set(metaobject);
00775 }
00776 
00777 Class* BindTemplateClass::ClassMetaobject()
00778 {
00779     return metaobject;
00780 }
00781 
00782 void BindTemplateClass::SetClassMetaobject(Class* c)
00783 {
00784     metaobject = c;
00785 }
00786 
00787 Bind::Kind BindTemplateFunction::What()
00788 {
00789     return isTemplateFunction;
00790 }
00791 
00792 void BindTemplateFunction::GetType(TypeInfo& t, Environment*)
00793 {
00794     t.Unknown();
00795 }
00796 
00797 bool BindTemplateFunction::IsType()
00798 {
00799     return FALSE;
00800 }

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