blob: 3d48df39776c5e546c3b809a29f08c8e1105ec15 [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: 15 janv. 2014
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "DataType.h"
#include <fml/type/BaseTypeSpecifier.h>
#include <fml/type/ContainerTypeSpecifier.h>
#include <fml/type/TypeManager.h>
#include <fml/infrastructure/BehavioralPart.h>
#include <fml/infrastructure/Machine.h>
#include <fml/infrastructure/Routine.h>
#include <fml/infrastructure/PropertyPart.h>
namespace sep
{
std::string DataType::ANONYM_ID = "_#type";
/**
* CONSTRUCTOR
* Interval
*/
DataType::DataType(Machine * aContainer, const std::string & aNameID,
const BF & aTypeSpecifier, IIntervalKind::KIND anIntervalKind,
const BF & anInfimum, const BF & aSupremum)
: ObjectElement(CLASS_KIND_T( DataType ), aContainer, aNameID),
mSpecifierKind( TYPE_INTERVAL_SPECIFIER ),
mTypeSpecifier( aTypeSpecifier ),
mConstraintRoutine( NULL ),
mMinimumSize( 1 ),
mMaximumSize( 1 ),
mPropertyPart( NULL ),
mBehavioralSpecification( NULL ),
mIntervalKind( anIntervalKind ),
mInfimum( anInfimum ),
mSupremum( aSupremum )
{
//!! NOTHING
}
/**
* CONSTRUCTOR
* Container
* Alias
*/
DataType::DataType(ObjectElement * aContainer,
const std::string & aNameID,
avm_type_specifier_kind_t aSpecifierKind,
const BF & aTypeSpecifier, long maxSize)
: ObjectElement(CLASS_KIND_T( DataType ), aContainer, aNameID),
mSpecifierKind( aSpecifierKind ),
mTypeSpecifier( aTypeSpecifier ),
mConstraintRoutine( NULL ),
mMinimumSize( 0 ),
mMaximumSize( maxSize ),
mPropertyPart( NULL ),
mBehavioralSpecification( NULL ),
mIntervalKind( IIntervalKind::CLOSED ),
mInfimum( ),
mSupremum( )
{
//!! NOTHING
}
/**
* CONSTRUCTOR
* Enum
* Structure
* Union
*/
DataType::DataType(ObjectElement * aContainer,
const std::string & aNameID,
avm_type_specifier_kind_t aSpecifierKind)
: ObjectElement(CLASS_KIND_T( DataType ), aContainer, aNameID),
mSpecifierKind( aSpecifierKind ),
mTypeSpecifier( ),
mConstraintRoutine( NULL ),
mMinimumSize( 1 ),
mMaximumSize( 1 ),
mPropertyPart( NULL ),
mBehavioralSpecification( NULL ),
mIntervalKind( IIntervalKind::CLOSED ),
mInfimum( ),
mSupremum( )
{
//!! NOTHING
}
/**
* CONSTRUCTOR
* Copy
*/
DataType::DataType(const DataType & aDataType)
: ObjectElement( aDataType ),
mSpecifierKind( aDataType.mSpecifierKind ),
mTypeSpecifier( aDataType.mTypeSpecifier ),
mConstraintRoutine( aDataType.mConstraintRoutine ),
mMinimumSize( aDataType.mMinimumSize ),
mMaximumSize( aDataType.mMaximumSize ),
mPropertyPart( (aDataType.mPropertyPart == NULL) ?
NULL : new PropertyPart( *(aDataType.mPropertyPart) ) ),
mBehavioralSpecification( (aDataType.mBehavioralSpecification == NULL) ?
NULL : new BehavioralPart( *(aDataType.mBehavioralSpecification) ) ),
mIntervalKind( aDataType.mIntervalKind ),
mInfimum( aDataType.mInfimum ),
mSupremum( aDataType.mSupremum )
{
//!! NOTHING
}
/**
* DESTRUCTOR
*/
DataType::~DataType()
{
delete( mPropertyPart );
delete( mBehavioralSpecification );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// INTERVAL
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Interval
*/
DataType * DataType::newInterval(
Machine * aContainer, const std::string & aNameID,
const BF & aTypeSpecifier, IIntervalKind::KIND anIntervalKind,
const BF & anInfimum, const BF & aSupremum)
{
return( new DataType(aContainer, aNameID, aTypeSpecifier,
anIntervalKind, anInfimum, aSupremum) );
}
/**
* GETTER
* Interval Length
*/
avm_integer_t DataType::getIntervalLength()
{
avm_integer_t infBound = AVM_NUMERIC_MIN_INTEGER;
avm_integer_t supBound = AVM_NUMERIC_MAX_INTEGER;
if( mInfimum.isUInteger() )
{
infBound = mInfimum.toUInteger();
}
else if( mInfimum.is< Variable >() )
{
Variable * aVar = mInfimum.to_ptr< Variable >();
if( aVar->hasValue() && aVar->getValue().isUInteger() )
{
infBound = aVar->getValue().toUInteger();
}
else
{
return( -1 );
}
}
else
{
return( -1 );
}
if( mSupremum.isUInteger() )
{
supBound = mSupremum.toUInteger();
}
else if( mSupremum.is< Variable >() )
{
Variable * aVar = mSupremum.to_ptr< Variable >();
if( aVar->hasValue() && aVar->getValue().isUInteger() )
{
supBound = aVar->getValue().toUInteger();
}
else
{
return( -1 );
}
}
else
{
return( -1 );
}
return( supBound - infBound + ( isCLOSED() ? 1 : 0 ) );
}
/**
* Serialization
*/
void DataType::toStreamInterval(OutStream & os) const
{
os << " interval< " << getTypeSpecifier().str() << strIso_Interval() << " >";
if( hasConstraintRoutine() )
{
os << " {" << EOL_INCR_INDENT;
getConstraintRoutine()->toStream(os);
os << DECR_INDENT_TAB << "}";
}
else
{
os << ";";
}
}
////////////////////////////////////////////////////////////////////////////////
// CONTAINER
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Container
*/
DataType * DataType::newContainer(
Machine * aContainer, const std::string & aNameID,
avm_type_specifier_kind_t aSpecifierKind, long aSize)
{
return( new DataType(aContainer, aNameID,
aSpecifierKind, TypeManager::UNIVERSAL, aSize) );
}
DataType * DataType::newContainer(
Machine * aContainer, const std::string & aNameID,
avm_type_specifier_kind_t aSpecifierKind,
const BF & aTypeSpecifier, long aSize)
{
return( new DataType(aContainer, aNameID,
aSpecifierKind, aTypeSpecifier, aSize) );
}
/**
* Serialization
*/
std::string DataType::strContainerId(
avm_type_specifier_kind_t aSpecifierKind, const BF & baseT, long aSize)
{
std::ostringstream oss;
if( aSpecifierKind != TYPE_ARRAY_SPECIFIER )
{
oss << ContainerTypeSpecifier::strSpecifierKing(aSpecifierKind) << "<";
}
if( baseT.valid() )
{
if( baseT == TypeManager::UNIVERSAL)
{
oss << "<universal>";
}
else if( baseT.is< BaseTypeSpecifier >() )
{
oss << baseT.to_ptr< BaseTypeSpecifier >()->strT();
}
else if( baseT.is< DataType >() )
{
oss << baseT.to_ptr< DataType >()->strT();
}
else if( baseT.is< ObjectElement >() )
{
oss << baseT.to_ptr< ObjectElement >()->getNameID();
}
else
{
oss << "<type>";
}
}
else
{
oss << "<null>";
}
if( aSpecifierKind != TYPE_ARRAY_SPECIFIER )
{
if( aSize >= 0 )
{
oss << " , " << aSize << ">";
}
else
{
oss << " , * >";
}
}
else
{
oss << "[ " << aSize << " ]";
}
return( oss.str() );
}
std::string DataType::strContainerId(
avm_type_specifier_kind_t aSpecifierKind, long aSize)
{
std::ostringstream os;
os << ContainerTypeSpecifier::strSpecifierKing(aSpecifierKind);
if( aSize >= 0 )
{
os << "<" << aSize << ">";
}
else
{
os << "<*>";
}
return( os.str() );
}
std::string DataType::strContainerType() const
{
std::ostringstream oss;
if( isTypedArray() )
{
if( mTypeSpecifier.is< BaseTypeSpecifier >() )
{
oss << mTypeSpecifier.to_ptr< BaseTypeSpecifier >()->strT();
}
else if( mTypeSpecifier.is< DataType >() )
{
oss << mTypeSpecifier.to_ptr< DataType >()->strT();
}
oss << "[ " << mMaximumSize << " ]";
}
else
{
oss << ContainerTypeSpecifier::strSpecifierKing(mSpecifierKind);
if( mTypeSpecifier.valid() )
{
if( mTypeSpecifier.is< BaseTypeSpecifier >() )
{
oss << "< " << mTypeSpecifier.to_ptr<
BaseTypeSpecifier >()->strT();
}
else if( mTypeSpecifier.is< DataType >() )
{
oss << "< " << mTypeSpecifier.to_ptr< DataType >()->strT();
}
else if( mTypeSpecifier.is< ObjectElement >() )
{
oss << "< "
<< mTypeSpecifier.to_ptr< ObjectElement >()->getNameID();
}
else
{
oss << "< ?";
}
}
else
{
oss << "< null<type>";
}
if( mMaximumSize >= 0 )
{
oss << " , " << mMaximumSize;
}
oss << " >";
}
return( oss.str() );
}
void DataType::toStreamContainer(OutStream & os) const
{
os << " " << strContainerType();
if( hasConstraintRoutine() )
{
os << " {" << EOL_INCR_INDENT;
getConstraintRoutine()->toStream(os);
os << DECR_INDENT_TAB << "}";
}
else
{
os << ";";
}
}
////////////////////////////////////////////////////////////////////////////////
// ENUMERATIOIN
// STRUCTURE
// UNION
////////////////////////////////////////////////////////////////////////////////
/**
* GETTER
* mPropertyPart
*/
bool DataType::hasProperty() const
{
return( (mPropertyPart != NULL)
&& mPropertyPart->nonempty() );
}
/**
* GETTER - SETTER
* mBehavioralSpecification
*/
BehavioralPart * DataType::getUniqBehaviorPart()
{
if( mBehavioralSpecification == NULL )
{
mBehavioralSpecification = new BehavioralPart(this, "moe");
}
return( mBehavioralSpecification );
}
////////////////////////////////////////////////////////////////////////////////
// ENUMERATIOIN
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Enum
*/
DataType * DataType::newEnum(
const PropertyPart & aPropertyPart, const std::string & aNameID)
{
DataType * newDataType = new DataType(
aPropertyPart.getContainer(), aNameID, TYPE_ENUM_SPECIFIER );
newDataType->setPropertyPart( new PropertyPart(newDataType, "symbol") );
return( newDataType );
}
/**
* GETTER
* Enumeration Size
* Interval Length
*/
avm_size_t DataType::getEnumSize()
{
return( (mPropertyPart != NULL) ? mPropertyPart->getVariables().size() : 0 );
}
/**
* GETTER - SETTER
* mVariables
*/
void DataType::appendVariable(const BF & aVariable)
{
mPropertyPart->appendVariable( aVariable );
}
void DataType::saveVariable(Variable * aVariable)
{
mPropertyPart->saveOwnedVariable( aVariable );
}
/**
* Serialization
*/
void DataType::toStreamEnum(OutStream & os) const
{
os << " enum {" << EOL_FLUSH;
if( mPropertyPart->hasVariable() )
{
TableOfVariable::const_raw_iterator it =
mPropertyPart->getVariables().begin();
TableOfVariable::const_raw_iterator endIt =
mPropertyPart->getVariables().end();
os << TAB2 << (it)->getNameID();
if( (it)->hasValue() )
{
os << " = " << (it)->strValue();
}
for( ++it ; it != endIt ; ++it )
{
os << "," << EOL;
os << TAB2 << (it)->getNameID();
if( (it)->hasValue() )
{
os << " = " << (it)->strValue();
}
}
os << EOL;
}
os << TAB << "}";
}
////////////////////////////////////////////////////////////////////////////////
// STRUCTURE
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Structure
*/
DataType * DataType::newStructure(
const PropertyPart & aPropertyPart, const std::string & aNameID)
{
DataType * newDataType = new DataType(
aPropertyPart.getContainer(), aNameID, TYPE_CLASS_SPECIFIER );
newDataType->setPropertyPart( new PropertyPart(newDataType, "property") );
return( newDataType );
}
/**
* Serialization
*/
void DataType::toStreamStructure(OutStream & os) const
{
os << " struct {" << EOL_FLUSH;
if( hasProperty() )
{
mPropertyPart->toStream(os);
}
if( hasBehavior() && mBehavioralSpecification->hasAnyRoutine() )
{
mBehavioralSpecification->toStreamAnyRoutine( os << EOL );
}
os << TAB << "}";
}
////////////////////////////////////////////////////////////////////////////////
// CHOICE
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Choice
*/
DataType * DataType::newChoice(
const PropertyPart & aPropertyPart, const std::string & aNameID)
{
DataType * newDataType = new DataType(
aPropertyPart.getContainer(), aNameID, TYPE_CHOICE_SPECIFIER );
newDataType->setPropertyPart( new PropertyPart(newDataType, "property") );
return( newDataType );
}
/**
* Serialization
*/
void DataType::toStreamChoice(OutStream & os) const
{
os << " choice {" << EOL_FLUSH;
if( hasProperty() )
{
mPropertyPart->toStream(os);
}
os << TAB << "}";
}
////////////////////////////////////////////////////////////////////////////////
// UNION
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Union
*/
DataType * DataType::newUnion(
const PropertyPart & aPropertyPart, const std::string & aNameID)
{
DataType * newDataType = new DataType(
aPropertyPart.getContainer(), aNameID, TYPE_UNION_SPECIFIER );
newDataType->setPropertyPart( new PropertyPart(newDataType, "property") );
return( newDataType );
}
/**
* Serialization
*/
void DataType::toStreamUnion(OutStream & os) const
{
os << " union {" << EOL_FLUSH;
if( hasProperty() )
{
mPropertyPart->toStream(os);
}
os << TAB << "}";
}
////////////////////////////////////////////////////////////////////////////////
// ALIAS
////////////////////////////////////////////////////////////////////////////////
/**
* CONSTRUCTOR
* Alias
*/
DataType * DataType::newAlias(const PropertyPart & aPropertyPart,
const std::string & aNameID, const BF & aTypeSpecifier)
{
return( new DataType(aPropertyPart.getContainer(),
aNameID, TYPE_ALIAS_SPECIFIER, aTypeSpecifier, 1) );
}
/**
* Serialization
*/
void DataType::toStreamAlias(OutStream & os) const
{
if( mTypeSpecifier.is< BaseTypeSpecifier >() )
{
os << " " << mTypeSpecifier.to_ptr< BaseTypeSpecifier >()->strT();
}
else if( mTypeSpecifier.is< DataType >() )
{
os << " " << mTypeSpecifier.to_ptr< DataType >()->strT();
}
else
{
os << str_indent( mTypeSpecifier );
}
if( mConstraintRoutine!= NULL )
{
os << " {" << EOL_INCR_INDENT;
mConstraintRoutine->toStream(os);
os << DECR_INDENT_TAB << "}";
}
else
{
os << ";";
}
}
/**
* Serialization
*/
std::string DataType::strTypeSpecifier(const BF & aTypeSpecifier)
{
if( aTypeSpecifier.valid() )
{
if( aTypeSpecifier.is< BaseTypeSpecifier >() )
{
return aTypeSpecifier.to_ptr< BaseTypeSpecifier >()->strT();
}
else if( aTypeSpecifier.is< DataType >() )
{
return aTypeSpecifier.to_ptr< DataType >()->strT();
}
else
{
return( OSS() << "type< " << aTypeSpecifier.str() << ">" );
}
}
else
{
return( "type<null>" );
}
}
void DataType::strHeader(OutStream & os) const
{
os << getModifier().toString()
<< "type " << getFullyQualifiedNameID(); //<< getNameID();
if( hasUnrestrictedName() )
{
os << " \"" << getUnrestrictedName() << "\"";
}
}
void DataType::toStream(OutStream & os) const
{
if( os.preferablyFQN() )
{
os << TAB << getFullyQualifiedNameID();
AVM_DEBUG_REF_COUNTER(os);
return;
}
os << TAB << getModifier().toString() << "type " << getNameID();
if( hasTypeContainer() )
{
toStreamContainer(os);
}
else if( isTypedInterval() )
{
toStreamInterval(os);
}
else if( isTypedEnum() )
{
toStreamEnum(os);
}
else if( isTypedStructure() )
{
toStreamStructure(os);
}
else if( isTypedChoice() )
{
toStreamChoice(os);
}
else if( isTypedUnion() )
{
toStreamUnion(os);
}
else// if( isTypedAlias() )
{
toStreamAlias(os);
}
os << EOL_FLUSH;
}
} /* namespace sep */