/*******************************************************************************
 * 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
 *
 * Contributors:
 *  Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
 *   - Initial API and implementation
 ******************************************************************************/

#include "Builder.h"

#include <builder/Loader.h>

#include <builder/primitive/CompilationEnvironment.h>

#include <computer/ExecutionEnvironment.h>

#include <fml/executable/AvmProgram.h>
#include <fml/executable/BaseInstanceForm.h>
#include <fml/executable/ExecutableForm.h>
#include <fml/executable/ExecutableQuery.h>
#include <fml/executable/ExecutableSystem.h>
#include <fml/executable/InstanceOfBuffer.h>
#include <fml/executable/InstanceOfConnect.h>
#include <fml/executable/InstanceOfData.h>
#include <fml/executable/InstanceOfMachine.h>
#include <fml/executable/InstanceOfPort.h>

#include <fml/expression/ExpressionConstant.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/StatementConstructor.h>

#include <fml/operator/Operator.h>

#include <fml/runtime/ExecutionConfiguration.h>
#include <fml/runtime/ExecutionContext.h>
#include <fml/runtime/ExecutionData.h>
#include <fml/runtime/LocalRuntime.h>
#include <fml/runtime/RuntimeForm.h>
#include <fml/runtime/TableOfRuntimeFormState.h>

#include <fml/infrastructure/System.h>
#include <fml/runtime/LocalRuntime.h>

#include <fml/workflow/UniFormIdentifier.h>

#include <sew/Configuration.h>
#include <sew/SymbexEngine.h>

#include <util/ExecutionTime.h>


