blob: 171d466710e4881a02cfb0f39065624cddf9ade1 [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: 7 déc. 2011
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#ifndef ROUTINE_H_
#define ROUTINE_H_
#include <fml/common/BehavioralElement.h>
#include <fml/common/SpecifierElement.h>
#include <collection/BFContainer.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/StatementConstructor.h>
#include <fml/expression/StatementTypeChecker.h>
#include <fml/operator/Operator.h>
namespace sep
{
class BehavioralPart;
class Machine;
class ObjectElement;
class Variable;
class Routine :
public BehavioralElement,
public SpecifierImpl,
AVM_INJECT_INSTANCE_COUNTER_CLASS( Routine )
{
AVM_DECLARE_CLONABLE_CLASS( Routine )
protected:
/**
* ATTRIBUTES
*/
BF mModel;
BFVector mParameters;
BFVector mReturns;
BFCode mCode;
public:
/**
* CONSTRUCTOR
* Default
*/
Routine(Machine * aContainer, const std::string & aNameID,
const Modifier & aModifier, const Specifier & aSpecifier,
const BF & aModel = BF::REF_NULL);
Routine(BehavioralElement * aContainer, const std::string & aNameID,
const Specifier & aSpecifier =
Specifier::DESIGN_PROTOTYPE_STATIC_SPECIFIER,
const BF & aModel = BF::REF_NULL)
: BehavioralElement( CLASS_KIND_T( Routine ), aContainer, aNameID ),
SpecifierImpl( aSpecifier ),
mModel( aModel ),
mParameters( ),
mReturns( ),
mCode( )
{
//!! NOTHING
}
Routine(const BehavioralPart & aBehavioralPart,
const std::string & aNameID,
const Specifier & aSpecifier =
Specifier::DESIGN_PROTOTYPE_STATIC_SPECIFIER);
public:
inline static Routine * newDefine(
Machine * aContainer, Modifier aModifier,
Specifier aSpecifier, const std::string & aNameID)
{
return( new Routine(aContainer, aNameID, aModifier,
aSpecifier.setDesignModel()) );
}
static Routine * newDefine(
Machine * aContainer, const std::string & aNameID);
inline static Routine * newDefine(
const BehavioralPart & aBehavioralPart,
const std::string & aNameID)
{
return( new Routine(aBehavioralPart, aNameID,
Specifier::DESIGN_MODEL_SPECIFIER) );
}
inline static Routine * newInvoke(
BehavioralElement * aContainer, const std::string & aNameID)
{
return( new Routine(aContainer, aNameID,
Specifier::DESIGN_INSTANCE_DYNAMIC_SPECIFIER) );
}
static Routine * newInvoke(Machine * aContainer, const BF & aModel);
/**
* DESTRUCTOR
*/
virtual ~Routine()
{
//!! NOTHING
}
/**
* GETTER - SETTER
* the Type Specifier
*/
inline const BF & getType() const
{
return( mModel );
}
// inline bool hasType() const
// {
// return( mModel.valid() );
// }
//
// inline void setType(const BF & aType)
// {
// mModel = aType;
// }
//
/**
* GETTER - SETTER
* mModel as Routine Model
*/
inline Routine * getModel() const
{
return( mModel.as_ptr< Routine >() );
}
inline bool hasModel() const
{
return( mModel.is< Routine >() );
}
inline void setModel(const BF & aModel)
{
mModel = aModel;
if( aModel.is< Routine >() )
{
BehavioralElement::setNameID(
aModel.to_ptr< Routine >()->getNameID() );
}
else
{
BehavioralElement::setNameID( aModel.str() );
}
}
// Model as Invokable Operator
inline Operator * getModelOperator() const
{
return( mModel.as_ptr< Operator >() );
}
inline bool hasModelOperator() const
{
return( mModel.is< Operator >() );
}
/**
* GETTER - SETTER
* mCode
*/
inline BFCode & getCode()
{
return( mCode );
}
inline const BFCode & getCode() const
{
return( mCode );
}
inline bool hasCode() const
{
return( mCode.valid() );
}
inline bool doSomething() const
{
return( mCode.valid() && StatementTypeChecker::doSomething(mCode) );
}
inline void setCode(const BFCode & aCode)
{
mCode = aCode;
}
inline void seqCode(const BFCode & aCode)
{
if( mCode.valid() )
{
mCode = StatementConstructor::newCodeFlat(
OperatorManager::OPERATOR_SEQUENCE, mCode, aCode);
}
else
{
mCode = aCode;
}
}
/**
* GETTER - SETTER
* mParameters
*/
inline BFVector & getParameters()
{
return( mParameters );
}
inline const BF & getParameter(avm_offset_t offset) const
{
return( mParameters[offset] );
}
inline const BF & getParameter(const std::string & aNameID) const
{
return( getByNameID(mParameters, aNameID) );
}
avm_offset_t getParameterOffset(const std::string & label) const
{
return( getOffsetByNameID(mParameters, label) );
}
inline bool hasParameters() const
{
return( mParameters.nonempty() );
}
bool hasParameterOffset(Variable * aParameter) const;
inline void appendParameter(const BF & anInput)
{
mParameters.append( anInput );
}
void saveParameter(Variable * anInput);
inline void appendParameter(const std::string & label, const BF & anInput)
{
mParameters.append( anInput );
}
/**
* GETTER - SETTER
* mReturns
*/
inline BFVector & getReturns()
{
return( mReturns );
}
inline const BF & getReturn(avm_offset_t offset) const
{
return( mReturns[offset] );
}
inline const BF & getReturn(const std::string & aNameID) const
{
return( getByNameID(mReturns, aNameID) );
}
avm_offset_t getReturnOffset(const std::string & label) const
{
return( getOffsetByNameID(mReturns, label) );
}
inline bool hasReturns() const
{
return( mReturns.nonempty() );
}
bool hasReturnOffset(Variable * aReturn) const;
inline void appendReturn(const BF & anOutput)
{
mReturns.append( anOutput );
}
void saveReturn(Variable * anOutput);
inline void appendReturn(const std::string & label, const BF & anOutput)
{
mReturns.append( anOutput );
}
/**
* GETTER
* the parameters / returns
*/
inline const BF & getParamReturn(const std::string & aNameID) const
{
const BF & bfParam = getParameter(aNameID);
return( bfParam.valid() ? bfParam : getReturn(aNameID) );
}
static const BF & getByNameID(
const BFVector & params, const std::string & aNameID);
static avm_offset_t getOffsetByNameID(
const BFVector & params, const std::string & label);
/**
* MACRO
* INLINING
*/
inline bool isInlinableStatement() const
{
return( getSpecifier().isDesignInstanceDynamic() && hasModel()
&& getModel()->getModifier().hasNatureMacro() );
}
inline BFCode inlineStatement() const
{
return( inlineCode( getModel()->mCode ) );
}
inline bool isInlinableExpression() const
{
return( getSpecifier().isDesignInstanceDynamic() && hasModel()
&& getModel()->getModifier().hasNatureMacro()
&& getModel()->getReturns().singleton()
&& getModel()->getCode()->isOpCode( AVM_OPCODE_RETURN ) );
}
inline BF inlineExpression() const
{
return( inlineCode( getModel()->mCode->first() ) );
}
BFCode inlineCode(const BFCode & aCode) const;
BF inlineCode(const BF & aCode) const;
/**
* Serialization
*/
void strParameters(OutStream & os, const std::string & sep = ", ") const;
void strReturns(OutStream & os, const std::string & sep = ", ") const;
void strHeader(OutStream & os) const;
void toStream(OutStream & os) const;
void strInvokeParameters(OutStream & os, const std::string & sep = ", ") const;
void strInvokeReturns(OutStream & os, const std::string & sep = ", ") const;
void toStreamInvoke(OutStream & os, const std::string & sep = ", ") const;
};
} /* namespace sep */
#endif /* ROUTINE_H_ */