From b55690aca6ad5d17e699e809af481d1ffd04191e Mon Sep 17 00:00:00 2001 From: Henrik Rentz-Reichert Date: Thu, 2 Feb 2012 10:42:09 +0100 Subject: [core.room, generator, ui.behavior] communication model for protocols --- .../etrice/generator/c/gen/ActorClassGen.xtend | 376 +++++++-------- .../etrice/generator/c/gen/StateMachineGen.xtend | 516 ++++++++++----------- 2 files changed, 446 insertions(+), 446 deletions(-) (limited to 'plugins/org.eclipse.etrice.generator.c/src/org/eclipse') diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend index 44fe509a8..5a19bfc60 100644 --- a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/ActorClassGen.xtend @@ -1,189 +1,189 @@ -/******************************************************************************* - * Copyright (c) 2011 protos software gmbh (http://www.protos.de). - * 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: - * Henrik Rentz-Reichert (initial contribution) - * Thomas Schuetz (changed for C code generator) - * - *******************************************************************************/ - -package org.eclipse.etrice.generator.c.gen - -import com.google.inject.Inject -import com.google.inject.Singleton -import org.eclipse.etrice.core.room.ActorClass -import org.eclipse.etrice.core.room.Message -import org.eclipse.etrice.generator.base.ILogger -import org.eclipse.etrice.generator.etricegen.ExpandedActorClass -import org.eclipse.etrice.generator.etricegen.Root -import org.eclipse.xtext.generator.JavaIoFileSystemAccess - -import org.eclipse.etrice.generator.extensions.RoomExtensions -import org.eclipse.etrice.generator.generic.ProcedureHelpers -import org.eclipse.etrice.generator.generic.TypeHelpers - - -@Singleton -class ActorClassGen { - - @Inject extension JavaIoFileSystemAccess fileAccess - @Inject extension CExtensions stdExt - @Inject extension RoomExtensions roomExt - - @Inject extension ProcedureHelpers helpers - @Inject extension TypeHelpers - @Inject extension StateMachineGen stateMachineGen - @Inject ILogger logger - - def doGenerate(Root root) { - for (xpac: root.xpActorClasses) { - var path = xpac.actorClass.generationTargetPath+xpac.actorClass.getPath - - // header file - logger.logInfo("generating ActorClass header '"+xpac.actorClass.getCHeaderFileName+"' in '"+path+"'") - fileAccess.setOutputPath(path) - fileAccess.generateFile(xpac.actorClass.getCHeaderFileName, root.generateHeaderFile(xpac, xpac.actorClass)) - - // header file - logger.logInfo("generating ActorClass header '"+xpac.actorClass.getCSourceFileName +"' in '"+path+"'") - fileAccess.setOutputPath(path) - fileAccess.generateFile(xpac.actorClass.getCSourceFileName , root.generateSourceFile(xpac, xpac.actorClass)) - } - } - - def generateHeaderFile(Root root, ExpandedActorClass xpac, ActorClass ac) {''' - #ifndef _«xpac.name»_H_ - #define _«xpac.name»_H_ - - #include "etDatatypes.h" - - package «ac.getPackage»; - -««« import org.eclipse.etrice.runtime.java.messaging.Address; -««« import org.eclipse.etrice.runtime.java.messaging.IRTObject; -««« import org.eclipse.etrice.runtime.java.messaging.IMessageReceiver; -««« import org.eclipse.etrice.runtime.java.modelbase.ActorClassBase; -««« import org.eclipse.etrice.runtime.java.modelbase.SubSystemClassBase; -««« import org.eclipse.etrice.runtime.java.modelbase.InterfaceItemBase; -««« import org.eclipse.etrice.runtime.java.debugging.DebuggingService; - - - «FOR dataClass : root.getReferencedDataClasses(ac)»#include "«dataClass.name».h" - «ENDFOR» - - «FOR pc : root.getReferencedProtocolClasses(ac)»#include "«pc.name».h" - «ENDFOR» - - «helpers.UserCode(ac.userCode1)» - - - public «IF ac.abstract»abstract «ENDIF»class «ac.name» extends «IF ac.base!=null»«ac.base.name»«ELSE»ActorClassBase«ENDIF» { - - «helpers.UserCode(ac.userCode2)» - - //--------------------- ports - «FOR ep : ac.getEndPorts()» - protected «ep.getPortClassName()» «ep.name» = null; - «ENDFOR» - //--------------------- saps - «FOR sap : ac.strSAPs» - protected «sap.getPortClassName()» «sap.name» = null; - «ENDFOR» - //--------------------- services - «FOR svc : ac.serviceImplementations» - protected «svc.getPortClassName()» «svc.spp.name» = null; - «ENDFOR» - - //--------------------- interface item IDs - «FOR ep : ac.getEndPorts()» - protected static final int IFITEM_«ep.name» = «xpac.getInterfaceItemLocalId(ep)+1»; - «ENDFOR» - «FOR sap : ac.strSAPs» - protected static final int IFITEM_«sap.name» = «xpac.getInterfaceItemLocalId(sap)+1»; - «ENDFOR» - «FOR svc : ac.serviceImplementations» - protected static final int IFITEM_«svc.spp.name» = «xpac.getInterfaceItemLocalId(svc.spp)+1»; - «ENDFOR» - - «helpers.Attributes(ac.attributes)» - «helpers.OperationsDeclaration(ac.operations, ac.name)» - - //--------------------- construction - public «ac.name»(IRTObject parent, String name, Address[][] port_addr, Address[][] peer_addr){ - «IF ac.base==null» - super(parent, name, port_addr[0][0], peer_addr[0][0]); - «ELSE» - super(parent, name, port_addr, peer_addr); - «ENDIF» - setClassName("«ac.name»"); - - «ac.attributes.attributeInitialization» - - // own ports - «FOR ep : ac.getEndPorts()» - «ep.name» = new «ep.getPortClassName()»(this, "«ep.name»", IFITEM_«ep.name», «IF ep.multiplicity==1»0, «ENDIF»port_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF», peer_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF»); - «ENDFOR» - // own saps - «FOR sap : ac.strSAPs» - «sap.name» = new «sap.getPortClassName()»(this, "«sap.name»", IFITEM_«sap.name», 0, port_addr[IFITEM_«sap.name»][0], peer_addr[IFITEM_«sap.name»][0]); - «ENDFOR» - // own service implementations - «FOR svc : ac.serviceImplementations» - «svc.spp.name» = new «svc.getPortClassName()»(this, "«svc.spp.name»", IFITEM_«svc.spp.name», port_addr[IFITEM_«svc.spp.name»], peer_addr[IFITEM_«svc.spp.name»]); - «ENDFOR» - } - - - //--------------------- lifecycle functions - public void init(){ - initUser(); - } - - public void start(){ - startUser(); - } - - «IF !ac.overridesStop()» - public void stop(){ - stopUser(); - } - «ENDIF» - - public void destroy(){ - destroyUser(); - } - - «IF ac.stateMachine != null» - «stateMachineGen.genStateMachine(xpac, ac)» - «ELSEIF !xpac.hasStateMachine()» - //--------------------- no state machine - @Override - public void receiveEvent(InterfaceItemBase ifitem, int evt, Object data) { - handleSystemEvent(ifitem, evt, data); - } - - @Override - public void executeInitTransition(){ - } - «ENDIF» - }; - - #endif /* _«xpac.name»_H_ */ - - ''' - } - - def generateSourceFile(Root root, ExpandedActorClass xpac, ActorClass ac) {''' - #include "«xpac.getCHeaderFileName»" - - ''' - } - - def msgArgs(Message msg) { - '''«IF msg.data!=null»«msg.data.defaultValue()»«ENDIF»''' - } +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * 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: + * Henrik Rentz-Reichert (initial contribution) + * Thomas Schuetz (changed for C code generator) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import org.eclipse.etrice.core.room.ActorClass +import org.eclipse.etrice.core.room.Message +import org.eclipse.etrice.generator.base.ILogger +import org.eclipse.etrice.generator.etricegen.ExpandedActorClass +import org.eclipse.etrice.generator.etricegen.Root +import org.eclipse.xtext.generator.JavaIoFileSystemAccess + +import org.eclipse.etrice.generator.extensions.RoomExtensions +import org.eclipse.etrice.generator.generic.ProcedureHelpers +import org.eclipse.etrice.generator.generic.TypeHelpers + + +@Singleton +class ActorClassGen { + + @Inject extension JavaIoFileSystemAccess fileAccess + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + + @Inject extension ProcedureHelpers helpers + @Inject extension TypeHelpers + @Inject extension StateMachineGen stateMachineGen + @Inject ILogger logger + + def doGenerate(Root root) { + for (xpac: root.xpActorClasses) { + var path = xpac.actorClass.generationTargetPath+xpac.actorClass.getPath + + // header file + logger.logInfo("generating ActorClass header '"+xpac.actorClass.getCHeaderFileName+"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(xpac.actorClass.getCHeaderFileName, root.generateHeaderFile(xpac, xpac.actorClass)) + + // header file + logger.logInfo("generating ActorClass header '"+xpac.actorClass.getCSourceFileName +"' in '"+path+"'") + fileAccess.setOutputPath(path) + fileAccess.generateFile(xpac.actorClass.getCSourceFileName , root.generateSourceFile(xpac, xpac.actorClass)) + } + } + + def generateHeaderFile(Root root, ExpandedActorClass xpac, ActorClass ac) {''' + #ifndef _«xpac.name»_H_ + #define _«xpac.name»_H_ + + #include "etDatatypes.h" + + package «ac.getPackage»; + +««« import org.eclipse.etrice.runtime.java.messaging.Address; +««« import org.eclipse.etrice.runtime.java.messaging.IRTObject; +««« import org.eclipse.etrice.runtime.java.messaging.IMessageReceiver; +««« import org.eclipse.etrice.runtime.java.modelbase.ActorClassBase; +««« import org.eclipse.etrice.runtime.java.modelbase.SubSystemClassBase; +««« import org.eclipse.etrice.runtime.java.modelbase.InterfaceItemBase; +««« import org.eclipse.etrice.runtime.java.debugging.DebuggingService; + + + «FOR dataClass : root.getReferencedDataClasses(ac)»#include "«dataClass.name».h" + «ENDFOR» + + «FOR pc : root.getReferencedProtocolClasses(ac)»#include "«pc.name».h" + «ENDFOR» + + «helpers.UserCode(ac.userCode1)» + + + public «IF ac.abstract»abstract «ENDIF»class «ac.name» extends «IF ac.base!=null»«ac.base.name»«ELSE»ActorClassBase«ENDIF» { + + «helpers.UserCode(ac.userCode2)» + + //--------------------- ports + «FOR ep : ac.getEndPorts()» + protected «ep.getPortClassName()» «ep.name» = null; + «ENDFOR» + //--------------------- saps + «FOR sap : ac.strSAPs» + protected «sap.getPortClassName()» «sap.name» = null; + «ENDFOR» + //--------------------- services + «FOR svc : ac.serviceImplementations» + protected «svc.getPortClassName()» «svc.spp.name» = null; + «ENDFOR» + + //--------------------- interface item IDs + «FOR ep : ac.getEndPorts()» + protected static final int IFITEM_«ep.name» = «xpac.getInterfaceItemLocalId(ep)+1»; + «ENDFOR» + «FOR sap : ac.strSAPs» + protected static final int IFITEM_«sap.name» = «xpac.getInterfaceItemLocalId(sap)+1»; + «ENDFOR» + «FOR svc : ac.serviceImplementations» + protected static final int IFITEM_«svc.spp.name» = «xpac.getInterfaceItemLocalId(svc.spp)+1»; + «ENDFOR» + + «helpers.Attributes(ac.attributes)» + «helpers.OperationsDeclaration(ac.operations, ac.name)» + + //--------------------- construction + public «ac.name»(IRTObject parent, String name, Address[][] port_addr, Address[][] peer_addr){ + «IF ac.base==null» + super(parent, name, port_addr[0][0], peer_addr[0][0]); + «ELSE» + super(parent, name, port_addr, peer_addr); + «ENDIF» + setClassName("«ac.name»"); + + «ac.attributes.attributeInitialization» + + // own ports + «FOR ep : ac.getEndPorts()» + «ep.name» = new «ep.getPortClassName()»(this, "«ep.name»", IFITEM_«ep.name», «IF ep.multiplicity==1»0, «ENDIF»port_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF», peer_addr[IFITEM_«ep.name»]«IF ep.multiplicity==1»[0]«ENDIF»); + «ENDFOR» + // own saps + «FOR sap : ac.strSAPs» + «sap.name» = new «sap.getPortClassName()»(this, "«sap.name»", IFITEM_«sap.name», 0, port_addr[IFITEM_«sap.name»][0], peer_addr[IFITEM_«sap.name»][0]); + «ENDFOR» + // own service implementations + «FOR svc : ac.serviceImplementations» + «svc.spp.name» = new «svc.getPortClassName()»(this, "«svc.spp.name»", IFITEM_«svc.spp.name», port_addr[IFITEM_«svc.spp.name»], peer_addr[IFITEM_«svc.spp.name»]); + «ENDFOR» + } + + + //--------------------- lifecycle functions + public void init(){ + initUser(); + } + + public void start(){ + startUser(); + } + + «IF !ac.overridesStop()» + public void stop(){ + stopUser(); + } + «ENDIF» + + public void destroy(){ + destroyUser(); + } + + «IF ac.stateMachine != null» + «stateMachineGen.genStateMachine(xpac, ac)» + «ELSEIF !xpac.hasStateMachine()» + //--------------------- no state machine + @Override + public void receiveEvent(InterfaceItemBase ifitem, int evt, Object data) { + handleSystemEvent(ifitem, evt, data); + } + + @Override + public void executeInitTransition(){ + } + «ENDIF» + }; + + #endif /* _«xpac.name»_H_ */ + + ''' + } + + def generateSourceFile(Root root, ExpandedActorClass xpac, ActorClass ac) {''' + #include "«xpac.getCHeaderFileName»" + + ''' + } + + def msgArgs(Message msg) { + '''«IF msg.data!=null»«msg.data.defaultValue()»«ENDIF»''' + } } \ No newline at end of file diff --git a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend index 44fdc9e43..d5d802277 100644 --- a/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend +++ b/plugins/org.eclipse.etrice.generator.c/src/org/eclipse/etrice/generator/c/gen/StateMachineGen.xtend @@ -1,258 +1,258 @@ -/******************************************************************************* - * Copyright (c) 2011 protos software gmbh (http://www.protos.de). - * 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: - * Henrik Rentz-Reichert (initial contribution) - * - *******************************************************************************/ - -package org.eclipse.etrice.generator.c.gen - -import com.google.inject.Inject -import com.google.inject.Singleton -import java.util.List -import org.eclipse.etrice.core.room.ActorClass -import org.eclipse.etrice.core.room.NonInitialTransition -import org.eclipse.etrice.core.room.Transition -import org.eclipse.etrice.core.room.TriggeredTransition -import org.eclipse.etrice.generator.etricegen.ExpandedActorClass -import org.eclipse.etrice.generator.etricegen.TransitionChain -import static extension org.eclipse.etrice.generator.extensions.RoomNameProv.* -import org.eclipse.etrice.generator.extensions.RoomExtensions -import org.eclipse.etrice.generator.generic.LanguageGenerator - - -@Singleton -class StateMachineGen { - - @Inject extension CExtensions stdExt - @Inject extension RoomExtensions roomExt - @Inject LanguageGenerator languageGen - - def genStateMachine(ExpandedActorClass xpac, ActorClass ac) {''' - //****************************************** - // START of generated code for FSM - //****************************************** - - // State IDs for FSM - «var offset = ac.getNumberOfInheritedBaseStates()» - «var baseStates = ac.stateMachine.getBaseStateList()» - «FOR state : baseStates» - protected static final int «state.getStateId()» = «baseStates.indexOf(state)+2+offset»; - «ENDFOR» - protected static final String stateStrings[] = {"","",«FOR state : ac.getAllBaseStates() SEPARATOR ","»"«state.getStatePathName()»" - «ENDFOR»}; - - // history - // TODOHRR: history defined in ActorClassBase, init in constructor - // history = new int[5]; - // for (int i = 0; i < history.length; i++) { - // history[i] = NO_STATE; - // } - protected int history[] = {NO_STATE,NO_STATE«FOR state : ac.getAllBaseStates()»,NO_STATE«ENDFOR»}; - - «var List chains = xpac.getOwnTransitionChains()» - «var offset_tc = xpac.getTransitionChains().size-chains.size» - // transition chains - «FOR tc : chains» - protected static final int «tc.getChainId()» = «chains.indexOf(tc)+1+offset_tc»; - «ENDFOR» - - «var triggers = xpac.getOwnTriggers()» - // triggers for FSM - «FOR mif : triggers»protected static final int «xpac.getTriggerCodeName(mif)» = IFITEM_«mif.from.name» + EVT_SHIFT*«xpac.getMessageID(mif)»; - «ENDFOR» - - // receiveEvent contains the main implementation of the FSM - @Override - public void receiveEvent(InterfaceItemBase ifitem, int evt, Object generic_data) { - int trigger = ifitem.getLocalId() + EVT_SHIFT*evt; - int chain = NOT_CAUGHT; - int catching_state = NO_STATE; - boolean is_handler = false; - boolean skip_entry = false; - - if (!handleSystemEvent(ifitem, evt, generic_data)) { - switch (state) { - «FOR state : xpac.stateMachine.getLeafStateList()» - case «state.getStateId()»: - «var atlist = xpac.getActiveTriggers(state)» - «IF !atlist.isEmpty» - switch(trigger) { - «FOR at : atlist» - case «xpac.getTriggerCodeName(at.trigger)»: - «var needData = xpac.hasGuard(at)» - «IF needData»{ «at.msg.getTypedDataDefinition()»«ENDIF» - «FOR tt : at.transitions SEPARATOR " else "» - «var chain = xpac.getChain(tt)» - «guard(chain.transition, at.trigger, xpac)» - { - chain = «chain.getChainId()»; - catching_state = «chain.getContextId()»; - «IF chain.isHandler()»is_handler = true;«ENDIF» - «IF chain.skipEntry»skip_entry = true;«ENDIF» - } - «ENDFOR» - «IF needData»}«ENDIF» - break; - «ENDFOR» - } - «ENDIF» - break; - «ENDFOR» - } - } - if (chain != NOT_CAUGHT) { - exitTo(state, catching_state, is_handler); - int next = executeTransitionChain(chain, ifitem, generic_data); - next = enterHistory(next, is_handler, skip_entry); - setState(next); - } - } - - private void setState(int new_state) { - DebuggingService.getInstance().addActorState(this,stateStrings[new_state]); - if (stateStrings[new_state]!="Idle") { - // TODOTS: model switch for activation - System.out.println(getInstancePath() + " -> " + stateStrings[new_state]); - } - this.state = new_state; - } - - @Override - public void executeInitTransition() { - «var initt = xpac.stateMachine.getInitTransition()» - int chain = «xpac.getChain(initt).getChainId()»; - int next = executeTransitionChain(chain, null, null); - next = enterHistory(next, false, false); - setState(next); - } - - /** - * calls exit codes while exiting from the current state to one of its - * parent states while remembering the history - * @param current - the current state - * @param to - the final parent state - * @param handler - entry and exit codes are called only if not handler (for handler TransitionPoints) - */ - private void exitTo(int current, int to, boolean handler) { - while (current!=to) { - switch (current) { - «FOR state : xpac.stateMachine.getBaseStateList()» - case «state.getStateId()»: - «IF state.hasExitCode()»if (!handler) «state.getExitCodeOperationName()»();«ENDIF» - history[«state.getParentStateId()»] = «state.getStateId()»; - current = «state.getParentStateId()»; - break; - «ENDFOR» - } - } - } - /** - * calls action, entry and exit codes along a transition chain. The generic data are cast to typed data - * matching the trigger of this chain. The ID of the final state is returned - * @param chain - the chain ID - * @param generic_data - the generic data pointer - * @return the ID of the final state - */ - private int executeTransitionChain(int chain, InterfaceItemBase ifitem, Object generic_data) { - switch (chain) { - «var allchains = xpac.getTransitionChains()» - «FOR tc : allchains» - case «tc.getChainId()»: - { - «xpac.getExecuteChainCode(tc)» - } - «ENDFOR» - } - return NO_STATE; - } - /** - * calls entry codes while entering a state's history. The ID of the final leaf state is returned - * @param state - the state which is entered - * @param handler - entry code is executed if not handler - * @return - the ID of the final leaf state - */ - private int enterHistory(int state, boolean handler, boolean skip_entry) { - while (true) { - switch (state) { - «FOR state : xpac.stateMachine.getBaseStateList()» - case «state.getStateId()»: - «IF state.hasEntryCode()»if (!(skip_entry || handler)) «state.getEntryCodeOperationName()»();«ENDIF» - «IF state.isLeaf()» - // in leaf state: return state id - return «state.getStateId()»; - «ELSE» - // state has a sub graph - «IF state.subgraph.hasInitTransition()» - // with init transition - if (history[«state.getStateId()»]==NO_STATE) { - «var sub_initt = state.subgraph.getInitTransition()» - state = executeTransitionChain(«xpac.getChain(sub_initt).getChainId()», null, null); - } - else { - state = history[«state.getStateId()»]; - } - «ELSE» - // without init transition - state = history[«state.getStateId()»]; - «ENDIF» - break; - «ENDIF» - «ENDFOR» - case STATE_TOP: - state = history[STATE_TOP]; - break; - } - skip_entry = false; - } - //return NO_STATE; // required by CDT but detected as unreachable by JDT because of while (true) - } - - //*** Entry and Exit Codes - «FOR state : xpac.stateMachine.getStateList()» - «IF xpac.isOwnObject(state)» - «IF state.hasEntryCode()» - protected void «state.getEntryCodeOperationName()»() { - «xpac.getEntryCode(state)» - } - «ENDIF» - «IF state.hasExitCode()» - protected void «state.getExitCodeOperationName()»() { - «xpac.getExitCode(state)» - } - «ENDIF» - «ENDIF» - «ENDFOR» - - //*** Action Codes - «FOR tr : xpac.stateMachine.getTransitionList()» - «IF xpac.isOwnObject(tr) && tr.hasActionCode()» - protected void «tr.getActionCodeOperationName()»(«IF tr instanceof NonInitialTransition»InterfaceItemBase ifitem«languageGen.getArgumentList(xpac, tr)»«ENDIF») { - «xpac.getActionCode(tr)» - } - «ENDIF» - «ENDFOR» - - //****************************************** - // END of generated code for FSM - //****************************************** - '''} - - def dispatch guard(TriggeredTransition tt, String trigger, ExpandedActorClass ac) {''' - «var tr = tt.triggers.findFirst(e|ac.isMatching(e, trigger))» - «IF tr.hasGuard()» - if («ac.getCode(tr.guard.guard)») - «ENDIF» - ''' - } - - def dispatch guard(Transition t, String trigger, ExpandedActorClass ac) {''' - /* error */ - ''' - } -} +/******************************************************************************* + * Copyright (c) 2011 protos software gmbh (http://www.protos.de). + * 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: + * Henrik Rentz-Reichert (initial contribution) + * + *******************************************************************************/ + +package org.eclipse.etrice.generator.c.gen + +import com.google.inject.Inject +import com.google.inject.Singleton +import java.util.List +import org.eclipse.etrice.core.room.ActorClass +import org.eclipse.etrice.core.room.NonInitialTransition +import org.eclipse.etrice.core.room.Transition +import org.eclipse.etrice.core.room.TriggeredTransition +import org.eclipse.etrice.generator.etricegen.ExpandedActorClass +import org.eclipse.etrice.generator.etricegen.TransitionChain +import static extension org.eclipse.etrice.generator.extensions.RoomNameProv.* +import org.eclipse.etrice.generator.extensions.RoomExtensions +import org.eclipse.etrice.generator.generic.LanguageGenerator + + +@Singleton +class StateMachineGen { + + @Inject extension CExtensions stdExt + @Inject extension RoomExtensions roomExt + @Inject LanguageGenerator languageGen + + def genStateMachine(ExpandedActorClass xpac, ActorClass ac) {''' + //****************************************** + // START of generated code for FSM + //****************************************** + + // State IDs for FSM + «var offset = ac.getNumberOfInheritedBaseStates()» + «var baseStates = ac.stateMachine.getBaseStateList()» + «FOR state : baseStates» + protected static final int «state.getStateId()» = «baseStates.indexOf(state)+2+offset»; + «ENDFOR» + protected static final String stateStrings[] = {"","",«FOR state : ac.getAllBaseStates() SEPARATOR ","»"«state.getStatePathName()»" + «ENDFOR»}; + + // history + // TODOHRR: history defined in ActorClassBase, init in constructor + // history = new int[5]; + // for (int i = 0; i < history.length; i++) { + // history[i] = NO_STATE; + // } + protected int history[] = {NO_STATE,NO_STATE«FOR state : ac.getAllBaseStates()»,NO_STATE«ENDFOR»}; + + «var List chains = xpac.getOwnTransitionChains()» + «var offset_tc = xpac.getTransitionChains().size-chains.size» + // transition chains + «FOR tc : chains» + protected static final int «tc.getChainId()» = «chains.indexOf(tc)+1+offset_tc»; + «ENDFOR» + + «var triggers = xpac.getOwnTriggers()» + // triggers for FSM + «FOR mif : triggers»protected static final int «xpac.getTriggerCodeName(mif)» = IFITEM_«mif.from.name» + EVT_SHIFT*«xpac.getMessageID(mif)»; + «ENDFOR» + + // receiveEvent contains the main implementation of the FSM + @Override + public void receiveEvent(InterfaceItemBase ifitem, int evt, Object generic_data) { + int trigger = ifitem.getLocalId() + EVT_SHIFT*evt; + int chain = NOT_CAUGHT; + int catching_state = NO_STATE; + boolean is_handler = false; + boolean skip_entry = false; + + if (!handleSystemEvent(ifitem, evt, generic_data)) { + switch (state) { + «FOR state : xpac.stateMachine.getLeafStateList()» + case «state.getStateId()»: + «var atlist = xpac.getActiveTriggers(state)» + «IF !atlist.isEmpty» + switch(trigger) { + «FOR at : atlist» + case «xpac.getTriggerCodeName(at.trigger)»: + «var needData = xpac.hasGuard(at)» + «IF needData»{ «at.msg.getTypedDataDefinition()»«ENDIF» + «FOR tt : at.transitions SEPARATOR " else "» + «var chain = xpac.getChain(tt)» + «guard(chain.transition, at.trigger, xpac)» + { + chain = «chain.getChainId()»; + catching_state = «chain.getContextId()»; + «IF chain.isHandler()»is_handler = true;«ENDIF» + «IF chain.skipEntry»skip_entry = true;«ENDIF» + } + «ENDFOR» + «IF needData»}«ENDIF» + break; + «ENDFOR» + } + «ENDIF» + break; + «ENDFOR» + } + } + if (chain != NOT_CAUGHT) { + exitTo(state, catching_state, is_handler); + int next = executeTransitionChain(chain, ifitem, generic_data); + next = enterHistory(next, is_handler, skip_entry); + setState(next); + } + } + + private void setState(int new_state) { + DebuggingService.getInstance().addActorState(this,stateStrings[new_state]); + if (stateStrings[new_state]!="Idle") { + // TODOTS: model switch for activation + System.out.println(getInstancePath() + " -> " + stateStrings[new_state]); + } + this.state = new_state; + } + + @Override + public void executeInitTransition() { + «var initt = xpac.stateMachine.getInitTransition()» + int chain = «xpac.getChain(initt).getChainId()»; + int next = executeTransitionChain(chain, null, null); + next = enterHistory(next, false, false); + setState(next); + } + + /** + * calls exit codes while exiting from the current state to one of its + * parent states while remembering the history + * @param current - the current state + * @param to - the final parent state + * @param handler - entry and exit codes are called only if not handler (for handler TransitionPoints) + */ + private void exitTo(int current, int to, boolean handler) { + while (current!=to) { + switch (current) { + «FOR state : xpac.stateMachine.getBaseStateList()» + case «state.getStateId()»: + «IF state.hasExitCode()»if (!handler) «state.getExitCodeOperationName()»();«ENDIF» + history[«state.getParentStateId()»] = «state.getStateId()»; + current = «state.getParentStateId()»; + break; + «ENDFOR» + } + } + } + /** + * calls action, entry and exit codes along a transition chain. The generic data are cast to typed data + * matching the trigger of this chain. The ID of the final state is returned + * @param chain - the chain ID + * @param generic_data - the generic data pointer + * @return the ID of the final state + */ + private int executeTransitionChain(int chain, InterfaceItemBase ifitem, Object generic_data) { + switch (chain) { + «var allchains = xpac.getTransitionChains()» + «FOR tc : allchains» + case «tc.getChainId()»: + { + «xpac.getExecuteChainCode(tc)» + } + «ENDFOR» + } + return NO_STATE; + } + /** + * calls entry codes while entering a state's history. The ID of the final leaf state is returned + * @param state - the state which is entered + * @param handler - entry code is executed if not handler + * @return - the ID of the final leaf state + */ + private int enterHistory(int state, boolean handler, boolean skip_entry) { + while (true) { + switch (state) { + «FOR state : xpac.stateMachine.getBaseStateList()» + case «state.getStateId()»: + «IF state.hasEntryCode()»if (!(skip_entry || handler)) «state.getEntryCodeOperationName()»();«ENDIF» + «IF state.isLeaf()» + // in leaf state: return state id + return «state.getStateId()»; + «ELSE» + // state has a sub graph + «IF state.subgraph.hasInitTransition()» + // with init transition + if (history[«state.getStateId()»]==NO_STATE) { + «var sub_initt = state.subgraph.getInitTransition()» + state = executeTransitionChain(«xpac.getChain(sub_initt).getChainId()», null, null); + } + else { + state = history[«state.getStateId()»]; + } + «ELSE» + // without init transition + state = history[«state.getStateId()»]; + «ENDIF» + break; + «ENDIF» + «ENDFOR» + case STATE_TOP: + state = history[STATE_TOP]; + break; + } + skip_entry = false; + } + //return NO_STATE; // required by CDT but detected as unreachable by JDT because of while (true) + } + + //*** Entry and Exit Codes + «FOR state : xpac.stateMachine.getStateList()» + «IF xpac.isOwnObject(state)» + «IF state.hasEntryCode()» + protected void «state.getEntryCodeOperationName()»() { + «xpac.getEntryCode(state)» + } + «ENDIF» + «IF state.hasExitCode()» + protected void «state.getExitCodeOperationName()»() { + «xpac.getExitCode(state)» + } + «ENDIF» + «ENDIF» + «ENDFOR» + + //*** Action Codes + «FOR tr : xpac.stateMachine.getTransitionList()» + «IF xpac.isOwnObject(tr) && tr.hasActionCode()» + protected void «tr.getActionCodeOperationName()»(«IF tr instanceof NonInitialTransition»InterfaceItemBase ifitem«languageGen.getArgumentList(xpac, tr)»«ENDIF») { + «xpac.getActionCode(tr)» + } + «ENDIF» + «ENDFOR» + + //****************************************** + // END of generated code for FSM + //****************************************** + '''} + + def dispatch guard(TriggeredTransition tt, String trigger, ExpandedActorClass ac) {''' + «var tr = tt.triggers.findFirst(e|ac.isMatching(e, trigger))» + «IF tr.hasGuard()» + if («ac.getCode(tr.guard.guard)») + «ENDIF» + ''' + } + + def dispatch guard(Transition t, String trigger, ExpandedActorClass ac) {''' + /* error */ + ''' + } +} -- cgit v1.2.3