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

📄 class.cpp

📁 UC Library Extensions UnderC comes with a pocket implementation of the standard C++ libraries, wh
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        m_field_list.push_back(pe);
        if(t.is_object()) m_obj_list.push_back(pe);
      }
    }
    // if we have a base class, then create a fake entry
    Class *bc = base_class();
    if (bc) {
     PEntry pe = new Entry;
     *pe =  *(bc->entry());
     pe->rmode = OREL;
     pe->data = 0;
     //  m_obj_list->push_back(pe);
     m_base_entry = pe;
    }

    // *fix 1.1.0 Returns false if there is nothing requiring construction
    return m_obj_list.size() > 0 || m_base_entry != NULL;
}

void compile(PExpr ex)
{
// *fix 0.9.6 Is necessary to check the temp context after every expression compile!
 Parser::code().compile(ex,DROP_VALUE);
 Parser::check_temp_context();
}

PExpr call_function(Function *pf, PExpr e=NULL)
// shortcut for calling functions of one or none arguments;
// always forces call of actual function, virtual or not (see compile_function_call() in code.cpp)
{
 return new Expr(DCALL,pf->return_type(),pf,Expressions::expr_list(e));
}

// auto contruction/destruction code generation
// do note that the _base class_ is treated specially; we have already physically
// constructed the object, so all we do is call the inherited method!
bool Class::auto_construct(bool make_method)
{
 using namespace Expressions;
 bool copy_ctor = false;
 if (!make_method) { // if we were called to initialize an existing constructor...
   FunctionContext *fc = (FunctionContext *)&Parser::state.context();
   // which was a copy constructor, a special case; (no default operation!)
   // *fix 1.0.0 But we do need to use any explicit initializations in the ctor init list
   copy_ctor = fc->function() == copy_constructor();
 } else  if (imported()) { // *change 1.2.0 Special case of importing a class moved here....
    declare_method(constructor_name(),t_void,NULL,t_void,IsConstructor);
    return true;
 }

 if (m_field_list.size() == 0) { // then build the list of fields....
   bool needs_construction = build_obj_list(); 
   // *fix 1.1.0 Don't interfere with attempts to finalize existing ctors or dtors.
   if (! make_method) needs_construction = true;   
   // *fix 1.1.0 Create a default ctor if there's a VMT, even if nothing needs to be constructed
   // *fix 1.2.6 I've uncommented this line, having forgotten why it was commented ;)
   // for GCC3 imports, we really do need to know if something's a 'plain old data struct'!
   if (! needs_construction && ! has_VMT()) return false;
 }

 try {

 if (make_method) {
    begin_method(constructor_name(),t_void,NULL,t_void,IsConstructor);  
 } 

 // *fix 0.9.5 One place where you can construct an abstract base class
 if (!copy_ctor && m_base_entry != NULL && !base_class()->simple_struct()) {
   PExpr ec = construct_op(base_class(), s_entry_map[m_base_entry],false);
   if (ec->is_nil()) throw "cannot construct base class";
   compile(ec);

 // Imported constructors of classes w/ vtables must be followed by 
 // code to (optionally) patch the vtable, if a derived UC class is
 // overriding any methods!
 // *fix 1.2.0 We must emit VTABLE_PATCH for _any_ class which has modified the vtable
 // of some imported ancestor class. (This was only working for directly derived classes!)
    if (vtable_size() > 0)
       Parser::code().out(CodeGenerator::instruction_with_pointer(VTABLE_PATCH,this));
  }

 EntryList::iterator eli;
 FORALL(eli, m_field_list) {
   PEntry pe = *eli;
   bool obj_has_ctor = pe->type.is_object() && as_class(pe)->has_constructors();
   // if there was a class init list, this map has been filled in.
   PExprList pel = s_entry_map[pe];
   if ((!copy_ctor && obj_has_ctor) || pel != NULL) {
       PExpr ec = initialize_op(pe,NULL,pel,0);
       if (ec->is_nil()) throw "cannot initialize member object";
       compile(ec);
   }
 }
 } catch(char *msg) {
   error (msg);
 }
 // *fix 0.9.5 Absolutely essential that this ALWAYS happens!
 s_entry_map.clear();
 if (make_method) end_method();
 return true;
}

