diff options
author | Henrik Rentz-Reichert | 2012-02-02 09:42:09 +0000 |
---|---|---|
committer | Henrik Rentz-Reichert | 2012-02-02 09:42:09 +0000 |
commit | b55690aca6ad5d17e699e809af481d1ffd04191e (patch) | |
tree | 20d32381f24b1cad365c9b9ec06c8bf1d351fff5 /plugins/org.eclipse.etrice.generator.c/src/org/eclipse | |
parent | 0dc402844ba53dbd6afca52e8ec4f7a7dcd196da (diff) | |
download | org.eclipse.etrice-b55690aca6ad5d17e699e809af481d1ffd04191e.tar.gz org.eclipse.etrice-b55690aca6ad5d17e699e809af481d1ffd04191e.tar.xz org.eclipse.etrice-b55690aca6ad5d17e699e809af481d1ffd04191e.zip |
[core.room, generator, ui.behavior] communication model for protocols
Diffstat (limited to 'plugins/org.eclipse.etrice.generator.c/src/org/eclipse')
2 files changed, 446 insertions, 446 deletions
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[] = {"<no state>","<top>",«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<TransitionChain> 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[] = {"<no state>","<top>",«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<TransitionChain> 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 */
+ '''
+ }
+}
|