Logo Search packages:      
Sourcecode: falconpl version File versions  Download package

bool Falcon::VMachine::linkSubClass ( LiveModule mod,
const Symbol clssym,
Map props,
AttribHandler **  attribs 
) [protected]

Service recursive function called by LinkClass to create a class.

Definition at line 709 of file vm.cpp.

References Falcon::Item::asAttribute(), Falcon::AttribHandler::attrib(), Falcon::InheritDef::base(), Falcon::Map::begin(), Falcon::ListElement::data(), Falcon::Symbol::declaredAt(), Falcon::Map::find(), Falcon::Symbol::getClassDef(), Falcon::LiveModule::globals(), Falcon::ClassDef::has(), Falcon::ClassDef::hasnt(), Falcon::ClassDef::inheritance(), Falcon::Map::insert(), Falcon::Item::isAttribute(), Falcon::Symbol::isClass(), Falcon::Symbol::isUndefined(), Falcon::Symbol::itemId(), Falcon::SymModule::liveModule(), Falcon::VMachine::VarDefMod::lmod, Falcon::Symbol::module(), Falcon::Module::name(), Falcon::Symbol::name(), Falcon::AttribHandler::next(), Falcon::ListElement::next(), Falcon::AttribHandler::prev(), Falcon::ClassDef::properties(), raiseError(), Falcon::SymModule::symbol(), and Falcon::VMachine::VarDefMod::vd.

Referenced by linkClass().

{
   // first sub-instantiates all the inheritances.
   ClassDef *cd = clssym->getClassDef();
   ListElement *from_iter = cd->inheritance().begin();
   const Module *class_module = clssym->module();

   while( from_iter != 0 )
   {
      const InheritDef *def = (const InheritDef *) from_iter->data();
      const Symbol *parent = def->base();

      // iterates in the parent. Where is it?
      // 1) in the same module or 2) in the global modules.
      if( parent->isClass() )
      {
         // we create the item anew instead of relying on the already linked item.
         if ( ! linkSubClass( lmod, parent, props, attribs ) )
            return false;
      }
      else if ( parent->isUndefined() )
      {
         const SymModule *sym_mod = findGlobalSymbol( parent->name() );
         // Can't be 0, because we have already linked all the external
         // symbols
         fassert( sym_mod != 0 );

         parent = sym_mod->symbol();
         if ( ! parent->isClass() )
         {
            raiseError(
               new CodeError( ErrorParam( e_inv_inherit, clssym->declaredAt() ).origin( e_orig_vm ).
                  symbol( clssym->name() ).
                  module( class_module->name() ) )
                  );
            return false;
         }
         if ( ! linkSubClass( sym_mod->liveModule(), parent, props, attribs ) )
            return false;
      }
      else
      {
         raiseError( new CodeError( ErrorParam( e_inv_inherit, clssym->declaredAt() ).origin( e_orig_vm ).
                  symbol( clssym->name() ).
                  module( class_module->name() ) )
         );
         return false;
      }
      from_iter = from_iter->next();
   }

   // then copies the vardefs declared in this class.
   MapIterator iter = cd->properties().begin();
   while( iter.hasCurrent() )
   {
      String *key = *(String **) iter.currentKey();
      VarDefMod *value = new VarDefMod;
      value->vd = *(VarDef **) iter.currentValue();
      value->lmod = lmod;
      // TODO: define vardefvalue traits
      VarDefMod **oldValue = (VarDefMod **) props.find( key );
      if ( oldValue != 0 )
         delete *oldValue;
      //==========================
      props.insert( key, value );

      iter.next();
   }

   // and set attributes;
   // first has
   AttribHandler *&head = *attribs;
   ListElement *hiter = cd->has().begin();
   while( hiter != 0 )
   {
      const Symbol *sym = (const Symbol *) hiter->data();
      Item *hitem = lmod->globals().itemAt( sym->itemId() ).dereference();
      if ( hitem->isAttribute() ) {
         if ( head == 0 )
         {
            head = new AttribHandler( hitem->asAttribute(), 0 );
         }
         else
         {
            head->prev( new AttribHandler( hitem->asAttribute(), 0, 0, head ) );
            head = head->prev();
         }
      }
      else {
         raiseError( new CodeError(
            ErrorParam( e_no_attrib, sym->declaredAt() ).origin( e_orig_vm ).
            symbol( sym->name() ).
            module( sym->module()->name() ) )
            );
      }

      hiter = hiter->next();
   }

   // ... then hasnt
   hiter = cd->hasnt().begin();
   while( hiter != 0 )
   {
      const Symbol *sym = (const Symbol *) hiter->data();
      Item *hitem = lmod->globals().itemAt( sym->itemId() ).dereference();
      if ( hitem->isAttribute() )
      {
         AttribHandler *head = *attribs;
         Attribute *att = hitem->asAttribute();
         if ( head != 0 )
         {
            if ( head->attrib() == att )
            {
               *attribs = head->next();
               if ( *attribs )
                  (*attribs)->prev(0);
               delete head;
            }
            else {
               head = head->next();
               while( head != 0 )
               {
                  if ( head->attrib() == att )
                  {
                     head->prev()->next( head->next() );
                     if( head->next() != 0 )
                        head->next()->prev( head->prev() );
                     delete head;
                     break;
                  }
                  head = head->next();
               }
            }
         }
      }
      else {
         raiseError( new CodeError(
            ErrorParam( e_no_attrib, sym->declaredAt() ).origin( e_orig_vm ).
            symbol( sym->name() ).
            module( sym->module()->name() ) )
            );
      }
      hiter = hiter->next();
   }

   return true;
}


Generated by  Doxygen 1.6.0   Back to index