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

📄 types.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* TYPES.CPP
 * The UC type system interface
 * UnderC C++ interpreter
 * Steve Donovan, 2001
 * This is GPL'd software, and the usual disclaimers apply.
 * See LICENCE
 */

#include "types.h"

#include "common.h"
#include "templates.h"

 ostream& operator << (ostream&, string);
 istream& operator >> (istream&, string&);


const Type 
  t_bool(TT_BOOL), t_null(TT_NULL,0), t_template_type((Class *)-1),
  t_void, t_char(TT_CHAR), t_uchar(TT_CHAR,TT_UNSIGNED), t_int(TT_INT), t_uint(TT_INT,TT_UNSIGNED),
  t_short(TT_SHORT), t_ushort(TT_SHORT,TT_UNSIGNED), t_long(TT_INT,TT_LONG),
  t_ulong(TT_INT,TT_LONG | TT_UNSIGNED), 
  t_float(TT_FLOAT), t_double(TT_FLOAT,TT_LONG),
  t_void_ptr(TT_VOID,TT_PTR), t_char_ptr(TT_CHAR,TT_PTR),
  t_zero(TT_ZERO),t_label(TT_NULL,1);

namespace { // local to this module
 std::vector<Class *>      _classes_;
 std::vector<Signature *>  _signatures_;
 std::vector<Enum *>       _enums_;
}

template <class T>
int index_into(std::vector<T>& v, T val)
{
 for(int i = 0; i < v.size(); i++)
  if (v[i] == val) return i;

 // otherwise it ain't here - add to vector!
 v.push_back(val);
 return v.size()-1;
}

// *fix 0.9.4 Looks through the signature list for matches...
// *fix 1.1.0 Insist that they are completely equal, down to the return type
// Should this not be part of what it means for signatures to match?
Signature *unique_signature(Signature *sig)
{
  std::vector<Signature *>::iterator is = _signatures_.begin(),
                                     ie = _signatures_.end();
  for(; is != ie; ++is) {
    Signature *s = *is;  
    // *change 1.2.3a Signature::match() is here called in "exact match" mode!
    if (s->return_type()==sig->return_type() && s->match(*sig,true)) return *is;
  }
  return sig;
}

Signature *find_signature(void *type_data)
{
   Signature *orig = (Signature *)type_data;
   Signature *uniq = unique_signature(orig);
   return uniq ? uniq : orig;
}


Type::Type(TypeEnum t, int extra)
{
  *((long *)this) = 0;  //*SJD* Nasty but effective!
  if(t == TT_NULL) {
    m_extra = extra;   
    return;
  }
// hmm...are bools considered a kind of integer?
 if (t != TT_VOID && t != TT_FLOAT && t != TT_BOOL) m_int = 1;
 else m_int = 0;
 if (t==TT_CHAR)  m_char = 1;   else
 if (t==TT_SHORT) m_short = 1;  else
 if (t==TT_VOID) m_char = 1;    else  // a fiddle....
 if (t==TT_FLOAT) m_float = 1;  else
 if (t==TT_ZERO) { m_zero = 1; m_const = 1; } else
 if (t==TT_BOOL) {
    m_bool = 1;
 }

 if (extra & TT_LONG) m_long = 1;
 if (extra & TT_UNSIGNED) m_unsigned = 1;
 if (extra & TT_PTR) m_ptr = 1;

 m_extra = 0;
}

void Type::complex_init(TypeEnum t, void *type_data)
{
  *((long *)this) = 0;  //*SJD* Nasty but effective!
  if (t == TT_CLASS || t == TT_NAMESPACE) {
    m_class = 1;       m_extra = index_into(_classes_,(Class *)type_data);
  // this might seem like asking for trouble, but namespace entries
  // are always TYPENAMEs not IDENs.  So the chances of confusion are slim.
    if (t == TT_NAMESPACE) m_zero = 1;
  } else
  if (t == TT_SIGNATURE) {
 // *change 1.2.2 (Eric) Always try to keep signatures unique
    m_signature = 1;   m_extra = index_into(_signatures_,find_signature(type_data));
  } else
  if (t == TT_ENUM || t == TT_DUMMY) {
    if (t == TT_DUMMY) m_short = 1;
    m_enum = 1;     
    // for dummies , _identical names_ means equality!
    // (can get away with this because both types derive from NamedType)
    Enum *ndata = (Enum *)type_data;
    int sz = _enums_.size();
    if (ndata->name() != "" || t != TT_DUMMY) {
      for(int i = 0; i < sz; i++)
        if (_enums_[i]==ndata 
          /*|| t == TT_DUMMY && _enums_[i]->name() == ndata->name()*/)
            { m_extra = i;    return; }
    } else {
      //*change 1.2.9 To support numerical template parameters properly,
      // we have to keep dummies with the same value identical;  this
      // code will only work with integer types (you're on your own
      // with other types)
       DummyType* dt = (DummyType*)type_data;
       int val = Parser::const_int_expr(dt->entry());
       for(int i = 0; i < sz; i++) {
           if (_enums_[i]->name() == "") {
               DummyType* de = (DummyType*)_enums_[i];
               if (val == Parser::const_int_expr(de->entry())) {
                   m_extra = i; return;
               }
           }
       }
    }
    // otherwise, add to the end!!
    m_extra = _enums_.size();
    _enums_.push_back(ndata);
  }
 
}

bool Type::operator == (Type t)  const
{
// a complete kludge!
// again, a basic assumption that the Type object fits snugly into a 32-bit word.
 return *((long *)this) == *((long *)&t);
}

bool Type::is_null() const
{ return *((long *)this) == 0; }

bool Type::is_bare() const
{ 
  return !is_const() && !is_pointer() && !is_reference();
}

bool Type::is_unbound() const
{
if (is_null()) return false;   // null!
if (!is_dummy()) return true;  // everything else has a definite type value
return as_dummy()->unbound();
}

bool Type::is_template_class() const
{
 return is_class() && as_class()->get_template() != NULL;
}


Type Type::make_dummy(const string& name, Type t, PEntry pe)
{
 Type rt;
 DummyType *pdum = new DummyType(name,t,pe);
 rt.complex_init(TT_DUMMY,pdum);
 return rt;
}

bool Type::is_dummy() const
{
  if (m_enum && m_short) return true; // plain dummy
  if (is_template_class()) { // otherwise it may have at least one dummy parameter!
    Class *pc = as_class();
    const TypeList& tl = pc->get_template()->type_parms();
    TypeList::const_iterator tli;
    int kount = 0;
    FORALL(tli,tl)
      if (tli->is_dummy()) kount++;
    return kount > 0;
  }
  return false;
}


Signature *Type::as_signature() const
{
 if (m_signature) return _signatures_[m_extra]; else return NULL;
}

Class     *Type::as_class() const
{
 if (m_class) return _classes_[m_extra]; else return NULL;
}

Enum      *Type::as_enum() const
{
 return _enums_[m_extra]; 
}

//----- depth of derivation; 0 for no relation (delegated to class object)
int      Type::inherits_from(Type t) const
{
 if (is_class() && t.is_class()) return as_class()->inherits_from(t.as_class());
 else return 0;
}

int Type::size() const                 // implements sizeof()
{
  if (is_pointer()) return sizeof(void *);
  else 
  if (is_enum()) return sizeof(int);   else;  // for now....
  if (is_int()) {
   if (is_short()) return sizeof(short);  else
   if (is_long())  return sizeof(long);  else
   if (is_char())  return sizeof(char);  
   else return sizeof(int);
  } else
  if (is_float()) {
   if (is_double()) return sizeof(double); else return sizeof(float);
  } else
  if (is_class()) return as_class()->size();
  // *fix 1.2.3 Our bools now have standard size (8-bits)
  else if (is_bool()) return sizeof(bool);  
  else return sizeof(int);
}

class TypeSearch: public TableSearcher {
private:
	Class* m_class;
	Type m_type;
	Type m_dummy;
	Type m_result;
	
public:
	TypeSearch() {
		m_dummy = Type::make_dummy("_*_",t_void,NULL);
    }
	void set_type(Type t) {
      m_type = t;
	  m_class = t.as_class();
    }

	Type result() { return m_result; }

    virtual bool match(PEntry pe)
    {
    Type tt = pe->type;
    if (tt.is_class() && tt.as_class() == m_class) {
	 Type ta = m_type, td = m_dummy;
	 if (ta.is_const() && ! tt.is_const()) {
		 ta.strip_const();
		 td.make_const();
     }
	 while (ta.is_pointer() && ! tt.is_pointer()) {
		 ta.decr_pointer();
		 td.incr_pointer();
     }
	 if (ta.is_reference() &&  ! tt.is_reference()) {
		 ta.strip_reference();
		 td.make_reference();
     }
	 if (ta == tt) {
		 td.as_dummy()->set_name(pe->name);
		 m_result = td;
		 return true;
     }
    }
    return false;
   }

};

// *fix 1.2.7 We dump out the fully qualified names of classes and enums,
// which was necessary for delayed compilation of method bodies.
// *add 1.2.7 debug.use_typedef_names not only forces a global search for
// a typedef for a particular type, but leaves off 'std::' when std has
// been injected.  Not likely to be a popular feature with the ISO committee.

NamedTable* nested_context(PEntry pe)
{
  int type = pe->context->type();
  if (type == IS_NAMESPACE || type == IS_STRUCT) {
	  if (Parser::debug.use_typedef_names && pe->context == Parser::std_namespace()
		  && Parser::global().is_injected((Namespace*)pe->context)) return NULL;
	  else return (NamedTable*) pe->context;
  }
  else return NULL;
}

⌨️ 快捷键说明

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