⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 types.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 2 页
字号:
string enum_as_str(Enum *em)
{
 string s = em->name();
 // the issue here is that in C mode 'enum Fred' actually generates
 // a slightly mangled name $_Fred.
 if (s[0]=='$' && s[1] == '_') s = s.substr(2,s.length()-2);
 NamedTable* parent = nested_context(em->entry());
 if (parent) s = parent->name() + "::" + s;
 return s;
}

bool lookup_typedef_name(Type t, string& s)
{
  static TypeSearch type_search;
  type_search.set_type(t);
  PEntry pe = Parser::global().search_entries(&type_search,NULL,TYPEDEFS);
  if (pe != NULL) {
	 type_search.result().as_string(s);
	 return true;
  } else return false;
}

string class_as_str(Class *pc)
{
 string s;
 NamedTable* parent = nested_context(pc->entry());
 if (parent) s = parent->name() + "::";
 s += pc->name();
 return s;
}

void Type::as_string(string& s) const
{ 
 if (Parser::debug.use_typedef_names && lookup_typedef_name(*this,s)) return;
 s = "";
 if (is_enum()) { s = enum_as_str(as_enum()); return; }
 if (is_const()) s += "const ";
 if (is_unsigned()) s += "unsigned ";
 if (is_long() && is_int()) s += "long ";
 if (is_char())   s += "char"; else
 if (is_short())  s += "short"; else
 if (is_double()) s += "double"; else
 if (is_float())  s += "float"; else
 if (is_void())   s += "void"; else
 if (is_int())    s += "int"; else
 if (is_bool())   s += "bool"; else
 if (is_class())  s += class_as_str(as_class());
 else
 if (is_signature()) {
   char buff[256];
   ostrstream out(buff,256);
   if (is_pointer()) Signature::set_fun_name("(*)");
   out << *as_signature();
   if (is_pointer()) Signature::set_fun_name("");
   out << ends;
   s = buff;   
   return;
 } else 
 if (is_dummy()) s += as_dummy()->value_as_string();

 if (is_pointer()) {
    for(int i = 0; i < pointer_depth(); i++) s += "*";
 }
 #ifdef _DEBUG
 if (is_variable()) s += "!"; else  
 #endif
 if (is_reference() && !is_variable()) s += "&";
 
}

ostream& operator << (ostream& os, Type t)
{
 string stemp="";
 t.as_string(stemp);
 os << stemp;
 return os;
}

// in these match functions, the first arg represents the formal
// parameter, and the second the actual argument.

// Must remove the zero bit, in case we had a variable! (see note(3), Expressions::entry_op)
inline Type make_const(Type t)
{ Type tc = t; tc.make_const(); tc.make_zero_int(); return tc; }

inline Type strip_qualifiers(Type t)
{ Type tc = t; tc.strip_qualifiers(); return tc; }

inline Type make_const_ref(Type t)
{ Type tc = t; tc.make_const_reference(); tc.make_zero_int(); return tc; }

inline Type make_ref(Type t)
{ Type tc = t; tc.make_reference(); tc.make_zero_int(); return tc; }


TypeDistance
 trivial_match(Type t1, Type t2)
 //-----------------------------
{
// trivial match between t2 (actual) and t1 (formal) argument.
 if (t1.is_reference()) {
    if (t1.is_variable() && strip_qualifiers(t1) == strip_qualifiers(t2))
       return TRIVIAL_MATCH;    //const T& => T! (variable type) is fine...
    t2.make_zero_int();  // clear VARIABLE type
    t1.make_zero_int();

 // these are really exact or trivial matches but we need to know for arg passing
   if (t1 == t2) return REFERENCE_MATCH;     
   if (t1.is_const()) {
     // a non-const reference converts trivially to its const equivalent; 
     if(t1 == make_const(t2)) return REFERENCE_MATCH;  //T& => const T&   
     // T => const T& -- always cool because our constants have addresses
     // *fix 1.2.1 Must however exclude const T => T&!
     Type t2r = t2;
     t2r.make_reference();
     if (t2.is_const()) {
        if (t1 == t2r) return REFERENCE_MATCH;  // const T => const T&
     } else {  // exclude const T => T& !
        t2r.make_const();
        if (t1 == t2r) return REFERENCE_MATCH;  // T => const T&
     }
   }
 } 
 t2.make_zero_int(); 
 t1.make_zero_int();  
 if (!t1.is_ref_or_ptr()) t2.strip_const();
 if (t1 == t2) return EXACT_MATCH;
 
 // T * => const T *;  T[] => T*, T* => T[]
 if (t1.is_pointer()) {
     if (t1.is_const()) t1.strip_const();
     if (t1.is_array()) t1.strip_array();
     if (t2.is_array()) t2.strip_array();
     if (t2 == t1)  return TRIVIAL_MATCH;
 }
 //T  => T&,const T&
 // *fix 1.2.1 Must however exclude const T => T&!
// if (!t2.is_ref_or_ptr()) t2.strip_const();
 if (t2.is_reference() && strip_qualifiers(t2) == t1) return TRIVIAL_MATCH;
 //if (t1.is_reference() && strip_qualifiers(t1) == t2) return TRIVIAL_MATCH;
 return NO_MATCH;
}