namespace sep
{


/**
 * LOADER
 */
void Builder::load()
{
	CompilationEnvironment::initCache();
}


/**
 * DISPOSER
 */
void Builder::dispose()
{
	CompilationEnvironment::finalizeCache();
}



/**
 * CONFIGURE
 */
bool Builder::configure()
{
	if( not mCompiler.configure() )
	{
		AVM_OS_ERROR_ALERT
				<< "Builder::configure:> "
					"the XLIA compiler configuration failed !!!"
				<< SEND_ALERT;

		return( false );
	}

	return( true );
}


/**
 * START
 */
bool Builder::start()
{
	// COMPILATION
//CHRONO
//AVM_OS_DEBUG << std::endl << "Building:> start chrono !" << std::endl;
//ExecutionTime chrono( true );

	if( mConfiguration.hasSpecification() )
	{
		mCompiler.start( mConfiguration.getSpecification() );

		mCompiler.reportCompilation(AVM_OS_LOG);
		if( mCompiler.hasError() )
		{
			mCompiler.reportCompilation(AVM_OS_COUT);
			mCompiler.reportCompilation(AVM_OS_TRACE);

			return( false );
		}
		else if( mCompiler.hasErrorWarning() )
		{
			mCompiler.reportCompilation(AVM_OS_COUT);
		}
	}
	else if( AVM_ERROR_COUNT == 0 )
	{
		++AVM_ERROR_COUNT;
	}


	if( (AVM_ERROR_COUNT > 0) && (AVM_WARNING_COUNT > 0) )
	{
		AVM_OS_EXIT( FAILED )
				<< "Compilation : error"
				<< ( (AVM_ERROR_COUNT > 0) ? "s " : " " ) << AVM_ERROR_COUNT
				<< " : warning"
				<< ( (AVM_ERROR_COUNT > 0) ? "s " : " " ) << AVM_WARNING_COUNT
				<< SEND_EXIT;
	}


//	CHRONO
//chrono.finish_time();
//AVM_OS_DEBUG << std::endl << "chrono stop:> " << chrono.time_stat() << std::endl;


AVM_IF_DEBUG_FLAG( COMPILING )
	mConfiguration.serializeDebugExecutable( "compiled" );
AVM_ENDIF_DEBUG_FLAG(COMPILING )


	// LOADING INSTANCE FOR EXECUTION
//CHRONO
//AVM_OS_DEBUG << std::endl << "Loading:> start chrono !" << std::endl;
//chrono.start_time();

	/*
	 * Creating the first/initial execution data/context
	 */
	APExecutionData theInitialExecutionData = createInitialExecutionData();

	mConfiguration.setMainExecutionData( theInitialExecutionData );

	ExecutionContext * anInitialExecutionContext =
			new ExecutionContext(theInitialExecutionData, 0, 1);

	mConfiguration.appendInputContext( anInitialExecutionContext );

//CHRONO
//chrono.finish_time();
//AVM_OS_DEBUG << std::endl << "chrono stop:> " << chrono.time_stat() << std::endl;

	return( true );
}


/*
 * Initial Execution Context creation
 */
APExecutionData Builder::createInitialExecutionData()
{
	ExecutableSystem & anExecutableSystem =
			mConfiguration.getExecutableSystem();

	APExecutionData theInitialExecutionData( new ExecutionData(
			anExecutableSystem.getMachineCount() + 1 /* for PARAMETERS */ ) );

	theInitialExecutionData->setNodeCondition(
			ExpressionConstant::BOOLEAN_TRUE );
	theInitialExecutionData->setNodeTimedCondition(
			ExpressionConstant::BOOLEAN_TRUE );

	theInitialExecutionData->setPathCondition(
			ExpressionConstant::BOOLEAN_TRUE );
	theInitialExecutionData->setPathTimedCondition(
			ExpressionConstant::BOOLEAN_TRUE );

	/*
	 * Loading instance
	 */
	int thePid = 0;
	avm_offset_t theOffset = 0;

	Loader & theLoader = mSymbexEngine.getLoader();

	/*
	 * Loading parameters instance
	 */
	// ExecutionData::PARAM_MACHINE_RUNTIME_OFFSET === theOffset === 0
	RuntimeID parametersRID(RuntimeID::REF_NULL, thePid++,
			theOffset++, anExecutableSystem.rawParametersInstance());

	mConfiguration.appendRID( parametersRID );

	theInitialExecutionData->saveRuntimeForm(parametersRID.getOffset(),
			new ParametersRuntimeForm( parametersRID ) );

	theInitialExecutionData->setRuntimeFormState(
			parametersRID.getOffset(), PROCESS_UNDEFINED_STATE);

	/*
	 * Loading system instance
	 */
	// ExecutionData::SYSTEM_RUNTIME_OFFSET === theOffset === 1
	RuntimeForm * theSystemRuntime = theLoader.loadSystemInstance(
			theInitialExecutionData, RuntimeID::REF_NULL,
			anExecutableSystem.rawSystemInstance(), thePid, theOffset);

AVM_IF_DEBUG_LEVEL_FLAG( HIGH , LOADING )
	theSystemRuntime->toStream( AVM_OS_TRACE );
AVM_ENDIF_DEBUG_LEVEL_FLAG( HIGH , LOADING )

	/**
	 * RUNNING onCREATE
	 */
	if( not theLoader.finalizeRunningOnCreate(ENV, theInitialExecutionData) )
	{
		AVM_OS_FATAL_ERROR_EXIT
				<< "createInitialExecutionContext:> Failed to finalize "
						"loading by running << onCreate Primitive >> !!!"
				<< SEND_EXIT;
	}

	// WARNING Assume possible auto-destruction of <theSystemExecutable>
	// after running< system->onCreate() > due to makeWritable... process !
	const RuntimeID & theSystemRID = theInitialExecutionData->getSystemRID();

	ExecutableForm * theSystemExecutable = theSystemRID.getExecutable();


//!![MIGRATION]:MONITOR --> onCreate Routine
//	theLoader.loadInitialMonitorData(theInitialExecutionData,
//			theSystemRID, anExecutableSystem.rawSystemInstance(), true);

AVM_IF_DEBUG_FLAG( LOADING )
	mConfiguration.serializeDebugExecutable( "loaded" );
AVM_ENDIF_DEBUG_FLAG( LOADING )

	/*
	 * Setting the main program
	 */
	theInitialExecutionData->setOnInit( theSystemExecutable->getOnInit() );

	theInitialExecutionData->setOnSchedule( theSystemExecutable->getOnRun() );

//	if( theInitialExecutionData->getOnSchedule()->nonempty()
//		&& theInitialExecutionData->getOnSchedule()
//				->isOpCode( AVM_OPCODE_SCHEDULE_INVOKE )
//		&& theSystemExecutable->isMocKindAnd() )
//	{
//		theInitialExecutionData->setOnSchedule(
//				theSystemExecutable->getOnSchedule() );
//	}

	theInitialExecutionData->setSystemRID();

	theInitialExecutionData->setRuntimeFormState(
			theSystemRID, PROCESS_RUNNING_STATE );

	return( theInitialExecutionData );
}




/**
 * BUILDER
 * Replace a qualified element by its runtime's counterpart
 */

BF Builder::compileExpression(const BF & aCode)
{
	return( compileExpression( mConfiguration.
			getExecutableSystem().defaultExecutableForm(), aCode) );
}

BFCode Builder::compileStatement(const BFCode & aCode)
{
	return( compileStatement( mConfiguration.
			getExecutableSystem().defaultExecutableForm(), aCode) );
}



BF Builder::searchSymbolInstance(TableOfSymbol & aliasTable,
		const ExecutionData & anED, UniFormIdentifier * anUFI)
{
	std::ostringstream osUFI;

	std::string aFullyQualifiedNameID = anUFI->str();

	{
		const BF & foundInstance =
				aliasTable.getByFQNameID( aFullyQualifiedNameID );
		if( foundInstance.valid() )
		{
			return( foundInstance );
		}
	}


	if( anED.hasLocalRuntimeStack() )
	{
		StackOfLocalRuntime::const_reverse_iterator it =
				anED.getLocalRuntimes()->rbegin();
		StackOfLocalRuntime::const_reverse_iterator itEnd =
				anED.getLocalRuntimes()->rend();
		for(  ; it != itEnd ; ++it )
		{
			const BF & anInstance = (*it).getProgram()->getAllData().
					getByFQNameID( aFullyQualifiedNameID );
			if( anInstance.valid() )
			{
				return( anInstance );
			}
		}
	}


	UniFormIdentifier::iterator it = anUFI->begin();
	UniFormIdentifier::iterator itEnd = anUFI->end();

	// recherche de la machine PRINCIPALE (ROOT)
	osUFI << "inst::" << (*it).str();

	const RuntimeID & theSystemRID = anED.getSystemRID();
	RuntimeID theMachineID = theSystemRID;

	for( ++it ; (it != itEnd) ; ++it )
	{
		if( theMachineID.getInstance()->fqnEquals( osUFI.str() ) )
		{
			break;
		}
		osUFI << "." << (*it).str();
	}

	if( it != itEnd )
	{
		VectorOfInstanceOfMachine aliasPath;

		RuntimeID rid = theMachineID;

		// comme c'est la spec RID
//		aliasPath.append( theMachineID.getInstance() );

		// recherche de la machine FEUILLE
		for( ; it != itEnd ; ++it)
		{
			osUFI << "." << (*it).str();
			rid = anED.getRuntime(rid).getChild( osUFI.str() );
			if( rid.valid() )
			{
				theMachineID = rid;
				aliasPath.append( theMachineID.getInstance() );
			}
			else
			{
				break;
			}
		}

		if( (it == itEnd) && (theMachineID == theSystemRID) )
		{
			--it;
		}

		if( it != itEnd )
		{
			ExecutableForm * anExecutable = theMachineID.getExecutable();
			osUFI.str( "" );

			osUFI << "inst::"      // with std::strlen( "exec::" ) --> 6
					<< anExecutable->getFullyQualifiedNameID().substr( 6 );

			for( ; it != itEnd ; ++it)
			{
				osUFI << "." << (*it).str();
			}


			// The ORIGINAL INSTANCE
			BF anInstance = anExecutable->getAllData().getByFQNameID(
					osUFI.str() );

			if( anInstance.invalid() )
			{
				anInstance = anExecutable->getConstData().getByFQNameID(
						osUFI.str() );
			}
			if( anInstance.invalid() )
			{
				anInstance = anExecutable->getPort().getByFQNameID(
						osUFI.str() );
			}
			if( anInstance.invalid() )
			{
				anInstance = anExecutable->getBuffer().getByFQNameID(
						osUFI.str() );
			}
			if( anInstance.invalid() )
			{
				anInstance = anExecutable->getConnect().getByFQNameID(
						osUFI.str() );
			}

			if( anInstance.valid() )
			{

//				AVM_OS_TRACE << TAB << "Searching " << anUFI->str() << std::endl
//						<< TAB << "Found " << std::endl;
//				anInstance.toStream(AVM_OS_TRACE << TAB);
//				AVM_OS_TRACE << std::flush;

				if( aliasPath.nonempty() )
				{
					BaseInstanceForm * newInstance = NULL;

					switch ( anInstance.classKind() )
					{
						case FORM_INSTANCE_DATA_KIND:
						{
							newInstance = new InstanceOfData(
									theSystemRID.getExecutable(),
									anInstance.to_ptr< InstanceOfData >(),
									aliasPath);
							newInstance->setCreatorContainerRID( theMachineID );
							newInstance->setRuntimeContainerRID( theMachineID );
							aliasTable.save( newInstance );

							break;
						}

						case FORM_INSTANCE_MACHINE_KIND:
						{
							newInstance = new InstanceOfMachine(
									theSystemRID.getExecutable(),
									anInstance.to_ptr< InstanceOfMachine >(),
									aliasPath);
							newInstance->setCreatorContainerRID( theMachineID );
							newInstance->setRuntimeContainerRID( theMachineID );

							return( aliasTable.save( newInstance ) );
						}

						case FORM_INSTANCE_PORT_KIND:
						{
							newInstance = new InstanceOfPort(
									theSystemRID.getExecutable(),
									anInstance.to_ptr< InstanceOfPort >(),
									aliasPath);
							newInstance->setCreatorContainerRID( theMachineID );
							newInstance->setRuntimeContainerRID( theMachineID );

							return( aliasTable.save( newInstance ) );
						}

						case FORM_INSTANCE_BUFFER_KIND:
						{
							newInstance = new InstanceOfBuffer(
									theSystemRID.getExecutable(),
									anInstance.to_ptr< InstanceOfBuffer >(),
									aliasPath);
							newInstance->setCreatorContainerRID( theMachineID );
							newInstance->setRuntimeContainerRID( theMachineID );

							return( aliasTable.save( newInstance ) );
						}

						case FORM_INSTANCE_CONNECTOR_KIND:
						{
							newInstance = new InstanceOfConnect(
									theSystemRID.getExecutable(),
									anInstance.to_ptr< InstanceOfConnect >(),
									aliasPath);
							newInstance->setCreatorContainerRID( theMachineID );
							newInstance->setRuntimeContainerRID( theMachineID );

							return( aliasTable.save( newInstance ) );
						}

						default :
						{
							return( BF::REF_NULL );
						}
					}
				}
			}

			return( anInstance );
		}

		else if( aliasPath.nonempty() )
		{
			return( BF(	sep::incrReferenceCount(aliasPath.last()) ) );
		}


		else
		{
			AVM_OS_EXIT( FAILED )
					<< "Unfound leaf machine : " << osUFI.str()
					<< " >> container of << " << aFullyQualifiedNameID
					<< " >> !!!"
					<< SEND_EXIT;
		}
	}

	return( BF::REF_NULL );
}


const BF & Builder::searchSymbolInstance(TableOfSymbol & aliasTable,
		const ExecutionData & anED, const ObjectElement * astElement)
{
	{
		const BF & foundInstance = aliasTable.getByAstElement(astElement);
		if( foundInstance.valid() )
		{
			return( foundInstance );
		}
	}

	if( anED.hasLocalRuntimeStack() )
	{
		StackOfLocalRuntime::const_reverse_iterator it =
				anED.getLocalRuntimes()->rbegin();
		StackOfLocalRuntime::const_reverse_iterator itEnd =
				anED.getLocalRuntimes()->rend();
		for( ; it != itEnd ; ++it )
		{
			const BF & anInstance =
					(*it).getProgram()->getAllData().getByAstElement(astElement);
			if( anInstance.valid() )
			{
				return( anInstance );
			}
		}
	}

	{
		ExecutableQuery XQuery( mConfiguration );

		const BF & foundInstance = XQuery.getInstanceByAstElement(astElement);

		return( foundInstance );
	}
}


const BF & Builder::searchSymbolInstance(TableOfSymbol & aliasTable,
		const ExecutionData & anED, const BF & aBaseInstance)
{
	if( aliasTable.contains(aBaseInstance) )
	{
		return( aBaseInstance );
	}

	if( anED.hasLocalRuntimeStack() )
	{
		StackOfLocalRuntime::const_reverse_iterator it =
				anED.getLocalRuntimes()->rbegin();
		StackOfLocalRuntime::const_reverse_iterator itEnd =
				anED.getLocalRuntimes()->rend();
		for( ; it != itEnd ; ++it )
		{
			if( (*it).getProgram()->containsData( aBaseInstance ) )
			{
				return( aBaseInstance );
			}
		}
	}

	const RuntimeID & theSystemRID = anED.getSystemRID();

	VectorOfInstanceOfMachine aliasPath;

	TableOfRuntimeT::const_iterator itRF = anED.getTableOfRuntime().begin();
	TableOfRuntimeT::const_iterator endRF = anED.getTableOfRuntime().end();
	for( RuntimeID itRID ; itRF != endRF ; ++itRF)
	{
		itRID = (*itRF)->getRID();

		switch( aBaseInstance.classKind() )
		{
			case FORM_INSTANCE_DATA_KIND:
			{
				if( itRID.getExecutable()->containsData(
						aBaseInstance.to_ptr< InstanceOfData >() ) )
				{
					aliasPath.append( itRID.getInstance() );

					InstanceOfData * newInstance = new InstanceOfData(
							theSystemRID.getExecutable(),
							aBaseInstance.to_ptr< InstanceOfData >(), aliasPath);
					newInstance->setCreatorContainerRID( itRID );
					newInstance->setRuntimeContainerRID( itRID );

					aliasTable.save( newInstance );
				}

				break;
			}

			case FORM_INSTANCE_MACHINE_KIND:
			{
				if( itRID.getExecutable()->
						getInstanceStatic().contains(aBaseInstance) )
				{
					aliasPath.append( itRID.getInstance() );

					InstanceOfMachine * newInstance = new InstanceOfMachine(
							theSystemRID.getExecutable(),
							aBaseInstance.to_ptr< InstanceOfMachine >(),
							aliasPath );
					newInstance->setCreatorContainerRID( itRID );
					newInstance->setRuntimeContainerRID( itRID );

					aliasTable.save( newInstance );
				}
				break;
			}

			case FORM_INSTANCE_PORT_KIND:
			{
				if( itRID.getExecutable()->getPort().contains(aBaseInstance) )
				{
					aliasPath.append( itRID.getInstance() );

					InstanceOfPort * newInstance = new InstanceOfPort(
							theSystemRID.getExecutable(),
							aBaseInstance.to_ptr< InstanceOfPort >(), aliasPath);
					newInstance->setCreatorContainerRID( itRID );
					newInstance->setRuntimeContainerRID( itRID );

					aliasTable.save( newInstance );
				}
				break;
			}

			case FORM_INSTANCE_BUFFER_KIND:
			{
				InstanceOfBuffer * bufferInstance =
						aBaseInstance.to_ptr< InstanceOfBuffer >();

				if( itRID.getExecutable()->getBuffer().contains(bufferInstance) )
				{
					aliasPath.append( itRID.getInstance() );

					InstanceOfBuffer * newInstance = new InstanceOfBuffer(
							theSystemRID.getExecutable(),
							bufferInstance, aliasPath );
					newInstance->setCreatorContainerRID( itRID );
					newInstance->setRuntimeContainerRID( itRID );

					aliasTable.save( newInstance );
				}
				break;
			}

			case FORM_INSTANCE_CONNECTOR_KIND:
			{
				InstanceOfConnect * connectInstance =
						aBaseInstance.to_ptr< InstanceOfConnect >();

				if( itRID.getExecutable()->getConnect().contains(connectInstance) )
				{
					aliasPath.append( itRID.getInstance() );

					InstanceOfConnect * newInstance = new InstanceOfConnect(
							theSystemRID.getExecutable(),
							connectInstance, aliasPath );
					newInstance->setCreatorContainerRID( itRID );
					newInstance->setRuntimeContainerRID( itRID );

					aliasTable.save( newInstance );
				}
				break;
			}

			default :
			{
				break;
			}
		}
	}

	return( aBaseInstance );
}



BF Builder::build(TableOfSymbol & aliasTable,
		const ExecutionData & anED, const AvmProgram & aProgram, const BF & aCode)
{
	if( aProgram.hasData() )
	{
		bool destroyLocalRuntimeStackFlag = false;

		ExecutionData cloneED( anED );

		if( not cloneED.hasLocalRuntimeStack() )
		{
			destroyLocalRuntimeStackFlag = true;
			cloneED.createLocalRuntimeStack();
		}
		cloneED.getLocalRuntimes()->push( LocalRuntime(aProgram) );

		BF buildCode = build(aliasTable, cloneED, aCode);

		cloneED.getLocalRuntimes()->pop();
		if( destroyLocalRuntimeStackFlag )
		{
			cloneED.destroyLocalRuntimeStack();
		}


		return( buildCode );
	}
	else
	{
		return( build(aliasTable, anED, aCode) );
	}
}


BF Builder::build(const ExecutionData & anED, const BF & aCode)
{
	TableOfSymbol aliasTable;

	BF buildCode = build(aliasTable, anED, aCode);

	aliasTable.clear();

	return( buildCode );
}


BF Builder::build(TableOfSymbol & aliasTable,
		const ExecutionData & anED, const BF & aCode)
{
	BF compileCode = compile(aliasTable, anED, aCode);
	if( compileCode.is< AvmCode >() )
	{
		compileCode = mAvmcodeCompiler.optimizeExpression(
				mConfiguration.getExecutableSystem().rawSystemInstance()
						->getExecutable(), compileCode.bfCode());
	}

	return( ExpressionConstructor::newExpr( compileCode ) );
}


BF Builder::compile(TableOfSymbol & aliasTable,
		const ExecutionData & anED, const BF & aCode)
{
	switch( aCode.classKind() )
	{
		case FORM_AVMCODE_KIND:
		{
			BFCode anAvmCode = aCode.bfCode();
			Operator * mainOperator = anAvmCode->getOperator();

			BFCode newCode( mainOperator );

			AvmCode::iterator itArg = anAvmCode->begin();
			AvmCode::iterator itEndArg = anAvmCode->end();
			for( ; itArg != itEndArg ; ++itArg )
			{
				switch( (*itArg).classKind() )
				{
					case FORM_AVMCODE_KIND:
					{
						BF bf = compile(aliasTable, anED, *itArg);

						if( bf.is< AvmCode >() )
						{
							anAvmCode = bf.bfCode();
							if( anAvmCode->isOpCode( mainOperator ) &&
								mainOperator->isAssociative() )
							{
								newCode->append( anAvmCode->getArgs() );
							}
							else
							{
								newCode->append( bf );
							}
						}
						else
						{
							newCode->append( bf );
						}

						break;
					}


					default:
					{
						newCode->append( compile(aliasTable, anED, *itArg) );

						break;
					}
				}

			}

			return( newCode );
		}


		case FORM_UFI_KIND:
		{
			BF anInstance = searchSymbolInstance(aliasTable,
					anED, aCode.to_ptr< UniFormIdentifier>());
			if( anInstance.valid() )
			{
				if( anInstance.is< InstanceOfData >() )
				{
					InstanceOfData * aData = anInstance.to_ptr< InstanceOfData >();
					if( aData->getModifier().hasFeatureFinal() && aData->hasValue() )
					{
						return( aData->getValue() );
					}
				}

				return( anInstance );
			}
			else
			{
				ExecutableQuery XQuery( mConfiguration );

				const BF & aProgram = XQuery.getExecutableOrProgram(aCode.str());
				if( aProgram.valid() )
				{
					return( aProgram );
				}
				else
				{
					AVM_OS_EXIT( FAILED )
							<< "Unfound UFI symbol : " << aCode.str()
							<< SEND_EXIT;

					return( aCode );
				}
			}

			break;
		}

		case FORM_XFSP_BUFFER_KIND:
		case FORM_XFSP_CHANNEL_KIND:
		case FORM_XFSP_CONNECTOR_KIND:
		case FORM_XFSP_MACHINE_KIND:
		case FORM_XFSP_PORT_KIND:
		case FORM_XFSP_ROUTINE_KIND:
		case FORM_XFSP_SYSTEM_KIND:
		case FORM_XFSP_TRANSITION_KIND:
		case FORM_XFSP_DATATYPE_KIND:
		case FORM_XFSP_VARIABLE_KIND:
		{
			const BF & anInstance = searchSymbolInstance(
					aliasTable, anED, aCode.to_ptr< ObjectElement >() );
			if( anInstance.valid() )
			{
				if( anInstance.is< InstanceOfData >() )
				{
					InstanceOfData * aData = anInstance.to_ptr< InstanceOfData >();
					if( aData->getModifier().hasFeatureFinal() && aData->hasValue() )
					{
						return( aData->getValue() );
					}
				}

				return( anInstance );
			}
			else
			{
				ExecutableQuery XQuery( mConfiguration );

				const BF & aProgram = XQuery.getExecutableOrProgram(
						aCode.to_ptr< ObjectElement >() );
				if( aProgram.valid() )
				{
					return( aProgram );
				}
				else
				{
					AVM_OS_EXIT( FAILED )
							<< "Unfound FORM symbol : " << aCode.str()
							<< SEND_EXIT;

					return( aCode );
				}
			}

			break;
		}

		case FORM_OPERATOR_KIND:
		{
			return( aCode );
		}

		case FORM_INSTANCE_DATA_KIND:
		{
			const BF & anInstance = searchSymbolInstance(aliasTable, anED, aCode);
			if( anInstance.valid() )
			{
				if( anInstance.is< InstanceOfData >() )
				{
					InstanceOfData * aData = anInstance.to_ptr< InstanceOfData >();
					if( aData->getModifier().hasFeatureFinal() && aData->hasValue() )
					{
						return( aData->getValue() );
					}
				}

				return( anInstance );
			}

			return( aCode );
		}

		case FORM_INSTANCE_BUFFER_KIND:
		case FORM_INSTANCE_CONNECTOR_KIND:
		case FORM_INSTANCE_MACHINE_KIND:
		case FORM_INSTANCE_PORT_KIND:
		{
			BF anInstance = searchSymbolInstance(aliasTable, anED, aCode);
			if( anInstance.valid() )
			{
				// AVM_OS_TRACE << " --> bOK" << std::endl;

				return( anInstance );
			}

			return( aCode );
		}

		case FORM_RUNTIME_ID_KIND:
		{
			return( aCode );
		}


		//@deprecated
		//case FORM_EXPRESSION_GINAC_KIND:

		case FORM_BUILTIN_BOOLEAN_KIND:
		case FORM_BUILTIN_CHARACTER_KIND:
		case FORM_BUILTIN_INTEGER_KIND:
		case FORM_BUILTIN_RATIONAL_KIND:
		case FORM_BUILTIN_FLOAT_KIND:
		case FORM_BUILTIN_STRING_KIND:
		case FORM_BUILTIN_IDENTIFIER_KIND:
		case FORM_BUILTIN_QUALIFIED_IDENTIFIER_KIND:
		{
			return( aCode );
		}

		default:
		{
			AVM_OS_EXIT( FAILED )
					<< "Unexpected FORM KIND for compileAvmCode\n"
					<< aCode.toString()
					<< SEND_EXIT;

			return( aCode );
		}
	}

	return( BF::REF_NULL );

}


}