void Class::auto_destruct(bool make_method)
{
 using namespace Expressions;
 if (m_obj_list.size() == 0 && !build_obj_list()) return;

 // *fix 1.2.3 Derived objects may have needed the building of a ctor,
 // but that doesn't mean they need a dtor.
 if (m_obj_list.size() == 0 && base_class()->destructor() == NULL) return;
 if (imported()) { // *add 1.2.0 needing to force the import of a class dtor
    declare_method(destructor_name(),t_void,NULL,t_void,IsDestructor);
    return;
 }
 // Build up a list of member fields which have dtors
 EntryList::iterator eli;
 EntryList ls;
 FORALL(eli,m_obj_list)
   if (as_class(*eli)->destructor()) ls.push_back(*eli);
 // *fix 0.9.6 we can bail out if there's no such member fields AND no base dtor
 bool base_has_dtor = m_base_entry != NULL && base_class()->destructor() != NULL;
 if (ls.size()==0 && ! base_has_dtor) return;
 if (make_method) begin_method(destructor_name(),t_void,NULL,t_void,IsDestructor);
 if (base_has_dtor) {
    compile(call_function(base_class()->destructor()));
 }
 // and call the dtor for all such member objects...
 for(eli = ls.begin(); eli != ls.end(); eli++) {
   Function *pd = as_class(*eli)->destructor();
   compile(method_call(pd,entry_op(*eli),NULL));
 }
 if (make_method) end_method();
}

void Class::auto_assign_copy(bool is_assign)
// either creates a default assignment operator,
// or a copy constructor, using memberwise
// assigment/initialization
// Construct these in all cases!
{
 using namespace Expressions;
 // *fix 1.2.7 Ensure that the field list has been updated.
 if (m_field_list.size() == 0) build_obj_list();
  
  char *arg_name = "$obj";
  Type t_const_oref = ref_to(this,true);
  
  PEntry pe;
  PExpr ex,em,ea,eo; 
  Class *bc = base_class();
  if (is_assign) {
   PEntry pe = lookup("="); // *fix 0.9.5 auto-assign calls _inherited_ operator=
   // ea is the formal parameter (const T&)
   ea = entry_op(begin_method("=",ref_to(this,false),arg_name,t_const_oref,IsPlain));
   if (bc && pe) {  // but do we have operator=(const T&) ??
       PExpr efn = function_op(entry_op(pe),expr_list(ea));
       if (!efn->is_nil()) compile(efn);
   } 
  } else { 
   ea = entry_op(begin_method(constructor_name(),t_void,arg_name,t_const_oref,IsConstructor));
   if (bc && bc->copy_constructor()) compile(call_function(bc->copy_constructor(),ea));
  }

  // over all non-function non-static members of this class...
  EntryList::iterator eli;
  FORALL(eli,m_field_list){
     pe = *eli;
     em = entry_op(pe);
     eo = make_op(DOT,pe->type,ea,em);
	 // *fix 1.1.4 Don't enforce constness check when generating these assignments!
     if (is_assign) ex = assign_op(em,eo,false);
     else {
		 // *hack 1.1.4 Ignore arrays when building copy ctor for now
         if (Parser::array_size(pe) > 1) continue; 
         else ex = initialize_op(pe,eo,NULL,0);
     }
     if (ex && !ex->is_nil()) compile(ex);
	 else if (m_obj_list.size() != 0) warning("cannot build assign/copy ctor");
  } 
  // operator= must return its reference argument...
  // Crucial not to _drop_ the stack at this point!
  if (is_assign) Parser::code().compile(ea,0);
  end_method();
}

///// Friendship mangement /////////////
bool Class::is_friend_class(Class *pc)
{
  return is_friend_function(pc);
}

bool Class::is_friend_function(void *fn)
{
 return utils::find(m_friend_objects,(Function *)fn);
}

void Class::add_friend_object(void *pc, bool is_class)
{ 
 m_friend_objects.push_back((Function *)pc);
}

