blob: da7fc83bb7148609116f7423332c4ae20666740e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 10 nov. 2014
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "TransitionReachability.h"
#include <computer/primitive/AvmCommunicationFactory.h>
#include <fml/executable/AvmTransition.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/runtime/ExecutionContext.h>
#include <fml/runtime/ExecutionData.h>
#include <fml/runtime/Message.h>
#include <fml/runtime/RuntimeForm.h>
#include <fml/runtime/RuntimeID.h>
#include <fml/trace/TracePoint.h>
#include <fml/trace/TraceSequence.h>
namespace sep
{
/**
* CONSTRUCTOR
* Default
*/
TransitionReachability::TransitionReachability(const ExecutionContext & anEC,
const RuntimeID & aRID, AvmTransition * aTransition)
: theEC( anEC ),
theED( anEC.refExecutionData() ),
theRID( aRID ),
theTransition( aTransition ),
theTransitionPoint( NULL ),
theTraceElement( ),
theRuntimePathComputingCountLimit( 16 ),
theGoalAchievedFlag( false ),
theVirtualBuffer(theTransition, NULL, 0, TYPE_LIFO_SPECIFIER, -1),
theEmitOutput( & theVirtualBuffer ),
theTableOfRuntimeStatus( *( theED.getRuntimeFormStateTable() ) )
{
//!! NOTHING
}
/**
* UTILS
*/
bool TransitionReachability::initialize()
{
theGoalAchievedFlag = false;
if( theRID.invalid() )
{
if( theED.mRID.getExecutable()->getTransition().contains(theTransition) )
{
theRID = theED.mRID;
}
if( theRID.invalid() )
{
if( theTransitionPoint != NULL )
{
theTransitionPoint->updateRID( theED );
theRID = theTransitionPoint->RID;
}
else
{
theRID = theED.getRuntimeID( theTransition->getExecutable() );
}
}
}
return( theRID.valid() );
}
bool TransitionReachability::computePath()
{
if( initialize() )
{
AvmCommunicationFactory::collectBufferMessage(theED, theEmitOutput);
return( theGoalAchievedFlag = computePath(theRID, theTransition) );
}
return( false );
}
bool TransitionReachability::computePath(TraceSequence & aTraceElement)
{
if( initialize() )
{
AvmCommunicationFactory::collectBufferMessage(theED, theEmitOutput);
if( computePath(theRID, theTransition) )
{
aTraceElement.copyTrace( theTraceElement );
theGoalAchievedFlag = true;
return( true );
}
}
return( false );
}
void TransitionReachability::report(OutStream & os)
{
os << "Trace to reach :> " << theTransition->strTransitionHeader();
theTraceElement.toStream(os);
// os << TAB << "Emit Output :>" << to_stream( theEmitOutput );
os << ( theGoalAchievedFlag ? "NEW" : "NO" ) << " OBJECTIVE !!!" << std::endl;
}
bool TransitionReachability::computePath(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB << "computePath from :> ";
theEC.traceMinimum(AVM_OS_COUT);
AVM_OS_COUT << TAB2 << aRID.strUniqId() << " |==> ";
aTransition->toStreamHeader(AVM_OS_COUT); AVM_OS_COUT << std::endl;
if( aTransition->hasInternalCommunicationCode() )
{
AVM_OS_COUT << TAB2 << "com |==> ";
BaseCompiledForm::toStreamStaticCom(AVM_OS_COUT,
aTransition->getInternalCommunicationCode());
}
AVM_OS_COUT << TAB2 << "Emit Output :>" << to_stream( theEmitOutput )
<< TAB << "end //computePath" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
if( theED.isIdleOrRunning(aRID) )
{
return( fireTransition(aRID, aTransition) );
}
else
{
return( computePathToTransition(aRID, aTransition) );
}
return( false );
}
bool TransitionReachability::fireTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << std::endl
<< TAB << "fireTransition :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl
<< TAB2 << "Emit Output :>" << to_stream( theEmitOutput )
<< TAB << "end //fireTransition" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
theTableOfRuntimeStatus.stateSet(aRID.getOffset(), PROCESS_SUSPENDED_STATE);
if( aTransition->hasInputCom() )
{
ListOfInstanceOfPort anInputTrace( aTransition->getInputCom() );
if( theEmitOutput.uncontains( anInputTrace ) )
{
// trouver des émetteurs pour les INPUT attendu au regard de ED< SC >
while( anInputTrace.nonempty() )
{
if( computePathToInput(aRID, anInputTrace.front()) )
{
anInputTrace.pop_front();
}
else
{
break;
}
}
if( anInputTrace.empty() )
{
traceTransition(aRID, aTransition);
return( true );
}
return( false );
}
else
{
traceTransition(aRID, aTransition);
}
}
else
{
traceTransition(aRID, aTransition);
}
return( true );
}
void TransitionReachability::traceTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
TracePoint * tmpTP = new TracePoint(
ENUM_TRACE_POINT::TRACE_TRANSITION_NATURE,
AVM_OPCODE_INVOKE_TRANSITION, aRID, aTransition);
theTraceElement.points.append( BF(tmpTP) );
// Virtual Eval Of aTransition
if( aTransition->hasOutputCom() )
{
ListOfInstanceOfPort::const_iterator itOutput =
aTransition->getOutputCom().begin();
ListOfInstanceOfPort::const_iterator endOutput =
aTransition->getOutputCom().end();
for( ; itOutput != endOutput ; ++itOutput )
{
theEmitOutput.push( Message(aRID, INCR_BF(*itOutput)) );
}
}
}
bool TransitionReachability::computePathToTransition(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << std::endl
<< TAB << "computePathToTransition using :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
RuntimeID tmpRID = aRID.getPRID();
for( ; tmpRID.valid() ; tmpRID = tmpRID.getPRID() )
{
// AVM_OS_COUT << tmpRID.strUniqId() << " : "
// << tmpRID.getInstance()->getFullyQualifiedNameID() << std::endl;
if( theED.isIdleOrRunning(tmpRID) )
{
break;
}
}
AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( tmpRID )
<< "Runnable Ancestor Statemachine for "
<< aRID.strUniqId() << " in the context of "
<< aTransition->getFullyQualifiedNameID() << " !!!"
<< SEND_EXIT;
const RuntimeForm & tmpRF = theED.getRuntime(tmpRID);
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB2 << "Runnable Ancestor Statemachine :> "
<< tmpRID.str() << std::endl
<< TAB2 << "Runnable Ancestor State Scheduler :> {";
tmpRF.getOnSchedule()->toStreamRoutine( AVM_OS_COUT )
<< TAB2 << "}" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
if( tmpRF.getOnSchedule()->isOpCode( AVM_OPCODE_RUN ) &&
tmpRF.getOnSchedule()->first().is< RuntimeID >() )
{
return( computePathFromRunnable(
tmpRF.getOnSchedule()->first().bfRID(), aTransition) );
}
return( false );
}
bool TransitionReachability::computePathFromRunnable(
const RuntimeID & aRID, AvmTransition * aTransition)
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << std::endl
<< TAB << "computePathFromRunnable using :> " << aRID.strUniqId()
<< " |==> " << aTransition->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
if( not aRID.getExecutable()->
containsForwardReachableTransition(aTransition) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB2 << "Unreachable transition :> "
<< theTransition->strTransitionHeader() << std::endl
<< TAB2 << "from : " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
return( false );
}
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB << "Looking for a path to :> " << aRID.str() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
ListOfAvmTransition oneTransitionPath;
if( computePathToTransition(aRID, aTransition, oneTransitionPath) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << INCR_INDENT;
AvmTransition::toStream(AVM_OS_COUT, oneTransitionPath);
AVM_OS_COUT << DECR_INDENT << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
// All found path
// ListOfListOfAvmTransition allTransitionPaths;
// computePathToTransition(aRID, aTransition, allTransitionPaths);
RuntimeID tmpRID = aRID;
do
{
aTransition = oneTransitionPath.front();
if( fireTransition(tmpRID, aTransition) )
{
oneTransitionPath.pop_front();
if( not computeTargetMachine(tmpRID, aTransition->getCode()) )
{
return( false );
}
}
else
{
break;
}
}
while( oneTransitionPath.nonempty() );
return( oneTransitionPath.empty() );
}
return( false );
}
//bool TransitionReachability::computePathFromRunnable(
// const RuntimeID & aRID, AvmTransition * aTransition)
//{
//AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
// AVM_OS_COUT << std::endl
// << TAB << "computePathFromRunnable using :> " << aRID.strUniqId()
// << " |==> " << aTransition->strTransitionHeader() << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
//
// if( not aRID.getExecutable()->
// containsForwardReachableTransition(aTransition) )
// {
//AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
// AVM_OS_COUT << TAB2 << "Unreachable transition :> "
// << theTransition->strTransitionHeader() << std::endl
// << TAB2 << "from : " << aRID.str() << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
//
// return( false );
// }
//
//
//AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
// AVM_OS_COUT << TAB << "Looking for a path to :> " << aRID.str() << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
//
//
// // All found path
// ListOfListOfAvmTransition allTransitionPaths;
// computePathToTransition(aRID, aTransition, allTransitionPaths);
//
// BFList saveTracePoints( theTraceElement.points );
//
// ListOfAvmTransition oneTransitionPath;
// RuntimeID tmpRID;
//
//// if( computePathToTransition(aRID, aTransition, oneTransitionPath) )
// while( allTransitionPaths.nonempty() )
// {
// oneTransitionPath.clear();
// oneTransitionPath.splice( allTransitionPaths.front() );
// allTransitionPaths.pop_front();
//
//AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
// AVM_OS_COUT << TAB << "Found Path --> "
// << aTransition->getFullyQualifiedNameID() << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_COUT, oneTransitionPath);
// AVM_OS_COUT << DECR_INDENT << std::endl;
//AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
//
// tmpRID = aRID;
// do
// {
// aTransition = oneTransitionPath.front();
//
// if( fireTransition(tmpRID, aTransition) )
// {
// oneTransitionPath.pop_front();
//
// computeTargetMachine(tmpRID, aTransition->getCode());
// }
// else
// {
// break;
// }
// }
// while( oneTransitionPath.nonempty() );
//
// if( oneTransitionPath.empty() )
// {
// return( true );
// }
// else if( allTransitionPaths.empty() )
// {
// return( false );
// }
//
// // BACKTRACK
// else if( saveTracePoints.empty() )
// {
// theTraceElement.points.clear();
// }
// else
// {
// while( theTraceElement.points.back().isNTEQ( saveTracePoints.back() ) )
// {
// theTraceElement.points.pop_back();
// }
// }
// }
//
// return( false );
//}
bool TransitionReachability::computePathToInput(
const RuntimeID & aRID, InstanceOfPort * anInputTrace)
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB << "computePathToInput :> " << std::endl
<< TAB2 << "Expected Input :> "
<< anInputTrace->getFullyQualifiedNameID() << std::endl
<< TAB2 << "Emit Output :>" << to_stream( theEmitOutput )
<< TAB << "end //computePathToInput" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
ExecutableForm * tmpExecutable = NULL;
RuntimeID srcRID;
// Parcourir tous les états et repérer ceux contenant les bons output/outputTo
TableOfRuntimeT::const_iterator itRF = theED.getTableOfRuntime().begin();
TableOfRuntimeT::const_iterator endRF = theED.getTableOfRuntime().end();
for( ; itRF != endRF ; ++itRF )
{
srcRID = (*itRF)->getRID();
tmpExecutable = srcRID.getExecutable();
if( theTableOfRuntimeStatus.isSuspended(srcRID.getOffset()) )
{
//!! Exclude machine
}
else if( theED.isIdleOrRunning( srcRID ) &&
tmpExecutable->getForwardReachableTransition().nonempty() )
{
ListOfAvmTransition::const_iterator itTrans =
tmpExecutable->getForwardReachableTransition().begin();
ListOfAvmTransition::const_iterator endTrans =
tmpExecutable->getForwardReachableTransition().end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (*itTrans)->getOutputCom().contains(anInputTrace) )
{
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB << "found Output in :> " << srcRID.strUniqId() << " |==> "
<< (*itTrans)->strTransitionHeader() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
if( tmpExecutable != (*itTrans)->getExecutable() )
{
if( computePathFromRunnable(srcRID, (*itTrans)) )
{
return( true );
}
}
else if( fireTransition(srcRID, (*itTrans)) )
{
return( true );
}
}
}
}
}
AVM_IF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
AVM_OS_COUT << TAB << "Unfound Input :> "
<< anInputTrace->getFullyQualifiedNameID() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG2( MEDIUM , PROCESSOR , TRANSITION )
return( false );
}
bool TransitionReachability::computePathToTransition(const RuntimeID & aRID,
AvmTransition * aTransition, ListOfAvmTransition & oneTransitionPath)
{
ListOfListOfAvmTransition anyTransitionPaths;
ListOfAvmTransition listOfOutgoingTransition;
InstanceOfMachine * tgtInstance;
// Initialization step
ExecutableForm * fwdMachine = aRID.getExecutable();
fwdMachine->getOutgoingTransition( listOfOutgoingTransition );
ExecutableForm * tgtMachine = fwdMachine;
ListOfAvmTransition::const_iterator itTrans = listOfOutgoingTransition.begin();
ListOfAvmTransition::const_iterator endTrans = listOfOutgoingTransition.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
}
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
anyTransitionPaths.append( ListOfAvmTransition(*itTrans) );
}
}
ListOfAvmTransition aTransitionPath;
// Iterative step
while( anyTransitionPaths.nonempty() )
{
aTransitionPath.clear();
aTransitionPath.splice( anyTransitionPaths.front() );
anyTransitionPaths.pop_front();
if( (tgtInstance = aTransitionPath.back()->getTransitionTarget()) != NULL )
{
fwdMachine = tgtInstance->getExecutable();
}
if( fwdMachine->getTransition().contains(aTransition) )
{
oneTransitionPath.splice( aTransitionPath );
oneTransitionPath.push_back( aTransition );
return( true );
}
else
{
listOfOutgoingTransition.clear();
fwdMachine->getOutgoingTransition( listOfOutgoingTransition );
itTrans = listOfOutgoingTransition.begin();
endTrans = listOfOutgoingTransition.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( not aTransitionPath.contains( *itTrans ) )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
}
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
if( anyTransitionPaths.size() <
theRuntimePathComputingCountLimit )
{
anyTransitionPaths.push_back( aTransitionPath );
anyTransitionPaths.back().push_back( *itTrans );
}
}
}
}
}
}
return( false );
}
bool TransitionReachability::computePathToTransition(const RuntimeID & aRID,
AvmTransition * aTransition, ListOfListOfAvmTransition & allTransitionPaths)
{
ListOfListOfAvmTransition anyTransitionPaths;
ListOfListOfAvmTransition prefixLoopTransitionPaths;
ListOfAvmTransition aTransitionPath;
ListOfAvmTransition listOfOutgoingTransition;
InstanceOfMachine * tgtInstance;
// Initialization step
ExecutableForm * fwdMachine = aRID.getExecutable();
fwdMachine->getOutgoingTransition( listOfOutgoingTransition );
ExecutableForm * tgtMachine = fwdMachine;
ListOfAvmTransition::const_iterator itTrans = listOfOutgoingTransition.begin();
ListOfAvmTransition::const_iterator endTrans = listOfOutgoingTransition.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
}
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
anyTransitionPaths.append( ListOfAvmTransition(*itTrans) );
}
}
// Iterative step
while( anyTransitionPaths.nonempty() )
{
// AVM_OS_COUT << TAB << "TMP found paths :> " << std::endl;
// ListOfListOfAvmTransition::const_iterator itList = allTransitionPaths.begin();
// ListOfListOfAvmTransition::const_iterator endList = allTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_COUT << TAB << "Path number :" << number << ">"
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_COUT, *itList);
// AVM_OS_COUT << std::endl << DECR_INDENT;
// }
//
// AVM_OS_COUT << TAB << "TMP Computing paths :> " << std::endl;
// itList = anyTransitionPaths.begin();
// endList = anyTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_COUT << TAB << "Path number :" << number << ">"
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_COUT, *itList);
// AVM_OS_COUT << DECR_INDENT;
// }
// AVM_OS_COUT << std::endl;
aTransitionPath.clear();
aTransitionPath.splice( anyTransitionPaths.front() );
anyTransitionPaths.pop_front();
if( (tgtInstance = aTransitionPath.back()->getTransitionTarget()) != NULL )
{
fwdMachine = tgtInstance->getExecutable();
}
if( fwdMachine->getTransition().contains(aTransition) )
{
allTransitionPaths.push_back( aTransitionPath );
allTransitionPaths.back().push_back( aTransition );
}
else
{
listOfOutgoingTransition.clear();
fwdMachine->getOutgoingTransition( listOfOutgoingTransition );
itTrans = listOfOutgoingTransition.begin();
endTrans = listOfOutgoingTransition.end();
for( ; itTrans != endTrans ; ++itTrans )
{
if( aTransitionPath.contains( *itTrans ) )
{
prefixLoopTransitionPaths.push_back( aTransitionPath );
prefixLoopTransitionPaths.back().push_back( *itTrans );
}
else
{
if( (tgtInstance = (*itTrans)->getTransitionTarget()) != NULL )
{
tgtMachine = tgtInstance->getExecutable();
}
if( tgtMachine->containsForwardReachableTransition(aTransition) )
{
anyTransitionPaths.push_back( aTransitionPath );
anyTransitionPaths.back().push_back( *itTrans );
}
}
}
}
}
AVM_OS_COUT << TAB << "List of found paths :> " << std::endl;
ListOfListOfAvmTransition::const_iterator itList = allTransitionPaths.begin();
ListOfListOfAvmTransition::const_iterator endList = allTransitionPaths.end();
for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
{
AVM_OS_COUT << TAB << "Path number :" << number << " --> "
<< aTransition->getFullyQualifiedNameID() << std::endl << INCR_INDENT;
AvmTransition::toStream(AVM_OS_COUT, *itList);
AVM_OS_COUT << std::endl << DECR_INDENT;
}
// AVM_OS_COUT << TAB << "List of found prefix-paths :> " << std::endl;
// itList = prefixLoopTransitionPaths.begin();
// endList = prefixLoopTransitionPaths.end();
// for( avm_size_t number = 0 ; itList != endList ; ++itList , ++number )
// {
// AVM_OS_COUT << TAB << "Prefix number :" << number << ">"
// << std::endl << INCR_INDENT;
// AvmTransition::toStream(AVM_OS_COUT, *itList);
// AVM_OS_COUT << std::endl << DECR_INDENT;
// }
return( allTransitionPaths.nonempty() );
}
bool TransitionReachability::computeTargetMachine(
RuntimeID & aRID, AvmCode * aCode)
{
switch( aCode->getAvmOpCode() )
{
case AVM_OPCODE_ENABLE_INVOKE:
case AVM_OPCODE_ENABLE_SET:
{
const BF & targetMachine = aCode->first();
if( targetMachine.is< InstanceOfMachine >() )
{
if( (targetMachine.to_ptr< InstanceOfMachine >()
!= aRID.getInstance())
&& theED.getRuntime(aRID).hasChild() )
{
aRID = theED.getRuntimeFormChild(aRID,
targetMachine.to_ptr< InstanceOfMachine >() );
}
}
else if( targetMachine.is< RuntimeID >() )
{
aRID = targetMachine.bfRID();
}
return( true );
}
case AVM_OPCODE_DISABLE_SELF:
{
aRID = aRID.getPRID();
return( true );
}
case AVM_OPCODE_DISABLE_INVOKE:
{
if( (aCode->first() == ExecutableLib::MACHINE_SELF)
|| (aRID == aCode->first()) )
{
aRID = aRID.getPRID();
return( true );
}
else
{
return( false );
}
}
case AVM_OPCODE_DISABLE_SELVES:
{
if( aCode->first().isInteger() )
{
for( avm_uinteger_t level = aCode->first().toInteger() ;
level > 0 ; --level )
{
aRID = aRID.getPRID();
}
}
else
{
aRID = aRID.getPRID();
}
return( true );
}
default:
{
if( StatementTypeChecker::isSchedule(aCode) )
{
AvmCode::const_iterator it = aCode->begin();
AvmCode::const_iterator endIt = aCode->end();
for( ; it != endIt ; ++it )
{
if( (*it).is< AvmCode >() )
{
if( not computeTargetMachine(aRID,
(*it).to_ptr< AvmCode >()) )
{
return( false );
}
}
}
}
return( true );
}
}
}
} /* namespace sep */