TypeDistance 
 promote_match(Type t1, Type t2)
{
// promotions between t2 (actual) and t1 (formal) argument.
// *fix 0.9.7 Allow for t2 => const t1&, if we can promote t2 to t1.
 bool is_ref = t1.is_reference() & t1.is_const();
 if (is_ref) t1.strip_qualifiers();
 Type pt = t2.promote();
 if (pt == t1) return is_ref ? REF_PROMOTE_MATCH : PROMOTE_MATCH;
 return NO_MATCH;
}

TypeDistance
 std_match(Type t1, Type t2)
{
// standard conversions between t2 (actual) and t1 (formal) argument.
//cout << "std: f= " << t1 << " a= " << t2 << endl;
 bool ref_argument = t1.is_plain_reference();
 // *add 1.1.4 C is less fussy about integer conversions to enumerations...
 if (Parser::debug.c_mode && t1.is_enum() && t2.is_int()) return STD_MATCH;
 if (t1.is_number() && !ref_argument) {
  // in strict mode, there are no implicit bool conversions...
  // *change 1.2.3 Retired until we can think this through.....
  // if (t2==t_bool && Parser::debug.strict) return NO_MATCH;
   if (t2.is_number() || t2.is_enum()) return STD_MATCH;
   if (t2.is_zero()) return STD_MATCH;
  } else
 if (t2.is_pointer()) {
    if (t1.is_void() && t1.pointer_depth()==1) 
        return ref_argument ? REF_STD_MATCH : STD_MATCH;
    if (!t1.is_pointer()) return NO_MATCH;
 } 

 if (t1 == t_bool && t2.is_int()) {       
    return STD_MATCH;
 } 
 if (t1.is_pointer()) {
   if(t2.is_zero()) return STD_MATCH;
   if(t1.is_signature() && t2.is_signature() /*&& t1.as_signature()==t2.as_signature()*/)
       return FUN_PTR_MATCH; //*note* t2 is not a ptr in 'pf = sin' etc!
   if(!t2.is_pointer()) return NO_MATCH;
  }
// *fix 0.9.5 Standard reference matches score lower than ordinary reference matches
 if (t2.inherits_from(t1)) return (ref_argument && ! t2.is_plain_reference()) ?
                                      REF_STD_MATCH : STD_MATCH;
                              
 return NO_MATCH; // for now
}

TypeDistance  
 match(Type t1,Type t2)
{
 TypeDistance td = trivial_match(t1,t2);
 if (td != NO_MATCH) return td;
 td = promote_match(t1,t2);
 if (td != NO_MATCH) return td;
 td = std_match(t1,t2);
 if (td != NO_MATCH) return td;

 // for now
 return NO_MATCH;
}

Type Type::promote()  const
{
// from Lippman (2nd, 174)
 if (is_pointer() || is_reference() && ! is_variable()) return *this; //* doesn't apply!! 
 if (is_char() || is_short()) return t_int;
 if (is_short() && is_unsigned()) return t_int; // sizeof(int) > sizeof(short)
 if (is_float()) return t_double;
 if (is_bool()) return t_int; 
 return *this;
}

typedef unsigned long unsigned_t;

string Type::value_as_string(void *ptr, bool do_quotes) const
{
// *add 1.1.2 Putting quotes around strings is now optional.
 static char buff[512];
 memset(buff,0,512);
 ostrstream out(buff,512);  
 if (is_pointer()) {
     //*fix 1.2.6 Was attempting to dump char** etc as character constants
    if (is_char() && pointer_depth() == 1){  
    char *cp = *(char **)ptr;
    if (cp) {
		if (do_quotes) out << '"';
		out	<< cp;
		if (do_quotes) out << '"'; 
    } else out << "NULL";
   } else
   out << (void *)*(int **)ptr; 
 }  else
 if (is_enum()) { // *add 1.2.6 show enumeration constants, if possible
    int val = *(int *)ptr;
    string name = as_enum()->lookup_value(val);
    out << val << ' ' << name;
 }  else  
 if (is_bool()) out << (*(int *)ptr ? "true" : "false"); else
 if (is_int()) {
     bool unsign = is_unsigned();
     if(is_char()) {
        out << '\'' << *(char *)ptr << '\'';
        if (unsign) out << " (" << (unsigned_t)*(unsigned char *)ptr << ')';
     } else if(is_short()) {
        if (unsign) out << (unsigned_t)*(unsigned short *)ptr;
        else        out << *(short *)ptr;
     } else {
       if (unsign)  out << (unsigned_t)*(unsigned int *)ptr;
       else         out << *(int *)ptr;
     }
 } else 
 if (is_double()) out << *(double *)ptr;   else
 if (is_float()) out << *(float *)ptr; else
 if (is_class()) {
   PClass pc = as_class();
   // HACK02 -- strings outputed directly - assume first member field is char *
   if (pc->name()=="string") {
	   if (do_quotes) out << '\'';
	   out << **(char ***)ptr;
	   if (do_quotes) out << '\'';
   } else out << pc->name() << " {}"; 
 }
 out << ends;
 return buff;
}

ostream& operator << (ostream& os, TypeDistance td)
 {
   char *txt;
   switch(td) {
   #define CASE(x) case x: txt = #x; break;
   CASE(EXACT_MATCH)
   CASE(REFERENCE_MATCH)
   CASE(TRIVIAL_MATCH)
   CASE(PROMOTE_MATCH)
   CASE(STD_MATCH)
   CASE(CONVERT_FROM_MATCH)
   CASE(CONVERT_TO_MATCH)
   CASE(FUN_PTR_MATCH)
   CASE(NO_MATCH)
   #undef CASE
   }
   os << txt;
   return os;
 }

  



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -