blob: 814822105deef2d14883b0c38e3fd24c0d1e8eeb [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: 5 août 2008
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "InstanceOfData.h"
#include <fml/executable/AvmProgram.h>
#include <fml/executable/BaseAvmProgram.h>
#include <fml/executable/InstanceOfMachine.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/expression/ExpressionFactory.h>
#include <fml/symbol/TableOfSymbol.h>
#include <fml/runtime/RuntimeID.h>
#include <fml/type/ContainerTypeSpecifier.h>
#include <fml/type/EnumTypeSpecifier.h>
namespace sep
{
/**
* DEFAULT
* Empty TableOfSymbol
*/
TableOfSymbol InstanceOfData::NULL_TABLE_OF_SYMBOL(0);
/**
* SETTER
* updateFullyQualifiedNameID()
*/
void InstanceOfData::updateFullyQualifiedNameID()
{
if( hasAstElement() )
{
std::string aFullyQualifiedNameID = getAstFullyQualifiedNameID();
std::string::size_type pos =
aFullyQualifiedNameID.find(FQN_ID_ROOT_SEPARATOR);
if( pos != std::string::npos )
{
setFullyQualifiedNameID( (getModifier().hasFeatureConst() ?
"const" : "inst") + aFullyQualifiedNameID.substr(pos) );
}
else
{
setFullyQualifiedNameID( aFullyQualifiedNameID );
}
}
else if( isTypedEnum() )
{
std::string aFullyQualifiedNameID = getFullyQualifiedNameID();
std::string::size_type pos =
aFullyQualifiedNameID.find(FQN_ID_ROOT_SEPARATOR);
if( pos != std::string::npos )
{
setFullyQualifiedNameID( "enum" + aFullyQualifiedNameID.substr(pos) );
}
}
else
{
setFullyQualifiedNameID("");
}
updateNameID();
}
/**
* GETTER - SETTER
* The Identifier
*/
void InstanceOfData::updateNameID()
{
if( hasParent() )
{
std::string ufiSuffix =
NamedElement::extractNameID( mFullyQualifiedNameID );
if( getParent()->getTypeSpecifier()->isTypedArray() )
{
InstanceOfData * aParent = getParent();
while( (aParent != NULL) &&
aParent->getTypeSpecifier()->isTypedArray() )
{
aParent = aParent->getParent();
}
if( aParent != NULL )
{
setNameID( aParent->getNameID() + "." + ufiSuffix );
}
else
{
setNameID( ufiSuffix );
}
}
else
{
setNameID( getParent()->getNameID() + "." + ufiSuffix );
}
}
else if( hasDataPath() )
{
std::ostringstream oss;
TableOfSymbol::const_iterator it = getDataPath()->begin();
TableOfSymbol::const_iterator itEnd = getDataPath()->end();
for( ; it != itEnd ; ++it )
{
switch( (*it).getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
oss << "." << NamedElement::extractNameID( (*it).getFullyQualifiedNameID() );
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
{
oss << "[" << (*it).getOffset() << "]";
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
oss << "[" << (*it).strValue() << "]";
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "InstanceOfData::updateNameID:> Unexpected "
"POINTER NATURE for the instance of data :>\n"
<< (*it).toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
break;
}
}
}
setNameID( oss.str() );
}
else
{
BaseInstanceForm::updateNameID();
}
}
/**
* GETTER
* mOnWriteRoutine
*/
const BFCode & InstanceOfData::getOnWriteCode() const
{
return( (mOnWriteRoutine != NULL) ?
mOnWriteRoutine->getCode() : BFCode::REF_NULL );
}
/**
* GETTER - SETTER
* mValue
*/
ArrayBF * InstanceOfData::getArrayValue() const
{
return( mValue.as_ptr< ArrayBF >() );
}
bool InstanceOfData::hasArrayValue() const
{
return( mValue.is< ArrayBF >() );
}
BuiltinArray * InstanceOfData::getBuiltinArrayValue() const
{
return( mValue.as_ptr< BuiltinArray >() );
}
bool InstanceOfData::hasBuiltinArrayValue() const
{
return( mValue.is< BuiltinArray >() );
}
/**
* GETTER - SETTER
* mRelativeOffsetPath
*/
std::string InstanceOfData::strOffsetPath(const std::string & tab) const
{
if( hasDataPath() )
{
std::ostringstream oss;
// +1 for << this >> which is the root of the path
avm_size_t pathLength = mRelativeDataPath->size() + 1;
oss << tab << "[ " << mRelativeOffsetPath[0];
for( avm_size_t k = 1 ; k < pathLength ; ++k )
{
oss << " , " << mRelativeOffsetPath[k];
}
oss << " ]";
return( oss.str() );
}
return( "" );
}
void InstanceOfData::updateOffsetPath()
{
if( isUfiOffsetPointer() && hasDataPath() )
{
// +1 for << this >> which is the root of the path
avm_size_t pathLength = mRelativeDataPath->size() + 1;
mRelativeOffsetPath = new avm_size_t[ pathLength ];
mRelativeOffsetPath[0] = this->getOffset();
TableOfSymbol::const_iterator itPath = getDataPath()->begin();
for( avm_size_t k = 1 ; k < pathLength ; ++k, ++itPath )
{
mRelativeOffsetPath[k] = (*itPath).getOffset();
}
}
}
/**
* GETTER - SETTER
* mPointerNature
*/
bool InstanceOfData::isConcreteArrayIndex()
{
return( isUfiOffsetPointer() && hasParent()
&& getParent()->isTypedArray() );
}
bool InstanceOfData::isConcreteStructAttribute()
{
return( hasParent() && isUfiOffsetPointer()
&& getParent()->hasTypeStructureOrChoiceOrUnion() );
}
/**
* Format a value w.r.t. its type
*/
void InstanceOfData::formatStream(
OutStream & out, const BF & bfValue) const
{
if( bfValue.is< ArrayBF >() )
{
formatStream(out, bfValue.as_ref< ArrayBF >());
}
else if( hasTypeSpecifier() )
{
getTypeSpecifier()->formatStream(out, bfValue);
}
else
{
out << bfValue.str();
}
}
void InstanceOfData::formatStream(
OutStream & out, const ArrayBF & arrayValue) const
{
if( hasTypeSpecifier() )
{
getTypeSpecifier()->formatStream(out, arrayValue);
}
else
{
out << arrayValue[0].str();
for( avm_size_t offset = 1 ; offset < arrayValue.size() ; ++offset )
{
out << " , " << arrayValue[offset].str();
}
}
}
/**
* Serialization
*/
void InstanceOfData::strHeader(OutStream & out) const
{
out << getModifier().toString() << "var< id:" << getOffset() << ", ptr:"
<< IPointerDataNature::strPointer( getPointerNature() )
<< ( hasOffsetPath() ? strOffsetPath(", mem:") : "" ) << " > "
<< ( hasTypeSpecifier() ? getTypeSpecifier()->strT() : "" )
<< " " << getFullyQualifiedNameID();
AVM_IF_DEBUG_FLAG2_AND( COMPILING , QUALIFIED_NAME_ID , hasValue() )
out << " =";
strValue( out );
AVM_ENDIF_DEBUG_FLAG2_AND( COMPILING , QUALIFIED_NAME_ID )
AVM_DEBUG_REF_COUNTER(out);
}
std::string InstanceOfData::strHeaderId() const
{
StringOutStream oss;
oss << getModifier().toString() << "var< id:" << getOffset() << ", ptr:"
<< IPointerDataNature::strPointer( getPointerNature() )
<< ( hasOffsetPath() ? strOffsetPath(", mem:") : "" ) << " > "
<< ( hasTypeSpecifier() ? getTypeSpecifier()->strT() : "" )
<< " " << getNameID();
AVM_IF_DEBUG_FLAG2_AND( COMPILING , QUALIFIED_NAME_ID , hasValue() )
oss << " =";
strValue( oss );
AVM_ENDIF_DEBUG_FLAG2_AND( COMPILING , QUALIFIED_NAME_ID )
return( oss.str() );
}
void InstanceOfData::toStream(OutStream & out) const
{
if( out.preferablyFQN() )
{
out << TAB << getFullyQualifiedNameID();
AVM_DEBUG_REF_COUNTER(out);
return;
}
bool isEmpty = true;
out << TAB << getModifier().toString_not( Modifier::FEATURE_CONST_KIND )
<< ( getModifier().hasFeatureConst() ? "const" : "var" )
<< "< id:" << getOffset() << ", ptr:"
<< IPointerDataNature::strPointer( getPointerNature() )
<< ( hasOffsetPath() ? strOffsetPath(", mem:") : "" )
<< " > " ;
if( hasTypeSpecifier() )
{
out << getTypeSpecifier()->strT();
}
out << " " << getFullyQualifiedNameID() << " '" << getNameID() << "'";
AVM_DEBUG_REF_COUNTER(out);
AVM_IF_DEBUG_FLAG( COMPILING )
out << " {" << EOL; isEmpty = false;
if( hasAstElement() )
{
out << TAB2 << "//compiled = "
<< getAstFullyQualifiedNameID() << ";" << EOL;
}
out << TAB2 << "//container = "
<< (hasContainer() ? getContainer()->getFullyQualifiedNameID() : "NULL")
<< ";" << EOL;
AVM_ENDIF_DEBUG_FLAG( COMPILING )
if( hasParent() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "parent = " << str_header( getParent() ) << ";" << EOL;
}
if( hasAliasTarget() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "target = "
<< str_header( getAliasTarget()->as< InstanceOfData >() )
<< ";" << EOL;
}
if( hasCreatorContainerRID() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "rid#creator = " << getCreatorContainerRID().str()
<< ";" << EOL;
}
if( hasRuntimeContainerRID() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "rid#container = " << getRuntimeContainerRID().str()
<< ";" << EOL;
}
if( hasValue() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "value =";
if( getValue().is< AvmCode >() )
{
out << str_indent( getValue().to_ptr< AvmCode >() ) << ";" << EOL;
}
else
{
strValue( out );
out << ";" << EOL;
}
}
if( hasBValue() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB2 << "bvalue =";
if( getBValue().is< AvmCode >() )
{
out << str_indent( getBValue().to_ptr< AvmCode >() ) << ";" << EOL;
}
else
{
strBValue( out );
out << ";" << EOL;
}
}
if( hasMachinePath() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB << "path#machine:" << EOL;
ArrayOfInstanceOfMachine::const_iterator it = getMachinePath()->begin();
ArrayOfInstanceOfMachine::const_iterator itEnd = getMachinePath()->end();
for( ; it != itEnd ; ++it )
{
out << TAB2 << (*it)->getFullyQualifiedNameID() << EOL;
}
}
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , DATA )
if( hasDataPath() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB << "path#data:" << EOL_INCR_INDENT;
getDataPath()->toStream(out);
out << DECR_INDENT;
}
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , DATA )
AVM_IF_DEBUG_LEVEL_FLAG( HIGH , DATA )
if( hasAttribute() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB << "attribute:" << EOL_INCR_INDENT;
getAttribute()->toStream(out);
out << DECR_INDENT;
}
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , DATA )
if(hasOnWriteRoutine() )
{
if( isEmpty ) { out << " {" << EOL; isEmpty = false; }
out << TAB << "moe:" << EOL;
if( hasOnWriteRoutine() )
{
out << TAB2 << "on_write = " << EOL_INCR2_INDENT;
getOnWriteRoutine()->toStream(out);
out << DECR2_INDENT;
}
}
( isEmpty ? (out << ";") : (out << TAB << "}") ) << EOL_FLUSH;
}
}