PClass Class::generate_try_block_handler()
{
 using namespace Parser;
 using namespace Expressions;
 // Construct a class with a single 32-bit field and a constructor
 // for initializing same...NB that it has a VMT so that it gets put
 // on the ODS, where we will use it as a unique marker.
  Type  tc = state.add_class(STRUCT,TRY_BLOCK_HANDLER_CLASS,ForwardClass,t_void);  
  Class *pc = tc.as_class();
  pc->next_slot();     // a fiddle, since we don't have any v. methods!
  pc->construct_VMT();
  state.push_context(pc);
  PEntry field = state.add_variable(t_int,"_field_",NULL,None);

  PEntry arg = begin_method(pc->constructor_name(),t_void,"_arg_",t_int,IsConstructor);
  PExpr ea = assign_op(entry_op(field),entry_op(arg));
  code().compile(ea,DROP_VALUE);
  end_method();

  state.pop_context();
  return pc;
}


// *add 1.2.6 the Enum object now carries the list of its members
void Enum::add_entry(PEntry pe)
{
 m_entries.push_back(pe);
}

Table* Enum::context()
{
// we can assume that the entries have been added to the enclosing context
  return m_entries.size() > 0 ? m_entries.front()->context : NULL;
}

string Enum::lookup_value(int val)
{
    EntryList::iterator eli;
    for (eli = m_entries.begin(); eli != m_entries.end(); ++eli) {
        PEntry pe = *eli;
        int entry_val = *(int *)pe->global_ptr();
        if (val == entry_val) return pe->name;
    }
    return "<undef>";
}


namespace {
// private utilities!
bool grab_list(const TypeList& tl1, TypeList& tl2)
 {
   if (tl1.size()==0) return false;
   tl2 = tl1;
   return true;
 }

// these guys provide a simplified way of generating a class method,
// of one or none arguments.  Used to construct default constructors, etc.
PEntry begin_method(string name, Type rtype, char *arg_name, Type atype, int ftype)
{
 using Parser::state;
 Class *ccntxt;
 Sig sig(rtype);
 if (arg_name) sig << arg_name << atype;
 bool wuz_function = state.context().type() == FUNCTION;
 if (wuz_function) ccntxt = (Class *)state.pop_context();
 Function *pfn = Parser::state.start_function(sig.m_type,name.c_str());
 Parser::state.pop_context(); // usually done by block-end!
 if (wuz_function) state.push_context(ccntxt);
 pfn->set_construct_destruct(ftype);
 mFe = pfn->context();
 Parser::state.push_context(pfn->context());
 return mFe->lookup(arg_name);
}

void declare_method(string name, Type rtype, char *arg_name, Type atype, int ftype)
{
 Sig sig(rtype);
 if (arg_name) sig << arg_name << atype;
 Parser::state.set_construct_destruct(ftype);
 Parser::state.declare_function(sig.m_type,name.c_str());
}

void end_method()
{
  mFe->finalize();  
  Parser::state.pop_context(); // see ParserState::finalize_block()
  Parser::state.set_construct_destruct(IsPlain); // *fix 1.2.3b
}

typedef TypeDistance (*TypeMatch) (Type,Type);

Function *get_match(const TypeList& tl, const FunctionList& fl, Type t, TypeMatch tmatch)
{
  TypeList::const_iterator tli;
  FunctionList::const_iterator fli;
  t.strip_qualifiers();
  for(tli = tl.begin(), fli = fl.begin(); tli != tl.end();  ++tli,++fli)
        if (tmatch(*tli,t) != NO_MATCH) return *fli; // *fix 1.1.3 wuz (*tli,t)
  return NULL;
}

Function *get_std_match(const TypeList& tl, const FunctionList& fl, Type t)
{
  Function *pf = get_match(tl,fl,t,trivial_match);
  if (pf) return pf;
  pf = get_match(tl,fl,t,promote_match);
  if (pf) return pf;
  pf = get_match(tl,fl,t,std_match);
  return pf;
}

}

⌨️ 快捷键说明

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