blob: f5eb0a3dd39e23ec496efafd9c898c303057af18 [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. 2008
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "CompilerOfTransition.h"
#include <builder/analysis/CommunicationDependency.h>
#include <builder/primitive/AvmcodeCompiler.h>
#include <builder/primitive/CompilationEnvironment.h>
#include <builder/compiler/Compiler.h>
#include <builder/compiler/CompilerOfVariable.h>
#include <fml/executable/AvmLambda.h>
#include <fml/executable/ExecutableForm.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/expression/StatementConstructor.h>
#include <fml/expression/StatementFactory.h>
#include <fml/operator/Operator.h>
#include <fml/operator/OperatorManager.h>
#include <fml/infrastructure/BehavioralPart.h>
#include <fml/infrastructure/Transition.h>
namespace sep
{
/**
* CONSTRUCTOR
* Default
*/
CompilerOfTransition::CompilerOfTransition(Compiler & aCompiler)
: BaseCompiler(aCompiler),
mCompiler( aCompiler ),
mDataCompiler( aCompiler.mDataCompiler ),
mMocStack( ),
mCurrentMoc( NULL ),
mDefaultMoc( TransitionMoc::MOE_RDE_RUN )
{
setDefaultMoc();
}
void CompilerOfTransition::setDefaultMoc()
{
mCurrentMoc = & mDefaultMoc;
}
void CompilerOfTransition::pushMoc(WObject * mocTransition)
{
mCurrentMoc = new TransitionMoc( mocTransition );
mMocStack.push_back( mCurrentMoc );
}
void CompilerOfTransition::popMoc()
{
if( mMocStack.nonempty() )
{
delete( mMocStack.pop_last() );
}
if( mMocStack.nonempty() )
{
mCurrentMoc = mMocStack.last();
}
else
{
mCurrentMoc = & mDefaultMoc;
}
}
/**
*******************************************************************************
* PRECOMPILATION
*******************************************************************************
*/
void CompilerOfTransition::precompileTransition(
ExecutableForm * aContainer, Transition * aTransition)
{
// AVM_OS_TRACE << TAB << "<$$$$$ precompiling transition < "
// << aTransition->getFullyQualifiedNameID() << " >" << std::endl;
AvmTransition * anAvmTransition =
new AvmTransition(aContainer, aTransition, 0);
getSymbolTable().addTransition(
aContainer->saveTransition( anAvmTransition ) );
Machine * target = NULL;
if( aTransition->hasTarget() )
{
target = getTransitionTarget(aTransition, aTransition->getTarget());
if( target != NULL )
{
aTransition->getTarget().acquirePointer( target );
target->getUniqBehaviorPart()->
appendIncomingTransition( INCR_BF(aTransition) );
}
}
/*
* Allocation of declaration contents :>
* constant, variable, typedef, buffer, port
*/
if( aTransition->hasDeclaration() )
{
TableOfInstanceOfData tableOfVariable;
mCompiler.precompileDataType(anAvmTransition,
*(aTransition->getDeclaration()), tableOfVariable);
/*
* Update data table
*/
anAvmTransition->setData(tableOfVariable);
}
// AVM_OS_TRACE << TAB << ">$$$$$ end precompiling transition < "
// << aTransition->getFullyQualifiedNameID() << " >" << std::endl;
}
/**
*******************************************************************************
* COMPILATION
*******************************************************************************
*/
/**
* compile
* transition
*/
void CompilerOfTransition::compileTransition(AvmTransition * anAvmTransition)
{
const Transition * aTransition = anAvmTransition->getAstTransition();
// AVM_OS_TRACE << TAB << "<| compiling<transiton>: "
// << TRIM(aTransition->toString(AVM_OS_TRACE.INDENT))
// << std::endl;
const Machine * source = aTransition->getSource();
const Machine * target = NULL;
BF targetVariable;
BF targetMachine;
if( aTransition->hasTarget() )
{
BF tgt = compileTransitionTarget(anAvmTransition, aTransition->getTarget());
if( tgt.valid() )
{
anAvmTransition->setTarget( tgt );
if( tgt.is< InstanceOfMachine >() )
{
target = tgt.to_ptr< InstanceOfMachine >()->getAstMachine();
targetMachine = tgt;
if( target->getSpecifier().isPseudostateInitial() )
{
incrWarningCount();
aTransition->warningLocation(AVM_OS_WARN)
<< "Unexpected the pseudo-state< initial > '"
<< target->getFullyQualifiedNameID()
<< "' as target of the transition : "
<< str_header( aTransition ) << std::endl;
}
}
else if( tgt.is< InstanceOfData >() )
{
targetVariable = tgt;
}
}
}
// By default : the last active state
// Only for Trace usage
else if( not source->getSpecifier().isPseudostate() )
{
anAvmTransition->setTarget(
getSymbolTable().searchInstanceStatic(source) );
//???
// aTransition->setTarget( anAvmTransition->getTarget() );
// aTransition->setTarget( INCR_BF(source) );
}
else
{
// TODO found last stable state !!!
}
// COMPILATION OF DATA
mDataCompiler.compileData(anAvmTransition);
/*
* EVAL transition
*/
BFCode OnRun(OperatorManager::OPERATOR_SEQUENCE);
// DISABLE source / ENABLE target
BFCode disableSource;
BFCode enableTarget;
BFCodeList ienableAtomicSequence;
// DISABLE source
disableSource = StatementConstructor::newCode(
aTransition->hasMocAbort() ?
OperatorManager::OPERATOR_ABORT_INVOKE :
OperatorManager::OPERATOR_DISABLE_INVOKE);
if( targetMachine.valid() )
{
enableTarget = BFCode( OperatorManager::OPERATOR_ENABLE_INVOKE,
targetMachine);
if( target->getSpecifier().hasPseudostateHistory() )
{
//!! moe< statemachine > :> don't invoke ENABLE_SET
}
else if( target->getSpecifier().hasFamilyPseudostateEnding() )
{
enableTarget = StatementConstructor::newCode(
OperatorManager::OPERATOR_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_ENABLE_SET, targetMachine),
enableTarget);
}
else if( target->getSpecifier().isPseudostate() )
{
//!! moe< statemachine > :> no need to invoke ENABLE_SET
}
// TRANSITION INSTABLE
else if( aTransition->getModifier().hasFeatureTransient() )
{
enableTarget = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_IENABLE_INVOKE,
targetMachine),
StatementConstructor::newCode(
OperatorManager::OPERATOR_RUN, targetMachine) );
}
else if( COMPILE_CONTEXT::INLINE_ENABLE_MASK )
{
enableTarget = StatementConstructor::newCode(
OperatorManager::OPERATOR_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_ENABLE_SET, targetMachine),
enableTarget);
}
else
{
enableTarget = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_ENABLE_SET, targetMachine),
enableTarget);
}
if( source == target )
{
if( source->getSpecifier().isPseudostateInitial() )
{
incrErrorCount();
AVM_OS_WARN << source->errorLocation(aTransition)
<< "Unexpected transition loop in initial state << "
<< str_header( source ) << " >> !!!" << std::endl;
}
else if( source->getSpecifier().isPseudostate() )
{
incrWarningCount();
AVM_OS_WARN << source->warningLocation(aTransition)
<< "Transition loop in (unstable) pseudo state << "
<< str_header( source ) << " >> !!!" << std::endl;
}
//!! NOTHING
// BETWEEN DISABLE/ABORT SOURCE
// ==> ENABLE TARGET
}
else if( source->getContainerMachine() == target->getContainerMachine() )
{
//!! NOTHING
// BETWEEN DISABLE/ABORT SOURCE
// ==> ENABLE TARGET
}
else if( source == target->getContainerMachine() )
{
// IDISABLE/IABORT SOURCE
// ==> IENABLE & ENABLE TARGET
disableSource = StatementConstructor::newCode(
aTransition->hasMocAbort() ?
OperatorManager::OPERATOR_IABORT_INVOKE :
OperatorManager::OPERATOR_IDISABLE_INVOKE);
disableSource = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newCode(
aTransition->hasMocAbort() ?
OperatorManager::OPERATOR_ABORT_CHILD :
OperatorManager::OPERATOR_DISABLE_CHILD),
disableSource);
ienableAtomicSequence.push_front(
BFCode(OperatorManager::OPERATOR_IENABLE_INVOKE) );
// ExecutableLib::MACHINE_SELF) );
}
else if( source->getContainerMachine() == target )
{
// DISABLE/ABORT SOURCE & IDISABLE/IABORT CONTAINER
// ==> IENABLE & ENABLE TARGET
disableSource = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
disableSource,
StatementConstructor::newCode(
aTransition->hasMocAbort() ?
OperatorManager::OPERATOR_IABORT_INVOKE :
OperatorManager::OPERATOR_IDISABLE_INVOKE) );
enableTarget = BFCode(
aTransition->getModifier().hasFeatureTransient()
? OperatorManager::OPERATOR_RETURN
: OperatorManager::OPERATOR_ENABLE_INVOKE );
}
else
{
const Machine * lcaMachine = source->LCA(
( target->getSpecifier().hasPseudostateHistory()
|| target->getSpecifier().isPseudostateInitial() ) ?
target->getContainerMachine() : target );
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( lcaMachine ) "LCA( "
<< source->getFullyQualifiedNameID() << " , "
<< target->getFullyQualifiedNameID() << " ) !!!"
<< SEND_EXIT;
if( source != lcaMachine )
{
const Machine * containerOfSource = source->getContainerMachine();
if( containerOfSource != lcaMachine )
{
avm_uinteger_t disableLevel = 1;
for( ; containerOfSource != lcaMachine ; ++disableLevel )
{
containerOfSource =
containerOfSource->getContainerMachine();
}
disableSource = StatementConstructor::newCode(
aTransition->hasMocAbort()
? OperatorManager::OPERATOR_ABORT_SELVES
: OperatorManager::OPERATOR_DISABLE_SELVES,
ExpressionConstructor::newUInteger(disableLevel) );
if( source->hasMachine() )
{
disableSource = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newCode(
aTransition->hasMocAbort() ?
OperatorManager::OPERATOR_ABORT_CHILD :
OperatorManager::OPERATOR_DISABLE_CHILD),
disableSource);
}
}
}
if( target->getContainerMachine() != lcaMachine )
{
const Machine * containerOfTarget = target->getContainerMachine();
for( ; containerOfTarget != lcaMachine ;
containerOfTarget = containerOfTarget->getContainerMachine() )
{
if( (targetMachine = getSymbolTable().searchInstanceStatic(
containerOfTarget)).valid() )
{
ienableAtomicSequence.push_front(
BFCode(OperatorManager::OPERATOR_IENABLE_INVOKE,
targetMachine) );
// ExecutableLib::MACHINE_SELF) );
ienableAtomicSequence.push_front(
BFCode(OperatorManager::OPERATOR_ENABLE_SET,
targetMachine) );
}
else
{
incrErrorCount();
aTransition->errorLocation(AVM_OS_WARN)
<< "Unfound transition target container"
" state instance < "
<< str_header( containerOfTarget )
<< " > where LCA is < "
<< str_header( lcaMachine )<< " >"
<< std::endl
<< aTransition->toString(AVM_TAB1_INDENT)
<< std::endl;
}
}
}
}
}
else if( targetVariable.valid() )
{
enableTarget = BFCode( OperatorManager::OPERATOR_ENABLE_INVOKE,
targetVariable);
enableTarget = StatementConstructor::newCode(
OperatorManager::OPERATOR_ATOMIC_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_ENABLE_SET, targetVariable),
enableTarget);
}
if( aTransition->hasStatement() )
{
// Attention: création possible de variable local dans le conteneur,
// i.e. l'état source de la transition
OnRun->appendFlat( aTransition->getStatement() );
}
/*
* DISABLE source / ENABLE target
*/
if( disableSource.valid() && enableTarget.valid() &&
(! aTransition->isMocInternal()) )
{
switch( mCurrentMoc->getMoeRun() )
{
case TransitionMoc::MOE_RDE_RUN:
{
// OnRun->push_back( disableSource );
// OnRun->push_back( ienableAtomicSequence );
// OnRun->push_back( enableTarget );
if( ienableAtomicSequence.nonempty() )
{
BFCode disableEnableAtomicSequence(
StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
disableSource) );
disableEnableAtomicSequence->push_back(ienableAtomicSequence);
disableEnableAtomicSequence->push_back(enableTarget);
OnRun->push_back( disableEnableAtomicSequence );
}
else
{
OnRun->push_back( StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
disableSource, enableTarget ) );
}
break;
}
case TransitionMoc::MOE_DRE_RUN:
{
OnRun->push_front( disableSource );
if( ienableAtomicSequence.nonempty() )
{
BFCode ienableEnableAtomicSequence(
StatementConstructor::newCode(
OperatorManager::OPERATOR_SEQUENCE,
ienableAtomicSequence) );
ienableEnableAtomicSequence->push_back( enableTarget );
OnRun->push_back( ienableEnableAtomicSequence );
}
else
{
OnRun->push_back( enableTarget );
}
break;
}
case TransitionMoc::MOE_DER_RUN:
{
// OnRun->push_front( enableTarget );
// OnRun->push_front( ienableAtomicSequence );
// OnRun->push_front( disableSource );
if( ienableAtomicSequence.nonempty() )
{
BFCode disableEnableAtomicSequence(
StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
disableSource) );
disableEnableAtomicSequence->push_back( ienableAtomicSequence );
disableEnableAtomicSequence->push_back( enableTarget );
OnRun->push_front( disableEnableAtomicSequence );
}
else
{
OnRun->push_front( StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
disableSource, enableTarget ) );
}
break;
}
case TransitionMoc::MOE_UNDEFINED_RUN:
default:
{
//!!! NOTHING
break;
}
}
}
if( OnRun->nonempty() )
{
anAvmTransition->setCode( mAvmcodeCompiler.
compileStatement(anAvmTransition, OnRun) );
if( aTransition->hasStatement() )
{
// Attention: création possible de variable local dans le conteneur,
// i.e. l'état source de la transition
BFCode aCompiledCode = anAvmTransition->getCode();
// the communication information
bool hasMutableSchedule = false;
anAvmTransition->setCommunicationCode(
CommunicationDependency::getCommunicationCode(
anAvmTransition, aCompiledCode, hasMutableSchedule) );
anAvmTransition->setMutableCommunication( hasMutableSchedule );
anAvmTransition->setInternalCommunicationCode(
CommunicationDependency::getInternalCommunicationCode(
anAvmTransition, aCompiledCode, hasMutableSchedule) );
//??!!??
// if( anAvmTransition->getExecutableContainer()->
// getSpecifier().hasFeatureInputEnabled() )
{
CommunicationDependency::computeInputEnabledCom(
anAvmTransition, aCompiledCode );
CommunicationDependency::computeInputEnabledSave(
anAvmTransition, aCompiledCode );
CommunicationDependency::computeInputCom(
anAvmTransition, aCompiledCode);
CommunicationDependency::computeOutputCom(
anAvmTransition, aCompiledCode);
anAvmTransition->setEnvironmentCom(
CommunicationDependency::getEnvironmentCom(
anAvmTransition, aCompiledCode, hasMutableSchedule) );
anAvmTransition->setEnvironmentInputCom(
CommunicationDependency::getEnvironmentInputCom(
anAvmTransition, aCompiledCode, hasMutableSchedule) );
anAvmTransition->setEnvironmentOutputCom(
CommunicationDependency::getEnvironmentOutputCom(
anAvmTransition, aCompiledCode, hasMutableSchedule) );
// AVM_OS_COUT << "compileTransition:> "
// << str_header( anAvmTransition ) << std::endl;
// anAvmTransition->toStreamStaticCom(AVM_OS_COUT);
}
}
}
else
{
if( OperatorManager::isSchedule(OnRun->getOperator()) )
{
OnRun = StatementConstructor::nopCode();
}
anAvmTransition->setCode( OnRun );
}
// AVM_OS_TRACE << TAB << ">| compiling<transiton>: "
// << aTransition->getFullyQualifiedNameID() << std::endl;
}
/*
* GETTER
* for transition
*/
Machine * CompilerOfTransition::getTransitionTarget(
Transition * aTransition, const BF & smTarget)
{
if( smTarget.is< Machine >() )
{
return( smTarget.to_ptr< Machine >() );
}
else if( smTarget.is< Variable >() )
{
return( NULL );
}
else
{
Machine * tgtMachine = NULL;
Machine * srcMachine = aTransition->getContainer()->as< Machine >();
if( srcMachine->getNameID() == smTarget.str() )
{
return( srcMachine );
}
Machine * containerMachine = srcMachine;
while( containerMachine->hasContainer() &&
containerMachine->getContainer()->is< Machine >() )
{
tgtMachine = containerMachine;
containerMachine = containerMachine->getContainer()->as< Machine >();
tgtMachine = containerMachine->getrecMachine(smTarget.str(), tgtMachine);
if( tgtMachine != NULL )
{
if( tgtMachine->hasContainer()
&& tgtMachine->getContainer()->is< Machine >()
&& tgtMachine->getContainer()->to< Machine >()->
getSpecifier().isMocStateTransitionStructure() )
{
return( tgtMachine );
}
else
{
incrErrorCount();
aTransition->errorLocation(AVM_OS_WARN)
<< "Unexpected transition target without "
"a STATEMACHINE< or > container :> "
<< std::endl
<< TAB << "target state:> " << str_header( tgtMachine )
<< std::endl
<< TAB << "target super:> " << str_header(
tgtMachine->getContainer()->to< Machine >() )
<< std::endl
<< aTransition->toString(AVM_TAB1_INDENT)
<< std::endl;
return( tgtMachine );
}
}
}
if( srcMachine->hasMachine() )
{
Machine * tgtMachine =
srcMachine->getrecMachine(smTarget.str(), NULL);
if( tgtMachine != NULL )
{
if( tgtMachine->hasContainer()
&& tgtMachine->getContainer()->is< Machine >()
&& tgtMachine->getContainer()->to< Machine >()->
getSpecifier().isMocStateTransitionStructure() )
{
incrWarningCount();
aTransition->warningLocation(AVM_OS_WARN)
<< "The transition target is a sub-state"
" of the transition source "
<< std::endl
<< TAB << str_header(
tgtMachine->getContainer()->to< Machine >() )
<< " --> " << str_header( tgtMachine )
<< std::endl
<< aTransition->toString(AVM_TAB1_INDENT)
<< std::endl;
}
else
{
incrErrorCount();
aTransition->errorLocation(AVM_OS_WARN)
<< "Unexpected transition target without "
"a STATEMACHINE< or > container :> "
<< std::endl
<< TAB << "target state:> "
<< str_header( tgtMachine )
<< std::endl
<< TAB << "target super:> " << str_header(
tgtMachine->getContainer()->to< Machine >() )
<< std::endl
<< aTransition->toString(AVM_TAB1_INDENT)
<< std::endl;
}
return( tgtMachine );
}
}
incrErrorCount();
aTransition->errorLocation(AVM_OS_WARN)
<< "Unfound the transition target :> " << smTarget.str()
<< std::endl
<< aTransition->toString(AVM_TAB1_INDENT)
<< std::endl;
return( NULL );
}
}
BF CompilerOfTransition::compileTransitionTarget(
AvmTransition * anAvmTransition, const BF & smTarget)
{
if( smTarget.is< Variable >() )
{
CompilationEnvironment compilENV(anAvmTransition);
return( getSymbolTable().searchDataInstance(
compilENV.mCTX, smTarget.to_ptr< Variable >()) );
// if( not ExpressionTypeChecker::isTyped(TypeManager::MACHINE, smTarget) )
// {
// incrErrorCount();
// anAvmTransition->getAstElement()->errorLocation(AVM_OS_WARN)
// << "Unexpected the transition variable target type :> "
// << str_header( smTarget.to_ptr< Variable >() ) << std::endl;
// }
}
if( smTarget.is< Machine >() )
{
return( getSymbolTable().
searchInstanceStatic(smTarget.to_ptr< Machine >()) );
}
else
{
BFList foundTarget;
getSymbolTable().searchMachineInstanceByQualifiedNameID(
smTarget.str(), foundTarget);
if( foundTarget.singleton() )
{
return( foundTarget.pop_first() );
}
else if( foundTarget.populated() )
{
incrErrorCount();
AVM_OS_WARN << "Indeterminism:> found many target state < "
<< smTarget.str() << " > from program < "
<< str_header( anAvmTransition ) << " > !!!";
while( foundTarget.nonempty() )
{
AVM_OS_WARN << "\n\tFound :> " << str_header(
foundTarget.pop_first().to_ptr< InstanceOfMachine >() );
}
return( foundTarget.pop_first() );
}
else
{
incrErrorCount();
AVM_OS_WARN << "Unfound target state < "
<< smTarget.str() << " > from program < "
<< str_header( anAvmTransition ) << " > !!!";
while( foundTarget.nonempty() )
{
AVM_OS_WARN << "\n\tFound :> " << str_header(
foundTarget.pop_first().to_ptr< InstanceOfMachine >() );
}
return( BF::REF_NULL );
}
}
}
/**
* compile
* list of transition
*/
BFCode CompilerOfTransition::scheduleListOfTransition(
ExecutableForm * anExecutableForm, BFList & listOfTransition)
{
if( listOfTransition.populated() )
{
ListOfBFList schedList;
ListOfInt priorList;
int priority = 0;
BFList * tmpList = new BFList();
schedList.append( tmpList );
priorList.append( priority );
ListOfBFList::iterator itSched;
ListOfBFList::iterator endSched;
ListOfInt::iterator itPrior;
// TRI
BFList::iterator it = listOfTransition.begin();
for( ; it != listOfTransition.end() ; ++it )
{
priority = (*it).to_ptr< AvmTransition >()->
getAstTransition()->getPriority();
itSched = schedList.begin();
endSched = schedList.end();
itPrior = priorList.begin();
for( ; itSched != endSched ; ++itSched , ++itPrior )
{
if( (*itPrior) == priority )
{
(*itSched)->append( (*it) );
break;
}
else if( (mCurrentMoc->isUserPriorityMinFirst() &&
((*itPrior) > priority)) ||
((! mCurrentMoc->isUserPriorityMinFirst()) &&
((*itPrior) < priority)) )
{
tmpList = new BFList();
tmpList->append( (*it) );
schedList.insert( itSched , tmpList );
priorList.insert( itPrior , priority );
break;
}
}
if( itSched == endSched )
{
tmpList = new BFList();
tmpList->append( (*it) );
schedList.append( tmpList );
priorList.append( priority );
}
}
// SCHEDULE
if( schedList.populated() )
{
BFCode aCode(OperatorManager::OPERATOR_PRIOR_GT);
endSched = schedList.end();
for( itSched = schedList.begin() ; itSched != endSched ; ++itSched )
{
if( (*itSched)->populated() )
{
BFCode tmpCode( OperatorManager::OPERATOR_NONDETERMINISM );
BFList::iterator it = (*itSched)->begin();
for( ; it != (*itSched)->end() ; ++it )
{
tmpCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
(*it)) );
}
aCode->append( tmpCode );
}
else if( (*itSched)->nonempty() )
{
aCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
(*itSched)->last()) );
}
delete( (*itSched) );
}
return( aCode );
}
else
{
BFCode aTrans;
if( schedList.last()->populated() )
{
BFCode tmpCode( OperatorManager::OPERATOR_NONDETERMINISM );
BFList::iterator it = schedList.last()->begin();
for( ; it != schedList.last()->end() ; ++it )
{
tmpCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION, (*it)) );
}
aTrans = tmpCode;
}
else if( schedList.last()->nonempty() )
{
aTrans = StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
schedList.last()->last());
}
delete( schedList.last() );
return( aTrans );
}
}
else if( listOfTransition.nonempty() )
{
return( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
listOfTransition.first()) );
}
return( BFCode::REF_NULL );
}
void CompilerOfTransition::compileStatemachineTransition(
ExecutableForm * anExecutableForm, const BFCode & runRoutine)
{
const Machine * aStatemachine = anExecutableForm->getAstMachine();
// AVM_OS_TRACE << TAB << "<| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
bool hasTransition = aStatemachine->hasOutgoingTransition();
/*
* Compiling transition
*/
BFList listOfSimpleTransition;
BFList listOfSimpleElseTransition;
BFList listOfAbortTransition;
BFList listOfAbortElseTransition;
BFList listOfFinalTransition;
BFList listOfFinalElseTransition;
BFList listOfInternalTransition;
BFList listOfInternalElseTransition;
BFList listOfAutoTransition;
BFList listOfAutoElseTransition;
if( hasTransition )
{
ListOfAvmTransition usedTransition;
if( runRoutine.valid() )
{
StatementFactory::collectInvokeTransition(
anExecutableForm, runRoutine, usedTransition);
}
BehavioralPart::const_transition_iterator it =
aStatemachine->getBehavior()->outgoing_transition_begin();
BehavioralPart::const_transition_iterator endIt =
aStatemachine->getBehavior()->outgoing_transition_end();
for( ; it != endIt ; ++it )
{
const BF & compiledTransition =
anExecutableForm->getTransitionByAstElement(it);
if( usedTransition.nonempty() && usedTransition.contains(
compiledTransition.to_ptr< AvmTransition >()) )
{
continue;
}
switch( (it)->getMocKind() )
{
case Transition::MOC_SIMPLE_KIND:
{
listOfSimpleTransition.append(compiledTransition);
break;
}
case Transition::MOC_ELSE_KIND:
case Transition::MOC_SIMPLE_ELSE_KIND:
{
listOfSimpleElseTransition.append(compiledTransition);
break;
}
case Transition::MOC_ABORT_KIND:
{
listOfAbortTransition.append(compiledTransition);
break;
}
case Transition::MOC_ABORT_ELSE_KIND:
{
listOfAbortElseTransition.append(compiledTransition);
break;
}
case Transition::MOC_FINAL_KIND:
{
listOfFinalTransition.append(compiledTransition);
break;
}
case Transition::MOC_FINAL_ELSE_KIND:
{
listOfFinalElseTransition.append(compiledTransition);
break;
}
case Transition::MOC_INTERNAL_KIND:
{
listOfInternalTransition.append(compiledTransition);
break;
}
case Transition::MOC_INTERNAL_ELSE_KIND:
{
listOfInternalElseTransition.append(compiledTransition);
break;
}
case Transition::MOC_AUTO_KIND:
{
listOfAutoTransition.append(compiledTransition);
break;
}
case Transition::MOC_AUTO_ELSE_KIND:
{
listOfAutoElseTransition.append(compiledTransition);
break;
}
case Transition::MOC_UNDEFINED_KIND:
default:
{
incrErrorCount();
(it)->warningLocation(AVM_OS_WARN)
<< "Unexpected transition kind:> "
<< std::endl << (*it) << std::flush;
break;
}
}
}
}
/*
* OnRun
* whith high priority order
*
* StrongAbort Transition
* ActivityDo
* ( Simple Transition or submachine ) depend on MOC
* WeakAbort Transition
* NormalTerminaison Transition
*/
AvmCode::this_container_type listOfOrderArg;
if( hasTransition && runRoutine.valid() )
{
if( aStatemachine->hasModelOfComputation() )
{
}
// Abort Transition
if( listOfAbortTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfAbortTransition) );
}
// Else Transition< abort >
if( listOfAbortElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfAbortElseTransition) );
}
/*
* EVAL
* ( Simple Transition or submachine ) depend on MOC
*/
if( listOfSimpleTransition.nonempty() && runRoutine.valid() )
{
Operator * op = OperatorManager::OPERATOR_PRIOR_GT;
if( (mCurrentMoc->isLcaEnabled() &&
mCurrentMoc->isLcaMinFirst()) ||
(mCurrentMoc->isSourceEnabled() &&
mCurrentMoc->isSourceMinFirst()) )
{
listOfOrderArg.append( StatementConstructor::xnewCodeFlat(op,
runRoutine,
scheduleListOfTransition(
anExecutableForm, listOfSimpleTransition)) );
}
else if( (mCurrentMoc->isLcaEnabled() &&
(! mCurrentMoc->isLcaMinFirst())) ||
(mCurrentMoc->isSourceEnabled() &&
(! mCurrentMoc->isSourceMinFirst())) )
{
listOfOrderArg.append( StatementConstructor::xnewCodeFlat(op,
scheduleListOfTransition(
anExecutableForm, listOfSimpleTransition),
runRoutine) );
}
else
{
op = OperatorManager::OPERATOR_NONDETERMINISM;
listOfOrderArg.append( StatementConstructor::xnewCodeFlat(op,
runRoutine,
scheduleListOfTransition(
anExecutableForm, listOfSimpleTransition)) );
}
}
else if( listOfSimpleTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfSimpleTransition) );
}
else if( runRoutine.valid() )
{
listOfOrderArg.append( runRoutine );
}
// Else Transition< simple >
if( listOfSimpleElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfSimpleElseTransition) );
}
// Final Transition
// Auto Transition
if( listOfAutoTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfAutoTransition) );
}
// Else Transition< auto >
if( listOfAutoElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfAutoElseTransition) );
}
// Internal Transition
if( listOfInternalTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfInternalTransition) );
}
// Else Transition< simple >
if( listOfInternalElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfInternalElseTransition) );
}
}
else if( hasTransition )
{
/*
* OnRun
* StrongAbort Transition >
* ActivityDo >
* Simple Transition >
* WeakAbort Transition >
* NormalTerminaison Transition
*/
// Abort Transition
if( listOfAbortTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(anExecutableForm,
listOfAbortTransition) );
}
// Else Transition< abort >
if( listOfAbortElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(
anExecutableForm, listOfAbortElseTransition) );
}
// Simple Transition
if( listOfSimpleTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(anExecutableForm,
listOfSimpleTransition) );
}
// Else Transition< simple >
if( listOfSimpleElseTransition.nonempty() )
{
listOfOrderArg.append( scheduleListOfTransition(anExecutableForm,
listOfSimpleElseTransition) );
}
// Final Transition
}
else if( runRoutine.valid() )
{
listOfOrderArg.append( runRoutine );
}
/*
* Assemble OnRun code
*/
if( listOfOrderArg.populated() )
{
BFCode aCode = StatementConstructor::newCode(
OperatorManager::OPERATOR_PRIOR_GT, listOfOrderArg);
anExecutableForm->setOnRun( aCode );
}
else if( listOfOrderArg.nonempty() )
{
if( listOfOrderArg.first().is< AvmCode >() )
{
anExecutableForm->setOnRun( listOfOrderArg.first().bfCode() );
}
else
{
anExecutableForm->setOnRun( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
listOfOrderArg.first()) );
}
}
// Final Transition
if( listOfFinalTransition.nonempty() )
{
anExecutableForm->setOnFinal( StatementConstructor::xnewCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
anExecutableForm->getOnFinal(),
scheduleListOfTransition(anExecutableForm,
listOfFinalTransition) ) );
}
// Else Transition< final >
if( listOfFinalElseTransition.nonempty() )
{
anExecutableForm->setOnFinal( StatementConstructor::xnewCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
anExecutableForm->getOnFinal(),
scheduleListOfTransition(anExecutableForm,
listOfFinalElseTransition) ) );
}
// AVM_OS_TRACE << TAB << ">| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
}
void CompilerOfTransition::compileStateForkOutputTransition(
ExecutableForm * anExecutableForm, const BFCode & runRoutine)
{
const Machine * aStatemachine = anExecutableForm->getAstMachine();
// AVM_OS_TRACE << TAB << "<| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
/*
* Schedule transition
*/
BFCode forkCode(OperatorManager::OPERATOR_FORK);
BehavioralPart::const_transition_iterator it =
aStatemachine->getBehavior()->outgoing_transition_begin();
BehavioralPart::const_transition_iterator endIt =
aStatemachine->getBehavior()->outgoing_transition_end();
for( ; it != endIt ; ++it )
{
switch( (it)->getMocKind() )
{
case Transition::MOC_SIMPLE_KIND:
{
forkCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION,
anExecutableForm->getTransitionByAstElement(it)) );
break;
}
case Transition::MOC_ABORT_KIND:
case Transition::MOC_ELSE_KIND:
case Transition::MOC_FINAL_KIND:
case Transition::MOC_INTERNAL_KIND:
case Transition::MOC_AUTO_KIND:
case Transition::MOC_UNDEFINED_KIND:
default:
{
incrErrorCount();
(it)->warningLocation(AVM_OS_WARN)
<< "Unexpected outgoing transition kind:> "
<< (*it) << "for the pseudostate< fork > << "
<< str_header( aStatemachine ) << std::endl;
break;
}
}
}
anExecutableForm->setOnRun( StatementConstructor::xnewCodeFlat(
OperatorManager::OPERATOR_SEQUENCE, runRoutine, forkCode) );
// AVM_OS_TRACE << TAB << ">| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
}
void CompilerOfTransition::compileStateJoinInputTransition(
ExecutableForm * anExecutableForm)
{
const Machine * aStatemachine = anExecutableForm->getAstMachine();
// AVM_OS_TRACE << TAB << "<| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
/*
* Schedule transition
*/
BFCode syncCode(OperatorManager::OPERATOR_STRONG_SYNCHRONOUS);
CompilationEnvironment compilENV(anExecutableForm);
BehavioralPart::const_transition_iterator it =
aStatemachine->getBehavior()->incoming_transition_begin();
BehavioralPart::const_transition_iterator endIt =
aStatemachine->getBehavior()->incoming_transition_end();
for( ; it != endIt ; ++it )
{
switch( (it)->getMocKind() )
{
case Transition::MOC_SIMPLE_KIND:
{
const BF & aTransition =
getSymbolTable().searchTransition(compilENV.mCTX, (it));
if( aTransition.valid() )
{
syncCode->append( StatementConstructor::newCode(
OperatorManager::OPERATOR_INVOKE_TRANSITION, aTransition) );
}
else
{
incrErrorCount();
(it)->warningLocation(AVM_OS_WARN)
<< "compileStateJoinInputTransition:> "
"Unfound incoming transition :"
<< std::endl << (*it) << std::flush;
}
break;
}
case Transition::MOC_ABORT_KIND:
case Transition::MOC_ELSE_KIND:
case Transition::MOC_FINAL_KIND:
case Transition::MOC_INTERNAL_KIND:
case Transition::MOC_AUTO_KIND:
case Transition::MOC_UNDEFINED_KIND:
default:
{
incrErrorCount();
(it)->warningLocation(AVM_OS_WARN)
<< "Unexpected outgoing transition kind:> "
<< std::endl << (*it) << std::flush
<< "for the pseudostate< fork > << "
<< str_header( aStatemachine ) << std::endl;
break;
}
}
}
anExecutableForm->setOnEnable( StatementConstructor::xnewCodeFlat(
OperatorManager::OPERATOR_SEQUENCE,
StatementConstructor::newCode(
OperatorManager::OPERATOR_JOIN, syncCode),
anExecutableForm->getOnEnable()) );
// AVM_OS_TRACE << TAB << ">| compiling<transition> of "
// << str_header( aStatemachine ) << std::endl;
}
}