/******************************************************************************* | |
* 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 */ |