| /******************************************************************************* |
| * Copyright (c) 2016 CEA LIST. |
| * |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr |
| * - Initial API and implementation |
| ******************************************************************************/ |
| |
| #include "Compiler.h" |
| |
| #include <builder/analysis/CommunicationDependency.h> |
| |
| #include <fml/expression/AvmCode.h> |
| #include <fml/expression/ExpressionConstant.h> |
| #include <fml/expression/ExpressionFactory.h> |
| #include <fml/builtin/Identifier.h> |
| #include <fml/expression/StatementTypeChecker.h> |
| #include <fml/expression/StatementConstructor.h> |
| #include <fml/expression/StatementFactory.h> |
| #include <fml/builtin/QualifiedIdentifier.h> |
| |
| #include <fml/executable/AvmProgram.h> |
| #include <fml/executable/AvmTransition.h> |
| #include <fml/executable/BaseInstanceForm.h> |
| #include <fml/executable/ExecutableLib.h> |
| #include <fml/executable/ExecutableForm.h> |
| #include <fml/executable/ExecutableSystem.h> |
| #include <fml/executable/InstanceOfBuffer.h> |
| #include <fml/executable/InstanceOfData.h> |
| #include <fml/executable/InstanceOfMachine.h> |
| #include <fml/executable/InstanceOfPort.h> |
| #include <fml/executable/RoutingData.h> |
| |
| #include <fml/operator/OperatorManager.h> |
| |
| #include <fml/type/TypeManager.h> |
| |
| #include <fml/infrastructure/DataType.h> |
| #include <fml/infrastructure/Machine.h> |
| #include <fml/infrastructure/System.h> |
| #include <fml/infrastructure/Transition.h> |
| |
| #include <fml/infrastructure/BehavioralPart.h> |
| #include <fml/infrastructure/CompositePart.h> |
| #include <fml/infrastructure/PropertyPart.h> |
| |
| #include <fml/workflow/UniFormIdentifier.h> |
| #include <fml/workflow/WObject.h> |
| |
| #include <sew/Configuration.h> |
| |
| |
| namespace sep |
| { |
| |
| |
| /** |
| * CONSTRUCTOR |
| * Default |
| */ |
| Compiler::Compiler(Configuration & aConfiguration, |
| AvmcodeCompiler & anAvmcodeCompiler) |
| : BaseMachineCompiler( aConfiguration, anAvmcodeCompiler ), |
| mDataCompiler( *this ), |
| mProgramCompiler( *this ), |
| mTransitionCompiler( *this ), |
| mComCompiler( *this ) |
| { |
| //!! NOTHING |
| } |
| |
| |
| /** |
| * CONFIGURE |
| */ |
| bool Compiler::configure() |
| { |
| if( not mAvmcodeCompiler.configure() ) |
| { |
| AVM_OS_ERROR_ALERT << "Compiler::configure:> " |
| "the Avmcode compiler configuration failed !!!" |
| << SEND_ALERT; |
| |
| return( false ); |
| } |
| |
| return( true ); |
| } |
| |
| |
| /* |
| ****************************************************************************** |
| * START |
| ****************************************************************************** |
| */ |
| |
| bool Compiler::start(System & aSystem) |
| { |
| ExecutableSystem * aExecutableSystem = new ExecutableSystem( aSystem ); |
| mConfiguration.setExecutableSystem( aExecutableSystem ); |
| |
| precompileSystem(aSystem); |
| |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| mConfiguration.serializeDebugExecutable( "precompiling" ); |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| mComCompiler.updateMessageID(); |
| |
| compileExecutableSystem(); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| mConfiguration.serializeDebugExecutable( "compiling" ); |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| |
| postcompileExecutableSystem(); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| mConfiguration.serializeDebugExecutable( "postcompiling" ); |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| |
| return( hasZeroError() ); |
| } |
| |
| /** |
| ******************************************************************************* |
| * PRECOMPILATION |
| ******************************************************************************* |
| */ |
| |
| /** |
| * precompile |
| * declaration |
| */ |
| void Compiler::precompilePropertyPart(ExecutableForm * anExecutable, |
| PropertyPart & theDeclaration, TableOfInstanceOfData & tableOfVariable) |
| { |
| // User Variable-Parameters |
| PropertyPart::const_variable_iterator itVar = |
| theDeclaration.var_parameter_begin(); |
| PropertyPart::const_owned_iterator endVar = |
| theDeclaration.var_parameter_end(); |
| for( ; itVar != endVar ; ++itVar ) |
| { |
| AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( (*itVar) ) |
| << "data or type for compiling !!!" |
| << SEND_EXIT; |
| |
| // Allocation for variable |
| mDataCompiler.precompileData(anExecutable, |
| (*itVar).to_ptr< Variable >(), tableOfVariable); |
| } |
| |
| // User Variable-Returns |
| itVar = theDeclaration.var_return_begin(); |
| endVar = theDeclaration.var_return_end(); |
| for( ; itVar != endVar ; ++itVar ) |
| { |
| AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( (*itVar) ) |
| << "data or type for compiling !!!" |
| << SEND_EXIT; |
| |
| // Allocation for variable |
| mDataCompiler.precompileData(anExecutable, |
| (*itVar).to_ptr< Variable >(), tableOfVariable); |
| } |
| |
| // Other OwnedElements |
| PropertyPart::const_owned_iterator itWfO = theDeclaration.owned_begin(); |
| PropertyPart::const_owned_iterator endWfO = theDeclaration.owned_end(); |
| for( ; itWfO != endWfO ; ++itWfO ) |
| { |
| AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( (*itWfO) ) |
| << "data or type for compiling !!!" |
| << SEND_EXIT; |
| |
| // Allocation for variable |
| if( (*itWfO).is< Variable >() ) |
| { |
| Variable * aVariable = (*itWfO).to_ptr< Variable >(); |
| |
| if( aVariable->getModifier().noNatureParameter() ) |
| { |
| mDataCompiler.precompileData(anExecutable, |
| aVariable, tableOfVariable); |
| } |
| } |
| |
| // Allocation for buffer |
| else if( (*itWfO).is< Buffer >() ) |
| { |
| mComCompiler.precompileBuffer( |
| anExecutable, (*itWfO).to_ptr< Buffer >()); |
| } |
| |
| // Allocation for port |
| else if( (*itWfO).is< Port >() ) |
| { |
| // mComCompiler.precompilePort(anExecutable, |
| // (*it).to_ptr< Port >(), tableOfVariable); |
| } |
| |
| else if( (*itWfO).is< Channel >() ) |
| { |
| // mComCompiler.precompileChannel( |
| // anExecutable, (*it).to_ptr< Channel >()); |
| } |
| |
| else if( (*itWfO).is< Machine >() ) |
| { |
| // precompileInstanceStatic( |
| // anExecutable, (*it).to_ptr< Machine >()); |
| } |
| |
| // Allocation for typedef |
| else if( (*itWfO).is< DataType >() ) |
| { |
| precompileTypeSpecifier(anExecutable, (*itWfO)); |
| } |
| } |
| |
| // Allocation for ports / signals |
| mComCompiler.precompileComPoint( |
| anExecutable, theDeclaration, tableOfVariable); |
| |
| // Allocation for channels |
| mComCompiler.precompileChannel(anExecutable, |
| theDeclaration, tableOfVariable); |
| } |
| |
| |
| void Compiler::precompileDataType(AvmProgram * aProgram, |
| PropertyPart & theDeclaration, TableOfInstanceOfData & tableOfVariable) |
| { |
| PropertyPart::const_owned_iterator it = theDeclaration.owned_begin(); |
| PropertyPart::const_owned_iterator endIt = theDeclaration.owned_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| AVM_OS_ASSERT_FATAL_NULL_SMART_POINTER_EXIT( (*it) ) |
| << "data or type for compiling !!!" |
| << SEND_EXIT; |
| |
| // Allocation for variable |
| if( (*it).is< Variable >() ) |
| { |
| mDataCompiler.precompileData(aProgram, |
| (*it).to_ptr< Variable >(), tableOfVariable); |
| } |
| |
| // Allocation for typedef |
| else |
| { |
| precompileTypeSpecifier(aProgram, (*it)); |
| } |
| } |
| } |
| |
| |
| /** |
| * precompile |
| * specification |
| */ |
| void Compiler::precompileExecutableCompositePart( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| CompositePart * aCompositePart = anExecutableSpec->getCompositePart(); |
| |
| if( aCompositePart == NULL ) |
| { |
| //!! NOTHING |
| return; |
| } |
| |
| /* |
| * precompiling procedure |
| */ |
| if( aCompositePart->hasProcedure() ) |
| { |
| CompositePart::const_procedure_iterator it = |
| aCompositePart->procedure_begin(); |
| CompositePart::const_procedure_iterator endIt = |
| aCompositePart->procedure_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| precompileExecutable(aContainer, (it)); |
| } |
| } |
| |
| /* |
| * precompiling executable - instance static |
| */ |
| if( aCompositePart->hasMachine() ) |
| { |
| // precompiling sub-executable |
| anExecutableSpec->expandGroupStatemachine(); |
| |
| CompositePart::const_machine_iterator it = |
| aCompositePart->machine_begin(); |
| CompositePart::const_machine_iterator endIt = |
| aCompositePart->machine_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| precompileExecutable(aContainer, (it)); |
| } |
| } |
| |
| /* |
| * precompiling instance dynamic |
| */ |
| if( aCompositePart->hasInstanceDynamic() ) |
| { |
| CompositePart::const_machine_iterator it = |
| aCompositePart->instance_dynamic_begin(); |
| CompositePart::const_machine_iterator endIt = |
| aCompositePart->instance_dynamic_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| // if( (it)->getSpecifier().isDesignInstanceDynamic() ) |
| { |
| precompileExecutableInstanceDynamique(aContainer, (it)); |
| } |
| } |
| } |
| } |
| |
| |
| void Compiler::precompileExecutable( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| if( anExecutableSpec->getSpecifier().hasGroupMask() ) |
| { |
| precompileExecutableGroup(aContainer, anExecutableSpec); |
| } |
| else if( anExecutableSpec->getSpecifier().isDesignModel()) |
| { |
| precompileExecutableModel(aContainer, anExecutableSpec); |
| } |
| else if( anExecutableSpec->getSpecifier().isDesignPrototypeStatic() ) |
| { |
| precompileExecutablePrototype(aContainer, anExecutableSpec); |
| } |
| else if( anExecutableSpec->getSpecifier().isDesignInstanceStatic() ) |
| { |
| precompileExecutableInstanceStatic(aContainer, anExecutableSpec); |
| } |
| else if( anExecutableSpec->getSpecifier().isDesignInstanceDynamic() ) |
| { |
| precompileExecutableInstanceDynamique(aContainer, anExecutableSpec); |
| } |
| else |
| { |
| AVM_OS_FATAL_ERROR_EXIT |
| << "Unexpected in precompiling stage the executable: " |
| << std::endl << str_header( anExecutableSpec ) << std::endl |
| << "==> with specifier: " |
| << anExecutableSpec->getSpecifier().str() << " !!!" |
| << SEND_EXIT; |
| } |
| } |
| |
| |
| ExecutableForm * Compiler::precompileExecutableModel( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| //AVM_OS_CERR << TAB << "<** begin precompiling executable model:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| |
| // CREATE NEW EXECUTABLE |
| ExecutableForm * anExec = new ExecutableForm( |
| mConfiguration.getExecutableSystem(), |
| aContainer, anExecutableSpec); |
| |
| setInheritedSpecifier(aContainer, anExec); |
| |
| // APPEND NEW EXECUTABLE IN THE SYSTEM |
| // //?? For retrocompatibity serialization order |
| // getSymbolTable().addMachineExecutable( |
| // mExecutableSystem->saveExecutable( anExec ) ); |
| |
| avm_size_t maximalInstanceCount = anExecutableSpec->hasInstanceSpecifier() |
| ? anExecutableSpec->getInstanceSpecifier()->getMaximalInstanceCount() |
| : AVM_NUMERIC_MAX_SIZE_T; |
| |
| //??? Sera fait dans precompileExecutableInstanceXXX(...) ? |
| // anExec->incrPossibleStaticInstanciationCount( createdInstanceCount ); |
| |
| if( anExecutableSpec->getSpecifier().isFamilyComponentComposite() ) |
| { |
| Specifier aSpecifier( anExecutableSpec->getSpecifier() ); |
| |
| InstanceOfMachine * aModelInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, NULL, |
| aContainer->getInstanceModel().size(), |
| aSpecifier.setDesignModel() ); |
| |
| //??? Sera fait dans precompileExecutableInstanceXXX(...) ? |
| aModelInstance->setInstanceCount( |
| /*createdInstanceCount*/0, maximalInstanceCount); |
| |
| aContainer->saveInstanceModel( aModelInstance ); |
| } |
| |
| /* |
| * Allocation of declaration contents :> |
| * constant, variable, typedef, buffer, port |
| */ |
| TableOfInstanceOfData tableOfVariable; |
| |
| if( anExecutableSpec->hasProperty() ) |
| { |
| avm_offset_t parametersCount = anExecutableSpec-> |
| getPropertyPart().getVariableParametersCount(); |
| |
| anExec->setParamOffsetCount( 0 , parametersCount ); |
| |
| anExec->setReturnOffsetCount( parametersCount, anExecutableSpec-> |
| getPropertyPart().getVariableReturnsCount() ); |
| |
| precompilePropertyPart(anExec, |
| anExecutableSpec->getPropertyPart(), tableOfVariable); |
| } |
| |
| /* |
| * Update data table |
| */ |
| anExec->setData(tableOfVariable); |
| |
| |
| /* |
| * precompiling executable composite part |
| */ |
| if( anExecutableSpec->hasMachine() || anExecutableSpec->hasPortSignal() ) |
| { |
| Specifier aSpecifier( anExecutableSpec->getSpecifier() ); |
| |
| // Set the instance THIS at first position (index = 0) |
| InstanceOfMachine * aNewInstance = |
| InstanceOfMachine::newInstanceModelThis( |
| anExec, anExecutableSpec, anExec, NULL, |
| anExec->getInstanceModel().size(), |
| aSpecifier.setDesignModel() ); |
| |
| anExec->saveInstanceModel(aNewInstance); |
| |
| aNewInstance = InstanceOfMachine::newThis(anExec, |
| aNewInstance, anExec->getInstanceStatic().size() ); |
| // aNewInstance->setAutoStart( anExecutableSpec->hasInitialInstance() ); |
| |
| anExec->saveInstanceStatic(aNewInstance); |
| } |
| |
| precompileExecutableCompositePart(anExec, anExecutableSpec); |
| |
| |
| /* |
| * precompiling transition |
| */ |
| if( anExecutableSpec->hasOutgoingTransition() ) |
| { |
| BehavioralPart::const_transition_iterator it = anExecutableSpec-> |
| getBehavior()->outgoing_transition_begin(); |
| BehavioralPart::const_transition_iterator endIt = anExecutableSpec-> |
| getBehavior()->outgoing_transition_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| mTransitionCompiler.precompileTransition( anExec, (it) ); |
| } |
| } |
| |
| // APPEND NEW EXECUTABLE IN THE SYSTEM |
| //?? For retrocompatibity serialization order |
| getSymbolTable().addMachineExecutable( mConfiguration. |
| getExecutableSystem().saveExecutable( anExec ) ); |
| |
| //AVM_OS_TRACE << TAB << ">** end precompiling executable MODEL:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| |
| return( anExec ); |
| } |
| |
| |
| void Compiler::precompileExecutablePrototype( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| //AVM_OS_TRACE << TAB << "<++ begin precompiling executable #instance model:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| |
| ExecutableForm * anExec = |
| precompileExecutableModel(aContainer, anExecutableSpec); |
| |
| avm_size_t initialInstanceCount = 1; |
| avm_size_t maximalInstanceCount = AVM_NUMERIC_MAX_SIZE_T; |
| if( anExecutableSpec->hasInstanceSpecifier() ) |
| { |
| initialInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getInitialInstanceCount(); |
| |
| maximalInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getMaximalInstanceCount(); |
| } |
| |
| // Instances for << MODEL >> & INSTANCE |
| InstanceOfMachine * aModelInstance = NULL; |
| if( anExecutableSpec->getSpecifier().isFamilyComponentComposite() ) |
| { |
| aModelInstance = aContainer->getInstanceModel(). |
| getByAstElement( anExec->getAstElement() ).rawMachine(); |
| if( aModelInstance == NULL ) |
| { |
| AVM_OS_FATAL_ERROR_EXIT |
| << "Unfound model instance of #prototype executable !!!" |
| << std::endl << str_header( anExec->getAstElement() ) |
| << SEND_EXIT; |
| } |
| else |
| { |
| aModelInstance->incrInstanciationCount( initialInstanceCount ); |
| |
| anExec->incrPossibleStaticInstanciationCount( initialInstanceCount ); |
| } |
| } |
| |
| if( initialInstanceCount > 0 ) |
| { |
| Specifier aSpecifier( anExecutableSpec->getSpecifier() ); |
| |
| InstanceOfMachine * aNewInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, aModelInstance, |
| aContainer->getInstanceStatic().size(), |
| aSpecifier.setDesignPrototypeStatic() ); |
| |
| aNewInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| aNewInstance->setAutoStart( true ); |
| |
| setInheritedSpecifier(aContainer, aNewInstance); |
| |
| anExec->setPrototypeInstance( aNewInstance ); |
| |
| const Symbol & bfInstance = |
| aContainer->saveInstanceStatic(aNewInstance); |
| getSymbolTable().addInstanceStatic(bfInstance); |
| |
| aSpecifier.setDesignInstanceStatic(); |
| |
| avm_size_t offset = 1; |
| for( ; offset < initialInstanceCount ; ++offset ) |
| { |
| aNewInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, aModelInstance, |
| aContainer->getInstanceStatic().size(), aSpecifier); |
| aNewInstance->setInstanceCount(1, maximalInstanceCount); |
| |
| aNewInstance->updateUfid(offset); |
| |
| aNewInstance->setAutoStart( true ); |
| |
| setInheritedSpecifier(aContainer, aNewInstance); |
| |
| getSymbolTable().addInstanceStatic( |
| aContainer->saveInstanceStatic(aNewInstance)); |
| } |
| } |
| else |
| { |
| //!![TRACE]: to delete |
| //AVM_OS_DEBUG << "precompileExecutablePrototype Initial Instanciation Count: 0" |
| // << std::endl << str_header( anExec ) << std::endl; |
| } |
| |
| //AVM_OS_TRACE << TAB << ">++ end precompiling executable #instance model:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::precompileExecutableInstanceStatic( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| //AVM_OS_TRACE << TAB << "<-- begin precompiling executable #static instance:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| |
| ExecutableForm * anExec = |
| getSymbolTable().searchExecutableModel(anExecutableSpec); |
| |
| if( anExec != NULL ) |
| { |
| avm_size_t initialInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getInitialInstanceCount(); |
| avm_size_t maximalInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getMaximalInstanceCount(); |
| |
| anExec->incrPossibleStaticInstanciationCount( initialInstanceCount ); |
| |
| // Instances for << MODEL >> & INSTANCE |
| InstanceOfMachine * aModelInstance = aContainer->getInstanceModel(). |
| getByAstElement( anExec->getAstElement() ).rawMachine(); |
| if( aModelInstance == NULL ) |
| { |
| Specifier aSpecifier( |
| anExec->getAstMachine()->getSpecifier() ); |
| |
| aModelInstance = new InstanceOfMachine( aContainer, |
| anExec->getAstMachine(), anExec, NULL, |
| aContainer->getInstanceModel().size(), |
| aSpecifier.setDesignModel() ); |
| |
| aModelInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| aContainer->saveInstanceModel( aModelInstance ); |
| } |
| else |
| { |
| aModelInstance->incrInstanciationCount( initialInstanceCount ); |
| } |
| |
| InstanceOfMachine * aNewInstance = NULL; |
| avm_size_t offset = 0; |
| for( ; offset < initialInstanceCount ; ++offset ) |
| { |
| aNewInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, aModelInstance, |
| aContainer->getInstanceStatic().size() ); |
| |
| aNewInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| if( offset > 0 ) |
| { |
| aNewInstance->updateUfid(offset); |
| } |
| |
| aNewInstance->setAutoStart( anExecutableSpec->isAutoStart() ); |
| // aNewInstance->setAutoStart( true ); |
| |
| setInheritedSpecifier(aContainer, aNewInstance); |
| |
| getSymbolTable().addInstanceStatic( |
| aContainer->saveInstanceStatic(aNewInstance)); |
| } |
| } |
| |
| // ERROR REPORTING |
| else if( getSymbolTable().hasError() ) |
| { |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << getSymbolTable().getErrorMessage() |
| << std::endl << std::endl; |
| } |
| |
| else |
| { |
| |
| |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << "Unfound the model << " << anExecutableSpec->strType() |
| << " >> of the executable instance << " |
| << str_header( anExecutableSpec ) << " >>" |
| << std::endl << std::endl; |
| } |
| |
| //AVM_OS_TRACE << TAB << ">-- end precompiling executable #dynamic instance:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::precompileExecutableInstanceDynamique( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| //AVM_OS_WARN << TAB << "<-- begin precompiling executable #dynamic instance:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| |
| ExecutableForm * anExec = |
| getSymbolTable().searchExecutableModel(anExecutableSpec); |
| |
| avm_size_t initialInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getInitialInstanceCount(); |
| avm_size_t maximalInstanceCount = anExecutableSpec-> |
| getInstanceSpecifier()->getMaximalInstanceCount(); |
| |
| if( anExec != NULL ) |
| { |
| // Instances for << MODEL >> & INSTANCE |
| CompilationEnvironment cENV(anExec); |
| |
| InstanceOfMachine * aModelInstance = |
| getSymbolTable().searchInstanceModel( |
| cENV.mCTX, anExec->getAstElement()).rawMachine(); |
| if( aModelInstance == NULL ) |
| { |
| aModelInstance = aContainer->getInstanceModel(). |
| getByAstElement( anExec->getAstElement() ).rawMachine(); |
| } |
| if( aModelInstance == NULL ) |
| { |
| Specifier aSpecifier( |
| anExec->getAstMachine()->getSpecifier() ); |
| |
| aModelInstance = new InstanceOfMachine( aContainer, |
| anExec->getAstMachine(), anExec, NULL, |
| aContainer->getInstanceModel().size(), |
| aSpecifier.setDesignModel() ); |
| |
| aModelInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| aContainer->saveInstanceModel( aModelInstance ); |
| |
| anExec->incrPossibleDynamicInstanciationCount( |
| initialInstanceCount ); |
| } |
| else |
| { |
| aModelInstance->incrPossibleDynamicInstanciationCount( |
| initialInstanceCount ); |
| } |
| |
| InstanceOfMachine * aNewInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, aModelInstance, |
| aContainer->getInstanceStatic().size() ); |
| |
| aNewInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| aNewInstance->setAutoStart( true ); |
| |
| setInheritedSpecifier(aContainer, aNewInstance); |
| |
| aContainer->saveInstanceDynamic(aNewInstance); |
| } |
| |
| // ERROR REPORTING |
| else if( getSymbolTable().hasError() ) |
| { |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << getSymbolTable().getErrorMessage() |
| << std::endl << std::endl; |
| } |
| |
| else |
| { |
| incrWarningCount(); |
| anExecutableSpec->warningLocation(AVM_OS_LOG) |
| << "Unfound the executable model << " |
| << anExecutableSpec->strType() |
| << " >> of the #dynamic instance !!!" |
| << std::endl << str_header( anExecutableSpec ) |
| << std::endl << std::endl; |
| |
| InstanceOfMachine * aNewInstance = new InstanceOfMachine( |
| aContainer, anExecutableSpec, anExec, NULL, |
| aContainer->getInstanceStatic().size() ); |
| |
| aNewInstance->setInstanceCount( |
| initialInstanceCount, maximalInstanceCount); |
| |
| aNewInstance->setAutoStart( false ); |
| |
| setInheritedSpecifier(aContainer, aNewInstance); |
| |
| aContainer->saveInstanceDynamic(aNewInstance); |
| } |
| |
| //AVM_OS_WARN << TAB << ">-- end precompiling executable #dynamic instance:>" |
| // << std::endl << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::precompileExecutableGroup( |
| ExecutableForm * aContainer, Machine * anExecutableSpec) |
| { |
| // Machine * containerSM = anExecutableSpec->getContainerMachine(); |
| // |
| // if( anExecutableSpec->getSpecifier().isGroupEvery()) |
| // { |
| // containerSM->appendOutgoingTransitionToEveryState(anExecutableSpec); |
| // } |
| // else if( anExecutableSpec->getSpecifier().isGroupSome()) |
| // { |
| // containerSM->appendOutgoingTransitionToSomeState(anExecutableSpec); |
| // } |
| // else if( anExecutableSpec->getSpecifier().isGroupExcept() ) |
| // { |
| // containerSM->appendOutgoingTransitionToExceptState(anExecutableSpec); |
| // } |
| } |
| |
| |
| |
| |
| |
| /** |
| * precompile |
| * specification |
| */ |
| void Compiler::precompileSystem(System & aSystem) |
| { |
| //AVM_OS_TRACE << TAB << "< begin precompiling specification:> " |
| // << aSystem.getFullyQualifiedNameID() << std::endl; |
| |
| /* |
| * For the system executable |
| */ |
| ExecutableForm * systemExec = new ExecutableForm( |
| mConfiguration.getExecutableSystem(), NULL, (& aSystem)); |
| |
| // APPEND NEW EXECUTABLE IN THE SYSTEM |
| // //?? For retrocompatibity serialization order |
| // getSymbolTable().addMachineExecutable( |
| // mExecutableSystem->saveExecutable( systemExec ) ); |
| |
| // Structural decompositon |
| systemExec->setMainComponent( true ); |
| |
| |
| Specifier aSpecifier( aSystem.getSpecifier() ); |
| |
| InstanceOfMachine * aNewInstance = new InstanceOfMachine(NULL, (& aSystem), |
| systemExec, NULL, 0, aSpecifier.setDesignPrototypeStatic() ); |
| |
| aNewInstance->setAutoStart( true ); |
| // aSystem.getInstanceSpecifier()->hasInitialInstance() ); |
| |
| aNewInstance->setInstanceCount(1, 1); |
| |
| systemExec->setPrototypeInstance( aNewInstance ); |
| systemExec->incrPossibleStaticInstanciationCount(1); |
| |
| getSymbolTable().addInstanceStatic( mConfiguration. |
| getExecutableSystem().setSystemInstance(aNewInstance) ); |
| |
| |
| // Set the instance THIS in first position (index = 0) |
| // for << MODEL >> & INSTANCE |
| aNewInstance = InstanceOfMachine::newInstanceModelThis( |
| systemExec, (& aSystem), systemExec, NULL, |
| systemExec->getInstanceModel().size(), |
| aSpecifier.setDesignModel() ); |
| |
| aNewInstance->setInstanceCount(0, 1); |
| |
| systemExec->saveInstanceModel( aNewInstance ); |
| |
| aNewInstance = InstanceOfMachine::newThis(systemExec, |
| aNewInstance, systemExec->getInstanceStatic().size() ); |
| |
| systemExec->saveInstanceStatic(aNewInstance); |
| |
| /* |
| * Allocation of declaration contents :> |
| * constant, variable, typedef, buffer, port |
| */ |
| if( aSystem.hasProperty() ) |
| { |
| TableOfInstanceOfData tableOfVariable; |
| |
| precompilePropertyPart(systemExec, |
| aSystem.getPropertyPart(), tableOfVariable); |
| |
| /* |
| * Update data table |
| */ |
| systemExec->setData(tableOfVariable); |
| } |
| |
| |
| /* |
| * precompiling executable composite part |
| */ |
| precompileExecutableCompositePart(systemExec, (& aSystem)); |
| |
| //AVM_OS_TRACE << TAB << "> end precompiling specification:> " |
| // << aSystem.getFullyQualifiedNameID() << std::endl << std::endl; |
| |
| // APPEND NEW EXECUTABLE IN THE SYSTEM |
| //?? For retrocompatibity serialization order |
| getSymbolTable().addMachineExecutable( mConfiguration. |
| getExecutableSystem().saveExecutable( systemExec ) ); |
| } |
| |
| |
| /** |
| * setInheritedSpecifier from container to owned elements |
| */ |
| void Compiler::setInheritedSpecifier( |
| ExecutableForm * aContainer, ExecutableForm * anExecutable) |
| { |
| if( aContainer->getSpecifier().hasFeatureInputEnabled() ) |
| { |
| anExecutable->getwSpecifier().setFeatureInputEnabled(); |
| |
| const_cast< Machine * >(anExecutable->getAstMachine() ) |
| ->getwSpecifier().setFeatureInputEnabled(); |
| |
| } |
| } |
| |
| void Compiler::setInheritedSpecifier( |
| ExecutableForm * aContainer, InstanceOfMachine * aMachine) |
| { |
| if( aContainer->getSpecifier().hasFeatureInputEnabled() ) |
| { |
| aMachine->getwSpecifier().setFeatureInputEnabled(); |
| } |
| } |
| |
| |
| |
| |
| /** |
| ******************************************************************************* |
| * COMPILATION OF EXECUTABLE |
| ******************************************************************************* |
| */ |
| |
| void Compiler::compileExecutableSystem() |
| { |
| TableOfExecutableForm::const_raw_iterator itProc; |
| TableOfExecutableForm::const_raw_iterator endProc; |
| |
| TableOfExecutableForm::const_raw_iterator itExec = |
| mConfiguration.getExecutableSystem().getExecutables().begin(); |
| TableOfExecutableForm::const_raw_iterator endIt = |
| mConfiguration.getExecutableSystem().getExecutables().end(); |
| for( ; itExec != endIt ; ++itExec ) |
| { |
| compileExecutable( (itExec) ); |
| |
| if( (itExec)->hasExecutable() ) |
| { |
| itProc = (itExec)->getExecutables().begin(); |
| endProc = (itExec)->getExecutables().end(); |
| for( ; itProc != endProc ; ++itProc ) |
| { |
| compileProcedure( itProc ); |
| } |
| } |
| } |
| } |
| |
| |
| void Compiler::compileExecutable(ExecutableForm * anExecutable) |
| { |
| if( anExecutable->isCompiledFlag() ) |
| { |
| return; |
| } |
| else |
| { |
| anExecutable->setCompiledFlag(); |
| } |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << INCR_INDENT_TAB << "<| compiling<executable>: " |
| << anExecutable->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| // Compile data & all machine MOE program |
| compileBaseMachine(anExecutable); |
| |
| // Compile data & all instance MOE program |
| compileAllInstances( anExecutable ); |
| |
| if( anExecutable->getAstElement()->is< System >() ) |
| { |
| compileSystem( anExecutable ); |
| } |
| |
| else if( anExecutable->getAstElement()->is_exactly< Machine >() ) |
| { |
| if( anExecutable->getSpecifier().isFamilyComponentStatemachine() ) |
| { |
| compileStatemachine( anExecutable ); |
| } |
| |
| else |
| { |
| compileMachine( anExecutable ); |
| } |
| } |
| |
| else |
| { |
| AVM_OS_EXIT( FAILED ) |
| << "Unexpected executable form for compiling :\n" |
| << anExecutable->toString() |
| << SEND_EXIT; |
| } |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << TAB_DECR_INDENT << ">| compiling<executable>: " |
| << anExecutable->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| } |
| |
| |
| /** |
| ******************************************************************************* |
| * COMPILATION OF INSTANCE MACHINE PARAM |
| ******************************************************************************* |
| */ |
| void Compiler::compileAllInstances(ExecutableForm * anExecutableForm) |
| { |
| if( anExecutableForm->hasInstanceStatic() ) |
| { |
| // Compilation of InstanceOfMachine Parameters / Behaviors |
| TableOfSymbol::const_iterator itMachine = |
| anExecutableForm->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| anExecutableForm->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| compileInstance(anExecutableForm, (*itMachine).rawMachine()); |
| |
| if( not (*itMachine).hasExecutable() ) |
| { |
| AVM_OS_FATAL_ERROR_EXIT |
| << "Unexpected a #static instance " |
| "without executable model !!!" |
| << std::endl << str_header( (*itMachine) ) |
| << SEND_EXIT; |
| } |
| } |
| } |
| |
| if( anExecutableForm->hasInstanceDynamic() ) |
| { |
| // Compilation of InstanceOfMachine Parameters / Behaviors |
| TableOfSymbol::const_iterator itMachine = |
| anExecutableForm->instance_dynamic_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| anExecutableForm->instance_dynamic_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| compileInstance(anExecutableForm, (*itMachine).rawMachine()); |
| |
| if( not (*itMachine).hasExecutable() ) |
| { |
| AVM_OS_FATAL_ERROR_EXIT |
| << "Unexpected a #dynamic instance " |
| "without executable model !!!" |
| << std::endl << str_header( (*itMachine) ) |
| << SEND_EXIT; |
| } |
| } |
| } |
| } |
| |
| void Compiler::compileInstance( |
| ExecutableForm * theExecutableContainer, InstanceOfMachine * anInstance) |
| { |
| const Machine * anExecutableSpec = anInstance->getAstMachine(); |
| |
| //AVM_OS_WARN << TAB << "<-- begin compiling executable instance:>" << std::endl |
| // << to_stream( anInstance )// << std::endl |
| // << to_stream( anExecutableSpec ) << std::endl; |
| |
| ExecutableForm * anExec = anInstance->getExecutable(); |
| |
| if( anExec == NULL ) |
| { |
| anExec = getSymbolTable().searchExecutableModel(anExecutableSpec); |
| |
| if( anExec != NULL ) |
| { |
| anInstance->setExecutable( anExec ); |
| |
| anInstance->setAutoStart( true ); |
| |
| // Instances for << MODEL >> & INSTANCE |
| CompilationEnvironment cENV(anExec); |
| |
| InstanceOfMachine * aModelInstance = |
| getSymbolTable().searchInstanceModel( |
| cENV.mCTX, anExec->getAstElement()).rawMachine(); |
| if( aModelInstance == NULL ) |
| { |
| aModelInstance = theExecutableContainer->getInstanceModel(). |
| getByAstElement( anExec->getAstElement() ).rawMachine(); |
| } |
| if( aModelInstance != NULL ) |
| { |
| anInstance->setInstanceModel( aModelInstance ); |
| } |
| |
| if( anInstance->getSpecifier().hasDesignInstanceDynamic() ) |
| { |
| if( aModelInstance != NULL ) |
| { |
| aModelInstance->incrPossibleDynamicInstanciationCount( 1 ); |
| } |
| else |
| { |
| anExec->incrPossibleDynamicInstanciationCount( 1 ); |
| } |
| } |
| else |
| { |
| anExec->incrPossibleStaticInstanciationCount( 1 ); |
| } |
| } |
| |
| // ERROR REPORTING |
| else if( getSymbolTable().hasError() ) |
| { |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << getSymbolTable().getErrorMessage() |
| << std::endl << std::endl; |
| } |
| |
| else |
| { |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << "Unfound the model << " |
| << anExecutableSpec->strType() |
| << " >> of the statemachine instance << " |
| << str_header( anExecutableSpec ) << " >>" |
| << std::endl << std::endl; |
| } |
| } |
| |
| if( anExec != NULL ) |
| { |
| compileExecutable( anExec ); |
| |
| if( anExec->hasParamReturn() ) |
| { |
| compileInstanceParameters(theExecutableContainer, anInstance); |
| } |
| } |
| else |
| { |
| AVM_OS_FATAL_ERROR_EXIT |
| << "Unexpected a instance without executable model !!!" |
| << std::endl << str_header( anInstance ) |
| << SEND_EXIT; |
| |
| return; |
| } |
| |
| BehavioralPart * theBehavior = anExecutableSpec->getBehavior(); |
| |
| if( theBehavior != NULL ) |
| { |
| /* |
| * onCreate |
| */ |
| if( theBehavior->hasOnCreate() |
| && StatementTypeChecker::doSomething(theBehavior->getOnCreate()) ) |
| { |
| CompilationEnvironment cENV(NULL, anExec, theExecutableContainer); |
| |
| BFCode onCreate = theBehavior->getOnCreate(); |
| if( anExec->hasOnCreate() |
| && anInstance->getSpecifier().hasDesignInstanceNotModel() ) |
| { |
| onCreate = StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExec->getOnCreate(), onCreate ); |
| } |
| |
| anInstance->setOnCreate( |
| mAvmcodeCompiler.compileStatement(cENV.mCTX, onCreate) ); |
| } |
| |
| /* |
| * onStart |
| */ |
| if( theBehavior->hasOnStart() |
| && StatementTypeChecker::doSomething(theBehavior->getOnStart()) ) |
| { |
| CompilationEnvironment cENV(NULL, anExec, theExecutableContainer); |
| |
| BFCode onStart = theBehavior->getOnStart(); |
| if( anExec->hasOnStart() ) |
| { |
| onStart = StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExec->getOnStart(), onStart ); |
| } |
| |
| if( anExec->hasOnInit() ) |
| { |
| onStart = StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| onStart, anExec->getOnInit() ); |
| } |
| |
| anInstance->setOnStart( |
| mAvmcodeCompiler.compileStatement(cENV.mCTX, onStart) ); |
| } |
| } |
| |
| //AVM_OS_WARN << TAB << ">-- end compiling executable instance:>" << std::endl |
| // << to_stream( anInstance )// << std::endl |
| // << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::compileInstanceParameters( |
| ExecutableForm * theExecutableContainer, InstanceOfMachine * anInstance) |
| { |
| ExecutableForm * anExecutableForm = anInstance->getExecutable(); |
| |
| const Machine * aMachine = anInstance->getAstMachine(); |
| |
| if( (anExecutableForm != NULL) && anExecutableForm->hasParamReturn() ) |
| { |
| APTableOfData aParamTable( new TableOfData( |
| anExecutableForm->getParamReturnCount() ) ); |
| anInstance->setParamReturnTable( aParamTable ); |
| |
| anInstance->setReturnOffset( anExecutableForm->getParamCount() ); |
| |
| bool hasInitialInstance = |
| aMachine->getInstanceSpecifier()->hasInitialInstance(); |
| |
| |
| if( anExecutableForm->hasParam() ) |
| { |
| if( aMachine->hasVariableParameter() ) |
| { |
| BF paramValue; |
| |
| TableOfVariable::const_raw_iterator it = |
| aMachine->getVariableParameters().begin(); |
| TableOfVariable::const_raw_iterator itEnd = |
| aMachine->getVariableParameters().end(); |
| for( avm_offset_t offset = 0 ; it != itEnd ; ++it , ++offset ) |
| { |
| if( (*it).invalid() ) |
| { |
| if( hasInitialInstance ) |
| { |
| incrWarningCount(); |
| aMachine->errorLocation(AVM_OS_WARN) |
| << "Compile param warning << " |
| << str_header( |
| anExecutableForm->rawParamData(offset) ) |
| << " >> for the statemachine instance << " |
| << str_header( aMachine ) << " >> " |
| << "Unexpected non-instanciated parameters !" |
| << std::endl << std::endl; |
| //!! Generation of symbolic parameter |
| //!! Generation of symbolic parameter |
| } |
| } |
| else if( (it)->hasValue() ) |
| { |
| paramValue = mAvmcodeCompiler.decode_compileExpression( |
| theExecutableContainer, (it)->getValue() ); |
| if( paramValue.valid() ) |
| { |
| aParamTable->set(offset, paramValue); |
| } |
| else |
| { |
| incrErrorCount(); |
| aMachine->errorLocation(AVM_OS_WARN) |
| << "Compile param error << " |
| << str_header( *it ) |
| << " >> for the statemachine instance << " |
| << str_header( aMachine ) << " >>" |
| << std::endl << std::endl; |
| } |
| } |
| else if( hasInitialInstance ) |
| { |
| incrWarningCount(); |
| aMachine->warningLocation(AVM_OS_WARN) |
| << "Compile param warning << " |
| << str_header( *it ) |
| << " >> for the statemachine instance << " |
| << str_header( aMachine ) << " >> " |
| << "Unexpected non-instanciated parameters !" |
| << std::endl << std::endl; |
| //!! Generation of symbolic parameter |
| //!! Generation of symbolic parameter |
| } |
| } |
| } |
| } |
| |
| if( anExecutableForm->hasReturn() ) |
| { |
| if( aMachine->hasVariableReturn() ) |
| { |
| BF returnValue; |
| |
| TableOfVariable::const_raw_iterator it = |
| aMachine->getVariableReturns().begin(); |
| TableOfVariable::const_raw_iterator itEnd = |
| aMachine->getVariableReturns().end(); |
| for( avm_offset_t offset = 0 ; it != itEnd ; ++it , ++offset ) |
| { |
| if( (*it).invalid() ) |
| { |
| incrWarningCount(); |
| aMachine->errorLocation(AVM_OS_WARN) |
| << "Compile return warning << " |
| << str_header( |
| anExecutableForm->rawReturnData(offset) ) |
| << " >> for the statemachine instance << " |
| << str_header( aMachine ) << " >> " |
| << "Unexpected non-instanciated parameters !" |
| << std::endl << std::endl; |
| //!! Generation of symbolic parameter |
| //!! Generation of symbolic parameter |
| } |
| else if( (it)->hasValue() ) |
| { |
| returnValue = mAvmcodeCompiler.decode_compileExpression( |
| theExecutableContainer, (it)->getValue() ); |
| if( returnValue.valid() ) |
| { |
| aParamTable->set(anExecutableForm->getReturnOffset() |
| + offset, returnValue); |
| } |
| else |
| { |
| incrErrorCount(); |
| aMachine->errorLocation(AVM_OS_WARN) |
| << "Compile return error << " |
| << str_header( *it ) |
| << " >> for the statemachine instance << " |
| << str_header( aMachine ) << " >>" |
| << std::endl << std::endl; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| |
| /** |
| ******************************************************************************* |
| * COMPILATION OF AVMPROGRAM |
| ******************************************************************************* |
| */ |
| |
| void Compiler::compileAvmPrograms() |
| { |
| AvmProgram * aProgram; |
| avm_size_t offset; |
| |
| TableOfExecutableForm::const_raw_iterator itExec = |
| mConfiguration.getExecutableSystem().getExecutables().begin(); |
| TableOfExecutableForm::const_raw_iterator endExec = |
| mConfiguration.getExecutableSystem().getExecutables().end(); |
| for( ; itExec != endExec ; ++itExec ) |
| { |
| for( offset = 0 ; offset < (itExec)->getProgram().size() ; ++offset ) |
| { |
| aProgram = (itExec)->getProgram().rawAt(offset); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << INCR_INDENT_TAB << "<| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| mProgramCompiler.compileProgram( aProgram ); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| // (*itProg)->toStream(AVM_OS_TRACE); |
| AVM_OS_TRACE << TAB_DECR_INDENT << ">| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| } |
| } |
| } |
| |
| |
| /** |
| * compile |
| * Executable |
| */ |
| void Compiler::compileBaseMachine(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aMachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<machine>: " |
| // << str_header( aMachine ) << std::endl; |
| |
| |
| // COMPILATION OF PORT |
| mComCompiler.compilePort(anExecutableForm); |
| |
| // COMPILATION OF DATA |
| mDataCompiler.compileData(anExecutableForm); |
| |
| |
| if( not aMachine->hasBehavior() ) |
| { |
| return; |
| } |
| |
| BehavioralPart * theBehavior = aMachine->getBehavior(); |
| |
| /* |
| * onCreate |
| */ |
| if( theBehavior->hasOnCreate() && |
| StatementTypeChecker::doSomething(theBehavior->getOnCreate()) ) |
| { |
| anExecutableForm->setOnCreate( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnCreate()) ); |
| } |
| |
| /* |
| * onInit |
| */ |
| if( theBehavior->hasOnInit() && |
| StatementTypeChecker::doSomething(theBehavior->getOnInit()) ) |
| { |
| anExecutableForm->setOnInit( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnInit()) ); |
| } |
| |
| /* |
| * onFinal |
| */ |
| if( theBehavior->hasOnFinal() && |
| StatementTypeChecker::doSomething(theBehavior->getOnFinal()) ) |
| { |
| anExecutableForm->setOnFinal( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnFinal()) ); |
| } |
| |
| |
| /* |
| * onReturn |
| */ |
| if( theBehavior->hasOnReturn() && |
| StatementTypeChecker::doSomething(theBehavior->getOnReturn()) ) |
| { |
| anExecutableForm->setOnReturn( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnReturn()), |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_FINAL) ) ); |
| } |
| |
| |
| /* |
| * onStart |
| */ |
| if( theBehavior->hasOnStart() && |
| StatementTypeChecker::doSomething(theBehavior->getOnStart()) ) |
| { |
| anExecutableForm->setOnStart( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnStart()) ); |
| } |
| |
| /* |
| * onStop |
| */ |
| if( theBehavior->hasOnStop() && |
| StatementTypeChecker::doSomething(theBehavior->getOnStop()) ) |
| { |
| anExecutableForm->setOnStop( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnStop()) ); |
| } |
| |
| |
| /* |
| * onIEnable |
| */ |
| if( theBehavior->hasOnIEnable() && |
| StatementTypeChecker::doSomething(theBehavior->getOnIEnable()) ) |
| { |
| anExecutableForm->setOnIEnable( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnIEnable()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnIEnable(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| StatementConstructor::newComment( "begin<ienable> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnIEnable(), |
| |
| StatementConstructor::newComment( "end<ienable> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| } |
| |
| /* |
| * onEnable |
| */ |
| if( theBehavior->hasOnEnable() && |
| StatementTypeChecker::doSomething(theBehavior->getOnEnable()) ) |
| { |
| anExecutableForm->setOnEnable( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnEnable()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnEnable(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| StatementConstructor::newComment( "begin<enable> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnEnable(), |
| |
| StatementConstructor::newComment( "end<enable> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| } |
| |
| // EXPAND IENABLE / ENABLE |
| if( anExecutableForm->hasOnIEnable() ) |
| { |
| if( anExecutableForm->hasOnEnable() ) |
| { |
| if( not AvmCodeFactory::contains(anExecutableForm, |
| anExecutableForm->getOnEnable(), AVM_OPCODE_IENABLE_INVOKE) ) |
| { |
| anExecutableForm->setOnEnable( |
| StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIEnable(), |
| |
| anExecutableForm->getOnEnable() ) ); |
| } |
| else |
| { |
| // EXPAND IENABLE |
| } |
| } |
| else |
| { |
| // (*it)->setOnEnable( BFCode(OperatorManager::OPERATOR_IENABLE) ); |
| |
| //Optimization |
| anExecutableForm->setOnEnable( anExecutableForm->getOnIEnable() ); |
| } |
| } |
| |
| |
| |
| /* |
| * onIDisable |
| */ |
| if( theBehavior->hasOnIDisable() && |
| StatementTypeChecker::doSomething(theBehavior->getOnIDisable()) ) |
| { |
| anExecutableForm->setOnIDisable( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnIDisable()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnIDisable(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newComment( "begin<idisable> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnIDisable(), |
| |
| StatementConstructor::newComment( "end<idisable> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| } |
| |
| /* |
| * onDisable |
| */ |
| if( theBehavior->hasOnDisable() && |
| StatementTypeChecker::doSomething(theBehavior->getOnDisable()) ) |
| { |
| anExecutableForm->setOnDisable( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnDisable()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnDisable(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newComment( "begin<disable> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnDisable(), |
| |
| StatementConstructor::newComment( "end<disable> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| |
| anExecutableForm->setOnDisable( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnDisable(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_SELF) ) ); |
| } |
| |
| // EXPAND IDISABLE / DISABLE |
| if( anExecutableForm->hasOnIDisable() ) |
| { |
| if( anExecutableForm->hasOnDisable() ) |
| { |
| if( not AvmCodeFactory::contains(anExecutableForm, |
| anExecutableForm->getOnDisable(), AVM_OPCODE_IDISABLE_INVOKE) ) |
| { |
| anExecutableForm->setOnDisable( |
| StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIDisable(), |
| |
| anExecutableForm->getOnDisable() ) ); |
| } |
| else |
| { |
| // EXPAND IDISABLE |
| } |
| } |
| else |
| { |
| // (*it)->setOnDisable( BFCode(OperatorManager::OPERATOR_IDISABLE) ); |
| |
| //Optimization |
| anExecutableForm->setOnDisable( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIDisable(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_SELF) ) ); |
| } |
| |
| anExecutableForm->setOnIDisable( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIDisable(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_SELF) ) ); |
| } |
| |
| |
| /* |
| * onIAbort |
| */ |
| if( theBehavior->hasOnIAbort() && |
| StatementTypeChecker::doSomething(theBehavior->getOnIAbort()) ) |
| { |
| anExecutableForm->setOnIAbort( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnIAbort()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnIAbort(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newComment( "begin<iabort> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnIAbort(), |
| |
| StatementConstructor::newComment( "end<iabort> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| } |
| |
| /* |
| * onAbort |
| */ |
| if( theBehavior->hasOnAbort() && |
| StatementTypeChecker::doSomething(theBehavior->getOnAbort()) ) |
| { |
| anExecutableForm->setOnAbort( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnAbort()) ); |
| |
| AVM_IF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| anExecutableForm->setOnAbort(StatementConstructor::newCodeFlatMiddle( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newComment( "begin<abort> " + |
| anExecutableForm->getFullyQualifiedNameID() ), |
| |
| anExecutableForm->getOnAbort(), |
| |
| StatementConstructor::newComment( "end<abort> " + |
| anExecutableForm->getFullyQualifiedNameID() ) ) ); |
| AVM_ENDIF_DEBUG_LEVEL_FLAG2( HIGH , COMPUTING , STATEMENT ) |
| |
| anExecutableForm->setOnAbort( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnAbort(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ABORT_SELF) ) ); |
| } |
| |
| // EXPAND IABORT / ABORT |
| if( anExecutableForm->hasOnIAbort() ) |
| { |
| if( anExecutableForm->hasOnAbort() ) |
| { |
| if( not AvmCodeFactory::contains(anExecutableForm, |
| anExecutableForm->getOnAbort(), AVM_OPCODE_IABORT_INVOKE) ) |
| { |
| anExecutableForm->setOnAbort( |
| StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIAbort(), |
| |
| anExecutableForm->getOnAbort() ) ); |
| } |
| else |
| { |
| // EXPAND IABORT |
| } |
| } |
| else |
| { |
| // (*it)->setOnAbort( BFCode(OperatorManager::OPERATOR_IABORT) ); |
| |
| //Optimization |
| anExecutableForm->setOnAbort( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIAbort(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ABORT_SELF) ) ); |
| } |
| |
| anExecutableForm->setOnIAbort( StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| |
| anExecutableForm->getOnIAbort(), |
| |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ABORT_SELF) ) ); |
| } |
| |
| |
| /* |
| * onIRun |
| */ |
| if( theBehavior->hasOnIRun() && |
| StatementTypeChecker::doSomething(theBehavior->getOnIRun()) ) |
| { |
| anExecutableForm->setOnIRun( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnIRun()) ); |
| } |
| |
| /* |
| * onRun |
| */ |
| if( theBehavior->hasOnRun() && |
| StatementTypeChecker::doSomething(theBehavior->getOnRun()) ) |
| { |
| anExecutableForm->setOnRun( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnRun()) ); |
| } |
| |
| /* |
| * onRtc |
| */ |
| if( theBehavior->hasOnRtc() && |
| StatementTypeChecker::doSomething(theBehavior->getOnRtc()) ) |
| { |
| anExecutableForm->setOnRtc( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnRtc()) ); |
| } |
| |
| |
| /* |
| * onSchedule |
| */ |
| if( theBehavior->hasOnSchedule() ) |
| { |
| if( StatementTypeChecker::isEmptySchedule(theBehavior->getOnSchedule()) ) |
| { |
| //!! NOTHING |
| } |
| else |
| { |
| anExecutableForm->setOnSchedule( |
| compileSchedulerRoutine( |
| anExecutableForm, |
| theBehavior->getOnSchedule() ) ); |
| } |
| } |
| |
| /* |
| * onConcurrency |
| */ |
| if( theBehavior->hasOnConcurrency() ) |
| { |
| if( StatementTypeChecker::isEmptySchedule(theBehavior->getOnConcurrency()) ) |
| { |
| anExecutableForm->setOnConcurrency( theBehavior->getOnConcurrency() ); |
| } |
| else |
| { |
| anExecutableForm->setOnConcurrency( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnConcurrency()) ); |
| } |
| } |
| else if( StatementTypeChecker::isSchedule(theBehavior->getOnSchedule()) ) |
| { |
| anExecutableForm->setOnConcurrency( |
| theBehavior->getOnSchedule().getOperator() ); |
| } |
| |
| |
| /* |
| * onSynchronize |
| */ |
| if( theBehavior->hasOnSynchronize() ) |
| { |
| anExecutableForm->setOnSynchronize( |
| mAvmcodeCompiler.compileStatement( |
| anExecutableForm, theBehavior->getOnSynchronize()) ); |
| } |
| |
| |
| /* |
| * other user Routines |
| */ |
| BehavioralPart::const_routine_iterator it = theBehavior->routine_begin(); |
| BehavioralPart::const_routine_iterator endIt = theBehavior->routine_end(); |
| for( ; it != endIt ; ++it ) |
| { |
| anExecutableForm->saveProgram( |
| mAvmcodeCompiler.compileRoutine(this, anExecutableForm, it) ); |
| } |
| |
| |
| //AVM_OS_TRACE << TAB << ">| compiling<machine>: " |
| // << str_header( aMachine ) << std::endl << std::endl; |
| } |
| |
| |
| /** |
| * compile |
| * executable procedure |
| */ |
| void Compiler::compileProcedure(ExecutableForm * anExecutableForm) |
| { |
| // Compile data & all machine MOE program |
| compileBaseMachine(anExecutableForm); |
| |
| const Machine * aProcedure = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aProcedure ) << std::endl; |
| |
| // PUSH MOC |
| WObject * moc_transition = NULL;//aProcedure::getTransitionMoc(); |
| if( moc_transition != NULL ) |
| { |
| mTransitionCompiler.pushMoc(moc_transition); |
| } |
| |
| |
| // Compile all specific statemachine |
| if( aProcedure->getSpecifier().isStateBasic() ) |
| { |
| compileStatemachineBasic(anExecutableForm); |
| } |
| |
| else if( aProcedure->getSpecifier().isMocStateTransitionStructure() ) |
| { |
| compileExecutableMocStateTransitionStructure(anExecutableForm); |
| } |
| else if( aProcedure->getSpecifier().isMocCompositeStructure() ) |
| { |
| compileExecutableMocCompositeStructure(anExecutableForm); |
| } |
| |
| else |
| { |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( |
| anExecutableForm->hasOnSchedule() ); |
| |
| /* |
| * Compiling communication |
| */ |
| bool hasSynchronizeMachine = false; |
| bool hasUpdateBuffer = false; |
| |
| mComCompiler.compileCommunication(anExecutableForm, |
| hasUpdateBuffer, hasSynchronizeMachine); |
| |
| if( anExecutableForm->hasOnRun() ) |
| { |
| //!! NOTHING |
| } |
| else if( anExecutableForm->hasOnRtc() ) |
| { |
| anExecutableForm->setOnRun(StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RTC)); |
| } |
| |
| else if( anExecutableForm->hasOnSchedule() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE)); |
| } |
| } |
| |
| // POP MOC |
| if( moc_transition != NULL ) |
| { |
| mTransitionCompiler.popMoc(); |
| } |
| |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aProcedure ) << std::endl; |
| } |
| |
| |
| /** |
| * compile |
| * executable machine |
| */ |
| void Compiler::compileMachine(ExecutableForm * anExecutableForm) |
| { |
| //AVM_OS_TRACE << TAB << "<| compiling<machine>: " |
| // << str_header( aMachine ) << std::endl; |
| |
| // COMPILE PROGRAM |
| if( anExecutableForm->hasProgram() ) |
| { |
| AvmProgram * aProgram; |
| |
| avm_size_t offset = 0; |
| for( ; offset < anExecutableForm->getProgram().size() ; ++offset ) |
| { |
| aProgram = anExecutableForm->getProgram().rawAt(offset); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << INCR_INDENT_TAB << "<| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| mProgramCompiler.compileProgram( aProgram ); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| // (*itProg)->toStream(AVM_OS_TRACE); |
| AVM_OS_TRACE << TAB_DECR_INDENT << ">| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| } |
| } |
| |
| |
| const Machine * aMachine = anExecutableForm->getAstMachine(); |
| |
| // Compile all specific machine |
| if( aMachine->getSpecifier().isMocStateTransitionStructure() ) |
| { |
| compileExecutableMocStateTransitionStructure(anExecutableForm); |
| } |
| else if( aMachine->getSpecifier().isMocCompositeStructure() ) |
| { |
| compileExecutableMocCompositeStructure(anExecutableForm); |
| } |
| else |
| { |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( |
| anExecutableForm->hasOnSchedule() ); |
| |
| /* |
| * Compiling communication |
| */ |
| bool hasSynchronizeMachine = false; |
| bool hasUpdateBuffer = false; |
| |
| mComCompiler.compileCommunication(anExecutableForm, |
| hasUpdateBuffer, hasSynchronizeMachine); |
| |
| if( anExecutableForm->hasOnRun() ) |
| { |
| //!! NOTHING |
| } |
| else if( anExecutableForm->hasOnRtc() ) |
| { |
| anExecutableForm->setOnRun(StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RTC)); |
| } |
| |
| else if( anExecutableForm->hasOnSchedule() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE)); |
| } |
| } |
| |
| //AVM_OS_TRACE << TAB << ">| compiling<machine>: " |
| // << str_header( aMachine ) << std::endl << std::endl; |
| } |
| |
| |
| /** |
| * compile |
| * specification |
| */ |
| void Compiler::compileSystem(ExecutableForm * anExecutableForm) |
| { |
| const System * aSystem = anExecutableForm->getAstSystem(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<system>: " |
| // << aSystem->getFullyQualifiedNameID() << std::endl; |
| |
| // Compile all specific machine |
| if( aSystem->getSpecifier().isMocStateTransitionStructure() ) |
| { |
| compileExecutableMocStateTransitionStructure(anExecutableForm); |
| } |
| else //if( aSystem->getSpecifier().isMocCompositeStructure() |
| //|| (not aSystem->hasRunnableBehavior()) ) |
| { |
| compileExecutableMocCompositeStructure(anExecutableForm); |
| } |
| |
| if( not anExecutableForm->hasOnInit() ) |
| { |
| anExecutableForm->setOnInit( StatementConstructor::nopCode() ); |
| } |
| |
| if( anExecutableForm->hasOnIRun() ) |
| { |
| if( anExecutableForm->hasOnRun() ) |
| { |
| anExecutableForm->setOnRun( |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SEQUENCE_SIDE, |
| anExecutableForm->getOnIRun(), |
| anExecutableForm->getOnRun()) ); |
| } |
| else |
| { |
| anExecutableForm->setOnRun( anExecutableForm->getOnIRun() ); |
| } |
| } |
| else if( (not anExecutableForm->hasOnSchedule()) |
| && (not anExecutableForm->hasOnRun()) ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| |
| |
| //AVM_OS_TRACE << TAB << ">| compiling<system>: " |
| // << aSystem->getFullyQualifiedNameID() << std::endl << std::endl; |
| } |
| |
| |
| |
| |
| /** |
| * compile |
| * statemachine |
| */ |
| void Compiler::compileStatemachine(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aStatemachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| |
| // PUSH MOC |
| WObject * moc_transition = NULL;//aStatemachine::getTransitionMoc(); |
| if( moc_transition != NULL ) |
| { |
| mTransitionCompiler.pushMoc(moc_transition); |
| } |
| |
| // Compile all specific statemachine |
| if( aStatemachine->getSpecifier().hasFamilyPseudostateEnding() ) |
| { |
| compilePseudostateEnding(anExecutableForm); |
| } |
| else if( aStatemachine->getSpecifier().hasPseudostateMocHISTORY() ) |
| { |
| compileStatemachineHistory(anExecutableForm); |
| } |
| else if( aStatemachine->getSpecifier().isPseudostate() ) |
| { |
| compileStatemachinePseudo(anExecutableForm); |
| } |
| |
| else if( aStatemachine->getSpecifier().isStateBasic() ) |
| { |
| compileStatemachineBasic(anExecutableForm); |
| } |
| |
| else if( aStatemachine->getSpecifier().isMocStateTransitionStructure() ) |
| { |
| compileExecutableMocStateTransitionStructure(anExecutableForm); |
| } |
| else if( aStatemachine->getSpecifier().isMocCompositeStructure() ) |
| { |
| compileExecutableMocCompositeStructure(anExecutableForm); |
| } |
| else if( aStatemachine->getSpecifier().isComponentProcedure() ) |
| { |
| compileExecutableMocCompositeStructure(anExecutableForm); |
| } |
| |
| else |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected statemachine type << " |
| << str_header( aStatemachine ) << " >>" |
| << std::endl << std::endl; |
| } |
| |
| |
| // COMPILE TRANSITION |
| if( anExecutableForm->hasTransition() ) |
| { |
| AvmTransition * aTransition; |
| |
| avm_size_t offset = 0; |
| for( ; offset < anExecutableForm->getTransition().size() ; ++offset ) |
| { |
| aTransition = anExecutableForm->getTransition().rawAt(offset); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << INCR_INDENT_TAB << "<| compiling<transition>: " |
| << aTransition->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| mTransitionCompiler.compileTransition( aTransition ); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| // (*itProg)->toStream(AVM_OS_TRACE); |
| AVM_OS_TRACE << TAB_DECR_INDENT << ">| compiling<transition>: " |
| << aTransition->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| } |
| |
| if( anExecutableForm->getSpecifier().hasFeatureInputEnabled() ) |
| { |
| computeInputEnabledCom( anExecutableForm ); |
| } |
| } |
| |
| |
| // COMPILE PROGRAM |
| if( anExecutableForm->hasProgram() ) |
| { |
| AvmProgram * aProgram; |
| |
| avm_size_t offset = 0; |
| for( ; offset < anExecutableForm->getProgram().size() ; ++offset ) |
| { |
| aProgram = anExecutableForm->getProgram().rawAt(offset); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| AVM_OS_TRACE << INCR_INDENT_TAB << "<| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| |
| mProgramCompiler.compileProgram( aProgram ); |
| |
| AVM_IF_DEBUG_FLAG( COMPILING ) |
| // (*itProg)->toStream(AVM_OS_TRACE); |
| AVM_OS_TRACE << TAB_DECR_INDENT << ">| compiling<program>: " |
| << aProgram->getFullyQualifiedNameID() << std::endl; |
| AVM_ENDIF_DEBUG_FLAG( COMPILING ) |
| } |
| |
| if( anExecutableForm->getSpecifier().hasFeatureInputEnabled() ) |
| { |
| computeInputEnabledCom( anExecutableForm ); |
| } |
| } |
| |
| |
| // POP MOC |
| if( moc_transition != NULL ) |
| { |
| mTransitionCompiler.popMoc(); |
| } |
| |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| } |
| |
| |
| void Compiler::compileExecutableMocCompositeStructure( |
| ExecutableForm * anExecutableForm) |
| { |
| const Machine * anExecutableSpec = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling executable< moc: and >: " |
| // << str_header( anExecutableSpec ) << std::endl; |
| |
| bool hasInstanceStatic = anExecutableSpec->hasMachine(); |
| bool hasSynchronizeMachine = false; |
| bool hasUpdateBuffer = false; |
| |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( false ); |
| |
| /** |
| * compile all routines which defined the executable's behavior |
| */ |
| compileAllBehavioralRoutines( anExecutableForm ); |
| |
| /* |
| * Compiling communication |
| */ |
| mComCompiler.compileCommunication(anExecutableForm, |
| hasUpdateBuffer, hasSynchronizeMachine); |
| |
| |
| /* |
| * OnRun |
| * whith high priority order |
| * |
| * StrongAbort Transition |
| * OnIRun |
| * ( Simple Transition or submachine ) depend on MOC |
| * WeakAbort Transition |
| * NormalTerminaison Transition |
| */ |
| |
| BFCode onRunProgram; |
| |
| // Update Buffer |
| if( hasInstanceStatic ) |
| { |
| if( hasSynchronizeMachine ) // only if has RDV protocol |
| { |
| anExecutableForm->setRdvCommunication( hasSynchronizeMachine ); |
| |
| setRdvScheduling( anExecutableForm ); |
| } |
| |
| if( anExecutableForm->hasOnRun() ) |
| { |
| onRunProgram = anExecutableForm->getOnRun(); |
| |
| anExecutableForm->setOnRun( BFCode::REF_NULL ); |
| |
| if( not AvmCodeFactory::contains(anExecutableForm, |
| onRunProgram, AVM_OPCODE_SCHEDULE_INVOKE) ) |
| { |
| if( (not anExecutableForm->hasOnRtc()) && |
| AvmCodeFactory::contains(anExecutableForm, |
| onRunProgram, AVM_OPCODE_RTC) ) |
| { |
| anExecutableForm->setOnRtc( |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE) ); |
| } |
| else if( anExecutableForm->hasOnSchedule() |
| || anExecutableForm->isMutableSchedule() ) |
| { |
| onRunProgram = StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, onRunProgram, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE) ); |
| } |
| } |
| } |
| else if( anExecutableForm->hasOnSchedule() |
| || anExecutableForm->isMutableSchedule() ) |
| { |
| onRunProgram = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE); |
| } |
| |
| if( hasUpdateBuffer ) // only if has BROADCAST protocol |
| { |
| onRunProgram = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_UPDATE_BUFFER, onRunProgram); |
| } |
| } |
| |
| if( anExecutableSpec->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm, onRunProgram ); |
| } |
| else if( onRunProgram.valid() ) |
| { |
| anExecutableForm->setOnRun( onRunProgram ); |
| } |
| else if( anExecutableForm->hasOnIRun() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| |
| |
| //AVM_OS_TRACE << TAB << ">| compiling executable< moc: and >: " |
| // << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::compileExecutableMocStateTransitionStructure( |
| ExecutableForm * anExecutableForm) |
| { |
| const Machine * anExecutableSpec = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling executable< moc: and >: " |
| // << str_header( anExecutableSpec ) << std::endl; |
| |
| bool hasSynchronizeMachine = false; |
| bool hasUpdateBuffer = false; |
| |
| // /* |
| // * Compiling program |
| // */ |
| // |
| // TableOfAvmProgram::iterator it = anExecutableForm->getProgram().begin(); |
| // for( ; it != anExecutableForm->getProgram().end() ; ++it ) |
| // { |
| // compileProgram(anExecutableForm, (*it)); |
| // } |
| |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( true ); |
| |
| if( anExecutableSpec->hasMachine() ) |
| { |
| /* |
| * ON_INIT |
| * ON_ENABLE |
| */ |
| // non determinism: simulation of enabling for |
| // each [ start ] state or [ initial ] state ... |
| BFCode onInitCode( OperatorManager::OPERATOR_NONDETERMINISM ); |
| |
| BFCode onEnableCode( OperatorManager::OPERATOR_NONDETERMINISM ); |
| |
| BFCode onScheduleCode( OperatorManager::OPERATOR_NONDETERMINISM ); |
| |
| bool hasnotOwnedPseudostateHistory = (not anExecutableSpec-> |
| getOwnedElementsSpecifier().hasPseudostateMocHISTORY()); |
| |
| bool hasnotOwnedPseudostateInitialOrStateStart = |
| (not anExecutableSpec-> |
| getOwnedElementsSpecifier().hasMocINITIAL_START()); |
| |
| TableOfSymbol::const_iterator itMachine = |
| anExecutableForm->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| anExecutableForm->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| const Specifier & itSpecifier = |
| (*itMachine).getExecutable()->getSpecifier(); |
| |
| if( itSpecifier.isPseudostateInitialOrStateStart() ) |
| { |
| onInitCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_INIT, (*itMachine) ) ); |
| |
| if( hasnotOwnedPseudostateHistory ) |
| { |
| onEnableCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ENABLE_INVOKE, |
| (*itMachine) ) ); |
| } |
| |
| onScheduleCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN, (*itMachine)) ); |
| } |
| else if( itSpecifier.hasPseudostateHistory() ) |
| { |
| onEnableCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ENABLE_INVOKE, |
| (*itMachine) ) ); |
| } |
| else if( hasnotOwnedPseudostateInitialOrStateStart ) |
| { |
| onInitCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_INIT, (*itMachine) ) ); |
| |
| if( hasnotOwnedPseudostateHistory ) |
| { |
| onEnableCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ENABLE_SET, |
| (*itMachine) ), |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ENABLE_INVOKE, |
| (*itMachine) ) ) ); |
| } |
| |
| onScheduleCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN, (*itMachine) ) ); |
| } |
| } |
| |
| // ON INIT |
| if( onInitCode->nonempty() ) |
| { |
| anExecutableForm->setOnInit( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnInit(), |
| (onInitCode->singleton() ? |
| onInitCode->first().bfCode() : onInitCode) ) ); |
| } |
| |
| // ON ENABLE |
| if( onEnableCode->nonempty() ) |
| { |
| anExecutableForm->setOnEnable( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnEnable(), |
| (onEnableCode->singleton() ? |
| onEnableCode->first().bfCode() : onEnableCode) ) ); |
| } |
| |
| /** |
| * ON SCHEDULE |
| */ |
| if( anExecutableForm->hasOnSchedule() ) |
| { |
| incrErrorCount(); |
| anExecutableSpec->errorLocation(AVM_OS_WARN) |
| << "Unexpected a State-Transition-System << " |
| << str_header( anExecutableSpec ) |
| << " >> with user schedule code: " |
| << anExecutableForm->getOnSchedule() << std::endl; |
| } |
| else if( onScheduleCode->nonempty() ) |
| { |
| anExecutableForm->setOnSchedule( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnSchedule(), |
| (onScheduleCode->singleton() ? |
| onScheduleCode->first().bfCode() : onScheduleCode) ) ); |
| } |
| else if( anExecutableForm->hasOneInstanceStatic() ) |
| { |
| anExecutableForm->setOnSchedule( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN, |
| anExecutableForm->firstInstanceStatic() ) ); |
| } |
| |
| /* |
| * ON_DISABLE |
| */ |
| if( anExecutableForm->hasOnDisable() ) |
| { |
| anExecutableForm->setOnDisable( |
| StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_CHILD), |
| anExecutableForm->getOnDisable() ) ); |
| } |
| else |
| { |
| anExecutableForm->setOnDisable( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_CHILD), |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_SELF) ) ); |
| } |
| } |
| |
| /* |
| * Compiling communication |
| */ |
| mComCompiler.compileCommunication(anExecutableForm, |
| hasUpdateBuffer, hasSynchronizeMachine); |
| |
| |
| /* |
| * OnRun |
| * whith high priority order |
| * |
| * StrongAbort Transition |
| * OnIRun |
| * ( Simple Transition or submachine ) depend on MOC |
| * WeakAbort Transition |
| * NormalTerminaison Transition |
| */ |
| |
| BFCode onRunProgram; |
| |
| // Update Buffer |
| if( anExecutableSpec->hasMachine() ) |
| { |
| if( hasSynchronizeMachine ) // only if has RDV protocol |
| { |
| anExecutableForm->setRdvCommunication( hasSynchronizeMachine ); |
| |
| setRdvScheduling( anExecutableForm ); |
| } |
| |
| if( anExecutableForm->hasOnRun() ) |
| { |
| onRunProgram = anExecutableForm->getOnRun(); |
| |
| if( AvmCodeFactory::contains(anExecutableForm, |
| onRunProgram, AVM_OPCODE_SCHEDULE_INVOKE) ) |
| { |
| //!!NOTHING |
| } |
| else if( (not anExecutableForm->hasOnRtc()) |
| && AvmCodeFactory::contains(anExecutableForm, |
| onRunProgram, AVM_OPCODE_RTC) ) |
| { |
| anExecutableForm->setOnRtc( |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE) ); |
| } |
| else |
| { |
| onRunProgram = StatementConstructor::newCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, onRunProgram, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE) ); |
| } |
| |
| anExecutableForm->setOnRun( BFCode::REF_NULL ); |
| } |
| else |
| { |
| onRunProgram = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SCHEDULE_INVOKE); |
| } |
| |
| if( hasUpdateBuffer ) // only if has BROADCAST protocol |
| { |
| onRunProgram = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_UPDATE_BUFFER, onRunProgram); |
| } |
| } |
| |
| if( anExecutableSpec->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm, onRunProgram); |
| } |
| else if( onRunProgram.valid() ) |
| { |
| anExecutableForm->setOnRun( onRunProgram ); |
| } |
| else if( anExecutableForm->hasOnIRun() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| |
| |
| //AVM_OS_TRACE << TAB << ">| compiling executable< moc: and >: " |
| // << str_header( anExecutableSpec ) << std::endl; |
| } |
| |
| |
| void Compiler::compilePseudostateEnding(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aStatemachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( false ); |
| |
| /* |
| * ON ENABLE |
| */ |
| BFCode onTerminalCode; |
| |
| if( aStatemachine->getSpecifier().isPseudostateTerminal() ) |
| { |
| onTerminalCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DESTROY, ExecutableLib::MACHINE_PARENT); |
| } |
| else //if( aStatemachine->getSpecifier().isPseudostateReturn() ) |
| { |
| onTerminalCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_FINAL); |
| } |
| |
| anExecutableForm->setOnEnable( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnEnable(), onTerminalCode) ); |
| |
| if( aStatemachine->hasOutgoingTransition() ) |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected state< terminal > << " |
| << str_header( aStatemachine ) |
| << " >> with outgoing transitions" |
| << std::endl << std::endl; |
| } |
| |
| //aStatemachine->toStream(AVM_OS_TRACE << TAB); |
| //anExecutableForm->toStream(AVM_OS_TRACE << TAB); |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| } |
| |
| |
| void Compiler::compileStatemachineHistory(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aStatemachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( false ); |
| |
| if( aStatemachine->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm , anExecutableForm->getOnRun()); |
| } |
| |
| BFCode onEnableCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN); |
| |
| BFCode onHistoryCode = StatementConstructor::newCode( |
| aStatemachine->getSpecifier().isPseudostateDeepHistory() ? |
| OperatorManager::OPERATOR_DEEP_HISTORY_INVOKE : |
| OperatorManager::OPERATOR_SHALLOW_HISTORY_INVOKE, |
| ExecutableLib::MACHINE_PARENT); |
| |
| if( anExecutableForm->hasOnRun() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_PRIOR_GT, |
| anExecutableForm->getOnRun(), onHistoryCode) ); |
| } |
| else if( anExecutableForm->hasOnIRun() ) |
| { |
| anExecutableForm->setOnRun( onHistoryCode ); |
| } |
| else |
| { |
| onEnableCode = onHistoryCode; |
| } |
| |
| |
| /* |
| * ON INIT |
| * ON ENABLE |
| */ |
| // this is aStatemachine->getSpecifier().isPseudostate() |
| // ON INIT |
| anExecutableForm->setOnInit( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnInit(), onEnableCode) ); |
| |
| // ON ENABLE |
| anExecutableForm->setOnEnable( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnEnable(), onEnableCode) ); |
| |
| //aStatemachine->toStream(AVM_OS_TRACE << TAB); |
| //anExecutableForm->toStream(AVM_OS_TRACE << TAB); |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| } |
| |
| |
| void Compiler::compileStatemachinePseudo(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aStatemachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( false ); |
| |
| /* |
| * ON INIT |
| * ON ENABLE |
| */ |
| BFCode onEnableCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN); |
| |
| // ON INIT |
| if( aStatemachine->getSpecifier().isPseudostateInitial() |
| && anExecutableForm->hasOnEnable() ) |
| { |
| anExecutableForm->setOnInit( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnInit(), |
| anExecutableForm->getOnEnable(), onEnableCode) ); |
| } |
| else |
| { |
| anExecutableForm->setOnInit( StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnInit(), onEnableCode) ); |
| } |
| |
| anExecutableForm->setOnEnable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnEnable(), onEnableCode) ); |
| |
| |
| |
| /* |
| * Schedule State Transition |
| */ |
| if( aStatemachine->getSpecifier().isPseudostateFork() ) |
| { |
| if( aStatemachine->hasOutgoingTransition() && |
| aStatemachine->getBehavior()-> |
| getOutgoingTransitions().populated() ) |
| { |
| // Schedule State< fork > Transition |
| mTransitionCompiler.compileStateForkOutputTransition( |
| anExecutableForm, anExecutableForm->getOnRun()); |
| } |
| else |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected pseudostate< fork > << " |
| << str_header( aStatemachine ) |
| << " >> with less than 2 outgoing transitions" |
| << std::endl << std::endl; |
| } |
| } |
| |
| else if( aStatemachine->getSpecifier().isPseudostateJoin() ) |
| { |
| if( aStatemachine->hasIncomingTransition() |
| && aStatemachine->getBehavior()-> |
| getIncomingTransitions().populated() ) |
| { |
| // SYnchronize incoming Transition |
| mTransitionCompiler.compileStateJoinInputTransition( |
| anExecutableForm ); |
| } |
| else |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected pseudostate< join > << " |
| << str_header( aStatemachine ) |
| << " >> with less than 2 incoming transitions" |
| << std::endl << std::endl; |
| } |
| |
| |
| if( aStatemachine->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm , anExecutableForm->getOnRun()); |
| } |
| else |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected pseudostate< join > << " |
| << str_header( aStatemachine ) |
| << " >> without outgoing transitions" |
| << std::endl << std::endl; |
| } |
| } |
| |
| |
| else if( aStatemachine->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm , anExecutableForm->getOnRun() ); |
| } |
| |
| |
| if( not anExecutableForm->hasOnRun() ) |
| { |
| if( not aStatemachine->getSpecifier().hasFamilyPseudostateENDING() ) |
| { |
| incrWarningCount(); |
| aStatemachine->warningLocation(AVM_OS_WARN) |
| << "No eval code for << " << str_header( aStatemachine ) |
| << " >> which is not TERMINAL or RETURN moc!" << std::endl; |
| } |
| else if( aStatemachine->getSpecifier().isPseudostateInitial() ) |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "No eval code for << " << str_header( aStatemachine ) |
| << " >> which is an INITIAL state!!!" << std::endl; |
| |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| AVM_OS_WARN << std::endl; |
| |
| if( anExecutableForm->hasOnIRun() ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| } |
| |
| //aStatemachine->toStream(AVM_OS_TRACE << TAB); |
| //anExecutableForm->toStream(AVM_OS_TRACE << TAB); |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| } |
| |
| |
| void Compiler::compileStatemachineBasic(ExecutableForm * anExecutableForm) |
| { |
| const Machine * aStatemachine = anExecutableForm->getAstMachine(); |
| |
| //AVM_OS_TRACE << TAB << "<| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| |
| // MOC Attribute for mutable Schedule |
| anExecutableForm->setMutableSchedule( false ); |
| |
| |
| // ON INIT |
| if( aStatemachine->getSpecifier().isStateStart() |
| && anExecutableForm->hasOnEnable() ) |
| { |
| anExecutableForm->setOnInit( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnInit(), |
| anExecutableForm->getOnEnable()) ); |
| } |
| |
| |
| /* |
| * Schedule State Transition |
| */ |
| if( aStatemachine->getSpecifier().isStateFinal() ) |
| { |
| anExecutableForm->setOnEnable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| anExecutableForm->getOnEnable(), |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_FINAL)) ); |
| |
| if( aStatemachine->hasOutgoingTransition() ) |
| { |
| incrErrorCount(); |
| aStatemachine->errorLocation(AVM_OS_WARN) |
| << "Unexpected state< final > << " |
| << str_header( aStatemachine ) |
| << " >> with outgoing transitions" |
| << std::endl << std::endl; |
| } |
| } |
| |
| |
| else if( aStatemachine->hasOutgoingTransition() ) |
| { |
| // Compile Statemachine Transition |
| mTransitionCompiler.compileStatemachineTransition( |
| anExecutableForm , anExecutableForm->getOnRun() ); |
| } |
| |
| if( aStatemachine->getSpecifier().isStateSync() ) |
| { |
| Variable * aVar = new Variable( |
| const_cast< Machine * >( aStatemachine ), |
| Modifier::PROPERTY_PUBLIC_VOLATILE_MODIFIER, |
| TypeManager::INTEGER, |
| aStatemachine->getNameID() + "#syncVar" ); |
| |
| const_cast< Machine * >( aStatemachine )-> |
| getPropertyPart().saveOwnedVariable( aVar ); |
| |
| InstanceOfData * syncInstance = new InstanceOfData( |
| IPointerDataNature::POINTER_STANDARD_NATURE, |
| anExecutableForm, aVar, TypeManager::INTEGER, |
| anExecutableForm->getDataSize(), |
| Modifier::PROPERTY_PUBLIC_VOLATILE_MODIFIER); |
| //!![MIGRATION]:MODIFIER |
| // Modifier::PROPERTY_VOLATILE_FEATURE); |
| syncInstance->setValue( ExpressionConstant::INTEGER_ZERO ); |
| |
| const BF & syncVar = anExecutableForm->saveData(syncInstance); |
| |
| |
| BFCode incrSyncVar = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ASSIGN, syncVar, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_PLUS, syncVar, |
| ExpressionConstant::INTEGER_ONE) ); |
| |
| anExecutableForm->setOnEnable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| anExecutableForm->getOnEnable(), incrSyncVar) ); |
| |
| |
| BFCode decrSyncVar = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ASSIGN, syncVar, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_PLUS, syncVar, |
| ExpressionConstant::INTEGER_MINUS_ONE) ); |
| |
| anExecutableForm->setOnDisable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_ATOMIC_SEQUENCE, |
| anExecutableForm->getOnDisable(), decrSyncVar) ); |
| |
| |
| BFCode guardSyncVar = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_GUARD, |
| StatementConstructor::newCode( |
| OperatorManager::OPERATOR_GT, syncVar, |
| ExpressionConstant::INTEGER_ZERO) ); |
| |
| anExecutableForm->setOnRun( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| guardSyncVar, anExecutableForm->getOnRun()) ); |
| } |
| |
| |
| if( anExecutableForm->hasOnIRun() |
| && (not anExecutableForm->hasOnRun()) ) |
| { |
| anExecutableForm->setOnRun( StatementConstructor::nopCode() ); |
| } |
| |
| if( (not anExecutableForm->hasOnRun()) |
| && (not aStatemachine->getSpecifier().isStateFinal()) ) |
| { |
| incrWarningCount(); |
| aStatemachine->warningLocation(AVM_OS_WARN) |
| << "No eval code for << " << str_header( aStatemachine ) |
| << " >> which is not FINAL!" |
| << std::endl << std::endl; |
| } |
| |
| //aStatemachine->toStream(AVM_OS_TRACE << TAB); |
| //anExecutableForm->toStream(AVM_OS_TRACE << TAB); |
| //AVM_OS_TRACE << TAB << ">| compiling<statemachine>: " |
| // << str_header( aStatemachine ) << std::endl; |
| } |
| |
| |
| /** |
| * compile |
| * statemachine input_enabled |
| */ |
| |
| void Compiler::removeSubmachineInputEnabledCode( |
| ExecutableForm * anExecutableForm) |
| { |
| if( anExecutableForm->hasInstanceStatic() ) |
| { |
| TableOfSymbol::const_iterator itMachine = |
| anExecutableForm->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| anExecutableForm->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| if( (*itMachine).machine(). |
| getSpecifier().isDesignPrototypeStatic() |
| && (*itMachine).getExecutable()->hasOnRun() ) |
| { |
| if( (*itMachine).getExecutable()-> |
| getOnRun()->isOpCode( AVM_OPCODE_INPUT_ENABLED ) ) |
| { |
| BFCode newCode = (*itMachine).getExecutable()-> |
| getOnRun()->first().bfCode(); |
| (*itMachine).getExecutable()->setOnRun( newCode ); |
| } |
| |
| removeSubmachineInputEnabledCode( |
| (*itMachine).getExecutable() ); |
| } |
| } |
| } |
| } |
| |
| |
| void Compiler::computeInputEnabledCom(ExecutableForm * anExecutableForm) |
| { |
| AVM_OS_ASSERT_FATAL_ERROR_EXIT( |
| anExecutableForm->getSpecifier().hasFeatureInputEnabled() ) |
| << "Unexpected a non INPUT_ENABLED Executable !!!" |
| << SEND_EXIT; |
| |
| // input enabled running code |
| CommunicationDependency::computeInputEnabledCom( |
| anExecutableForm, anExecutableForm->getOnRun() ); |
| |
| if( anExecutableForm->getSpecifier().isState() ) |
| { |
| computeInputEnabledBuffer( anExecutableForm ); |
| |
| if( anExecutableForm->getInputEnabledBuffer().populated() ) |
| { |
| incrErrorCount(); |
| anExecutableForm->getAstMachine()->errorLocation(AVM_OS_WARN) |
| << "InputEnabled:> NO SUPPORT for multiple buffer " |
| "at runtime for << " |
| << str_header( anExecutableForm->getAstMachine() ) |
| << " >> !" << std::endl; |
| |
| AVM_OS_FATAL_ERROR_EXIT << "Expect the Future !!!" << SEND_EXIT; |
| } |
| else if( anExecutableForm->getInputEnabledBuffer().empty() ) |
| { |
| incrErrorCount(); |
| anExecutableForm->getAstMachine()->errorLocation(AVM_OS_WARN) |
| << "InputEnabled:> Unfound runtime buffer for << " |
| << str_header( anExecutableForm->getAstMachine() ) |
| << " >> !" << std::endl; |
| } |
| |
| if( anExecutableForm->hasContainer() && |
| anExecutableForm->getExecutableContainer()->hasTransition() ) |
| { |
| //!! NOTHING |
| } |
| else |
| { |
| anExecutableForm->setOnRun( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_INPUT_ENABLED, |
| anExecutableForm->getOnRun() )); |
| |
| removeSubmachineInputEnabledCode( anExecutableForm ); |
| } |
| } |
| } |
| |
| |
| void Compiler::computeInputEnabledBuffer(ExecutableForm * anExecutableForm) |
| { |
| for( ExecutableForm * tmpExec = anExecutableForm ; tmpExec != NULL ; |
| tmpExec = tmpExec->getExecutableContainer() ) |
| { |
| if( tmpExec->hasBuffer() ) |
| { |
| const TableOfSymbol & bufferTable = tmpExec->getBuffer(); |
| for( avm_size_t offset = 0 ; offset < bufferTable.size() ; ++offset ) |
| { |
| anExecutableForm->addInputEnabledBuffer( |
| bufferTable[ offset ].rawBuffer()); |
| } |
| return; |
| } |
| |
| if( tmpExec->hasRouter4This() ) |
| { |
| return; |
| } |
| |
| if( tmpExec->hasRouter4Instance() ) |
| { |
| return; |
| } |
| |
| if( tmpExec->hasRouter4Model() ) |
| { |
| return; |
| } |
| } |
| } |
| |
| |
| /** |
| * compile statemachine |
| * initialization |
| * enabling |
| * scheduling |
| */ |
| void Compiler::compileAllBehavioralRoutines(ExecutableForm * theExecutable) |
| { |
| const Machine * aMachine = theExecutable->getAstMachine(); |
| |
| if( aMachine->hasMachine() ) |
| { |
| //compiling initialization |
| compileBehaviorInitialization(theExecutable); |
| |
| //compiling scheduler |
| compileBehaviorScheduling(theExecutable); |
| |
| //enabling |
| compileBehaviorEnabling(theExecutable); |
| |
| //disabling |
| compileBehaviorDisabling(theExecutable); |
| |
| //aborting |
| compileBehaviorAborting(theExecutable); |
| } |
| } |
| |
| |
| |
| void Compiler::compileBehaviorInitialization(ExecutableForm * theExecutable) |
| { |
| BFCodeList listOfCode; |
| |
| ListOfInstanceOfMachine usedInstance; |
| if( theExecutable->hasOnInit() ) |
| { |
| StatementFactory::collectActivityMachine( |
| theExecutable, AVM_OPCODE_INIT, AVM_OPCODE_START, |
| theExecutable->getOnInit(), usedInstance); |
| } |
| |
| TableOfSymbol::const_iterator itMachine = |
| theExecutable->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| theExecutable->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| if( (*itMachine).getExecutable()->isSchedulable() |
| && (*itMachine).machine().isAutoStart() |
| && (not usedInstance.contains( (*itMachine).rawMachine() )) ) |
| { |
| listOfCode.append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_INIT, (*itMachine)) ); |
| } |
| } |
| |
| /** |
| * Optimisization |
| */ |
| BFCode onInitCode; |
| if( listOfCode.populated() ) |
| { |
| onInitCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_STRONG_SYNCHRONOUS, listOfCode); |
| } |
| else if( listOfCode.nonempty() ) |
| { |
| onInitCode = listOfCode.first(); |
| } |
| else if( not theExecutable->hasOnInit() ) |
| { |
| // incrWarningCount(); |
| theExecutable->getAstElement()->warningLocation(AVM_OS_LOG) |
| << "Unfound InstanceStatic for onInit code compilation " |
| "of composite machine << " |
| << theExecutable->getAstElement()->getFullyQualifiedNameID() |
| << " >>" << std::endl << std::endl; |
| } |
| |
| if( onInitCode.valid() ) |
| { |
| theExecutable->setOnInit( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| theExecutable->getOnInit(), onInitCode) ); |
| } |
| |
| // onSTART |
| theExecutable->setOnStart( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| theExecutable->getOnStart(), |
| theExecutable->getOnInit()) ); |
| } |
| |
| |
| void Compiler::compileBehaviorEnabling(ExecutableForm * theExecutable) |
| { |
| BFCodeList listOfCode; |
| |
| ListOfInstanceOfMachine usedInstance; |
| if( theExecutable->hasOnEnable() ) |
| { |
| StatementFactory::collectActivityMachine( |
| theExecutable, AVM_OPCODE_ENABLE_INVOKE, |
| theExecutable->getOnEnable(), usedInstance); |
| } |
| |
| TableOfSymbol::const_iterator itMachine = |
| theExecutable->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| theExecutable->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| if( ( (*itMachine).getExecutable()->hasOnInit() |
| || (*itMachine).getExecutable()->hasOnRun() |
| || (*itMachine).getExecutable()->hasOnEnable() ) |
| && (*itMachine).machine().isAutoStart() |
| && (not usedInstance.contains( (*itMachine).rawMachine() )) ) |
| { |
| listOfCode.append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ENABLE_INVOKE, (*itMachine)) ); |
| } |
| } |
| |
| /** |
| * Optimisization |
| */ |
| BFCode onEnableCode; |
| if( listOfCode.populated() ) |
| { |
| onEnableCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_STRONG_SYNCHRONOUS, listOfCode); |
| } |
| else if( listOfCode.nonempty() ) |
| { |
| onEnableCode = listOfCode.first(); |
| } |
| else if( not theExecutable->hasOnInit() ) |
| { |
| // incrWarningCount(); |
| theExecutable->getAstElement()->warningLocation(AVM_OS_LOG) |
| << "Unfound InstanceStatic for onEnable code compilation " |
| "of composite machine << " |
| << theExecutable->getAstElement()->getFullyQualifiedNameID() |
| << " >>" << std::endl << std::endl; |
| } |
| |
| if( onEnableCode.valid() ) |
| { |
| theExecutable->setOnEnable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| theExecutable->getOnEnable(), onEnableCode) ); |
| } |
| } |
| |
| |
| void Compiler::compileBehaviorDisabling(ExecutableForm * theExecutable) |
| { |
| BFCodeList listOfCode; |
| |
| ListOfInstanceOfMachine usedInstance; |
| if( theExecutable->hasOnDisable() ) |
| { |
| StatementFactory::collectActivityMachine( |
| theExecutable, AVM_OPCODE_DISABLE_INVOKE, |
| theExecutable->getOnDisable(), usedInstance); |
| } |
| |
| TableOfSymbol::const_iterator itMachine = |
| theExecutable->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| theExecutable->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| if( (*itMachine).machine().isAutoStart() |
| && (not usedInstance.contains( (*itMachine).rawMachine() )) ) |
| { |
| listOfCode.append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_DISABLE_INVOKE, (*itMachine)) ); |
| } |
| } |
| |
| /** |
| * Optimisization |
| */ |
| BFCode onDisableCode; |
| if( listOfCode.populated() ) |
| { |
| onDisableCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_STRONG_SYNCHRONOUS, listOfCode); |
| } |
| else if( listOfCode.nonempty() ) |
| { |
| onDisableCode = listOfCode.first(); |
| } |
| |
| if( onDisableCode.valid() ) |
| { |
| theExecutable->setOnDisable( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| onDisableCode, theExecutable->getOnDisable()) ); |
| } |
| } |
| |
| |
| void Compiler::compileBehaviorAborting(ExecutableForm * theExecutable) |
| { |
| BFCodeList listOfCode; |
| |
| ListOfInstanceOfMachine usedInstance; |
| if( theExecutable->hasOnAbort() ) |
| { |
| StatementFactory::collectActivityMachine( |
| theExecutable, AVM_OPCODE_ABORT_INVOKE, |
| theExecutable->getOnAbort(), usedInstance); |
| } |
| |
| TableOfSymbol::const_iterator itMachine = |
| theExecutable->instance_static_begin(); |
| TableOfSymbol::const_iterator endMachine = |
| theExecutable->instance_static_end(); |
| for( ; itMachine != endMachine ; ++itMachine ) |
| { |
| if( (*itMachine).machine().isAutoStart() |
| && (not usedInstance.contains( (*itMachine).rawMachine() )) ) |
| { |
| listOfCode.append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_ABORT_INVOKE, (*itMachine)) ); |
| } |
| } |
| |
| /** |
| * Optimisization |
| */ |
| BFCode onAbortCode; |
| if( listOfCode.populated() ) |
| { |
| onAbortCode = StatementConstructor::newCode( |
| OperatorManager::OPERATOR_STRONG_SYNCHRONOUS, listOfCode); |
| } |
| else if( listOfCode.nonempty() ) |
| { |
| onAbortCode = listOfCode.first(); |
| } |
| |
| if( onAbortCode.valid() ) |
| { |
| theExecutable->setOnAbort( |
| StatementConstructor::xnewCodeFlat( |
| OperatorManager::OPERATOR_SEQUENCE, |
| onAbortCode, theExecutable->getOnAbort()) ); |
| } |
| } |
| |
| |
| void Compiler::compileBehaviorScheduling(ExecutableForm * theExecutable) |
| { |
| ListOfInstanceOfMachine usedInstance; |
| Operator * defaultConcurrencyOp = NULL; |
| BFCode userScheduler; |
| |
| // INIT STEP |
| // Collect unscheduled submachines |
| // get default concurrency policy |
| if( theExecutable->hasOnRun() ) |
| { |
| StatementFactory::collectRunMachine( |
| theExecutable, theExecutable->getOnRun(), usedInstance); |
| } |
| |
| if( theExecutable->hasOnSchedule() ) |
| { |
| userScheduler = theExecutable->getOnSchedule(); |
| |
| if( userScheduler->empty() ) |
| { |
| defaultConcurrencyOp = userScheduler->getOperator(); |
| theExecutable->setOnSchedule( userScheduler = BFCode::REF_NULL ); |
| } |
| else |
| { |
| if( OperatorManager::isSchedule( userScheduler->getOperator() ) ) |
| { |
| defaultConcurrencyOp = userScheduler->getOperator(); |
| } |
| |
| StatementFactory::collectRunMachine( |
| theExecutable, userScheduler, usedInstance); |
| } |
| } |
| |
| if( theExecutable->hasOnConcurrency() ) |
| { |
| defaultConcurrencyOp = theExecutable->getOnConcurrencyOperator(); |
| } |
| else |
| { |
| if( defaultConcurrencyOp == NULL ) |
| { |
| defaultConcurrencyOp = OperatorManager::OPERATOR_INTERLEAVING; |
| } |
| |
| theExecutable->setOnConcurrency( |
| StatementConstructor::newCode(defaultConcurrencyOp) ); |
| } |
| |
| // STEP case for singleton submachine |
| if( usedInstance.empty() |
| && theExecutable->hasOneInstanceStatic() |
| && theExecutable->hasOneInstanceModel() ) |
| { |
| BFCode runMachineCode(OperatorManager::OPERATOR_RUN, |
| theExecutable->getInstanceStatic().last()); |
| |
| if( userScheduler.valid() ) |
| { |
| if( userScheduler->isOperator( defaultConcurrencyOp ) ) |
| { |
| userScheduler->append( runMachineCode ); |
| } |
| else |
| { |
| userScheduler = StatementConstructor::newCode( |
| defaultConcurrencyOp, userScheduler, runMachineCode ); |
| } |
| |
| theExecutable->setOnSchedule( userScheduler ); |
| } |
| else |
| { |
| theExecutable->setOnSchedule( runMachineCode ); |
| } |
| } |
| |
| // STEP case for many submachines |
| else if( usedInstance.size() < (theExecutable->sizeInstanceStatic() |
| + theExecutable->sizeInstanceModel()) ) |
| { |
| BFCode aScheduleCode; |
| |
| if( userScheduler.valid() ) |
| { |
| aScheduleCode = compileSchedulerRoutine( |
| theExecutable, usedInstance, userScheduler); |
| |
| if( aScheduleCode->isnotOperator( defaultConcurrencyOp ) ) |
| { |
| aScheduleCode = StatementConstructor::newCode( |
| defaultConcurrencyOp, aScheduleCode ); |
| } |
| } |
| else |
| { |
| userScheduler = aScheduleCode = |
| StatementConstructor::newCode( defaultConcurrencyOp ); |
| } |
| |
| TableOfSymbol::const_iterator itInstance = |
| theExecutable->instance_static_begin(); |
| TableOfSymbol::const_iterator endInstance = |
| theExecutable->instance_static_end(); |
| for( ; itInstance != endInstance ; ++itInstance ) |
| { |
| if( (*itInstance).getExecutable()->isSchedulable() |
| && (not usedInstance.contains((*itInstance).rawMachine())) ) |
| { |
| aScheduleCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN, (*itInstance)) ); |
| } |
| } |
| |
| itInstance = theExecutable->instance_model_begin(); |
| endInstance = theExecutable->instance_model_end(); |
| for( ; itInstance != endInstance ; ++itInstance ) |
| { |
| if( (*itInstance).machine().hasPossibleDynamicInstanciation() |
| && (*itInstance).getExecutable()->isSchedulable() |
| && (not usedInstance.contains((*itInstance).rawMachine())) ) |
| { |
| aScheduleCode->append( StatementConstructor::newCode( |
| OperatorManager::OPERATOR_RUN, (*itInstance)) ); |
| } |
| } |
| |
| if( aScheduleCode->singleton() ) |
| { |
| aScheduleCode->pop_last_to( userScheduler ); |
| |
| if( userScheduler.valid() ) |
| { |
| theExecutable->setOnSchedule( userScheduler ); |
| } |
| } |
| else |
| { |
| theExecutable->setOnSchedule( aScheduleCode ); |
| } |
| } |
| else if( userScheduler.valid() ) |
| { |
| theExecutable->setOnSchedule( compileSchedulerRoutine( |
| theExecutable, usedInstance, userScheduler) ); |
| } |
| } |
| |
| |
| void Compiler::setRdvScheduling(ExecutableForm * theExecutable) |
| { |
| AVM_OS_ASSERT_FATAL_ERROR_EXIT( theExecutable->hasRdvCommunication() ) |
| << "Unexpected Executable without RDV comunication !!!" |
| << SEND_EXIT; |
| |
| |
| BFCode & aScheduleCode = theExecutable->getOnSchedule(); |
| switch( aScheduleCode.getAvmOpCode() ) |
| { |
| case AVM_OPCODE_ASYNCHRONOUS: |
| { |
| aScheduleCode.setOperator( |
| OperatorManager::OPERATOR_RDV_ASYNCHRONOUS ); |
| break; |
| } |
| |
| case AVM_OPCODE_STRONG_SYNCHRONOUS: |
| { |
| aScheduleCode.setOperator( |
| OperatorManager::OPERATOR_RDV_STRONG_SYNCHRONOUS ); |
| break; |
| } |
| |
| case AVM_OPCODE_WEAK_SYNCHRONOUS: |
| { |
| aScheduleCode.setOperator( |
| OperatorManager::OPERATOR_RDV_WEAK_SYNCHRONOUS ); |
| break; |
| } |
| |
| case AVM_OPCODE_INTERLEAVING: |
| { |
| aScheduleCode.setOperator( |
| OperatorManager::OPERATOR_RDV_INTERLEAVING ); |
| break; |
| } |
| |
| case AVM_OPCODE_PARALLEL: |
| { |
| aScheduleCode.setOperator( |
| OperatorManager::OPERATOR_RDV_PARALLEL ); |
| break; |
| } |
| |
| default: |
| { |
| theExecutable->setOnSchedule(StatementConstructor::newCode( |
| OperatorManager::OPERATOR_SYNCHRONIZE, aScheduleCode)); |
| break; |
| } |
| } |
| } |
| |
| |
| } |