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

typeinfo.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 "typeinfo.h"
00016 #include "encoding.h"
00017 #include "ptree-core.h"
00018 #include "env.h"
00019 #include "mop.h"
00020 
00021 TypeInfo::TypeInfo()
00022 {
00023     refcount = 0;
00024     encode = nil;
00025     metaobject = nil;
00026     env = nil;
00027 }
00028 
00029 void TypeInfo::Unknown()
00030 {
00031     refcount = 0;
00032     encode = nil;
00033     metaobject = nil;
00034     env = nil;
00035 }
00036 
00037 void TypeInfo::Set(char* type, Environment* e)
00038 {
00039     refcount = 0;
00040     encode = type;
00041     metaobject = nil;
00042     env = e;
00043 }
00044 
00045 void TypeInfo::Set(Class* m)
00046 {
00047     refcount = 0;
00048     encode = nil;
00049     metaobject = m;
00050     env = nil;
00051 }
00052 
00053 void TypeInfo::SetVoid()
00054 {
00055     refcount = 0;
00056     encode = "v";
00057     metaobject = nil;
00058     env = nil;
00059 }
00060 
00061 void TypeInfo::SetInt()
00062 {
00063     refcount = 0;
00064     encode = "i";
00065     metaobject = nil;
00066     env = nil;
00067 }
00068 
00069 void TypeInfo::SetMember(Ptree* member)
00070 {
00071     Class* c = ClassMetaobject();
00072     if(c == nil)
00073         Unknown();
00074     else{
00075         Environment* e = c->GetEnvironment();
00076         if(e == nil)
00077             Unknown();
00078         else
00079             e->Lookup(member, *this);
00080     }
00081 }
00082 
00083 TypeInfoId TypeInfo::WhatIs()
00084 {
00085     if(refcount > 0)
00086         return PointerType;
00087 
00088     Normalize();
00089     if(metaobject != nil)
00090         return ClassType;
00091 
00092     Environment* e = env;
00093     char* ptr = SkipCv(encode, e);
00094     if(ptr == nil)
00095         return UndefType;
00096 
00097     switch(*ptr){
00098     case 'T' :
00099         return TemplateType;
00100     case 'P' :
00101         return PointerType;
00102     case 'R' :
00103         return ReferenceType;
00104     case 'M' :
00105         return PointerToMemberType;
00106     case 'A' :
00107         return ArrayType;
00108     case 'F' :
00109         return FunctionType;
00110     case 'S' : case 'U' :
00111     case 'b' : case 'c' : case 'i' : case 's' : case 'l' : case 'j' :
00112     case 'f' : case 'd' : case 'r' : case 'v' :
00113         return BuiltInType;
00114     default :
00115         if(*ptr == 'Q' || *(unsigned char*)ptr >= 0x80){
00116             TypeInfo t;
00117             Class* c;
00118             t.Set(ptr, e);
00119             if(t.IsClass(c))
00120                 return ClassType;
00121             else if(t.IsEnum())
00122                 return EnumType;
00123         }
00124 
00125         return UndefType;
00126     };
00127 }
00128 
00129 bool TypeInfo::IsNoReturnType()
00130 {
00131     Normalize();
00132     Environment* e = env;
00133     char* ptr = SkipCv(encode, e);
00134     return(ptr != nil && *ptr == '?');
00135 }
00136 
00137 bool TypeInfo::IsConst()
00138 {
00139     Normalize();
00140     char* ptr = encode;
00141     return(ptr != nil && *ptr == 'C');
00142 }
00143 
00144 bool TypeInfo::IsVolatile()
00145 {
00146     Normalize();
00147     char* ptr = encode;
00148     if(ptr == nil)
00149         return FALSE;
00150     else if(*ptr == 'V')
00151         return TRUE;
00152     else if(*ptr == 'C')
00153         return(ptr[1] == 'V');
00154     else
00155         return FALSE;
00156 }
00157 
00158 uint TypeInfo::IsBuiltInType()
00159 {
00160     Normalize();
00161     Environment* e = env;
00162     char* ptr = SkipCv(encode, e);
00163     if(ptr == nil)
00164         return 0;
00165 
00166     uint result = 0;
00167     for(;; ++ptr){
00168         switch(*ptr){
00169         case 'b' :
00170             return(result | BooleanType);
00171         case 'c' :
00172             return(result | CharType);
00173         case 'i' :
00174             return(result | IntType);
00175         case 's' :
00176             return(result | ShortType);
00177         case 'l' :
00178             return(result | LongType);
00179         case 'j' :
00180             return(result | LongLongType);
00181         case 'f' :
00182             return(result | FloatType);
00183         case 'd' :
00184             return(result | DoubleType);
00185         case 'r' :
00186             return(result | LongDoubleType);
00187         case 'v' :
00188             return(result | VoidType);
00189         case 'S' :
00190             result |= SignedType;
00191             break;
00192         case 'U' :
00193             result |= UnsignedType;
00194             break;
00195         default :
00196             return 0;
00197         }
00198     }
00199 }
00200 
00201 bool TypeInfo::IsFunction()
00202 {
00203     Normalize();
00204     Environment* e = env;
00205     char* ptr = SkipCv(encode, e);
00206     return(ptr != nil && *ptr == 'F');
00207 }
00208 
00209 bool TypeInfo::IsEllipsis()
00210 {
00211     Normalize();
00212     Environment* e = env;
00213     char* ptr = SkipCv(encode, e);
00214     return(ptr != nil && *ptr == 'e');
00215 }
00216 
00217 bool TypeInfo::IsPointerType()
00218 {
00219     if(refcount > 0)
00220         return TRUE;
00221 
00222     Normalize();
00223     Environment* e = env;
00224     char* ptr = SkipCv(encode, e);
00225     if(ptr != nil){
00226         char c = *ptr;
00227         return c == 'P' || c == 'A' || c == 'M';
00228     }
00229 
00230     return FALSE;
00231 }
00232 
00233 bool TypeInfo::IsReferenceType()
00234 {
00235     Normalize();
00236     Environment* e = env;
00237     char* ptr = SkipCv(encode, e);
00238     return(ptr != nil && *ptr == 'R');
00239 }
00240 
00241 bool TypeInfo::IsArray()
00242 {
00243     Normalize();
00244     Environment* e = env;
00245     char* ptr = SkipCv(encode, e);
00246     return(ptr != nil && *ptr == 'A');
00247 }
00248 
00249 bool TypeInfo::IsPointerToMember()
00250 {
00251     Normalize();
00252     Environment* e = env;
00253     char* ptr = SkipCv(encode, e);
00254     return(ptr != nil && *ptr == 'M');
00255 }
00256 
00257 bool TypeInfo::IsTemplateClass()
00258 {
00259     Normalize();
00260     Environment* e = env;
00261     char* ptr = SkipCv(encode, e);
00262     return(ptr != nil && *ptr == 'T');
00263 }
00264 
00265 Class* TypeInfo::ClassMetaobject()
00266 {
00267     Class* c;
00268     IsClass(c);
00269     return c;
00270 }
00271 
00272 bool TypeInfo::IsClass(Class*& c)
00273 {
00274     Normalize();
00275     if(metaobject != nil){
00276         c = metaobject;
00277         return TRUE;
00278     }
00279     else{
00280         c = nil;
00281         Environment* e = env;
00282         char* encode2 = SkipCv(encode, e);
00283         if(encode == encode2)
00284             return FALSE;
00285 
00286         TypeInfo tinfo;
00287         tinfo.Set(encode2, e);
00288         return tinfo.IsClass(c);
00289     }
00290 }
00291 
00292 bool TypeInfo::IsEnum()
00293 {
00294     Ptree* spec;
00295     return IsEnum(spec);
00296 }
00297 
00298 bool TypeInfo::IsEnum(Ptree*& spec)
00299 {
00300     spec = nil;
00301     Normalize();
00302     if(metaobject != nil)
00303         return FALSE;
00304     else{
00305         Bind* bind;
00306         int len;
00307         Environment* e = env;
00308         char* name = Encoding::GetBaseName(encode, len, e);
00309         if(name != nil && e != nil)
00310             if(e->LookupType(name, len, bind))
00311                 if(bind != nil && bind->What() == Bind::isEnumName){
00312                     spec = ((BindEnumName*)bind)->GetSpecification();
00313                     return TRUE;
00314                 }
00315 
00316         e = env;
00317         name = SkipCv(encode, e);
00318         if(name == encode)
00319             return FALSE;
00320 
00321         TypeInfo tinfo;
00322         tinfo.Set(name, e);
00323         return tinfo.IsEnum(spec);
00324     }
00325 }
00326 
00327 void TypeInfo::Dereference(TypeInfo& t)
00328 {
00329     t.refcount = refcount - 1;
00330     t.encode = encode;
00331     t.metaobject = metaobject;
00332     t.env = env;
00333 }
00334 
00335 void TypeInfo::Reference(TypeInfo& t)
00336 {
00337     t.refcount = refcount + 1;
00338     t.encode = encode;
00339     t.metaobject = metaobject;
00340     t.env = env;
00341 }
00342 
00343 bool TypeInfo::NthArgument(int n, TypeInfo& t)
00344 {
00345     Environment* e = env;
00346     Normalize();
00347     char* ptr = SkipCv(encode, e);
00348     if(ptr == nil || *ptr != 'F'){
00349         t.Unknown();
00350         return FALSE;
00351     }
00352 
00353     ++ptr;
00354     if(*ptr == 'v'){
00355         t.SetVoid();
00356         return FALSE;           // no arguments
00357     }
00358 
00359     while(n-- > 0){
00360         ptr = SkipType(ptr, e);
00361         if(ptr == nil || *ptr == '_'){
00362             t.Unknown();
00363             return FALSE;
00364         }
00365     }
00366 
00367     t.Set(ptr, e);
00368     return TRUE;
00369 }
00370 
00371 int TypeInfo::NumOfArguments()
00372 {
00373     Environment* e = env;
00374     Normalize();
00375     char* ptr = SkipCv(encode, e);
00376     if(ptr == nil || *ptr != 'F')
00377         return -1;      // not a function
00378 
00379     ++ptr;
00380     if(*ptr == 'v')
00381         return 0;       // no arguments
00382 
00383     int n = 0;
00384     for(;;){
00385         ++n;
00386         ptr = SkipType(ptr, e);
00387         if(ptr == nil || *ptr == '_')
00388             return n;
00389     }
00390 }
00391 
00392 bool TypeInfo::NthTemplateArgument(int n, TypeInfo& t)
00393 {
00394     Environment* e = env;
00395     Normalize();
00396     char* ptr = SkipCv(encode, e);
00397     if(ptr == nil || *ptr != 'T'){
00398         t.Unknown();
00399         return FALSE;
00400     }
00401 
00402     int len;
00403     ptr = (char*)Encoding::GetTemplateArguments((unsigned char*)++ptr, len);
00404     char* end = ptr + len;
00405     while(n-- > 0){
00406         ptr = SkipType(ptr, e);
00407         if(ptr == nil || ptr >= end) {
00408             t.Unknown();
00409             return FALSE;
00410         }
00411     }
00412 
00413     t.Set(ptr, e);
00414     return TRUE;
00415 }
00416 
00417 Ptree* TypeInfo::FullTypeName()
00418 {
00419     Ptree *qname, *head;
00420 
00421     Normalize();
00422     if(metaobject != nil){
00423         qname = metaobject->Name();
00424         head = GetQualifiedName2(metaobject);
00425         if(head == nil)
00426             return qname;
00427         else
00428             return Ptree::Snoc(head, qname);
00429     }
00430 
00431     Environment* e = env;
00432     unsigned char* name = (unsigned char*)SkipCv(encode, e);
00433     if(name == nil)
00434         return nil;
00435 
00436     if(IsBuiltInType())
00437         return Encoding::MakePtree(name, nil)->First();
00438 
00439     if(*name == 'T'){
00440         ++name;
00441         qname = Encoding::MakeLeaf(name);
00442         head = GetQualifiedName(e, qname);
00443         if(head == nil)
00444             return qname;
00445         else
00446             return Ptree::Snoc(head, qname);
00447     }
00448     else if(*name == 'Q'){
00449         qname = Encoding::MakeQname(++name);
00450         head = GetQualifiedName(e, qname->Car());
00451         if(head == nil)
00452             return qname;
00453         else
00454             return Ptree::Nconc(head, qname);
00455     }
00456     else if(Encoding::IsSimpleName(name)){
00457         qname = Encoding::MakeLeaf(name);
00458         head = GetQualifiedName(e, qname);
00459         if(head == nil)
00460             return qname;
00461         else
00462             return Ptree::Snoc(head, qname);
00463     }
00464     else
00465         return nil;
00466 }
00467 
00468 Ptree* TypeInfo::GetQualifiedName(Environment* e, Ptree* tname)
00469 {
00470     Class* c = e->LookupClassMetaobject(tname);
00471     if(c == nil)
00472         return nil;
00473     else
00474         return GetQualifiedName2(c);
00475 }
00476 
00477 Ptree* TypeInfo::GetQualifiedName2(Class* c)
00478 {
00479     Ptree* qname = nil;
00480     Environment* e = c->GetEnvironment();
00481     if(e != nil)
00482         e = e->GetOuterEnvironment();
00483 
00484     for(; e != nil; e = e->GetOuterEnvironment()){
00485         c = e->IsClassEnvironment();
00486         if(c != nil)
00487             qname = Ptree::Cons(c->Name(),
00488                                 Ptree::Cons(Encoding::scope, qname));
00489     }
00490 
00491     return qname;
00492 }
00493 
00494 Ptree* TypeInfo::MakePtree(Ptree* name)
00495 {
00496     Normalize();
00497     if(metaobject != nil){
00498         Ptree* decl;
00499         if(name == nil)
00500             decl = nil;
00501         else
00502             decl = Ptree::List(name);
00503 
00504         return Ptree::List(FullTypeName(), decl);
00505     }
00506     else if(encode != nil){
00507         unsigned char* ptr = (unsigned char*)encode;
00508         return Encoding::MakePtree(ptr, name);
00509     }
00510     else
00511         return nil;
00512 }
00513 
00514 void TypeInfo::Normalize()
00515 {
00516     Environment* e = env;
00517     char* ptr = encode;
00518     int r = refcount;
00519 
00520     if(ptr == nil)
00521         return;
00522     else if(r > 0)
00523         return;
00524 
00525     while(r < 0)
00526         switch(*ptr){
00527         case 'C' :      // const
00528         case 'V' :      // volatile
00529             ++ptr;
00530             break;
00531         case 'A' :      // array
00532         case 'P' :      // pointer *
00533         case 'R' :      // reference &
00534             ++ptr;
00535             ++r;
00536             break;
00537         case 'F' :      // function
00538         case 'M' :      // pointer to member ::*
00539           {
00540             char* p;
00541             if(*ptr == 'F')
00542                 p = GetReturnType(ptr + 1, e);
00543             else
00544                 p = SkipName(ptr + 1, e);
00545 
00546             if(p == nil)
00547                 return;
00548             else{
00549                 ptr = p;
00550                 ++r;
00551             }
00552             break;
00553           }
00554         default :
00555             if(!ResolveTypedef(e, ptr, TRUE))
00556                 return;
00557         }
00558 
00559     while(ResolveTypedef(e, ptr, FALSE))
00560         ;
00561 }
00562 
00563 bool TypeInfo::ResolveTypedef(Environment*& e, char*& ptr, bool resolvable)
00564 {
00565     Bind* bind;
00566     int len;
00567     Class* c;
00568     Environment* orig_e = e;
00569     char* name = Encoding::GetBaseName(ptr, len, e);
00570     if(name != nil && e != nil && e->LookupType(name, len, bind))
00571         switch(bind->What()){
00572         case Bind::isTypedefName :
00573             ptr = bind->GetEncodedType();
00574             return TRUE;
00575         case Bind::isClassName :
00576             c = bind->ClassMetaobject();
00577             if(c == nil)
00578                 Set(ptr, orig_e);
00579             else if (*name == 'T')
00580                 Set(ptr, c->GetEnvironment());
00581             else
00582                 Set(c);
00583 
00584             return FALSE;
00585         case Bind::isTemplateClass :
00586             c = bind->ClassMetaobject();
00587             if(c == nil)
00588                 Set(ptr, orig_e);
00589             else
00590                 Set(ptr, c->GetEnvironment());
00591 
00592             return FALSE;
00593         default :
00594             break;
00595         }
00596 
00597     if(resolvable)
00598         Unknown();
00599     else
00600         Set(ptr, orig_e);
00601 
00602     return FALSE;
00603 }
00604 
00605 char* TypeInfo::SkipCv(char* ptr, Environment*& e)
00606 {
00607     if(ptr == nil)
00608         return nil;
00609 
00610     for(;;)
00611         switch(*ptr){
00612         case 'C' :      // const
00613         case 'V' :      // volatile
00614             ++ptr;
00615             break;
00616         default :
00617             goto finish;
00618         }
00619 
00620 finish:
00621     for(;;){
00622         Bind* bind;
00623         int len;
00624         char* name = Encoding::GetBaseName(ptr, len, e);
00625         if(name != nil && e != nil && e->LookupType(name, len, bind))
00626             if(bind->What() != Bind::isTypedefName)
00627                 return ptr;
00628             else
00629                 ptr = bind->GetEncodedType();
00630         else
00631             return ptr;
00632     }
00633 }
00634 
00635 char* TypeInfo::SkipName(char* encode, Environment* e)
00636 {
00637     if(e == nil)
00638         MopErrorMessage("TypeInfo::SkipName()", "nil environment");
00639 
00640     int len;
00641     Environment* e2 = e;
00642     char* ptr = Encoding::GetBaseName(encode, len, e2);
00643     if(ptr == nil)
00644         return nil;
00645     else
00646         return &ptr[len];
00647 }
00648 
00649 char* TypeInfo::GetReturnType(char* encode, Environment* env)
00650 {
00651     for(;;)
00652         switch(*encode){
00653         case '_' :
00654             return encode + 1;
00655         case '\0' :
00656             return nil;
00657         default :
00658             encode = SkipType(encode, env);
00659             break;
00660         }
00661 }
00662 
00663 char* TypeInfo::SkipType(char* ptr, Environment* env)
00664 {
00665     while(ptr != nil)
00666         switch(*ptr){
00667         case '\0' :
00668         case '_' :
00669             return nil;
00670         case 'S' :
00671         case 'U' :
00672         case 'C' :
00673         case 'V' :
00674         case 'P' :
00675         case 'R' :
00676         case 'A' :
00677             ++ptr;
00678             break;
00679         case 'F' :
00680             ptr =  GetReturnType(ptr + 1, env);
00681             break;
00682         case 'T' :
00683         case 'Q' :
00684             return SkipName(ptr, env);
00685         case 'M' :
00686             ptr = SkipName(ptr + 1, env);
00687             break;
00688         default :
00689             if(*(unsigned char*)ptr < 0x80)
00690                 return ptr + 1;
00691             else
00692                 return SkipName(ptr, env);
00693         }
00694 
00695     return ptr;
00696 }

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