فهرست منبع

Added two new features for inner function visibility and static operation callbacks.

markus.muehlbrandt@gmail.com 11 سال پیش
والد
کامیت
0bead67416

+ 18 - 1
plugins/org.yakindu.sct.doc.user/help/04_Reference/reference.textile

@@ -602,8 +602,25 @@ feature IdentifierSettings {
 	maxIdentifierLength = 31
 	separator =  "_" 
 }
-p. ==<!-- End sgen_feature_identifiersettings -->==		
+p. ==<!-- End sgen_feature_identifiersettings -->==
 
+==<!-- Start sgen_feature_generatoroptions -->==
+
+h4. GeneratorOptions
+
+The *GeneratorOptions* feature allows change the behavior of the C++ generator:
+
+# __innerFunctionVisibility__  (String, optional): This parameter is used to change the visibility of inner functions and variables. In default the "private" visibility is used. It can be changed to "protected" to allow function overriding for a class which inherits from the generated statemachine base class.
+# __staticOperationCallback__  (Boolean, optional): If set to 'true' the callback function declaration for statechart operations is static and the functions are called by the statemachine code statically.
+
+Example configuration:
+
+bc(prettyprint).. 
+feature GeneratorOptions {
+	innerFunctionVisibility =  "protected"
+	staticOperationCallback = true
+}
+p. ==<!-- End sgen_feature_generatoroptions -->==
 
 ==<!-- Start sgen_feature_junitwrapper -->==
 

+ 9 - 0
plugins/org.yakindu.sct.generator.c/src/org/yakindu/sct/generator/c/Naming.xtend

@@ -27,6 +27,7 @@ import org.yakindu.sct.model.stext.stext.OperationDefinition
 import org.yakindu.sct.model.stext.stext.VariableDefinition
 import org.yakindu.sct.model.sgen.GeneratorEntry
 import org.yakindu.sct.model.sexec.TimeEvent
