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

bool Falcon::VMachine::callItemPass ( const Item callable  )  [protected]

Passes current frame to the called item. Used by the PASS opcode, this element removes the local variables and prepares other local variables for the called item, but does not alter the stack frame. As the first ret opcode is hit, control returns to the caller of the item that generated this kind of pass; in other words, the Falcon function using callItem this way is effectively canceled as if never called (you won't see it even in a debug stack frame).

Definition at line 1456 of file vm.cpp.

References Falcon::Item::asFunction(), Falcon::Item::asMethodFunction(), Falcon::Item::asMethodObject(), Falcon::Item::asModule(), Falcon::ExtFuncDef::call(), Falcon::Item::callBom(), callReturn(), Falcon::Module::code(), Falcon::Symbol::getExtFuncDef(), Falcon::Symbol::getFuncDef(), Falcon::LiveModule::globals(), Falcon::Item::isCallable(), Falcon::Symbol::isFunction(), Falcon::FuncDef::locals(), m_bomParams, m_code, m_currentGlobals, m_currentModule, m_pc_next, m_stack, m_stackBase, m_symbol, Falcon::Symbol::module(), Falcon::FuncDef::offset(), paramCount(), Falcon::FuncDef::params(), Falcon::Item::setNil(), and Falcon::Item::type.

{
   Symbol *target;
   FuncDef *tg_def;
   CoreObject *self = 0;
   LiveModule *targetMod;

   if ( ! callable.isCallable() )
      return false;

   switch( callable.type() )
   {
      case FLC_ITEM_FBOM:
      {
         m_bomParams = paramCount();
         bool bomRet = callable.callBom( this );
         callReturn();
         return bomRet;
      }

      case FLC_ITEM_METHOD:
         self = callable.asMethodObject();
         target = callable.asMethodFunction();
         targetMod = callable.asModule();
      break;

      case FLC_ITEM_FUNC:
         target = callable.asFunction();
         targetMod = callable.asModule();
      break;

      default:
         // non callableitem
         return false;
   }

   if ( target->isFunction() )
   {
      tg_def = target->getFuncDef();
      // manage an internal function
      // ensure against optional parameters.

      m_stack->resize( m_stackBase );
      StackFrame &frame = *(StackFrame*) m_stack->at( m_stackBase - VM_FRAME_SPACE );

      if ( frame.m_param_count < tg_def->params() )
      {
         uint32 oldCount = frame.m_param_count;
         uint32 oldBase = m_stackBase;
         m_stackBase += tg_def->params() - frame.m_param_count;
         frame.m_param_count = (byte)tg_def->params();

         m_stack->resize( m_stackBase + VM_FRAME_SPACE ); // fr no more valid

         // reget old frame, it may have been changed
         StackFrame &frame = *(StackFrame*) m_stack->at( oldBase - VM_FRAME_SPACE );

         // now copy the frame in the right position
         StackFrame &newPos = *(StackFrame*)m_stack->at( m_stackBase - VM_FRAME_SPACE );
         newPos = frame;
         for ( ; oldCount < newPos.m_param_count; oldCount++ )
         {
            m_stack->itemAt( m_stackBase - VM_FRAME_SPACE - newPos.m_param_count + oldCount ).setNil();
         }
      }

      // space for locals
      m_stack->resize( m_stackBase + VM_FRAME_SPACE + tg_def->locals() );

      m_code = target->module()->code();
      m_currentModule = target->module();
      m_currentGlobals = &targetMod->globals();

      m_symbol = target;

      //jump
      m_pc_next = tg_def->offset();

      return true;
   }
   else
   {
      m_stack->resize( m_stackBase );
      regA().setNil(); // clear return value if calling external functions
      target->getExtFuncDef()->call( this );
      m_pc_next = ((StackFrame *)m_stack->at( m_stackBase - VM_FRAME_SPACE ))->m_ret_pc;
      callReturn();
   }
   return true;
}


Generated by  Doxygen 1.6.0   Back to index