blob: 9f3102e4aebe9c0827109c9a125ebbd51a728b34 [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: 6 janv. 2012
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "BaseEnvironment.h"
#include <collection/Bitset.h>
#include <computer/ExecutionEnvironment.h>
#include <computer/EvaluationEnvironment.h>
#include <computer/PathConditionProcessor.h>
#include <computer/primitive/AvmPrimitiveProcessor.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/executable/InstanceOfData.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/expression/BuiltinContainer.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/ExpressionTypeChecker.h>
#include <fml/symbol/TableOfSymbol.h>
#include <fml/runtime/ExecutionConfiguration.h>
#include <fml/runtime/LocalRuntime.h>
#include <fml/runtime/RuntimeLib.h>
#include <fml/type/BaseTypeSpecifier.h>
#include <fml/type/ClassTypeSpecifier.h>
#include <fml/type/ContainerTypeSpecifier.h>
#include <fml/type/TypeAliasSpecifier.h>
#include <sew/Configuration.h>
namespace sep
{
/**
* INDEX FOR NEW SYMBOLIC PARAMETER
*/
avm_uint32_t BaseEnvironment::NEW_PARAM_OFFSET = 0;
/**
* GETTER
* Builder
* Configuration
* ExecutableSystem
*/
Builder & BaseEnvironment::getBuilder() const
{
return( PRIMITIVE_PROCESSOR.getBuilder() );
}
Loader & BaseEnvironment::getLoader() const
{
return( PRIMITIVE_PROCESSOR.getLoader() );
}
SymbexEngine & BaseEnvironment::getSymbexEngine() const
{
return( PRIMITIVE_PROCESSOR.getSymbexEngine() );
}
Configuration & BaseEnvironment::getConfiguration() const
{
return( PRIMITIVE_PROCESSOR.getConfiguration() );
}
ExecutableSystem & BaseEnvironment::getExecutableSystem() const
{
return( PRIMITIVE_PROCESSOR.getConfiguration().getExecutableSystem() );
}
/**
* Serialization
*/
void BaseEnvironment::toStream(OutStream & os) const
{
os << TAB << "inEC : ";
inEC->traceDefault(os << NEW_LTRIM_INDENT(os));
os << END_INDENT << TAB << "inED : ";
inED->toStream(os << NEW_LTRIM_INDENT(os));
os << END_INDENT << TAB << "inFORM : " << inFORM.str() << EOL;
os << TAB << "inCODE : " << inCODE.str() << EOL;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// SYMBOLIC PARAMETRE CREATION
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
InstanceOfData * BaseEnvironment::create(const RuntimeID & aRID,
BaseTypeSpecifier * aTypeSpecifier, InstanceOfData * lvalue)
{
/*
* préfixage de l'UFI de la constante symbolique
* par le nom de l'instance conteneur
*/
std::ostringstream ossUfi;
std::ostringstream ossId;
//AVM_IF_DEBUG_FLAG( LOADING )
// ossUfi << aRID.getInstance()->getFullyQualifiedNameID()
// << lvalue->getAstFullyQualifiedNameID().substr(
// aRID.getExecutable()->getFullyQualifiedNameID().size());
//_AVM_ELSE_
ossUfi << "pid#" << aRID.getRid() << ":" << lvalue->getNameID();
ossId << lvalue->getNameID();
//AVM_ENDIF_DEBUG_FLAG( LOADING )
avm_uint32_t instNumber = lvalue->instanciationCountIncr();
ossUfi << "#" << instNumber;
ossId << "#" << instNumber;
InstanceOfData * theSymbolicParam = new InstanceOfData(
IPointerDataNature::POINTER_STANDARD_NATURE,
aRID.getExecutable(), lvalue->getAstElement(),
aTypeSpecifier, ossUfi.str(), 0,
Modifier::PARAMETER_PUBLIC_FINAL_STATIC_MODIFIER );
theSymbolicParam->setCreatorContainerRID( aRID );
theSymbolicParam->setNameID( ossId.str() );
return( theSymbolicParam );
}
BF BaseEnvironment::evalInitial(
APExecutionData & anED, const RuntimeID & aRID,
InstanceOfData * lvalue, const BF & anInitialValue)
{
if( anInitialValue.invalid() )
{
return( anInitialValue );
}
else if( anInitialValue.is< InstanceOfData >() )
{
if( anInitialValue.isTEQ(ExecutableLib::MACHINE_SELF) )
{
return( aRID );
}
else if( anInitialValue.isTEQ(ExecutableLib::MACHINE_PARENT) )
{
return( aRID.getPRID() );
}
}
else if( anInitialValue.is< InstanceOfMachine >() )
{
if( anInitialValue.isTEQ(ExecutableLib::MACHINE_ENVIRONMENT) )
{
return( RuntimeLib::RID_ENVIRONMENT );
}
else if( anInitialValue.isTEQ(ExecutableLib::MACHINE_NULL) )
{
return( RuntimeLib::RID_NIL );
}
}
else if( anInitialValue.is< ArrayBF >() )
{
ArrayBF * anInitialBuiltinArray = anInitialValue.to_ptr< ArrayBF >();
avm_size_t aSize = anInitialBuiltinArray->size();
for( avm_size_t offset = 0 ; offset < aSize ; ++offset )
{
BF & valOffset = anInitialBuiltinArray->at(offset);
valOffset = evalInitial(anED, aRID, lvalue, valOffset);
}
return( anInitialValue );
}
else if( anInitialValue.is< BuiltinArray >() )
{
return( anInitialValue );
}
else if( anInitialValue.is< BuiltinContainer >() )
{
BuiltinContainer * anInitialBuiltinContainer =
anInitialValue.to_ptr< BuiltinContainer >();
avm_size_t aSize = anInitialBuiltinContainer->size();
for( avm_size_t offset = 0 ; offset < aSize ; ++offset )
{
BF valOffset = anInitialBuiltinContainer->at(offset);
valOffset = evalInitial(anED, aRID, lvalue, valOffset);
}
return( anInitialValue );
}
return( anInitialValue );
}
BF BaseEnvironment::createInitial(APExecutionData & anED,
const RuntimeID & aRID, InstanceOfData * lvalue)
{
BF theInitialValue = lvalue->getValue();
if( lvalue->getModifier().hasNatureMacro() )
{
AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( theInitialValue )
<< "BaseEnvironment::createInitial:> "
"Unexpected an instance macro << "
<< lvalue->getFullyQualifiedNameID() << " >> without initial value !!!"
<< SEND_EXIT;
return( theInitialValue );
}
else if( lvalue->getModifier().hasNatureReference() )
{
if( theInitialValue.is< InstanceOfData >() )
{
InstanceOfData * theInitialInstance =
theInitialValue.to_ptr< InstanceOfData >();
if( theInitialInstance->getModifier().hasFeatureMutable() )
{
if( ExpressionTypeChecker::weaklyTyped(lvalue->getTypeSpecifier(),
theInitialInstance->getTypeSpecifier()))
{
return( theInitialValue );
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::createInitial:> "
"Unexpected an instance << "
<< str_header( lvalue )
<< " >> with non mutable initial instance << "
<< str_header( theInitialInstance ) << " >> !!!"
<< SEND_EXIT;
}
}
else if( theInitialValue.valid() )
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::createInitial:> "
"Unexpected an instance << "
<< str_header( lvalue ) << " >> with initial value <<"
<< str_indent( theInitialValue ) << " >> !!!"
<< SEND_EXIT;
}
else
{
return( anED.saveParameter( create(aRID, lvalue) ) );
}
}
else if( theInitialValue.is< InstanceOfData >() )
{
InstanceOfData * theInitialInstance =
theInitialValue.to_ptr< InstanceOfData >();
if( theInitialInstance->getModifier().
hasModifierPublicFinalStaticParameter() )
{
if( ExpressionTypeChecker::weaklyTyped(lvalue->getTypeSpecifier(),
theInitialInstance->getTypeSpecifier()))
{
return( theInitialValue );
}
}
else if( theInitialInstance->hasValue() )
{
theInitialValue = theInitialInstance->getValue();
}
else if( theInitialInstance->getModifier().hasFeatureMutable() )
{
theInitialValue = getRvalue(anED, aRID, theInitialInstance);
if( theInitialValue.invalid() )
{
theInitialValue = createInitial(anED, aRID, theInitialInstance);
theInitialInstance->setValue(theInitialValue);
}
if( ExpressionTypeChecker::weaklyTyped(lvalue->getTypeSpecifier(),
theInitialInstance->getTypeSpecifier()))
{
return( theInitialValue );
}
}
}
theInitialValue = evalInitial(anED, aRID, lvalue, theInitialValue);
if( lvalue->hasTypeSpecifier() )
{
BaseTypeSpecifier * aTypeSpecifier = lvalue->getTypeSpecifier();
if( aTypeSpecifier->is< TypeAliasSpecifier >() )
{
aTypeSpecifier = aTypeSpecifier->to< TypeAliasSpecifier >()->
targetTypeSpecifier();
}
if( aTypeSpecifier->isTypedArray() )
{
ContainerTypeSpecifier * containerT =
aTypeSpecifier->as< ContainerTypeSpecifier >();
avm_size_t sizeT = containerT->size();
if( theInitialValue.valid() )
{
if( theInitialValue.is< BuiltinArray >() )
{
return( createInitial(anED, aRID, lvalue,
theInitialValue.to_ptr< BuiltinArray >()) );
}
else
{
return( BF( new ArrayBF(containerT, theInitialValue) ));
}
}
else
{
ArrayBF * arrayValue = new ArrayBF(aTypeSpecifier, sizeT);
TableOfSymbol::iterator it = lvalue->getAttribute()->begin();
for( avm_size_t idx = 0 ; idx < sizeT ; ++idx , ++it )
{
arrayValue->set(idx, createInitial(anED, aRID, (*it)));
}
return( BF(arrayValue) );
}
}
else if( aTypeSpecifier->hasTypeCollection() )
{
BuiltinContainer * containerValue = BuiltinContainer::create(
aTypeSpecifier->as< ContainerTypeSpecifier >() );
if( theInitialValue.valid() )
{
if( theInitialValue.is< BuiltinArray >() )
{
BuiltinArray * theInitialBuiltinArray =
theInitialValue.to_ptr< BuiltinArray >();
containerValue->copy( theInitialBuiltinArray,
std::min(containerValue->capacity(),
theInitialBuiltinArray->size()) );
}
else
{
containerValue->add( theInitialValue );
}
}
return( BF(containerValue) );
}
else if( aTypeSpecifier->isTypedClass() )
{
avm_size_t sizeT = aTypeSpecifier->size();
if( theInitialValue.valid() )
{
if( theInitialValue.is< BuiltinArray >() )
{
return( createInitial(anED, aRID, lvalue,
theInitialValue.to_ptr< BuiltinArray >()) );
}
else
{
return( BF( new ArrayBF(
aTypeSpecifier, sizeT, theInitialValue )));
}
}
else
{
ArrayBF * arrayValue = new ArrayBF(aTypeSpecifier, sizeT);
TableOfSymbol::iterator it = lvalue->getAttribute()->begin();
for( avm_size_t idx = 0 ; idx < sizeT ; ++idx , ++it )
{
arrayValue->set(idx, createInitial(anED, aRID, (*it)));
}
return( BF(arrayValue) );
}
}
else //if( aTypeSpecifier->isTypedSimple() )
{
if( theInitialValue.valid() )
{
return( theInitialValue );
}
// else if( aTypeSpecifier->isTypedString() )
// {
// return( ExpressionConstructor::newString("") );
// }
else if( aTypeSpecifier->isTypedMachine() )
{
return( RuntimeLib::RID_NIL );
}
else if( aTypeSpecifier->isTypedChannel() )
{
return( ExecutableLib::CHANNEL_NIL );
}
else if( aTypeSpecifier->isTypedPort() )
{
return( ExecutableLib::PORT_NIL );
}
else if( aTypeSpecifier->isTypedBuffer() )
{
return( ExecutableLib::BUFFER_NIL );
}
else
{
return( anED.saveParameter( create(aRID, lvalue) ) );
}
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::createInitial:> Unexpected an instance << "
<< lvalue->getFullyQualifiedNameID() << " >> without typeSpecifier !!!"
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
BF BaseEnvironment::createInitial(
APExecutionData & anED, const RuntimeID & aRID,
InstanceOfData * lvalue, BuiltinArray * initialArray)
{
avm_size_t sizeT = lvalue->getTypeSpecifier()->size();
ArrayBF * bfValue = new ArrayBF(
( initialArray->hasTypeSpecifier() ?
initialArray->getTypeSpecifier() :
lvalue->getTypeSpecifier() ), sizeT);
if( ExpressionTypeChecker::isFinalSymbolicCompositeSymbol(initialArray) )
{
avm_size_t idx = initialArray->size();
if( idx <= sizeT )
{
bfValue->copy(initialArray, idx);
for( ; idx < sizeT ; ++idx )
{
bfValue->set(idx, createInitial(anED, aRID,
lvalue->getAttribute()->at(idx)));
}
}
else
{
bfValue->copy(initialArray, sizeT);
}
}
else //if( initialArray->is< ArrayBF >() )
{
ArrayBF * bfInitialArray = initialArray->to< ArrayBF >();
avm_size_t initSizeT = bfInitialArray->size();
if( initSizeT > sizeT )
{
initSizeT = sizeT;
}
for( avm_size_t idx = 0 ; idx < initSizeT ; ++idx )
{
if( ExpressionTypeChecker::isFinalSymbolicSymbol(
bfInitialArray->at(idx)) )
{
bfValue->set(idx, bfInitialArray->at(idx));
}
else
{
bfValue->set(idx, createInitial(anED, aRID,
lvalue->getAttribute()->at(idx)));
}
}
for( avm_size_t idx = initSizeT ; idx < sizeT ; ++idx )
{
bfValue->set(idx, createInitial(anED, aRID,
lvalue->getAttribute()->at(idx)));
}
}
return( BF(bfValue) );
}
BF BaseEnvironment::createNewFreshParam(const RuntimeID & aRID,
BaseTypeSpecifier * aTypeSpecifier,
InstanceOfData * lvalue, BFList & paramList)
{
if( aTypeSpecifier != NULL )
{
if( aTypeSpecifier->is< TypeAliasSpecifier >() )
{
aTypeSpecifier->to< TypeAliasSpecifier >()->targetTypeSpecifier();
}
if( aTypeSpecifier->isTypedArray() )
{
ContainerTypeSpecifier * containerT =
aTypeSpecifier->as< ContainerTypeSpecifier >();
avm_size_t sizeT = containerT->size();
ArrayBF * arrayValue = new ArrayBF(containerT, sizeT);
TableOfSymbol::iterator it = lvalue->getAttribute()->begin();
for( avm_size_t idx = 0 ; idx < sizeT ; ++idx , ++it )
{
arrayValue->set(idx,
createNewFreshParam(aRID, (*it), paramList));
}
return( BF(arrayValue) );
}
//TODO
else if( aTypeSpecifier->hasTypeCollection() )
{
BuiltinContainer * containerValue = BuiltinContainer::create(
aTypeSpecifier->as< ContainerTypeSpecifier >());
return( BF(containerValue) );
}
else if( aTypeSpecifier->isTypedClass() )
{
ClassTypeSpecifier * classType =
aTypeSpecifier->as< ClassTypeSpecifier >();
avm_size_t sizeT = classType->size();
ArrayBF * arrayValue = new ArrayBF(aTypeSpecifier, sizeT);
TableOfSymbol::iterator it = lvalue->getAttribute()->begin();
for( avm_size_t idx = 0 ; idx < sizeT ; ++idx , ++it )
{
arrayValue->set(idx,
createNewFreshParam(aRID, (*it), paramList));
}
return( BF(arrayValue) );
}
else //if( aTypeSpecifier->isTypedSimple() )
{
// if( aTypeSpecifier->isTypedString() )
// {
// return( ExpressionConstructor::newString("") );
// }
// else
// if( aTypeSpecifier->isTypedMachine() )
// {
// return( RuntimeLib::RID_NIL );
// }
// else
{
BF aNewFreshParam( create(aRID, aTypeSpecifier, lvalue) );
paramList.append( aNewFreshParam );
return( aNewFreshParam );
}
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "getInitialValue:> Unexpected an instance << "
<< lvalue->getFullyQualifiedNameID() << " >> without typeSpecifier !!!"
<< SEND_EXIT;
return( BF::REF_NULL );
}
return( BF::REF_NULL );
}
Symbol BaseEnvironment::create(
const RuntimeID & aRID, const std::string & paramID,
const TypeSpecifier & aTypeSpecifier, const BF & aValue)
{
std::ostringstream ossUfi;
ossUfi << "pid#" << aRID.getRid()
<< ":" << paramID << "#" << ++NEW_PARAM_OFFSET;
Symbol theSymbolicParam( new InstanceOfData(
IPointerDataNature::POINTER_STANDARD_NATURE,
aRID.getExecutable(), NULL, aTypeSpecifier, ossUfi.str(), 0,
Modifier::PARAMETER_PUBLIC_FINAL_STATIC_MODIFIER) );
theSymbolicParam.setCreatorContainerRID( aRID );
theSymbolicParam.setNameID( ossUfi.str() );
theSymbolicParam.setValue( aValue );
theSymbolicParam.setInstanciationCount(NEW_PARAM_OFFSET);
return( Symbol( theSymbolicParam ) );
}
Symbol BaseEnvironment::create4ArrayAccess(APExecutionData & apED,
const RuntimeID & aRID, const BF & arrayValue,
InstanceOfData * lvalueOfIndex)
{
std::ostringstream ossUFI;
std::ostringstream ossID;
ossUFI << "pid#" << aRID.getRid() << ":";
ossUFI << lvalueOfIndex->getContainer()->
getData().rawAt(lvalueOfIndex->getOffset())->getAstNameID();
ossUFI << "#" << ++NEW_PARAM_OFFSET;
// lvalueOfIndex->incrInstanciationCount();
ossID << ossUFI.str();
Symbol newParam;
TableOfSymbol aRelativeDataPath;
TableOfSymbol::iterator itEnd = lvalueOfIndex->getDataPath()->end();
TableOfSymbol::iterator it = lvalueOfIndex->getDataPath()->begin();
switch( lvalueOfIndex->getPointerNature() )
{
case IPointerDataNature::POINTER_UFI_OFFSET_NATURE:
{
for( ; it != itEnd ; ++it )
{
ossUFI << "[" << (*it).getOffset() << "]";
ossID << "[" << (*it).getOffset() << "]";
}
newParam = new InstanceOfData(
lvalueOfIndex->getPointerNature(), aRID.getExecutable(),
lvalueOfIndex, *(lvalueOfIndex->getDataPath()) );
break;
}
case IPointerDataNature::POINTER_UFI_RUNTIME_NATURE:
{
// NO +1 for << this >> which is the root of the path
avm_size_t pathLength = lvalueOfIndex->getDataPath()->size();
avm_size_t * theOffsetPath = lvalueOfIndex->getOffsetPath();
for( avm_size_t k = 1 ; k < pathLength ; ++k )
{
ossUFI << "[" << theOffsetPath[k] << "]";
ossID << "[" << theOffsetPath[k] << "]";
}
newParam = new InstanceOfData(
lvalueOfIndex->getPointerNature(), aRID.getExecutable(),
lvalueOfIndex, *(lvalueOfIndex->getDataPath()) );
break;
}
case IPointerDataNature::POINTER_UFI_MIXED_NATURE:
{
Symbol symbolicIndex;
for( ; it != itEnd ; ++it )
{
switch( (*it).getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
{
symbolicIndex = new InstanceOfData(
IPointerDataNature::
POINTER_FIELD_ARRAY_OFFSET_NATURE,
(*it).getContainer(), (*it).getAstElement(),
(*it).getTypeSpecifier(), (*it).getOffset() );
ossUFI << "." << symbolicIndex.str();
ossID << "." << symbolicIndex.str();
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
{
symbolicIndex = new InstanceOfData(
IPointerDataNature::
POINTER_FIELD_ARRAY_OFFSET_NATURE,
(*it).getContainer(), (*it).getAstElement(),
(*it).getTypeSpecifier(), (*it).getOffset() );
ossUFI << "[" << symbolicIndex.str() << "]";
ossID << "[" << symbolicIndex.str() << "]";
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED, aRID);
if( eENV.eval((*it).getValue()) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< (*it).strValue() << " >> in variable << "
<< lvalueOfIndex->str()
<< " >> for initializing a VVT !!!"
<< SEND_EXIT;
return( Symbol::REF_NULL );
}
if( eENV.outVAL.isNumeric() )
{
symbolicIndex = new InstanceOfData(
IPointerDataNature::
POINTER_FIELD_ARRAY_OFFSET_NATURE,
(*it).getContainer(), (*it).getAstElement(),
(*it).getTypeSpecifier(),
eENV.outVAL.toInteger() );
}
else
{
symbolicIndex = new InstanceOfData(
IPointerDataNature::
POINTER_FIELD_ARRAY_INDEX_NATURE,
(*it).getContainer(), (*it).getAstElement(),
(*it).getTypeSpecifier(), 0 );
symbolicIndex.setValue( eENV.outVAL );
}
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , DATA )
AVM_OS_TRACE << "indexArray:> " << eENV.outVAL.toString() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , DATA )
ossUFI << "[" << eENV.outVAL.str() << "]";
ossID << "[" << eENV.outVAL.str() << "]";
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "SymbolicParameterFactory::create4ArrayAccess:> "
"Unexpected POINTER NATURE "
"for the instance of data :>\n"
<< (*it).toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( Symbol::REF_NULL );
}
}
aRelativeDataPath.append(symbolicIndex);
}
newParam = new InstanceOfData(lvalueOfIndex->getPointerNature(),
aRID.getExecutable(), lvalueOfIndex, aRelativeDataPath);
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "SymbolicParameterFactory::create4ArrayAccess:> "
"Unexpected POINTER NATURE "
"for the instance of index :>\n"
<< lvalueOfIndex->toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( Symbol::REF_NULL );
}
}
newParam.setValue( arrayValue );
newParam.updateFullyQualifiedNameID( ossUFI.str() , ossID.str() );
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , DATA )
AVM_OS_TRACE << newParam.toString() << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , DATA )
return( newParam );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
///// the DATA ACCESS statement
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
*******************************************************************************
* GETTER
* Assigned Flags
*******************************************************************************
*/
bool BaseEnvironment::isAssigned(const APExecutionData & apED,
const RuntimeID & aRID, InstanceOfData * lvalue)
{
if( lvalue->hasRuntimeContainerRID() )
{
return( apED->isAssigned(
lvalue->getRuntimeContainerRID(), lvalue->getOffset()) );
}
else
{
RuntimeID aDataRID;
if( getRuntimeForm(apED, aRID, lvalue, aDataRID) )
{
return( apED->isAssigned(aDataRID, lvalue->getOffset()) );
}
}
return( false );
}
/*
*******************************************************************************
* GETTER
* runtime instance
*******************************************************************************
*/
bool BaseEnvironment::getRuntimeForm(
const APExecutionData & apED, const RuntimeID & aRID,
InstanceOfData * lvalue, RuntimeID & aDataRID)
{
aDataRID = aRID;
// if( lvalue->hasRuntimeContainerRID() )
// {
// aDataRID = lvalue->getRuntimeContainerRID();
//
// return( true );
// }
// else
if( lvalue->isAlias() )
{
if( lvalue->hasAliasTarget() &&
lvalue->getAliasTarget()->hasRuntimeContainerRID() )
{
lvalue->setRuntimeContainerRID( aDataRID =
lvalue->getAliasTarget()->getRuntimeContainerRID() );
return( true );
}
ArrayOfInstanceOfMachine::iterator it =
lvalue->getMachinePath()->begin();
// SEARCH of the RUNTIME FORM container
// where this INSTANCE of variable was declared
// SEARCH of the LCA(RID) of the current RID an the ALIAS container
while( aDataRID.valid()
&& (aDataRID.getExecutable() != (*it)->getContainer()) )
{
aDataRID = aDataRID.getPRID();
}
if( aDataRID.valid() )
{
// Use of Alias PATH to find the INSTANCE of variable
ArrayOfInstanceOfMachine::iterator itEnd =
lvalue->getMachinePath()->end();
for( ; it != itEnd ; ++it )
{
aDataRID = apED->getRuntimeFormChild(aDataRID, (*it));
}
// AVM_OS_ASSERT_FATAL_ERROR_EXIT( aDataRID.getVariable(
// lvalue->getOffset() )->isAstElement( lvalue->getAstElement() ) )
// << "Assign error " << aDataRID.getExecutable()
// ->getData(lvalue->getOffset())->getFullyQualifiedNameID()
// << " != " << lvalue->getFullyQualifiedNameID() << " !!!"
// << SEND_EXIT;
//
//AVM_IF_DEBUG_FLAG( DATA )
// AVM_OS_TRACE << INCR_INDENT_TAB << "begin BaseEnvironment::getRvalue\n";
// lvalue->toStream(AVM_OS_TRACE);
// apED->getRuntime(aDataRID).toStream(AVM_OS_TRACE);
//
// rvalue->toStream(AVM_OS_TRACE);
// AVM_OS_TRACE << TAB_DECR_INDENT << "end BaseEnvironment::getRvalue\n";
//AVM_ENDIF_DEBUG_FLAG( DATA )
return( true );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Access error : Unfound Runtime Data Container for << "
<< lvalue->getFullyQualifiedNameID() << " >> !!!"
<< SEND_EXIT;
}
}
else
{
////////////////////////////////////////////////////////////////////////
// NORMAL IMPLEMENTATION
////////////////////////////////////////////////////////////////////////
// SEARCH of the RUNTIME FORM container
// where this INSTANCE of variable was declared
while( aDataRID.valid() &&
(aDataRID.getExecutable() != lvalue->getContainer()) )
{
aDataRID = aDataRID.getPRID();
}
if( aDataRID.valid() )
{
// AVM_OS_ASSERT_FATAL_ERROR_EXIT( aDataRID.getVariable(
// lvalue->getOffset() )->isAstElement( lvalue->getAstElement() ) )
// << "Assign error "
// << aDataRID.getVariable(lvalue->getOffset())->getFullyQualifiedNameID()
// << " != " << lvalue->getFullyQualifiedNameID() << " !!!"
// << SEND_EXIT;
//
//AVM_IF_DEBUG_FLAG( DATA )
// AVM_OS_TRACE << INCR_INDENT_TAB << "begin BaseEnvironment::getRvalue\n";
// lvalue->toStream(AVM_OS_TRACE);
// apED->getRuntime(aDataRID).toStream(AVM_OS_TRACE);
//
// rvalue->toStream(AVM_OS_TRACE);
// AVM_OS_TRACE << TAB_DECR_INDENT << "end BaseEnvironment::getRvalue\n";
//AVM_ENDIF_DEBUG_FLAG( DATA )
return( true );
}
// else
// {
// AVM_OS_FATAL_ERROR_EXIT
// << "Access error : Unfound Runtime Data Container for :> "
// << aRID.str() << " |=> \n"
// << str_header( lvalue )
// << SEND_EXIT;
// }
}
return( false );
}
bool BaseEnvironment::getRuntimeForm(const APExecutionData & apED,
InstanceOfData * lvalue, LocalRuntime & aLocalRuntime)
{
if( apED->hasLocalRuntimeStack() )
{
StackOfLocalRuntime::
reverse_iterator it = apED->getLocalRuntimes()->rbegin();
StackOfLocalRuntime::
reverse_iterator itEnd = apED->getLocalRuntimes()->rend();
for( ; it != itEnd ; ++it )
{
if( (*it).getProgram() == lvalue->getContainer() )
{
aLocalRuntime = (*it) ;
break;
}
}
if( aLocalRuntime.valid() )
{
// AVM_OS_ASSERT_FATAL_ERROR_EXIT( aLocalRuntime.getProgram()->getData(
// lvalue->getOffset())->isAstElement( lvalue->getAstElement() ) )
// << "Assign error "
// << aLocalRuntime.getProgram()->getData(lvalue->getOffset())->getFullyQualifiedNameID()
// << " != " + lvalue->getFullyQualifiedNameID() << " !!!"
// << SEND_EXIT;
return( true );
}
}
return( false );
}
/**
* Generate numeric offset for array access using symbolic expression
*/
avm_size_t BaseEnvironment::genNumericOffset(
APExecutionData & apED, const RuntimeID & aRID,
const Symbol & lvSymbolicOffset, const BF & rvEvaluatedOffset,
avm_size_t offsetMin, avm_size_t offsetMax)
{
avm_size_t offset = AVM_NUMERIC_MAX_SIZE_T;
BF offsetExpr;
Bitset unusedOffsetBitset( offsetMax + 1 , true );
avm_size_t idx = offsetMin;
if( rvEvaluatedOffset.is< InstanceOfData >() )
{
offsetExpr = getRvalue( apED, apED->getParametersRID(),
rvEvaluatedOffset.to_ptr< InstanceOfData >() );
if( offsetExpr.isUInteger() &&
((offset = offsetExpr.toInteger()) <= offsetMax) )
{
// AVM_OS_INFO << "BaseEnvironment::genNumericOffset:> "
// "TRY PREVIOUS NUMERIC ARRAY INDEX in [ "
// << offsetMin << " , " << offsetMax
// << " ]\n for the expression: "
// << lvSymbolicOffset.strValue() << " |=> "
// << no_indent( rvEvaluatedOffset ) << " |-> "
// << offsetExpr.str() << "\n with constraint:> \n"
// << apED->getPathCondition().wrapStr() << " !!!"
// << std::endl;
if( PathConditionProcessor::addPathCondition(apED,
ExpressionConstructor::eqExpr(rvEvaluatedOffset, offsetExpr)) )
{
// forced to used << previous offset >>
idx = AVM_NUMERIC_MAX_SIZE_T;
// AVM_OS_INFO << "BaseEnvironment::genNumericOffset:> "
// "USED OLD NUMERIC ARRAY INDEX in [ "
// << offsetMin << " , " << offsetMax
// << " ]\n for the expression: "
// << lvSymbolicOffset.strValue() << " |=> "
// << no_indent( rvEvaluatedOffset ) << " |-> "
// << offset << "\n with constraint:> \n"
// << apED->getPathCondition().wrapStr() << " !!!"
// << std::endl << std::endl;
}
}
}
for( ; idx <= offsetMax ; ++idx )
{
offset = RANDOM::gen_uinteger(offsetMin, offsetMax);
if( unusedOffsetBitset[ offset ] )
{
unusedOffsetBitset[ offset ] = false;
offsetExpr = ExpressionConstructor::newInteger(offset);
if( PathConditionProcessor::addPathCondition(apED,
ExpressionConstructor::eqExpr(rvEvaluatedOffset, offsetExpr)) )
{
// forced to used this << random offset >>
idx = AVM_NUMERIC_MAX_SIZE_T;
break;
}
}
}
if( idx != AVM_NUMERIC_MAX_SIZE_T )
{
for( offset = offsetMin ; offset <= offsetMax ; ++offset )
{
if( unusedOffsetBitset[ offset ] )
{
offsetExpr = ExpressionConstructor::newInteger(offset);
if( PathConditionProcessor::addPathCondition(
apED, ExpressionConstructor::eqExpr(
rvEvaluatedOffset, offsetExpr)) )
{
// AVM_OS_INFO << "BaseEnvironment::genNumericOffset:> "
// "Found NUMERIC<RANDOM> ARRAY INDEX in [ "
// << offsetMin << " , " << offsetMax
// << " ]\n for the expression: "
// << lvSymbolicOffset.strValue() << " |=> "
// << no_indent( rvEvaluatedOffset ) << " |-> "
// << offset << "\n with constraint:> \n"
// << apED->getPathCondition().wrapStr() << " !!!"
// << std::endl;
break;
}
}
}
}
if( offset <= offsetMax )
{
if( lvSymbolicOffset.getValue().is< InstanceOfData >() )
{
InstanceOfData * lvIndex =
lvSymbolicOffset.getValue().to_ptr< InstanceOfData >();
if( lvIndex->getModifier().hasFeatureMutable() )
{
if( lvIndex->getModifier().hasNatureReference() )
{
lvIndex = getRvalue(apED, aRID, lvIndex).
to_ptr< InstanceOfData >();
}
if( lvIndex->getModifier().anyNatureReferenceMacro() )
{
setRvalue(apED, aRID, lvIndex, offsetExpr);
}
}
if( rvEvaluatedOffset.is< InstanceOfData >() )
{
lvIndex = rvEvaluatedOffset.to_ptr< InstanceOfData >();
if( not lvIndex->hasValue() )
{
setRvalue(apED, apED->getParametersRID(), lvIndex, offsetExpr);
// AVM_OS_INFO << "BaseEnvironment::genNumericOffset:> "
// "SAVE NUMERIC<RANDOM> ARRAY INDEX in [ "
// << offsetMin << " , " << offsetMax
// << " ]\n for the expression: "
// << lvSymbolicOffset.strValue() << " |=> "
// << no_indent( rvEvaluatedOffset ) << " |-> "
// << offset << "\n with constraint:> \n"
// << apED->getPathCondition().wrapStr() << " !!!"
// << std::endl << std::endl;
}
}
}
return( offset );
}
// apED.mwsetAEES( AEES_SYMBOLIC_EXECUTION_LIMITATION );
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::genNumericOffset:> "
"Unfound NUMERIC<RANDOM> ARRAY INDEX in [ " << offsetMin
<< " , " << offsetMax << " ]\n for the expression: "
<< lvSymbolicOffset.strValue() << " |=> "
<< no_indent( rvEvaluatedOffset ) << "\n with constraint:> \n"
<< apED->getPathCondition().wrapStr() << " !!!"
<< SEND_EXIT;
return( AVM_NUMERIC_MAX_SIZE_T );
}
/*
*******************************************************************************
* GETTER
* rvalue for an lvalue
*******************************************************************************
*/
BF & BaseEnvironment::getRvalue(
APExecutionData & apED, const RuntimeID & aRID,
InstanceOfData * lvUFI, BF & rvalue, const Symbol & offsetValue)
{
switch( offsetValue.getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
return( rvalue.at( offsetValue.getOffset() ) );
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED, aRID);
if( eENV.evalOffset(offsetValue.getValue()) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< offsetValue.strValue() << " >> in UFI << "
<< lvUFI->str() << " >> for reading in VVT !!!"
<< SEND_EXIT;
return( BF::REF_NULL );
}
if( eENV.outVAL.isNumeric() )
{
AVM_OS_ASSERT_FATAL_ARRAY_OFFSET_EXIT( eENV.outVAL.toInteger(),
static_cast< avm_integer_t >(rvalue.size()) )
<< "Failed to read in VVT with index << "
<< offsetValue.strValue() << " >> using UFI << "
<< lvUFI->str() << " >> !!!"
<< SEND_EXIT;
return( rvalue.at( eENV.outVAL.toInteger() ) );
}
else if( rvalue.size() > 0 )
{
avm_size_t offset = genNumericOffset( apED, aRID,
offsetValue, eENV.outVAL, 0, (rvalue.size() - 1) );
if( offset != AVM_NUMERIC_MAX_SIZE_T )
{
return( rvalue.at( offset ) );
}
else
{
return( BF::REF_NULL );
}
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getRvalue:> "
"Unexpected variable << " << lvUFI->str()
<< " >> with empty rvalue << " << rvalue.str()
<< " >> for the instance of data :>\n"
<< offsetValue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getRvalue:> "
"Unexpected POINTER NATURE in UFI << "
<< lvUFI->str() << " >> for the instance of data :>\n"
<< offsetValue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
}
BF & BaseEnvironment::getRvalue(APExecutionData & apED,
const RuntimeID & aRID, InstanceOfData * lvalue)
{
TableOfData * aDataTable = NULL;
if( lvalue->hasRuntimeContainerRID() )
{
aDataTable = apED->getRuntime(
lvalue->getRuntimeContainerRID()).getDataTable();
}
else
{
RuntimeID aDataRID;
if( getRuntimeForm(apED, aRID, lvalue, aDataRID) )
{
aDataTable = apED->getRuntime(aDataRID).getDataTable();
}
else
{
LocalRuntime aLocalRuntime;
if( getRuntimeForm(apED, lvalue, aLocalRuntime) )
{
aDataTable = &( aLocalRuntime.getDataTable() );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getRvalue:> Failed to found "
"data table for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
}
switch( lvalue->getPointerNature() )
{
case IPointerDataNature::POINTER_STANDARD_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
return( aDataTable->at( lvalue->getOffset() ) );
}
case IPointerDataNature::POINTER_UFI_OFFSET_NATURE:
case IPointerDataNature::POINTER_UFI_RUNTIME_NATURE:
{
BF rvalue = aDataTable->at( lvalue->getOffset() );
// NO +1 for << this >> which is the root of the path
avm_size_t pathLength = lvalue->getDataPath()->size();
avm_size_t * theOffsetPath = lvalue->getOffsetPath();
for( avm_size_t k = 1 ; k < pathLength ; ++k )
{
if( rvalue.is< BuiltinCollection >() )
{
rvalue.moveAt( theOffsetPath[k] );
}
else
{
BF * value = new BF( create4ArrayAccess(
apED, aRID, rvalue, lvalue) );
return( *value );
}
}
if( rvalue.is< BuiltinCollection >() )
{
return( rvalue.at( theOffsetPath[pathLength] ) );
}
else
{
BF * value = new BF( create4ArrayAccess(
apED, aRID, rvalue, lvalue) );
return( *value );
}
}
case IPointerDataNature::POINTER_UFI_MIXED_NATURE:
{
BF rvalue = aDataTable->at( lvalue->getOffset() );
TableOfSymbol::iterator it = lvalue->getDataPath()->begin();
TableOfSymbol::iterator itEnd = lvalue->getDataPath()->pred_end();
bool isSymbolicAccess = false;
for( ; it != itEnd ; ++it )
{
if( rvalue.is< BuiltinCollection >() )
{
rvalue = getRvalue(apED, aRID, lvalue, rvalue, (*it));
}
else
{
isSymbolicAccess = true;
break;
}
}
if( rvalue.is< BuiltinCollection >() )
{
return( getRvalue(apED, aRID, lvalue, rvalue, (*it)) );
}
else
{
isSymbolicAccess = true;
}
if( isSymbolicAccess )
{
BF * value = new BF( create4ArrayAccess(apED, aRID,
aDataTable->at( lvalue->getOffset() ),
lvalue) );
return( *value );
}
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getRvalue:> Unexpected "
"POINTER NATURE for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
return( BF::REF_NULL );
}
/*
* GETTER
* writable rvalue for an lvalue
*/
BF & BaseEnvironment::getWvalue(
APExecutionData & apED, const RuntimeID & aRID,
ArrayBF * rvArray, const Symbol & lvalue)
{
switch( lvalue.getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
return( rvArray->getWritable( lvalue.getOffset() ));
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED, aRID);
if( eENV.evalOffset(lvalue.getValue()) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< lvalue.strValue() << " >> in variable << "
<< lvalue.str() << " >> for reading in VVT !!!"
<< SEND_EXIT;
return( BF::REF_NULL );
}
if( eENV.outVAL.isNumeric() )
{
AVM_OS_ASSERT_FATAL_ARRAY_OFFSET_EXIT( eENV.outVAL.toInteger(),
static_cast< avm_integer_t >(rvArray->size()) )
<< "Failed to access to an ARRAY with index << "
<< lvalue.strValue() << " >> for reading in VVT !!!"
<< SEND_EXIT;
return( rvArray->getWritable( eENV.outVAL.toInteger() ));
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> "
"unexpected NON-INTEGER ARRAY OFFSET << "
<< eENV.outVAL.str() << " >> in instance FQN-ID :>\n"
<< lvalue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Unexpected "
"POINTER NATURE for the instance of data :>\n"
<< lvalue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
}
BF & BaseEnvironment::getWvalue(
APExecutionData & apED, const RuntimeID & aRID,
BuiltinContainer * rvArray, const Symbol & lvalue)
{
switch( lvalue.getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
return( rvArray->getWritable( lvalue.getOffset() ));
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED, aRID);
if( eENV.evalOffset(lvalue.getValue()) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< lvalue.strValue() << " >> in variable << "
<< lvalue.str() << " >> for reading in VVT !!!"
<< SEND_EXIT;
return( BF::REF_NULL );
}
if( eENV.outVAL.isNumeric() )
{
AVM_OS_ASSERT_FATAL_ARRAY_OFFSET_EXIT( eENV.outVAL.toInteger(),
static_cast< avm_integer_t >(rvArray->size()) )
<< "Failed to access to an ARRAY with index << "
<< lvalue.strValue() << " >> for reading in VVT !!!"
<< SEND_EXIT;
return( rvArray->getWritable( eENV.outVAL.toInteger() ) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> "
"unexpected NON-INTEGER ARRAY OFFSET << "
<< eENV.outVAL.str() << " >> in instance FQN-ID :>\n"
<< lvalue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Unexpected "
"POINTER NATURE for the instance of data :>\n"
<< lvalue.toString( AVM_TAB1_INDENT )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
}
BF & BaseEnvironment::getWvalue(APExecutionData & apED,
const RuntimeID & aRID, InstanceOfData * lvalue)
{
TableOfData * aDataTable = NULL;
if( lvalue->hasRuntimeContainerRID() )
{
aDataTable = apED.getWritableRuntime(
lvalue->getRuntimeContainerRID() ).getWritableDataTable();
}
else
{
RuntimeID aDataRID;
if( getRuntimeForm(apED, aRID, lvalue, aDataRID) )
{
aDataTable = apED.getWritableRuntime(
aDataRID ).getWritableDataTable();
}
else
{
LocalRuntime aLocalRuntime;
if( getRuntimeForm(apED, lvalue, aLocalRuntime) )
{
apED.makeModifiableLocalRuntime( aLocalRuntime );
aDataTable = &( aLocalRuntime.getDataTable() );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Failed to found "
"data table for the instance of data :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
}
switch( lvalue->getPointerNature() )
{
case IPointerDataNature::POINTER_STANDARD_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
return( aDataTable->getWritable( lvalue->getOffset() ) );
}
case IPointerDataNature::POINTER_UFI_OFFSET_NATURE:
case IPointerDataNature::POINTER_UFI_RUNTIME_NATURE:
{
BF rvalue = aDataTable->getWritable( lvalue->getOffset() );
// NO +1 for << this >> which is the root of the path
avm_size_t pathLength = lvalue->getDataPath()->size();
avm_size_t * theOffsetPath = lvalue->getOffsetPath();
for( avm_size_t k = 1 ; k < pathLength ; ++k )
{
if( rvalue.is< BuiltinCollection >() )
{
rvalue.moveAtWritable( theOffsetPath[k] );
}
else
{
break;
}
}
if( rvalue.is< BuiltinCollection >() )
{
return( rvalue.getWritable( theOffsetPath[pathLength] ) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Unexpected "
"rvalue container for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
case IPointerDataNature::POINTER_UFI_MIXED_NATURE:
{
BF rvalue = aDataTable->getWritable( lvalue->getOffset() );
TableOfSymbol::iterator it = lvalue->getDataPath()->begin();
TableOfSymbol::iterator itEnd = lvalue->getDataPath()->pred_end();
for( ; it != itEnd ; ++it )
{
if( rvalue.is< ArrayBF >() )
{
rvalue = getWvalue(apED, aRID,
rvalue.to_ptr< ArrayBF >(), (*it));
}
else if( rvalue.is< BuiltinContainer >() )
{
rvalue = getWvalue(apED, aRID,
rvalue.to_ptr< BuiltinContainer >(), (*it));
}
else
{
break;
}
}
if( rvalue.is< ArrayBF >() )
{
return( getWvalue(apED,
aRID, rvalue.to_ptr< ArrayBF >(), (*it)) );
}
else if( rvalue.is< BuiltinContainer >() )
{
return( getWvalue(apED, aRID,
rvalue.to_ptr< BuiltinContainer >(), (*it)) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Unexpected "
"rvalue container for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
return( BF::REF_NULL );
}
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::getWvalue:> Unexpected "
"POINTER NATURE for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
return( BF::REF_NULL );
}
}
return( BF::REF_NULL );
}
/*
*******************************************************************************
* SETTER
* lvalue := rvalue
*******************************************************************************
*/
bool BaseEnvironment::setRvalue(APExecutionData & apED,
InstanceOfData * lvalue, const BF & rvalue)
{
if( lvalue->hasRuntimeContainerRID() )
{
return( writeData(apED,
lvalue->getRuntimeContainerRID(), lvalue, rvalue) );
}
else
{
RuntimeID aDataRID;
if( getRuntimeForm(apED, apED->mRID, lvalue, aDataRID) )
{
return( writeData(apED, aDataRID, lvalue, rvalue) );
}
else
{
LocalRuntime aLocalRuntime;
if( getRuntimeForm(apED, lvalue, aLocalRuntime) )
{
return( setLocalRuntime(apED, aLocalRuntime, lvalue, rvalue) );
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setRvalue:> Failed to found "
"data table for the instance of data:\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: "
<< str_header( apED->mRID )
<< SEND_EXIT;
}
}
}
return( false );
}
bool BaseEnvironment::invokeOnWriteRoutine(APExecutionData & apED,
const RuntimeID & aRID, InstanceOfData * lvalue, const BF & rvalue)
{
if( lvalue->hasOnWriteRoutine() )
{
ExecutionEnvironment tmpENV(*this, apED, aRID, BFCode::REF_NULL);
if( not PRIMITIVE_PROCESSOR.invokeRoutine(
tmpENV, lvalue->getOnWriteRoutine(), rvalue) )
{
return( false );
}
if( tmpENV.outEDS.nonempty() )
{
const RuntimeID & saveRID = apED->mRID;
tmpENV.outEDS.pop_last_to( apED );
apED->mRID = saveRID;
if( tmpENV.outEDS.nonempty() )
{
AVM_OS_FATAL_ERROR_EXIT
<< "Unsupported << onWrite >> Routine which execution "
"create more than one Execution Context\n\t"
<< str_header( lvalue )
<< "\nin the runtime context: " << str_header( aRID )
<< SEND_EXIT;
}
}
else
{
return( false );
}
}
return( true );
}
/**
* setData
*/
bool BaseEnvironment::setData(
APExecutionData & apED, const RuntimeID & aRID,
InstanceOfData * lvalue, const BF & rvalue)
{
apED.getWritableRuntime( aRID ).makeWritableDataTable();
switch( lvalue->getPointerNature() )
{
case IPointerDataNature::POINTER_STANDARD_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
apED->getRuntime(aRID).setData(lvalue->getOffset(), rvalue);
break;
}
case IPointerDataNature::POINTER_UFI_OFFSET_NATURE:
case IPointerDataNature::POINTER_UFI_RUNTIME_NATURE:
{
BF rvContainer = apED->getRuntime(aRID).
getWritableData( lvalue->getOffset() );
// TableOfSymbol::iterator it = lvalue->getDataPath()->begin();
// TableOfSymbol::iterator itEnd = lvalue->getDataPath()->pred_end();
// for( ; it != itEnd ; ++it )
// {
// rvContainer.moveAtWritable( (*it)->getOffset() );
// }
// rvContainer->set((*it)->getOffset(), rvalue);
// NO +1 for << this >> which is the root of the path
avm_size_t pathLength = lvalue->getDataPath()->size();
avm_size_t * theOffsetPath = lvalue->getOffsetPath();
for( avm_size_t k = 1 ; k < pathLength ; ++k )
{
rvContainer.moveAtWritable( theOffsetPath[k] );
}
rvContainer.set(theOffsetPath[pathLength], rvalue);
break;
}
case IPointerDataNature::POINTER_UFI_MIXED_NATURE:
{
BF rvContainer = apED->getRuntime(aRID).
getWritableData( lvalue->getOffset() );
TableOfSymbol::iterator it = lvalue->getDataPath()->begin();
TableOfSymbol::iterator itEnd = lvalue->getDataPath()->pred_end();
for( ; it != itEnd ; ++it )
{
switch( (*it).getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
{
rvContainer.moveAtWritable( (*it).getOffset() );
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED);
if( eENV.evalOffset( (*it).getValue() ) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< (*it).strValue()
<< " >> in variable << " << (*it).str()
<< " >> for writing in VVT !!!"
<< SEND_EXIT;
return( false );
}
if( eENV.outVAL.isNumeric() )
{
AVM_OS_ASSERT_FATAL_ARRAY_OFFSET_EXIT(
eENV.outVAL.toInteger(),
static_cast< avm_integer_t >(rvContainer.size()) )
<< "Failed to write in ARRAY with index << "
<< eENV.outVAL.toInteger()
<< " >> in variable << " << lvalue->str()
<< " >> for writing in VVT !!!"
<< SEND_EXIT;
rvContainer.moveAtWritable( eENV.outVAL.toInteger() );
break;
}
else
{
avm_size_t offset = genNumericOffset(
apED, aRID, (*it), eENV.outVAL, 0,
(rvContainer.size() - 1) );
if( offset != AVM_NUMERIC_MAX_SIZE_T )
{
rvContainer.moveAtWritable( offset );
break;
}
}
apED.mwsetAEES( AEES_SYMBOLIC_EXECUTION_LIMITATION );
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setData:> "
"unexpected NON-INTEGER ARRAY INDEX << "
<< eENV.outVAL.str()
<< " >> in instance FQN-ID :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( false );
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setData:> Unexpected "
"POINTER NATURE for the instance of data :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( false );
}
}
}
switch( (*it).getPointerNature() )
{
case IPointerDataNature::POINTER_FIELD_CLASS_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_ARRAY_OFFSET_NATURE:
case IPointerDataNature::POINTER_FIELD_CHOICE_ATTRIBUTE_NATURE:
case IPointerDataNature::POINTER_FIELD_UNION_ATTRIBUTE_NATURE:
{
rvContainer.set((*it).getOffset(), rvalue);
break;
}
case IPointerDataNature::POINTER_FIELD_ARRAY_INDEX_NATURE:
{
EvaluationEnvironment eENV(*this, apED);
if( eENV.evalOffset((*it).getValue()) )
{
apED = eENV.outED;
}
else
{
AVM_OS_FATAL_ERROR_EXIT
<< "Failed to eval ARRAY index << "
<< (*it).strValue() << " >> in variable << "
<< (*it).str() << " >> for writing in VVT !!!"
<< SEND_EXIT;
return( false );
}
if( eENV.outVAL.isNumeric() )
{
AVM_OS_ASSERT_FATAL_ARRAY_OFFSET_EXIT(
eENV.outVAL.toInteger(),
static_cast< avm_integer_t >(rvContainer.size()) )
<< "Failed to access to an ARRAY with index << "
<< lvalue->strValue()
<< " >> for writing in VVT !!!"
<< SEND_EXIT;
rvContainer.set(eENV.outVAL.toInteger(), rvalue);
break;
}
else
{
avm_size_t offset = genNumericOffset(apED, aRID, (*it),
eENV.outVAL, 0, (rvContainer.size() - 1) );
if( offset != AVM_NUMERIC_MAX_SIZE_T )
{
rvContainer.set(offset, rvalue);
break;
}
}
// SYMBOLIC ACCES ERROR
apED.mwsetAEES( AEES_SYMBOLIC_EXECUTION_LIMITATION );
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setData:> Unexpected "
"NON-INTEGER ARRAY INDEX << "
<< eENV.outVAL.str() << " >> in instance FQN-ID :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( false );
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setData:> "
"Unexpected POINTER NATURE "
"for the instance of data :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( false );
}
}
break;
}
default:
{
AVM_OS_FATAL_ERROR_EXIT
<< "BaseEnvironment::setData:> Unexpected "
"POINTER NATURE for the instance of data :>\n"
<< str_header( lvalue )
<< SEND_EXIT;
return( false );
}
}
apED->mwsetAssigned(aRID, lvalue->getOffset(), true);
return( true );
}
/**
* setLocalRuntime
*/
bool BaseEnvironment::setLocalRuntime(
APExecutionData & apED, LocalRuntime & aLocalRuntime,
InstanceOfData * lvalue, const BF & rvalue)
{
apED.makeModifiableLocalRuntime( aLocalRuntime );
// TODO what to do with monitor in this case
aLocalRuntime.setData(lvalue->getOffset(), rvalue);
return( true );
}
/**
* TOOLS
*/
BFCode BaseEnvironment::searchTraceIO(const BF & aTrace, AvmCode * ioFormula)
{
if( aTrace.valid() )
{
BFCode ioTrace;
if( aTrace.is< AvmCode >() )
{
AvmCode::iterator it = aTrace.to_ptr< AvmCode >()->begin();
AvmCode::iterator itEnd = aTrace.to_ptr< AvmCode >()->end();
for( ; it != itEnd ; ++it )
{
ioTrace = searchTraceIO((*it), ioFormula);
if( ioTrace.valid() )
{
return( ioTrace );
}
}
}
else if( aTrace.is< ExecutionConfiguration >() )
{
const BF & ioAtomicTrace =
aTrace.to_ptr< ExecutionConfiguration >()->getCode();
if( ioAtomicTrace.is< AvmCode >() )
{
ioTrace = ioAtomicTrace.bfCode();
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PORT )
AVM_OS_TRACE
<< "ioTrace : " << ioTrace.str() << std::endl
<< "ioFormula : " << ioFormula->str()<< std::endl << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PORT )
if( ioTrace->sameOperator( ioFormula ) &&
(ioTrace->size() >= ioFormula->size()) )
{
BaseInstanceForm * ioTraceInstance =
ioTrace->first().as_ptr< BaseInstanceForm >();
BaseInstanceForm * ioFormulaInstance =
ioFormula->first().as_ptr< BaseInstanceForm >();
if( ioTraceInstance->equals(ioFormulaInstance) )
{
AVM_IF_DEBUG_LEVEL_FLAG( MEDIUM , PORT )
AVM_OS_TRACE << "Found match : YES !!!" << std::endl;
AVM_ENDIF_DEBUG_LEVEL_FLAG( MEDIUM , PORT )
return( ioTrace );
}
}
else
{
return( BFCode::REF_NULL );
}
}
}
}
return( BFCode::REF_NULL );
}
} /* namespace sep */