+import java.util.List
 
 class Naming {
 	
@@ -58,6 +59,14 @@ class Naming {
 //	def module(InterfaceScope it) {
 //		flow.type + (if (name.nullOrEmpty) 'Default' else name).asIdentifier.toFirstUpper	
 //	}
+	
+	def filterNullOrEmptyAndJoin(Iterable<CharSequence> it) {
+		filter[!it?.toString.nullOrEmpty].join('\n')
+	}
+
+	def filterNullOrEmptyAndJoin(List<String> it) {
+		filter[!it?.toString.nullOrEmpty].join('\n')
+	}
 	
 	def client(String it) {
 		it + "Required"	

+ 4 - 0
plugins/org.yakindu.sct.generator.cpp/library/FeatureTypeLibrary.xmi

@@ -27,5 +27,9 @@
     <parameters
         name="innerFunctionVisibility"
         optional="true"/>
+    <parameters
+        name="staticOperationCallback"
+        optional="true"
+        parameterType="BOOLEAN"/>
   </types>
 </sgen:FeatureTypeLibrary>

+ 5 - 5
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/ExpressionCode.xtend

@@ -6,6 +6,7 @@ import org.yakindu.base.expressions.expressions.BitwiseAndExpression
 import org.yakindu.base.expressions.expressions.BitwiseOrExpression
 import org.yakindu.base.expressions.expressions.BitwiseXorExpression
 import org.yakindu.base.expressions.expressions.BoolLiteral
+import org.yakindu.base.expressions.expressions.ConditionalExpression
 import org.yakindu.base.expressions.expressions.ElementReferenceExpression
 import org.yakindu.base.expressions.expressions.Expression
 import org.yakindu.base.expressions.expressions.FeatureCall
@@ -16,6 +17,7 @@ import org.yakindu.base.expressions.expressions.LogicalAndExpression
 import org.yakindu.base.expressions.expressions.LogicalNotExpression
 import org.yakindu.base.expressions.expressions.LogicalOrExpression
 import org.yakindu.base.expressions.expressions.LogicalRelationExpression
+import org.yakindu.base.expressions.expressions.NullLiteral
 import org.yakindu.base.expressions.expressions.NumericalAddSubtractExpression
 import org.yakindu.base.expressions.expressions.NumericalMultiplyDivideExpression
 import org.yakindu.base.expressions.expressions.NumericalUnaryExpression
@@ -24,7 +26,9 @@ import org.yakindu.base.expressions.expressions.PrimitiveValueExpression
 import org.yakindu.base.expressions.expressions.RealLiteral
 import org.yakindu.base.expressions.expressions.ShiftExpression
 import org.yakindu.base.expressions.expressions.StringLiteral
+import org.yakindu.base.expressions.expressions.TypeCastExpression
 import org.yakindu.base.types.ITypeSystem
+import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
 import org.yakindu.sct.model.sexec.naming.INamingService
 import org.yakindu.sct.model.sgraph.Event
 import org.yakindu.sct.model.stext.stext.ActiveStateReferenceExpression
@@ -33,10 +37,6 @@ import org.yakindu.sct.model.stext.stext.EventValueReferenceExpression
 import org.yakindu.sct.model.stext.stext.OperationDefinition
 import org.yakindu.sct.model.stext.stext.VariableDefinition
 import org.yakindu.sct.model.stext.types.ISTextTypeInferrer
-import org.yakindu.base.expressions.expressions.NullLiteral
-import org.yakindu.base.expressions.expressions.ConditionalExpression
-import org.yakindu.base.expressions.expressions.TypeCastExpression
-import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
 
 class ExpressionCode {
 
@@ -46,7 +46,7 @@ class ExpressionCode {
 	@Inject extension ISTextTypeInferrer
 	@Inject extension INamingService
 	@Inject extension ICodegenTypeSystemAccess
-
+	
 	/* Refering to declared elements */
 	def dispatch CharSequence code(ElementReferenceExpression it) {
 		it.code(it.definition)

+ 9 - 9
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/FlowCode.xtend

@@ -1,25 +1,25 @@
 package org.yakindu.sct.generator.cpp
 
-import org.yakindu.sct.model.sexec.SaveHistory
-import org.yakindu.sct.model.sexec.HistoryEntry
-import org.yakindu.sct.model.sexec.StateSwitch
-import org.yakindu.sct.model.sexec.ScheduleTimeEvent
-import org.yakindu.sct.model.sexec.UnscheduleTimeEvent
-import org.yakindu.sct.model.sexec.Call
 import com.google.inject.Inject
+import org.yakindu.sct.model.sexec.Call
 import org.yakindu.sct.model.sexec.Check
 import org.yakindu.sct.model.sexec.CheckRef
 import org.yakindu.sct.model.sexec.EnterState
-import org.yakindu.sct.model.sexec.ExitState
 import org.yakindu.sct.model.sexec.Execution
+import org.yakindu.sct.model.sexec.ExitState
+import org.yakindu.sct.model.sexec.HistoryEntry
+import org.yakindu.sct.model.sexec.SaveHistory
+import org.yakindu.sct.model.sexec.ScheduleTimeEvent
 import org.yakindu.sct.model.sexec.Sequence
+import org.yakindu.sct.model.sexec.StateSwitch
+import org.yakindu.sct.model.sexec.UnscheduleTimeEvent
 import org.yakindu.sct.model.sexec.naming.INamingService
 
 class FlowCode extends org.yakindu.sct.generator.c.FlowCode {
 	
-	@Inject extension Naming
+	@Inject extension Naming naming
+	@Inject extension ExpressionCode expressions
 	@Inject extension Navigation
-	@Inject extension ExpressionCode
 	@Inject extension INamingService
 	
 	override dispatch CharSequence code(SaveHistory it) '''

+ 13 - 5
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/Naming.xtend

@@ -23,12 +23,16 @@ import org.yakindu.sct.model.stext.stext.OperationDefinition
 import org.yakindu.sct.model.stext.stext.StatechartScope
 import org.yakindu.sct.model.stext.stext.VariableDefinition
 import org.yakindu.sct.model.sgraph.Scope
+import org.yakindu.sct.model.sgen.GeneratorEntry
+import org.yakindu.sct.generator.cpp.features.GenmodelEntriesExtension
 
 class Naming extends org.yakindu.sct.generator.c.Naming {
 	
 	@Inject extension Navigation
 	@Inject extension ICodegenTypeSystemAccess
 	@Inject extension INamingService
+	@Inject extension GenmodelEntriesExtension
+	@Inject GeneratorEntry entry
 	
 	def cpp(String it) { it + ".cpp" }
 	
@@ -154,13 +158,17 @@ class Naming extends org.yakindu.sct.generator.c.Naming {
 		"isActive"
 	}
 	
-	override dispatch access (OperationDefinition it) 
-		'''«scope.OCB_Instance»->«asFunction»'''
+	override dispatch access(OperationDefinition it){
+		if (entry.useStaticOPC) {
+			return '''«(scope as StatechartScope).interfaceOCBName»::«asFunction»'''
+		}
+		return '''«scope.OCB_Instance»->«asFunction»'''
+	}
 		
 	override dispatch access(TimeEvent it)
 		'''«timeEventsInstance»[«indexOf»]'''
 		
-	override dispatch access (VariableDefinition it) 
+	override dispatch access(VariableDefinition it) 
 		'''«scope.instance».«name.asEscapedIdentifier»'''
 	
 	override dispatch access (Event it) 
@@ -169,10 +177,10 @@ class Naming extends org.yakindu.sct.generator.c.Naming {
 	override valueAccess(Event it) 
 		'''«scope.instance».«name.asIdentifier.value»'''
 		
-	def dispatch localAccess (VariableDefinition it) 
+	def dispatch localAccess(VariableDefinition it) 
 		'''«name.asEscapedIdentifier»'''
 	
-	def dispatch localAccess (Event it) 
+	def dispatch localAccess(Event it) 
 		'''«name.asIdentifier.raised»'''
 	
 	def localValueAccess(Event it) 

+ 30 - 24
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/StatemachineHeader.xtend

@@ -33,14 +33,17 @@ import org.yakindu.sct.model.stext.stext.VariableDefinition
 
 class StatemachineHeader extends Statemachine {
 	
-	@Inject extension Naming cNaming
+	@Inject extension Naming
 	@Inject extension Navigation
 	@Inject extension ICodegenTypeSystemAccess
 	@Inject extension GenmodelEntriesExtension
 	@Inject extension INamingService
 	
+	protected GeneratorEntry entry
+	
 	def generateStatemachineHeader(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		 fsa.generateFile(flow.module().h, flow.statemachineHContent(entry) )
+		this.entry = entry
+		fsa.generateFile(flow.module().h, flow.statemachineHContent(entry) )
 	}
 	
 	override statemachineHContent(ExecutionFlow it,  GeneratorEntry entry) '''
@@ -58,17 +61,17 @@ class StatemachineHeader extends Statemachine {
 		/*! \file Header of the state machine '«name»'.
 		*/
 		
-		class «module()» : «interfaceExtensions» {
+		class «module» : «interfaceExtensions» {
 			
 			public:
 				
-				«flow.module()»();
+				«module»();
 				
-				~«flow.module()»();
+				~«module»();
 				
 				«statesEnumDecl»
 				
-				«FOR s : it.scopes»«s.createPublicScope(entry)»«ENDFOR»
+				«FOR s : it.scopes»«s.createPublicScope»«ENDFOR»
 				
 				«publicFunctionPrototypes»
 				
@@ -77,16 +80,15 @@ class StatemachineHeader extends Statemachine {
 			
 			«entry.innerClassVisibility»:
 			
-				«FOR s : scopes.filter(typeof(InternalScope))»«s.createInterface(entry)»«ENDFOR»
+				«FOR s : scopes.filter(typeof(InternalScope))»«s.createInterface»«ENDFOR»
 			
 				«statemachineTypeDecl»
 				
 				«prototypes»
 		};
-		
-		«FOR s : it.scopes.filter(typeof(StatechartScope)) SEPARATOR StringConcatenation.DEFAULT_LINE_DELIMITER»
-			«s.createInlineOCB_Destructor»
-		«ENDFOR»
+		«IF !entry.useStaticOPC»
+			«scopes.filter(typeof(StatechartScope)).map[createInlineOCB_Destructor].filterNullOrEmptyAndJoin»
+		«ENDIF»
 		#endif /* «module().define»_H_ */
 	'''
 	
@@ -103,23 +105,23 @@ class StatemachineHeader extends Statemachine {
 		return interfaces;
 	}
 	
-	def protected createInlineOCB_Destructor(StatechartScope it) {
+	def protected CharSequence createInlineOCB_Destructor(StatechartScope it) {
 		if (hasOperations) {
 			return '''inline «flow.module»::«interfaceOCBName»::~«interfaceOCBName»() {}'''
 		}
 		return ''''''
 	}
 	
-	def protected createPublicScope(Scope scope, GeneratorEntry entry) {
+	def protected createPublicScope(Scope scope) {
 		switch scope {
-			InterfaceScope: scope.createPublicScope(entry)
+			InterfaceScope: scope.createPublicScope
 			InternalScope: scope.createPublicScope
 		}
 	}
 	
-	def protected createPublicScope(InterfaceScope scope, GeneratorEntry entry)
+	def protected createPublicScope(InterfaceScope scope)
 	'''
-		«scope.createInterface(entry)»
+		«scope.createInterface»
 «««		«scope.createListenerInterface(entry)»
 		«scope.createOCBInterface»
 		
@@ -139,7 +141,7 @@ class StatemachineHeader extends Statemachine {
 		'''
 	}
 	
-	def protected createInterface(StatechartScope scope, GeneratorEntry entry)
+	def protected createInterface(StatechartScope scope)
 	'''
 		//! Inner class for «scope.simpleName» interface scope.
 		class «scope.interfaceName» {
@@ -164,15 +166,19 @@ class StatemachineHeader extends Statemachine {
 			//! Inner class for «scope.simpleName» interface scope operation callbacks.
 			class «scope.interfaceOCBName» {
 				public:
-					virtual ~«scope.interfaceOCBName»() = 0;
-					
+					«IF !entry.useStaticOPC»
+						virtual ~«scope.interfaceOCBName»() = 0;
+						
+					«ENDIF»
 					«FOR operation : scope.operations SEPARATOR StringConcatenation.DEFAULT_LINE_DELIMITER»
-						virtual «operation.signature» = 0;
+						«IF entry.useStaticOPC»static«ELSE»virtual«ENDIF» «operation.signature»«IF !entry.useStaticOPC» = 0«ENDIF»;
 					«ENDFOR»
 			};
-			
-			/*! Set the working instance of the operation callback interface '«scope.interfaceOCBName»'. */
-			«scope.OCB_InterfaceSetterDeclaration(false)»;
+			«IF !entry.useStaticOPC»
+				
+				/*! Set the working instance of the operation callback interface '«scope.interfaceOCBName»'. */
+				«scope.OCB_InterfaceSetterDeclaration(false)»;
+			«ENDIF»
 		«ENDIF»
 		'''
 	}
@@ -196,7 +202,7 @@ class StatemachineHeader extends Statemachine {
 		
 		«FOR s : scopes.filter(typeof(StatechartScope))»
 			«s.interfaceName» «s.instance»;
-			«IF s.hasOperations»«s.interfaceOCBName»* «s.OCB_Instance»;«ENDIF»
+			«IF s.hasOperations && !entry.useStaticOPC»«s.interfaceOCBName»* «s.OCB_Instance»;«ENDIF»
 		«ENDFOR»
 	'''
 	

+ 17 - 13
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/StatemachineImplementation.xtend

@@ -13,30 +13,34 @@ package org.yakindu.sct.generator.cpp
 import com.google.inject.Inject
 import java.util.List
 import org.eclipse.xtext.generator.IFileSystemAccess
+import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
+import org.yakindu.sct.generator.cpp.features.GenmodelEntriesExtension
 import org.yakindu.sct.model.sexec.Check
 import org.yakindu.sct.model.sexec.ExecutionFlow
 import org.yakindu.sct.model.sexec.Step
-import org.yakindu.sct.model.sgraph.Statechart
+import org.yakindu.sct.model.sexec.naming.INamingService
 import org.yakindu.sct.model.sgen.GeneratorEntry
-import org.yakindu.sct.generator.core.types.ICodegenTypeSystemAccess
-import org.yakindu.sct.generator.c.GenmodelEntries
import org.yakindu.sct.model.stext.stext.StatechartScope
+import org.yakindu.sct.model.sgraph.Statechart
 import org.yakindu.sct.model.stext.stext.InterfaceScope
-import org.yakindu.sct.model.sexec.naming.INamingService
+import org.yakindu.sct.model.stext.stext.StatechartScope
 
 class StatemachineImplementation {
 	
 	@Inject extension Naming
 	@Inject extension Navigation
 	@Inject extension FlowCode
-	@Inject extension GenmodelEntries
+	@Inject extension GenmodelEntriesExtension
 	@Inject extension ICodegenTypeSystemAccess
-	@Inject extension INamingService
+	@Inject extension INamingService
+	
+	protected GeneratorEntry entry
 	
-	def generateStatemachineImplemenation(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
-		 fsa.generateFile(flow.module.cpp, flow.statemachineContent(entry) )
+	def generateStatemachineImplemenation(ExecutionFlow flow, Statechart sc, IFileSystemAccess fsa, GeneratorEntry entry) {
+		this.entry = entry
+		fsa.generateFile(flow.module.cpp, flow.statemachineContent)
 	}
 	
-	def statemachineContent(ExecutionFlow it, GeneratorEntry entry) '''
+	def statemachineContent(ExecutionFlow it) '''
 		«entry.licenseText»
 		
 		#include "«module.h»"
@@ -72,9 +76,9 @@ class StatemachineImplementation {
 	def constructorDecl(ExecutionFlow it) '''
 		«module»::«module»() {
 			
-			«scopes.filter(typeof(StatechartScope)).filter[hasOperations].map['''«OCB_Instance» = null;'''].join('\n')»
-		«IF hasHistory»
-			
+			«scopes.filter(typeof(StatechartScope)).filter[hasOperations && !entry.useStaticOPC].map['''«OCB_Instance» = null;'''].join('\n')»
+			«IF hasHistory»
+				
 				for (int i = 0; i < «historyStatesConst»; ++i)
 					historyVector[i] = «last_state»;
 			«ENDIF»
@@ -312,7 +316,7 @@ class StatemachineImplementation {
 					«ENDIF»
 				«ENDIF»
 			«ENDFOR»
-			«IF scope.hasOperations»
+			«IF scope.hasOperations && !entry.useStaticOPC»
 				«scope.OCB_InterfaceSetterDeclaration(true)» {
 					«scope.OCB_Instance» = operationCallback;
 				}

+ 3 - 0
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/features/CPPDefaultFeatureValueProvider.java

@@ -63,6 +63,9 @@ public class CPPDefaultFeatureValueProvider extends
 				.getName()
 				.equals(CPPFeatureConstants.PARAMETER_INNER_FUNCTION_VISIBILITY)) {
 			parameterValue.setValue(Visibility.PRIVATE.toString().toLowerCase());
+		} else if (parameterValue.getParameter().getName()
+				.equals(CPPFeatureConstants.PARAMETER_STATIC_OPC)) {
+			parameterValue.setValue(false);
 		}
 	}
 

+ 2 - 0
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/features/CPPFeatureConstants.java

@@ -27,4 +27,6 @@ public interface CPPFeatureConstants {
 	public static final String FEATURE_GENERATOR_OPTIONS = "GeneratorOptions";
 	
 	public static final String PARAMETER_INNER_FUNCTION_VISIBILITY = "innerFunctionVisibility";
+	
+	public static final String PARAMETER_STATIC_OPC = "staticOperationCallback";
 }

+ 15 - 4
plugins/org.yakindu.sct.generator.cpp/src/org/yakindu/sct/generator/cpp/features/GenmodelEntriesExtension.xtend

@@ -5,19 +5,30 @@ import org.yakindu.sct.model.sgen.GeneratorEntry
 import org.yakindu.sct.generator.cpp.features.CPPFeatureConstants.Visibility
 
 class GenmodelEntriesExtension extends GenmodelEntries {
-	
+
 	def private getGeneratorOptionsFeature(GeneratorEntry it) {
 		getFeatureConfiguration(CPPFeatureConstants::FEATURE_GENERATOR_OPTIONS)
 	}
-	
+
 	def private getVisibilityParameter(GeneratorEntry it) {
 		generatorOptionsFeature?.getParameterValue(CPPFeatureConstants.PARAMETER_INNER_FUNCTION_VISIBILITY)
 	}
-	
+
 	def getInnerClassVisibility(GeneratorEntry it) {
 		if (visibilityParameter != null) {
 			return visibilityParameter.stringValue
 		}
 		return Visibility.PRIVATE.toString.toLowerCase
 	}
-}
+
+	def private getStaticOPCParameter(GeneratorEntry it) {
+		generatorOptionsFeature?.getParameterValue(CPPFeatureConstants.PARAMETER_STATIC_OPC)
+	}
+
+	def useStaticOPC(GeneratorEntry it) {
+		if (staticOPCParameter != null) {
+			return staticOPCParameter.booleanValue
+		}
+		return false
+	}
+}