00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00029
00030 PtreeArray* Environment::classkeywords = nil;
00031
00032 Environment::Environment(Walker* w)
00033 : baseclasses_or_using(0), namespaces(0)
00034 {
00035 htable = new BigHashTable;
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
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
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;
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;
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
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
00576
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;
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
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
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 }