blob: a7f516f2c9206c9a88eee278b73524b4403ffc4b [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: 9 juil. 2014
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#include "ParserUtil.h"
#include <fml/common/LocationElement.h>
#include <fml/common/ObjectElement.h>
#include <fml/common/SpecifierElement.h>
#include <fml/common/TraceableElement.h>
#include <fml/executable/ExecutableLib.h>
#include <fml/executable/InstanceOfMachine.h>
#include <fml/expression/AvmCode.h>
#include <fml/expression/BuiltinArray.h>
#include <fml/expression/ExpressionConstructor.h>
#include <fml/expression/StatementConstructor.h>
#include <fml/lib/AvmOperationFactory.h>
#include <fml/lib/IComPoint.h>
#include <fml/operator/Operator.h>
#include <fml/operator/OperatorManager.h>
#include <fml/type/TypeManager.h>
#include <fml/infrastructure/Buffer.h>
#include <fml/infrastructure/Channel.h>
#include <fml/infrastructure/DataType.h>
#include <fml/infrastructure/InstanceSpecifierPart.h>
#include <fml/infrastructure/Machine.h>
#include <fml/infrastructure/Package.h>
#include <fml/infrastructure/Port.h>
#include <fml/infrastructure/Routine.h>
#include <fml/infrastructure/Transition.h>
#include <fml/infrastructure/Variable.h>
#include <fml/infrastructure/BehavioralPart.h>
#include <fml/infrastructure/CompositePart.h>
#include <fml/infrastructure/PropertyPart.h>
#include <sew/Workflow.h>
namespace sep
{
////////////////////////////////////////////////////////////////////////////////
// XLIA MACRO
////////////////////////////////////////////////////////////////////////////////
#define OP(op) OperatorManager::OPERATOR_##op
#define NEW_ID(id) sep::ExpressionConstructor::newIdentifier(id)
#define NEW_UFID(qnid, nb) ( (nb > 1) ? \
ExpressionConstructor::newQualifiedIdentifier(qnid) : \
ExpressionConstructor::newIdentifier(qnid) )
#define NEW_INSTANCE_UFID(machine, var) \
ExpressionConstructor::newQualifiedIdentifier( \
OSS() << machine->getNameID() << '.' << var->getNameID() )
////////////////////////////////////////////////////////////////////////////////
// Current Parse Context :
// System -> Machine -> Routine
////////////////////////////////////////////////////////////////////////////////
ParserUtil::AvmParseContext ParserUtil::_CTX_;
std::stack< ParserUtil::AvmParseContext > ParserUtil::_CTX_STACK_;
////////////////////////////////////////////////////////////////////////////////
// XLIA_SYNTAX_ERROR_COUNT
////////////////////////////////////////////////////////////////////////////////
avm_size_t ParserUtil::XLIA_SYNTAX_ERROR_COUNT = 0;
////////////////////////////////////////////////////////////////////////////////
// SET LOCATION IN TRACEABLE FORM
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::setLocation(TraceableElement * aTraceableElement,
avm_size_t bLine, avm_size_t eLine)
{
if( aTraceableElement != NULL)
{
ParserUtil::setLocation( *aTraceableElement, bLine, eLine );
}
}
void ParserUtil::setLocation(TraceableElement & aTraceableElement,
avm_size_t bLine, avm_size_t eLine)
{
if( not aTraceableElement.hasLocation() )
{
aTraceableElement.setLocation( new LocationElement() );
}
aTraceableElement.getLocation()->setLine( bLine , eLine );
}
////////////////////////////////////////////////////////////////////////////////
// PROLOGUE OPTION
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::setPrologueOption(const std::string & id, BF value)
{
Workflow::INSTANCE->setPrologueOption(id, value);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET VARIABLE BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getObjectByNameID(const std::string & aNameID)
{
if( _CTX_.routine != NULL )
{
const BF & var = _CTX_.routine->getParamReturn(aNameID);
if( var.valid() )
{
return( var );
}
}
{
const BF & form = _CTX_.machine->getsemFormByNameID(aNameID);
if( form.valid() )
{
return( form );
}
}
return( BF::REF_NULL );
// return( NEW_ID(aNameID) );
}
const BF & ParserUtil::getObjectByQualifiedNameID(const std::string & qnid, avm_size_t count)
{
if( count == 1 )
{
return( getObjectByNameID(qnid) );
}
else
{
const BF & form = _CTX_.machine->getPropertyByQualifiedNameID(qnid);
if( form.valid() )
{
return( form );
}
}
return( BF::REF_NULL );
// return( NEW_UFID(qnid, count) );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET VARIABLE BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getvar(const std::string & qnid, avm_size_t count)
{
if( count > 1 )
{
const BF & var = _CTX_.machine->getrecVariable(qnid);
if( var.valid() )
{
return( var );
}
}
else
{
if( _CTX_.routine != NULL )
{
const BF & var = _CTX_.routine->getParamReturn(qnid);
if( var.valid() )
{
return( var );
}
}
{
const BF & var = _CTX_.machine->getsemVariable(qnid);
if( var.valid() )
{
return( var );
}
}
}
return( BF::REF_NULL );
}
BF ParserUtil::getVariable(const std::string & qnid, avm_size_t count)
{
const BF & var = getvar(qnid, count);
if( var.valid() )
{
return( var );
}
else
{
AVM_OS_WARN << "Error:> unfound variable< " << qnid
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF( new Variable(_CTX_.machine,
Modifier::PROPERTY_UNDEFINED_MODIFIER,
TypeManager::INTEGER, qnid) ) );
}
return( var );
}
BF ParserUtil::getDataType(const std::string & qnid, avm_size_t count)
{
const BF & var = ( count > 1 )
? _CTX_.machine->getrecDataType(qnid)
: _CTX_.machine->getsemDataType(qnid);
if( var.valid() )
{
return( var );
}
AVM_OS_WARN << "Error:> unfound typedef " << qnid
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF( new Variable(_CTX_.machine,
Modifier::PROPERTY_UNDEFINED_MODIFIER,
TypeManager::INTEGER, qnid) ) );
}
BF ParserUtil::getDataTypeQueue(const std::string & qnid, avm_size_t count)
{
if( count > 1 )
{
const BF & var = _CTX_.machine->getrecDataType(qnid);
if( var.is< DataType >()
&& var.to_ptr< DataType >()->hasTypeQueue() )
{
return( var );
}
}
else
{
const BF & var = _CTX_.machine->getsemDataType(qnid);
if( var.is< DataType >()
&& var.to_ptr< DataType >()->hasTypeQueue() )
{
return( var );
}
}
AVM_OS_WARN << "Error:> unexpected a non-queue variable< " << qnid
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF( DataType::newContainer(
_CTX_.machine, qnid, TYPE_FIFO_SPECIFIER, 1) ) );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET CONSTANT BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getConstant(
const std::string & qnid, avm_size_t count)
{
const BF & var = getvar(qnid, count);
if( var.valid() && var.to_ptr< Variable >()->getModifier().hasFeatureFinal() )
{
return( var );
}
return( BF::REF_NULL );
}
avm_size_t ParserUtil::getIntegerConstant(
const std::string & qnid, avm_size_t count)
{
const BF & var = getvar(qnid, count);
if( var.valid() )
{
Variable * pVar = var.to_ptr< Variable >();
if( pVar->getModifier().hasFeatureFinal() && pVar->hasValue() &&
pVar->getValue().isWeakInteger() )
{
return( pVar->getValue().toInteger() );
}
}
avm_syntax_error( "integer_constant (...)" )
<< "unfound the integer constant Qualified Name ID< " << qnid
<< " > from the machine< "
<< _CTX_.machine->getFullyQualifiedNameID() << " >"
<< SYNTAX_ERROR_EOL;
return( 0 );
}
avm_float_t ParserUtil::getFloatConstant(
const std::string & qnid, avm_size_t count)
{
const BF & var = getvar(qnid, count);
if( var.valid() )
{
Variable * pVar = var.to_ptr< Variable >();
if( pVar->getModifier().hasFeatureFinal() && pVar->hasValue() &&
pVar->getValue().isWeakFloat() )
{
return( pVar->getValue().toFloat() );
}
}
avm_syntax_error( "float_constant(...)" )
<< "unfound the float constant Qualified Name ID< " << qnid
<< " > from the machine< "
<< _CTX_.machine->getFullyQualifiedNameID() << " >"
<< SYNTAX_ERROR_EOL;
return( 0.0 );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET BUFFER BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
BF ParserUtil::getBuffer(Machine * machine,
const std::string & qnid, avm_size_t count)
{
const BF & buf = ( count > 1 )
? machine->getrecBuffer(qnid)
: machine->getsemBuffer(qnid);
if( buf.valid() )
{
return( buf );
}
// AVM_OS_WARN << "Warning:> unfound buffer< " << qnid << " > in machine< "
// << str_header( machine ) << " >!!!" << std::endl;
// ++XLIA_SYNTAX_ERROR_COUNT;
return( NEW_UFID(qnid, count) );
}
BF ParserUtil::getvarBuffer(const std::string & qnid, avm_size_t count)
{
const BF & buffer = ( count > 1 )
? _CTX_.machine->getrecBuffer(qnid)
: _CTX_.machine->getsemBuffer(qnid);
if( buffer.valid() )
{
return( buffer );
}
BF varBuffer = getvar(qnid, count);
if( varBuffer.valid() )
{
return( varBuffer );
}
else
{
return( NEW_UFID(qnid, count) );
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET CHANNEL BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
BF ParserUtil::getChannel(const std::string & qnid, avm_size_t count)
{
const BF & chan = ( count > 1 )
? _CTX_.machine->getrecChannel(qnid)
: _CTX_.machine->getsemChannel(qnid);
if( chan.valid() )
{
return( chan );
}
// AVM_OS_WARN << "Warning:> Unfound channel< " << qnid << " > in machine< "
// << str_header( _CTX_.machine ) << " >!!!" << std::endl;
// ++XLIA_SYNTAX_ERROR_COUNT;
return( NEW_UFID(qnid, count) );
}
void ParserUtil::updateSignalRoutingChannel(Modifier::DIRECTION_KIND ioDirection,
const BFCode & ioCode, const std::string & qnid, avm_size_t count)
{
const BF & chan = ( count > 1 )
? _CTX_.machine->getrecChannel(qnid)
: _CTX_.machine->getsemChannel(qnid);
if( chan.valid() )
{
// if( ioCode->first().is< Port >() )
// {
// ioCode->first().to_ptr< Port >()->setRoutingChannel(chan);
// }
BF chanSignal = chan.to_ptr< Channel >()->getSignal(
ioDirection, ioCode->first());
if( chanSignal.valid() )
{
ioCode->set(0, chanSignal);
}
return;
}
AVM_OS_WARN << "Warning:> unfound channel< " << qnid
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
//++XLIA_SYNTAX_ERROR_COUNT;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET PORT BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getComPort(Machine * machine,
const std::string & qnid, avm_size_t count)
{
if( count > 1 )
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getrecPort(qnid) );
const BF & port = machine->getrecPort(qnid);
if( port.valid() )
{
return( port );
}
}
else
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getsemPort(qnid) );
const BF & port = machine->getsemPort(qnid);
if( port.valid() )
{
return( port );
}
}
AVM_OS_WARN << "Error:> unfound port< " << qnid << " > in machine< "
<< str_header( machine ) << " >!!!" << std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF::REF_NULL );
}
BF ParserUtil::getvarPort(const std::string & qnid, avm_size_t count)
{
const BF & port = ( count > 1 )
? _CTX_.machine->getrecPort(qnid)
: _CTX_.machine->getsemPort(qnid);
if( port.valid() )
{
return( port );
}
else
{
BF varPort( getvar(qnid, count) );
if( varPort.valid() )
{
return( varPort );
}
else
{
return( NEW_UFID(qnid, count) );
}
}
}
void ParserUtil::appendPortParameter(Port * port,
const std::string & label, BFVector & labelledParams,
BFList & positionalParams, const BF & param)
{
if( label.empty() )
{
positionalParams.append( param );
}
else if( port != NULL )
{
avm_offset_t offset = port->getParameterOffset(label);
if( offset != AVM_NO_OFFSET )
{
labelledParams[ offset ] = param;
}
else
{
positionalParams.append( param );
avm_syntax_error( "ParserUtil::appendPortParameter(...)" )
<< "Unfound labelled < " << label
<< " > in port< " << str_header( port ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
else
{
positionalParams.append( param );
avm_syntax_error( "ParserUtil::appendPortParameter(...)" )
<< "Unfound labelled < " << label
<< " > in port< UNKNOWN at parsing time >"
<< SYNTAX_ERROR_EOL;
}
}
void ParserUtil::computePortParameter(
Port * port, const BFCode & ioStatement,
BFVector & labelledParams, BFList & positionalParams)
{
if( labelledParams.empty() )
{
ioStatement->append( positionalParams );
}
else if( port != NULL )
{
TableOfVariable::const_raw_iterator it = port->getParameters().begin();
TableOfVariable::const_raw_iterator endIt = port->getParameters().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
if( labelledParams[offset].valid() )
{
ioStatement->append( labelledParams[offset] );
}
else if( (it)->getModifier().hasNatureParameterBind() )
{
if( (it)->hasValue() )
{
ioStatement->append( (it)->getValue() );
}
else
{
avm_syntax_error( "ParserUtil::computePortParameter(...)" )
<< "Unexpected $bind parameters:" << std::endl
<< "#" << offset << " " << str_header( (*it) )
<< std::endl << "wihtout bind lvalue for port:"
<< std::endl << str_header( port )
<< SYNTAX_ERROR_EOL;
}
}
else if( (it)->getModifier().hasNatureParameter() )
{
if( positionalParams.nonempty() )
{
ioStatement->append( positionalParams.pop_first() );
}
else if( (it)->hasValue() )
{
ioStatement->append( (it)->getValue() );
}
}
else if( positionalParams.nonempty() )
{
ioStatement->append( positionalParams.pop_first() );
}
else
{
avm_syntax_error( "ParserUtil::computePortParameter(...)" )
<< "Unexpected parameters for port< "
<< str_header( port ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET SIGNAL BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getComSignal(Machine * machine,
const std::string & qnid, avm_size_t count)
{
if( count > 1 )
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getrecSignal(qnid) );
const BF & signal = machine->getrecSignal(qnid);
if( signal.valid() )
{
return( signal );
}
}
else
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getsemSignal(qnid) );
const BF & signal = machine->getsemSignal(qnid);
if( signal.valid() )
{
return( signal );
}
}
AVM_OS_WARN << "Error:> unfound signal< " << qnid << " > in machine< "
<< str_header( machine ) << " >!!!" << std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF::REF_NULL );
}
BF ParserUtil::getvarSignal(const std::string & qnid, avm_size_t count)
{
const BF & signal = ( count > 1 )
? _CTX_.machine->getrecSignal(qnid)
: _CTX_.machine->getsemSignal(qnid);
if( signal.valid() )
{
return( signal );
}
else
{
BF varSignal( getvar(qnid, count) );
if( varSignal.valid() )
{
return( varSignal );
}
else
{
return( NEW_UFID(qnid, count) );
}
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET PORT or SIGNAL BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
const BF & ParserUtil::getComPortSignal(Machine * machine,
const std::string & qnid, avm_size_t count)
{
if( count > 1 )
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getrecSignal(qnid) );
const BF & portSignal = machine->getrecPortSignal(qnid);
if( portSignal.valid() )
{
return( portSignal );
}
}
else
{
if( machine->getSpecifier().isDesignInstanceStatic()
&& machine->hasType()
&& machine->getType().is< Machine >() )
{
machine = machine->getType().to_ptr< Machine >();
}
//return( machine->getsemSignal(qnid) );
const BF & portSignal = machine->getsemPortSignal(qnid);
if( portSignal.valid() )
{
return( portSignal );
}
}
AVM_OS_WARN << "Error:> unfound port/signal< " << qnid << " > in machine< "
<< str_header( machine ) << " >!!!" << std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF::REF_NULL );
}
BF ParserUtil::getvarPortSignal(
const std::string & qnid, avm_size_t count)
{
const BF & portSignal = ( count > 1 )
? _CTX_.machine->getrecPortSignal(qnid)
: _CTX_.machine->getsemPortSignal(qnid);
if( portSignal.valid() )
{
return( portSignal );
}
else
{
BF var( getvar(qnid, count) );
if( var.valid() )
{
return( var );
}
else
{
return( NEW_UFID(qnid, count) );
}
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET ROUTINE BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Routine * ParserUtil::getRoutine(const std::string & aNameID)
{
Routine * foundRoutine = _CTX_.machine->rawsemRoutineByNameID(aNameID);
if( foundRoutine == NULL )
{
AVM_OS_WARN << "Error:> unfound routine< " << aNameID
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( Routine::newDefine(_CTX_.machine, aNameID) );
}
return( foundRoutine );
}
BF ParserUtil::getvarRoutine(const std::string & aNameID)
{
Routine * foundRoutine = _CTX_.machine->rawsemRoutineByNameID(aNameID);
if( foundRoutine == NULL )
{
Operator * op = AvmOperationFactory::get(aNameID);
if( op != NULL )
{
return( INCR_BF(op) );
}
else
{
AVM_OS_WARN << "Error:> unfound routine< " << aNameID
<< " > in machine< " << str_header( _CTX_.machine )
<< " >!!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
}
return( NEW_ID(aNameID) );
}
return( INCR_BF(foundRoutine) );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET PROCEDURE BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Machine * ParserUtil::getProcedure(const std::string & aNameID)
{
Machine * foundProcedure = _CTX_.machine->rawsemProcedureByNameID(aNameID);
if( foundProcedure == NULL )
{
AVM_OS_WARN << "Error:> unfound procedure< " << aNameID
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( Machine::newProcedure(_CTX_.machine, aNameID,
Specifier::COMPONENT_PROCEDURE_SPECIFIER) );
}
return( foundProcedure );
}
BF ParserUtil::getvarProcedure(const std::string & aNameID)
{
Machine * foundProcedure = _CTX_.machine->rawsemProcedureByNameID(aNameID);
if( foundProcedure == NULL )
{
AVM_OS_WARN << "Error:> unfound procedure< " << aNameID
<< " > in " << str_header( _CTX_.machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( NEW_ID(aNameID) );
}
return( INCR_BF(foundProcedure) );
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// GET MACHINE BY [ [ Fully ] Qualified ] Name ID
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Machine * ParserUtil::getMachine(Machine * machine,
const std::string & qnid, avm_size_t count)
{
Machine * foundMachine = ( count > 1 )
? machine->getrecMachine(qnid)
: machine->getsemMachineByNameID(qnid);
if( foundMachine == NULL )
{
AVM_OS_WARN << "Error:> unfound machine< " << qnid
<< " > in " << str_header( machine ) << " !!!"
<< std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( new Machine(machine, qnid,
Specifier::COMPONENT_EXECUTABLE_SPECIFIER) );
}
return( foundMachine );
}
BF ParserUtil::getvarMachine(const std::string & qnid, avm_size_t count)
{
Machine * foundMachine = NULL;
if( count > 1 )
{
if( (foundMachine = _CTX_.machine->getsemMachine(qnid)) == NULL )
{
foundMachine = _CTX_.machine->getrecMachine(qnid);
}
}
else
{
foundMachine = _CTX_.machine->getsemMachineByNameID(qnid);
}
if( foundMachine != NULL )
{
return( INCR_BF(foundMachine) );
}
else
{
const BF & var = getvar(qnid, count);
if( var.valid() )
{
return( var );
}
else
{
return( NEW_UFID(qnid, count) );
}
}
}
BF ParserUtil::getExecutableMachine(const std::string & qnid, avm_size_t count)
{
Machine * foundMachine = ( count > 1 )
? _CTX_.machine->getrecExecutableMachine(qnid)
: _CTX_.machine->getsemExecutableMachine(qnid);
if( foundMachine == NULL )
{
AVM_OS_WARN << "Error:> unfound typedef machine< " << qnid
<< " > in machine< " << str_header( _CTX_.machine )
<< " > !!!" << std::endl;
++XLIA_SYNTAX_ERROR_COUNT;
return( BF(new Machine(_CTX_.machine, qnid,
Specifier::COMPONENT_EXECUTABLE_SPECIFIER)) );
}
return( INCR_BF(foundMachine) );
}
void ParserUtil::appendInstanceMachineParameter(Machine * machine,
const std::string & label, BFVector & labelledParams,
BFList & positionalParams, const BF & param)
{
if( label.empty() )
{
positionalParams.append( param );
}
else if( labelledParams.nonempty() )
{
machine = machine->getType().as_ptr< Machine >();
avm_offset_t offset = machine->getVariableParameterOffset(label);
if( offset != AVM_NO_OFFSET )
{
labelledParams[ offset ] = param;
}
else
{
positionalParams.append( param );
avm_syntax_error( "ParserUtil::appendInstanceMachineParameter(...)" )
<< "Unfound labelled parameter < " << label
<< " > in " << str_header( machine )
<< SYNTAX_ERROR_EOL;
}
}
else
{
avm_syntax_error( "ParserUtil::appendInstanceMachineParameter(...)" )
<< "Unfound the instance machine model < "
<< str_header( machine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
void ParserUtil::computeInstanceMachineParameter(Machine * machine,
BFVector & labelledParams, BFList & positionalParams)
{
TableOfVariable::const_raw_iterator it = machine->getType().
as_ptr< Machine >()->getVariableParameters().begin();
TableOfVariable::const_raw_iterator endIt = machine->getType().
as_ptr< Machine >()->getVariableParameters().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
if( labelledParams[offset].valid() )
{
machine->getPropertyPart().saveOwnedVariable(
new Variable(machine,
Modifier::PROPERTY_PARAMETER_MODIFIER,
(it), labelledParams[offset]) );
}
else if( (it)->getModifier().hasNatureParameterBind() )
{
machine->getPropertyPart().dispatchOwnedElement( (*it) );
if( not (it)->hasValue() )
{
avm_syntax_error(
"ParserUtil::computeInstanceMachineParameter(...)" )
<< "Unexpected $bind parameters:" << std::endl
<< "#" << offset << " " << str_header( (*it) )
<< std::endl << "wihtout value for machine:"
<< std::endl << str_header( machine )
<< SYNTAX_ERROR_EOL;
}
}
else if( (it)->getModifier().hasNatureParameter() )
{
if( positionalParams.nonempty() )
{
machine->getPropertyPart().saveOwnedVariable(
new Variable( machine,
Modifier::PROPERTY_PARAMETER_MODIFIER,
(it), positionalParams.pop_first()) );
}
else //if( (it)->hasValue() )
{
machine->getPropertyPart().dispatchOwnedElement( (*it) );
}
}
else if( positionalParams.nonempty() )
{
machine->getPropertyPart().saveOwnedVariable(
new Variable( machine,
Modifier::PROPERTY_PARAMETER_MODIFIER,
(it), positionalParams.pop_first()) );
}
else
{
avm_syntax_error( "ParserUtil::computeInstanceMachineParameter(...)" )
<< "Unexpected parameters for machine< "
<< str_header( machine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
}
void ParserUtil::appendInstanceMachineReturn(Machine * machine,
const std::string & label, BFVector & labelledReturns,
BFList & positionalReturns, const BF & param)
{
if( label.empty() )
{
positionalReturns.append( param );
}
else if( labelledReturns.nonempty() )
{
machine = machine->getType().as_ptr< Machine >();
avm_offset_t offset = machine->getVariableReturnOffset(label);
if( offset != AVM_NO_OFFSET )
{
labelledReturns[ offset ] = param;
}
else
{
positionalReturns.append( param );
avm_syntax_error( "ParserUtil::appendInstanceMachineReturn(...)" )
<< "Unfound labelled parameter < " << label
<< " > in " << str_header( machine )
<< SYNTAX_ERROR_EOL;
}
}
else
{
avm_syntax_error( "ParserUtil::appendInstanceMachineReturn(...)" )
<< "Unfound the instance machine model < "
<< str_header( machine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
void ParserUtil::computeInstanceMachineReturn(Machine * machine,
BFVector & labelledReturns, BFList & positionalReturns)
{
TableOfVariable::const_raw_iterator it =
machine->getType().as_ptr< Machine >()->getVariableReturns().begin();
TableOfVariable::const_raw_iterator endIt =
machine->getType().as_ptr< Machine >()->getVariableReturns().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
if( labelledReturns[offset].valid() )
{
machine->getPropertyPart().saveOwnedVariable(
new Variable( machine,
Modifier::PROPERTY_RETURN_PARAMETER_MODIFIER,
(it), labelledReturns[offset]) );
}
else if( (it)->getModifier().hasModifierReturnBind() )
{
machine->dispatchOwnedElement( (*it) );
if( not (it)->hasValue() )
{
avm_syntax_error(
"ParserUtil::computeInstanceMachineReturn(...)" )
<< "Unexpected #bind parameters < #"
<< offset << " > wihtout value for machine< "
<< str_header( machine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
else
{
if( positionalReturns.nonempty() )
{
machine->getPropertyPart().saveOwnedVariable(
new Variable( machine,
Modifier::PROPERTY_RETURN_PARAMETER_MODIFIER,
(it), positionalReturns.pop_first()) );
}
else //if( (it)->hasValue() )
{
machine->getPropertyPart().dispatchOwnedElement( (*it) );
}
}
}
}
void ParserUtil::appendInstanceDynamicPositionalParameter(
Machine * anInstance, const BF & rvParameter, avm_size_t position)
{
const Machine * aModel = anInstance->getModelMachine();
BF lvParameter;
if( aModel != NULL )
{
if( aModel->hasVariableParameter() )
{
const PropertyPart & aPropertyPart = aModel->getPropertyPart();
if( position < aPropertyPart.getVariableParametersCount() )
{
lvParameter = aPropertyPart.getVariableParameter(position);
anInstance->getUniqBehaviorPart()->seqOnCreate(
StatementConstructor::newCode(
OP(ASSIGN), lvParameter, rvParameter ) );
}
else
{
// avm_syntax_error( "appendInstanceDynamicPositionalParameter(...)" )
// << "Unexpected an #dynamic instance with an"
// "executable model without enough parameter's"
// << SYNTAX_ERROR_EOL;
}
}
else
{
// avm_syntax_error( "appendInstanceDynamicPositionalParameter(...)" )
// << "Unexpected an #dynamic instance with an"
// "executable model without parameter's"
// << SYNTAX_ERROR_EOL;
}
}
else
{
// avm_syntax_error( "appendInstanceDynamicPositionalParameter(...)" )
// << "Unexpected an #dynamic instance with an unknown model "
// "at parsing stage"
// << SYNTAX_ERROR_EOL;
}
if( lvParameter.invalid() )
{
lvParameter = ExpressionConstructor::
newQualifiedPositionalIdentifier(anInstance, position);
anInstance->getUniqBehaviorPart()->seqOnCreate(
StatementConstructor::newCode(
OP(ASSIGN), lvParameter, rvParameter) );
}
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// ROUTINE Parameters / Returns arguments
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::appendRoutineParameters(Routine * routine,
const std::string & label, BFVector & labelledParams,
BFList & positionalParams, const BF & param)
{
if( label.empty() )
{
positionalParams.append( param );
}
else if( routine != NULL )
{
avm_offset_t offset = routine->getParameterOffset(label);
if( offset != AVM_NO_OFFSET )
{
labelledParams[ offset ] = param;
}
else
{
positionalParams.append( param );
avm_syntax_error( "ParserUtil::appendRoutineParameters(...)" )
<< "Unfound labelled parameter < " << label
<< " > in routine< " << str_header( routine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
else
{
positionalParams.append( param );
avm_syntax_error( "ParserUtil::appendRoutineParameters(...)" )
<< "Unexpected an unknown routine activity"
<< SYNTAX_ERROR_EOL;
}
}
void ParserUtil::appendRoutineReturns(Routine * routine,
const std::string & label, BFVector & labelledReturns,
BFList & positionalReturns, const BF & param)
{
if( label.empty() )
{
positionalReturns.append( param );
}
else if( routine != NULL )
{
avm_offset_t offset = routine->getReturnOffset(label);
if( offset != AVM_NO_OFFSET )
{
labelledReturns[ offset ] = param;
}
else
{
positionalReturns.append( param );
avm_syntax_error( "ParserUtil::appendRoutineReturns(...)" )
<< "Unfound labelled parameter < " << label
<< " > in routine< " << str_header( routine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
else
{
positionalReturns.append( param );
avm_syntax_error( "ParserUtil::appendRoutineReturns(...)" )
<< "Unexpected an unknown routine activity"
<< SYNTAX_ERROR_EOL;
}
}
void ParserUtil::computeRoutineParamReturn(const BF & ctxMachine,
Routine * routine, BFCode & activityStatement,
BFVector & labelledParams, BFList & positionalParams,
BFVector & labelledReturns, BFList & positionalReturns)
{
Machine * machine = ctxMachine.is< Machine >() ?
ctxMachine.to_ptr< Machine >() : NULL;
if( (routine != NULL) && (machine != NULL) )
{
BFCode invokeSequende = StatementConstructor::newCode( OP(SEQUENCE) );
Machine * machine = ctxMachine.is< Machine >() ?
ctxMachine.to_ptr< Machine >() : NULL;
computeActivityRoutineInput(machine, routine,
invokeSequende, labelledParams, positionalParams);
computeActivityRoutineDefaultOutput(machine, routine,
invokeSequende, labelledReturns, positionalReturns);
invokeSequende->append( activityStatement );
computeActivityRoutineOutput(machine, routine,
invokeSequende, labelledReturns, positionalReturns);
activityStatement = StatementConstructor::newCode(
OP(CONTEXT_SWITCHER), ctxMachine, invokeSequende );
}
else
{
if( labelledParams.empty() )
{
activityStatement->append( positionalParams );
}
else
{
computeActivityRoutineInput(machine, routine,
activityStatement, labelledParams, positionalParams);
}
if( labelledReturns.empty() )
{
activityStatement->append( positionalReturns );
}
else
{
computeActivityRoutineOutput(machine, routine,
activityStatement, labelledReturns, positionalReturns);
}
}
}
////////////////////////////////////////////////////////////////////////////////
// ACTIVITY ROUTINE Parameters / Returns arguments
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::computeActivityRoutineParamReturn(const BF & ctxMachine,
Routine * routine, BFCode & activityStatement,
BFVector & labelledParams, BFList & positionalParams,
BFVector & labelledReturns, BFList & positionalReturns)
{
Machine * machine = ctxMachine.is< Machine >() ?
ctxMachine.to_ptr< Machine >() : NULL;
if( (routine != NULL) && (machine != NULL) )
{
BFCode invokeSequende = StatementConstructor::newCode( OP(SEQUENCE) );
Machine * machine = ctxMachine.is< Machine >() ?
ctxMachine.to_ptr< Machine >() : NULL;
computeActivityRoutineInput(machine, routine,
invokeSequende, labelledParams, positionalParams);
computeActivityRoutineDefaultOutput(machine, routine,
invokeSequende, labelledReturns, positionalReturns);
invokeSequende->append( activityStatement );
computeActivityRoutineOutput(machine, routine,
invokeSequende, labelledReturns, positionalReturns);
activityStatement = StatementConstructor::newCode(
OP(CONTEXT_SWITCHER), ctxMachine, invokeSequende );
}
else
{
if( labelledParams.empty() )
{
activityStatement->append( positionalParams );
}
else
{
computeActivityRoutineInput(machine, routine,
activityStatement, labelledParams, positionalParams);
}
if( labelledReturns.empty() )
{
activityStatement->append( positionalReturns );
}
else
{
computeActivityRoutineOutput(machine, routine,
activityStatement, labelledReturns, positionalReturns);
}
}
}
static inline void appendParam(BFCode & paramCode, const BF & bfParamVar,
Variable * pParamVar, const BF & bfParamValue)
{
paramCode->append( StatementConstructor::newCode(
pParamVar->getModifier().hasNatureReference() ?
OP(ASSIGN_REF) : OP(ASSIGN),
pParamVar->getModifier().hasNatureMacro() ?
pParamVar->getBinding() : bfParamVar,
bfParamValue ) );
}
void ParserUtil::computeActivityRoutineInput(Machine * ctxMachine,
Routine * routine, BFCode & invokeSequende,
BFVector & labelledParams, BFList & positionalParams)
{
BFCode paramCode( OP(ATOMIC_SEQUENCE) );
Variable * variable = NULL;
BFVector::const_iterator it = routine->getParameters().begin();
BFVector::const_iterator endIt = routine->getParameters().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
variable = (*it).to_ptr< Variable >();
if( labelledParams[offset].valid() )
{
appendParam(paramCode, (*it), variable, labelledParams[offset]);
}
else if( variable->getModifier().hasNatureParameterBind() )
{
if( variable->hasValue() )
{
appendParam(paramCode, (*it), variable, variable->getValue());
}
else
{
avm_syntax_error( "ParserUtil::computeActivityRoutineInput(...)" )
<< "Unexpected $bind parameters:" << std::endl
<< "#" << offset << " " << str_header( variable )
<< std::endl << "wihtout value for routine:"
<< std::endl << str_header( routine )
<< SYNTAX_ERROR_EOL;
}
}
// else if( variable->getModifier().hasNatureParameter() )
// {
// if( positionalParams.nonempty() )
// {
// appendParam(paramCode, (*it),
// variable, positionalParams.pop_first());
// }
// else if( variable->hasValue() )
// {
// appendParam(paramCode, (*it), variable, variable->getValue());
// }
// }
else if( positionalParams.nonempty() )
{
appendParam(paramCode, (*it),
variable, positionalParams.pop_first());
}
else if( variable->hasValue() )
{
appendParam(paramCode, (*it), variable, variable->getValue());
}
else
{
avm_syntax_error( "ParserUtil::computeActivityRoutineInput(...)" )
<< "Unexpected parameters for routine< "
<< str_header( routine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
if( paramCode->nonempty() )
{
invokeSequende->append(
paramCode->singleton() ? paramCode->first() : paramCode );
}
}
static inline void appendReturn(BFCode & returnCode, const BF & bfReturnVar,
Variable * pReturnVar, const BF & bfReturnDest)
{
returnCode->append( StatementConstructor::newCode(
pReturnVar->getModifier().hasNatureReference() ?
OP(ASSIGN_REF) : OP(ASSIGN),
bfReturnDest,
pReturnVar->getModifier().hasNatureMacro() ?
pReturnVar->getBinding() : bfReturnVar ) );
}
void ParserUtil::computeActivityRoutineDefaultOutput(Machine * ctxMachine,
Routine * routine, BFCode & invokeSequende,
BFVector & labelledReturns, BFList & positionalReturns)
{
BFCode returnCode( OP(ATOMIC_SEQUENCE) );
Variable * variable = NULL;
BFVector::const_iterator it = routine->getReturns().begin();
BFVector::const_iterator endIt = routine->getReturns().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
variable = (*it).to_ptr< Variable >();
if( labelledReturns[offset].valid() && variable->hasValue() )
{
returnCode->append( StatementConstructor::newCode( OP(ASSIGN),
(*it), variable->getValue() ) );
}
else if( variable->getModifier().hasModifierReturnBind() )
{
if( variable->hasValue() )
{
appendReturn(returnCode, (*it), variable, variable->getValue());
}
else
{
avm_syntax_error(
"ParserUtil::computeActivityRoutineDefaultOutput(...)" )
<< "Unexpected $bind parameters:" << std::endl
<< "#" << offset << " " << str_header( variable )
<< std::endl << "wihtout value for routine:"
<< std::endl << str_header( routine )
<< SYNTAX_ERROR_EOL;
}
}
// else if( variable->getModifier().isDirectionReturn() )
// {
// if( positionalReturns.nonempty() && variable->hasValue() )
// {
// returnCode->append( StatementConstructor::newCode( OP(ASSIGN),
// (*it), variable->getValue() ) );
// }
// else if( variable->hasValue() )
// {
// }
// }
else if( positionalReturns.nonempty() && variable->hasValue() )
{
returnCode->append( StatementConstructor::newCode( OP(ASSIGN),
(*it), variable->getValue() ) );
}
else
{
}
}
if( returnCode->nonempty() )
{
invokeSequende->append(
returnCode->singleton() ? returnCode->first() : returnCode );
}
}
void ParserUtil::computeActivityRoutineOutput(Machine * ctxMachine,
Routine * routine, BFCode & invokeSequende,
BFVector & labelledReturns, BFList & positionalReturns)
{
BFCode returnCode( OP(ATOMIC_SEQUENCE) );
Variable * variable = NULL;
BFVector::const_iterator it = routine->getReturns().begin();
BFVector::const_iterator endIt = routine->getReturns().end();
for( avm_offset_t offset = 0 ; it != endIt ; ++it , ++offset )
{
variable = (*it).to_ptr< Variable >();
if( labelledReturns[offset].valid() )
{
appendReturn(returnCode, (*it), variable, labelledReturns[offset]);
}
else if( variable->getModifier().hasModifierReturnBind() )
{
if( variable->hasValue() )
{
appendReturn(returnCode, (*it), variable, variable->getValue());
}
else
{
avm_syntax_error( "ParserUtil::computeActivityRoutineOutput(...)" )
<< "Unexpected #bind returns < #"
<< offset << " > wihtout value for routine< "
<< str_header( routine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
else if( variable->getModifier().isDirectionReturn() )
{
if( positionalReturns.nonempty() )
{
appendReturn(returnCode, (*it),
variable, positionalReturns.pop_first());
}
else if( variable->hasValue() )
{
appendReturn(returnCode, (*it),
variable, variable->getValue());
}
}
else if( positionalReturns.nonempty() )
{
appendReturn(returnCode, (*it),
variable, positionalReturns.pop_first());
}
else
{
avm_syntax_error( "ParserUtil::computeActivityRoutineOutput(...)" )
<< "Unexpected returns for routine< "
<< str_header( routine ) << " >"
<< SYNTAX_ERROR_EOL;
}
}
if( returnCode->nonempty() )
{
invokeSequende->append(
returnCode->singleton() ? returnCode->first() : returnCode );
}
}
////////////////////////////////////////////////////////////////////////////////
// GET XLIA INVOKABLE BY ID
////////////////////////////////////////////////////////////////////////////////
BF ParserUtil::getInvokable(const BF & target, const std::string & aNameID)
{
Operator * op = AvmOperationFactory::get(target, aNameID);
if( op != NULL )
{
return( INCR_BF(op) );
}
return( ExpressionConstructor::newIdentifier(aNameID) );
}
////////////////////////////////////////////////////////////////////////////////
// DECLARE DEFAULT STATE #final, #terminal, #return if need
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::declareDefaultEndingStateIfNeed(
ListOfMachine & needDefaultStateFinal,
ListOfMachine & needDefaultStateTerminal,
ListOfMachine & needDefaultStateReturn)
{
Specifier aMocSpecifier;
aMocSpecifier.setStateMocFINAL();
while( needDefaultStateFinal.nonempty() )
{
needDefaultStateFinal.back()->saveOwnedElement( //saveMachine(
Machine::newState(
needDefaultStateFinal.back(),
"#final", aMocSpecifier) );
needDefaultStateFinal.pop_back();
}
aMocSpecifier.setPseudostateMocTERMINAL();
while( needDefaultStateTerminal.nonempty() )
{
needDefaultStateTerminal.back()->saveOwnedElement( //saveMachine(
Machine::newState(
needDefaultStateTerminal.back(),
"#terminal", aMocSpecifier) );
needDefaultStateTerminal.pop_back();
}
aMocSpecifier.setPseudostateMocRETURN();
while( needDefaultStateReturn.nonempty() )
{
needDefaultStateReturn.back()->saveOwnedElement( //saveMachine(
Machine::newState(
needDefaultStateReturn.back(),
"#return", aMocSpecifier) );
needDefaultStateReturn.pop_back();
}
}
////////////////////////////////////////////////////////////////////////////////
// INLINE XLIA PROCEDURE CALL IN TRANSITION
////////////////////////////////////////////////////////////////////////////////
void ParserUtil::checkProcedureCompositeMocKind(Machine * aProcedure)
{
if( aProcedure->getSpecifier().hasModelOfComputation() )
{
return;
}
bool isStateTransitionFlowFlag = false;
CompositePart::const_procedure_iterator it =
aProcedure->getCompositePart()->machine_begin();
CompositePart::const_procedure_iterator endIt =
aProcedure->getCompositePart()->machine_end();
for( ; it != endIt ; ++it )
{
if( (it)->getSpecifier().isPseudostate() )
{
if( not isStateTransitionFlowFlag )
{
isStateTransitionFlowFlag = true;
}
}
else if( (it)->getSpecifier().isState()
|| (it)->getSpecifier().isComponentStatemachine()
|| (it)->getSpecifier().isMocStateTransitionSystem() )
{
aProcedure->getwSpecifier().setMocStateTransitionSystem();
return;
}
else if( (it)->getSpecifier().isDesignInstanceStatic()
&& (it)->hasInstanceSpecifier() )
{
const BF & model = (it)->getInstanceSpecifier()->getModel();
if( model.is< Machine >()
&& model.to_ptr< Machine >()
->getSpecifier().isMocStateTransitionSystem() )
{
aProcedure->getwSpecifier().setMocStateTransitionSystem();
return;
}
}
}
if( isStateTransitionFlowFlag )
{
aProcedure->getwSpecifier().setMocStateTransitionFlow();
}
// aProcedure->getwSpecifier().setMocCompositeStructure();
}
static Transition * insertProcedureStatemachineCall(Transition * transition,
const std::string & refId, Machine * instanceProcedure,
const BFCode & paramCode, const BFCode &returnCode)
{
Machine * procedureStateCall = Machine::newStatemachine(
transition->getSourceContainer(),
(OSS() << refId << '#' << instanceProcedure->getNameID()),
Specifier::EXECUTABLE_PROCEDURE_COMPOSITE_SPECIFIER);
// instanceProcedure->getType());
transition->getSourceContainer()->saveOwnedElement(
procedureStateCall );
procedureStateCall->copyLocation( instanceProcedure->getLocation() );
procedureStateCall->saveOwnedElement( //saveMachine(
sep::incrReferenceCount(instanceProcedure) );
instanceProcedure->updateContainer( transition->getSourceContainer() );
// Parameters initialization
if( paramCode.valid() && paramCode->nonempty() )
{
procedureStateCall->getUniqBehaviorPart()->setOnEnable(
StatementConstructor::newCode( OP(CONTEXT_SWITCHER),
INCR_BF(instanceProcedure), paramCode->singleton() ?
paramCode->first().bfCode() : paramCode) );
}
// Returns finalization
if( returnCode.valid() && returnCode->nonempty() )
{
procedureStateCall->getUniqBehaviorPart()->setOnFinal(
// procedureStatemachine->getUniqBehaviorPart()->setOnReturn(
StatementConstructor::newCode( OP(CONTEXT_SWITCHER),
INCR_BF(instanceProcedure), returnCode->singleton() ?
returnCode->first().bfCode() : returnCode ) );
}
Transition * returnTransition = new Transition(procedureStateCall,
(OSS() << refId << '#' << instanceProcedure->getNameID() << "#end"),
Transition::MOC_FINAL_KIND);
returnTransition->copyLocation( instanceProcedure->getLocation() );
returnTransition->setTarget( transition->getTarget() );
transition->setTarget( INCR_BF(procedureStateCall) );
// transition->fullyUpdateAllNameID( OSS( ) << transition->getNameID()
// << '#' << instanceProcedure->getNameID() );
procedureStateCall->getUniqBehaviorPart()->
saveOutgoingTransition( returnTransition );
return( returnTransition );
}
static Transition * insertProcedureMachineCall(Transition * transition,
const std::string & refId, Machine * instanceProcedure,
const BFCode & paramCode, const BFCode &returnCode)
{
transition->getSourceContainer()->saveOwnedElement( //saveMachine(
sep::incrReferenceCount(instanceProcedure) );
instanceProcedure->updateContainer( transition->getSourceContainer() );
instanceProcedure->copyLocation( instanceProcedure->getLocation() );
if( paramCode.valid() && paramCode->nonempty() )
{
instanceProcedure->getUniqBehaviorPart()->seqOnStart( //seqOnCreate(
paramCode->singleton() ? paramCode->first().bfCode() : paramCode );
}
BFCode callingProcedure;
if( instanceProcedure->hasParamReturn() )
{
instanceProcedure->setAutoStart( false );
BFCode callingSequende = StatementConstructor::newCode( OP(SEQUENCE) );
callingProcedure = StatementConstructor::newCode( OP(CONTEXT_SWITCHER),
INCR_BF(instanceProcedure), callingSequende );
// Parameters initialization
// if( paramCode.valid() && paramCode->nonempty() )
// {
// callingSequende->append( paramCode->singleton() ?
// paramCode->first().bfCode() : paramCode );
// }
// Calling procedure
if( not instanceProcedure->getModelMachine()->
getSpecifier().isFamilyComponentStatemachine() )
{
instanceProcedure->getUniqBehaviorPart()->seqOnStart( OP(RUN) );
}
callingSequende->append( StatementConstructor::newCode(
OP(START), INCR_BF(instanceProcedure) ) );
// Returns finalization
if( returnCode.valid() && returnCode->nonempty() )
{
callingSequende->append( returnCode->singleton() ?
returnCode->first().bfCode() : returnCode );
}
}
else
{
callingProcedure = StatementConstructor::newCode(
OP(RUN), INCR_BF(instanceProcedure) );
}
transition->setStatement( StatementConstructor::xnewCodeFlat(
OP(SEQUENCE), transition->getStatement(), callingProcedure) );
return( transition );
}
static bool isOneStepRunningMachine(const Machine * aMachine)
{
if( not aMachine->getSpecifier().isMocStateTransitionFlow() )
{
CompositePart::const_machine_iterator itMachine =
aMachine->getCompositePart()->machine_begin();
CompositePart::const_machine_iterator endMachine =
aMachine->getCompositePart()->machine_end();
for( ; itMachine != endMachine ; ++itMachine )
{
if( (itMachine)->getSpecifier().isDesignInstanceStatic() )
{
if( (itMachine)->hasModelMachine() &&
(not isOneStepRunningMachine(
(itMachine)->getModelMachine() )) )
{
return( false );
}
}
else if( (itMachine)->getSpecifier().isComponentExecutable() )
{
if( (itMachine)->hasMachine() &&
(not isOneStepRunningMachine( (itMachine) )) )
{
return( false );
}
}
else if( not (itMachine)->getSpecifier().isPseudostate() )
{
return( false );
}
}
}
return( true );
}
static Transition * insertProcedureCall(Transition * transition,
const std::string & refId, Machine * instanceProcedure)
{
instanceProcedure->fullyUpdateAllNameID( OSS( ) << refId
<< '#' << instanceProcedure->getNameID() );
const Machine * modelProcedure = instanceProcedure->getModelMachine();
BFCode paramCode( OP(ATOMIC_SEQUENCE) );
BFCode returnCode( OP(ATOMIC_SEQUENCE) );
if( instanceProcedure->hasParamReturn() &&
instanceProcedure->hasModelMachine() )
{
// Parameters initialization
TableOfVariable::const_raw_iterator itParam =
instanceProcedure->getVariableParameters().begin();
TableOfVariable::const_raw_iterator endIt =
instanceProcedure->getVariableParameters().end();
for( avm_size_t offset = 0 ; itParam != endIt ; ++itParam , ++offset )
{
if( (itParam)->hasValue() )
{
paramCode->append( StatementConstructor::newCode(
(itParam)->getModifier().hasNatureReference()
? OP(ASSIGN_REF) : OP(ASSIGN),
modelProcedure->getVariableParameter(offset),
(itParam)->getValue() ) );
}
}
// Returns finalization
itParam = instanceProcedure->getVariableReturns().begin();
endIt = instanceProcedure->getVariableReturns().end();
for( avm_size_t offset = 0 ; itParam != endIt ; ++itParam , ++offset )
{
if( (itParam)->hasValue() )
{
// paramCode->append( StatementConstructor::newCode( OP(ASSIGN_REF),
// modelProcedure->getVariableReturn(offset),
// (itParam)->getValue() ) );
returnCode->append( StatementConstructor::newCode(OP(ASSIGN),
(itParam)->getValue(),
modelProcedure->getVariableReturn(offset) ) );
}
}
}
Transition * returnTransition = NULL;
if( isOneStepRunningMachine( modelProcedure ) )
{
returnTransition = insertProcedureMachineCall(transition,
refId, instanceProcedure, paramCode, returnCode);
}
else
{
returnTransition = insertProcedureStatemachineCall(transition,
refId, instanceProcedure, paramCode, returnCode);
}
return( returnTransition );
}
void ParserUtil::inlineTransitionProcedureCall(
Transition * transition, const std::string & refId)
{
Machine * sourceState = transition->getSource();
BFCode statement = transition->getStatement();
transition->setStatement( BFCode::REF_NULL );
if( statement->isOpCode(AVM_OPCODE_INVOKE_METHOD) &&
statement->first().is< Machine >() )
{
transition = insertProcedureCall(transition,
refId, statement->first().to_ptr< Machine >() );
if( not transition->hasTarget() )
{
transition->setStatement( StatementConstructor::xnewCodeFlat(
OP(SEQUENCE), transition->getStatement(),
StatementConstructor::newCode( OP(DISABLE_SELF)),
StatementConstructor::newCode( OP(ENABLE_SET),
INCR_BF(sourceState) ) ) );
transition->setStatement( StatementConstructor::xnewCodeFlat(
OP(SEQUENCE), transition->getStatement(),
StatementConstructor::newCode(
OP(ENABLE_SET), INCR_BF(sourceState) ) ));
}
}
else if( OperatorManager::isSequence(statement->getOperator()))
{
BFCode otherStatement( statement->getOperator() );
AvmCode::iterator itArg = statement->begin();
AvmCode::iterator endArg = statement->end();
for( ; itArg != endArg ; ++itArg )
{
if( (*itArg).is< AvmCode >() )
{
AvmCode * callStatement = (*itArg).to_ptr< AvmCode >();
if( callStatement->isOpCode(AVM_OPCODE_INVOKE_METHOD) &&
callStatement->first().is< Machine >() )
{
if( otherStatement->nonempty() )
{
transition->setStatement(
StatementConstructor::xnewCodeFlat(OP(SEQUENCE),
transition->getStatement(), otherStatement) );
otherStatement = StatementConstructor::newCode(
statement->getOperator() );
}
transition = insertProcedureCall(transition,
refId, callStatement->first().to_ptr< Machine >() );
continue;
}
}
otherStatement->append( *itArg );
}
if( otherStatement->nonempty() )
{
transition->setStatement( StatementConstructor::xnewCodeFlat(
OP(SEQUENCE), transition->getStatement(), otherStatement ));
}
if( not transition->hasTarget() )
{
transition->setStatement( StatementConstructor::xnewCodeFlat(
OP(SEQUENCE), transition->getStatement(),
StatementConstructor::newCode( OP(DISABLE_SELF)),
StatementConstructor::newCode(
OP(ENABLE_SET), INCR_BF(sourceState) ) ) );
}
}
}
////////////////////////////////////////////////////////////////////////////////
// ROUTINE INVOKATION
BFCode ParserUtil::invokeRoutine(Routine * aRoutineInstance)
{
if( aRoutineInstance->hasParameters() )
{
BF bfOP;
if( aRoutineInstance->hasModelOperator() )
{
bfOP = aRoutineInstance->getType();
}
else
{
Operator * op = AvmOperationFactory::get(
aRoutineInstance->getParameter(0),
aRoutineInstance->getType().str() );
if( op != NULL )
{
bfOP = INCR_BF(op);
}
}
if( bfOP.valid() )
{
BFVector::const_iterator it = aRoutineInstance->getParameters().begin();
BFVector::const_iterator endIt = aRoutineInstance->getParameters().end();
BFCode invokeCode( OP(INVOKE_METHOD), (*it), bfOP );
for( ++it ; it != endIt ; ++it )
{
invokeCode->append(*it );
}
return( invokeCode );
}
}
return( StatementConstructor::newCode(
OP(INVOKE_ROUTINE), sep::BF(aRoutineInstance) ) );
}
BFCode ParserUtil::invokeRoutineStatement(Routine * aRoutineInstance)
{
if( aRoutineInstance->hasModel() )
{
// AVM_OS_COUT << str_header(aRoutineInstance) << std::endl;
// AVM_OS_COUT << str_header(aRoutineInstance->getModel()) << std::endl;
if( aRoutineInstance->isInlinableStatement() )
{
BFCode substCode = aRoutineInstance->inlineStatement();
if( substCode.valid() )
{
return( substCode );
}
}
return( StatementConstructor::newCode(
OP(INVOKE_ROUTINE), sep::BF(aRoutineInstance) ) );
}
return( invokeRoutine(aRoutineInstance) );
}
BF ParserUtil::invokeRoutineExpression(Routine * aRoutineInstance)
{
if( aRoutineInstance->hasModel() )
{
if( aRoutineInstance->isInlinableExpression() )
{
BF substCode = aRoutineInstance->inlineExpression();
if( substCode.valid() )
{
return( substCode );
}
}
return( StatementConstructor::newCode(
OP(INVOKE_ROUTINE), sep::BF(aRoutineInstance) ) );
}
return( invokeRoutine(aRoutineInstance) );
}
} /* namespace sep */