Browse Source

Improvement on the generation of window sa

Casper Thule 3 years ago
parent
commit
84a3d1344f
15 changed files with 739 additions and 31 deletions
  1. 7 2
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/tests/CgCppBasicTest.xtend
  2. 93 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/tests/CgCppBasicTestKel.xtend
  3. 33 16
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/window/window_sa_canonical.BASE.sa
  4. BIN
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/windowKel/Window.fmu
  5. 69 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/windowKel/window_sa_canonical.BASE.sa
  6. 44 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ControlConditionSwitch.xtend
  7. 107 11
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/CppGenerator.xtend
  8. 157 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/InOutRulesConditionSwitch.xtend
  9. 31 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/InRulesConditionSwitch.xtend
  10. 79 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescription.xtend
  11. 1 1
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescriptionBuilder.java
  12. 4 1
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescriptionCreator.xtend
  13. 23 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/OutRulesConditionSwitch.xtend
  14. 22 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/Visitor.xtend
  15. 69 0
      DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/testInputs/single_folder_spec/windowKEL/window_sa_canonical.BASE.sa

+ 7 - 2
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/tests/CgCppBasicTest.xtend

@@ -40,8 +40,13 @@ class CgCppBasicTest extends AbstractSemanticAdaptationTest {
 		val IGeneratorContext ctxt = null;
 		new CppGenerator().doGenerate(model.eResource, fsa, ctxt);
 		
-		
-		System.out.println(fsa.allFiles)		
+		for(files : fsa.allFiles.entrySet)
+		{
+			System.out.println("########################")
+			System.out.println("Filename: " + files.key.substring(14))
+			System.out.println(files.value)
+		}
+		//System.out.println(fsa.allFiles)		
 	}
 
 	def __parseNoErrorsPrint(String filename) {

+ 93 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/tests/CgCppBasicTestKel.xtend

@@ -0,0 +1,93 @@
+/*
+ * generated by Xtext 2.10.0
+ */
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests
+
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
+import be.uantwerpen.ansymo.semanticadaptation.tests.AbstractSemanticAdaptationTest
+import be.uantwerpen.ansymo.semanticadaptation.tests.SemanticAdaptationInjectorProvider
+import com.google.inject.Inject
+import java.util.regex.Pattern
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.xtext.testing.InjectWith
+import org.eclipse.xtext.testing.XtextRunner
+import org.eclipse.xtext.testing.util.ParseHelper
+import org.eclipse.xtext.testing.validation.ValidationTestHelper
+import org.junit.Test
+import org.junit.runner.RunWith
+import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.CppGenerator
+import org.eclipse.xtext.generator.InMemoryFileSystemAccess
+import org.eclipse.xtext.generator.IGeneratorContext
+import org.eclipse.emf.ecore.resource.ResourceSet
+import org.junit.Ignore
+
+@RunWith(XtextRunner)
+@InjectWith(SemanticAdaptationInjectorProvider)
+class CgCppBasicTestKel extends AbstractSemanticAdaptationTest {
+
+	// @Inject CppGenerator underTest
+	@Inject extension ParseHelper<SemanticAdaptation>
+	@Inject extension  ValidationTestHelper
+
+	
+	@Test def powerwindow_model_only() { __parseNoErrors('test_input/single_folder_spec/windowKEL/window_sa_canonical.BASE.sa') }
+
+	def __parseNoErrors(String filename) {
+		val model = __parse(filename)
+		__assertNoParseErrors(model, filename)
+
+		val fsa = new InMemoryFileSystemAccess()
+		val IGeneratorContext ctxt = null;
+		new CppGenerator().doGenerate(model.eResource, fsa, ctxt);
+		
+		
+		System.out.println(fsa.allFiles)		
+	}
+
+	def __parseNoErrorsPrint(String filename) {
+		val root = __parse(filename)
+		print_ast(root)
+		__assertNoParseErrors(root, filename)
+	}
+
+	def __parse(String filename) {
+		return readFile(filename).parse
+	}
+
+	def __parse(String filename, ResourceSet resourceSetToUse) {
+
+		return readFile(filename).parse(resourceSetToUse)
+	}
+
+	def __assertNoParseErrors(EObject root, String filename) {
+		try {
+			root.assertNoErrors
+		} catch (AssertionError e) {
+			val p = Pattern.compile(".*, offset (?<offset>[0-9]+), length (?<length>[0-9]+)")
+			val code = readFile(filename)
+			for (String line : e.message.split("\n")) {
+				val m = p.matcher(line)
+				m.matches()
+				val count = __occurrencesInString(code.subSequence(0, Integer.valueOf(m.group("offset"))).toString(),
+					"\n")
+				print(filename + " at line " + (count + 1) + ": ")
+				println(line)
+			}
+			throw e
+		}
+	}
+
+	def __occurrencesInString(String str, String findstr) {
+		var lastIndex = 0
+		var count = 0
+		while (lastIndex != -1) {
+			lastIndex = str.indexOf(findstr, lastIndex)
+			if (lastIndex != -1) {
+				count++
+				lastIndex += findstr.length()
+			}
+		}
+		return count
+	}
+
+}

+ 33 - 16
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/window/window_sa_canonical.BASE.sa

@@ -26,42 +26,59 @@ control {
 	return H;
 }
 
-in var 	stored_windowsa_reaction_force := 0., 
-		stored_windowsa_displacement := 0., 
-		stored_windowsa_speed := 0.;
+in var 	stored_windowsa_reaction_force := 0.0, 
+		stored_windowsa_displacement := 0.0, 
+		stored_windowsa_speed := 0.0;
 
 in rules {
+	/*
+	is_set checks whether the input value is given in the setValues call of the adapted FMU.
+	Notice that in the canonical version, all ports are prefixed.
+	*/
+
 	true -> {
-		/*
-		is_set checks whether the input value is given in the setValues call of the adapted FMU.
-		Notice that in the canonical version, all ports are prefixed.
-		*/
 		if (is_set(windowSA.reaction_force)){
 			stored_windowsa_reaction_force := windowSA.reaction_force;
 		}
+	} --> {
+			window.reaction_force := stored_windowsa_reaction_force;
+		};
+	
+	true -> {
 		if (is_set(windowSA.displacement)){
-			stored_windowsa_displacement := windowSA.displacement;			
-		}
+				stored_windowsa_displacement := windowSA.displacement;			
+			}
+	} --> {
+		window.displacement := stored_windowsa_displacement; 
+		};
+	
+	
+	true -> {		
 		if (is_set(windowSA.speed)){
 			stored_windowsa_speed := windowSA.speed;
 		}
 	} --> {
-		window.reaction_force := stored_windowsa_reaction_force;
-		window.displacement := stored_windowsa_displacement; 
+		
 		window.speed := stored_windowsa_speed;
 	};
 }
 
-out var stored_window_reaction_torque := 0,
-		stored_window_height := 0;
+out var stored_window_reaction_torque := 0.0,
+		stored_window_height := 0.0;
 		
 out rules {
+
 	true -> {
-		stored_window_reaction_torque := window.reaction_torque;
-		stored_window_height := window.height;
+		stored_window_reaction_torque := window.tau;
 	} --> {
 		windowSA.tau := - stored_window_reaction_torque;
-		windowSA.disp := stored_window_height / 100;
 	};
+	
+	true -> {
+		stored_window_height := window.disp;
+	} --> {
+		windowSA.disp := stored_window_height * 100;
+	};
+
 }
 

BIN
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/windowKel/Window.fmu


+ 69 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp.tests/test_input/single_folder_spec/windowKel/window_sa_canonical.BASE.sa

@@ -0,0 +1,69 @@
+module Window_SA
+
+semantic adaptation mealy reactive window_sa
+
+for fmu Window window
+at "./path/to/Window.fmu"
+input ports displacement (rad), speed (rad/s), reaction_force (N)
+
+
+/*
+In the originial version, no input ports where declared, so all dangling inputs of the original fmus are bound to the input ports of the adapted FMU.
+In the canonical version, the input and output ports are all declared explicitly, and their bindings are implemented in the in/out rules.
+*/
+
+input ports 	reaction_force,
+				displacement,
+				speed;
+
+output ports	disp;
+				tau;
+
+in var 	stored_windowsa_reaction_force,
+		stored_windowsa_displacement,
+		stored_windowsa_speed;
+
+out var stored_window_reaction_torque,
+		stored_window_height;
+
+in rules {
+	true -> {
+		/*
+		is_set checks whether the input value is given in the setValues call of the adapted FMU.
+		Notice that in the canonical version, all ports are prefixed.
+		*/
+		if (is_set(window_sa.reaction_force))
+			stored_windowsa_reaction_force := window_sa.reaction_force;
+	} --> {
+		window.reaction_force := stored_windowsa_reaction_force;
+	};
+    true -> {
+		if (is_set(window_sa.displacement))
+			stored_windowsa_displacement := window_sa.displacement;
+	} --> {
+		window.displacement := stored_windowsa_displacement; 
+	};
+    true -> {
+		if (is_set(window_sa.speed))
+			stored_windowsa_speed := window_sa.speed;
+	} --> {
+		window.speed := stored_windowsa_speed;
+	};
+}
+
+control rules {
+	do_step(window, t, H); // includes update_in rules and update_out (update-in rules do not update state)
+}
+
+out rules {
+	true => {
+		stored_window_reaction_torque := window.reaction_torque;
+	} -> {
+		window_sa.tau := - stored_window_reaction_torque;
+	}
+	true => {
+		stored_window_height := window.height;
+	} -> {
+		window_sa.disp := stored_window_height * 100;
+	}
+}

+ 44 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ControlConditionSwitch.xtend

@@ -0,0 +1,44 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
+
+import java.util.LinkedHashMap
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CustomControlRule
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DoStep
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StepSize
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CurrentTime
+
+class ControlConditionSwitch<CharSequence> extends InOutRulesConditionSwitch {
+
+	new(String adaptationName, LinkedHashMap<String, Pair<String, Integer>> scalars) {
+		super(adaptationName, scalars, "");
+	}
+	
+	override String caseCustomControlRule(CustomControlRule object) {
+		var String returnVal = "";
+		
+		for(ruleStm : object.controlRulestatements)
+		{
+			returnVal += doSwitch(ruleStm);	
+		}
+		
+		var functionPrefix = "void ";
+		var functionNameArgs = "executeInternalControlFlow(double h, double dt)"
+		functionSignatures.add(functionPrefix+functionNameArgs+";");
+		return '''
+		«functionPrefix+this.adaptationName»::«functionNameArgs»
+		{
+			«returnVal»
+		}''';
+	}
+	
+	override String caseDoStep(DoStep object){
+		return '''this->doStep(«object.fmu.name»,«doSwitch(object.h)»,«doSwitch(object.t)»);'''
+	}
+	
+	override String caseStepSize(StepSize object){
+			return '''h''';
+	}
+	
+	override String caseCurrentTime(CurrentTime object){
+		return '''dt''';
+	}
+}

+ 107 - 11
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/CppGenerator.xtend

@@ -2,38 +2,134 @@ package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
 
 import be.uantwerpen.ansymo.semanticadaptation.generator.SemanticAdaptationGenerator
 import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMU
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutRulesBlock
 import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
+import java.io.File
+import java.util.LinkedHashMap
 import org.eclipse.emf.ecore.resource.Resource
 import org.eclipse.xtext.generator.IFileSystemAccess2
 import org.eclipse.xtext.generator.IGeneratorContext
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InRulesBlock
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.ControlRuleBlock
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.ControlRule
 
 class CppGenerator extends SemanticAdaptationGenerator {
 
 	var ModelDescriptionCreator mdCreator = new ModelDescriptionCreator()
+	var SwitchTest = new Visitor();
+	var InRulesConditionSwitch inrules;
+	var LinkedHashMap<String, Pair<String, Integer>> scalars = newLinkedHashMap();
+	private var IFileSystemAccess2 fsa;
 
 	override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
-
-		for (type : resource.allContents.toIterable.filter(SemanticAdaptation)){
-				fsa.generateFile(type.name + ".cpp", type.compile)
-				mdCreator.name = type.name;
-				fsa.generateFile("modelDescription.xml", mdCreator.modelDescription);
+		this.fsa = fsa;
+		for (type : resource.allContents.toIterable.filter(SemanticAdaptation)) {
+			type.compile;
+			//fsa.generateFile(type.name + ".cpp", type.compile)
+			mdCreator.name = type.name;
+			fsa.generateFile("modelDescription.xml", mdCreator.modelDescription);
 		}
+//		
+//		for(type : resource.allContents.toIterable)
+//		{
+//			SwitchTest.doSwitch(type);
+//		}
 	}
 
 // TODO: Verify adaptation.name is not a C++ keyword
 // TODO: Add initial value to inputs in the model description file
-	def CharSequence compile(SemanticAdaptation adaptation) {
-		var adaptationCharSequence = newArrayList()
+	def void compile(SemanticAdaptation adaptation) {
 		for (type : adaptation.elements.filter(Adaptation)) {
-			mdCreator.CreateInputsOutput(type);
-			adaptationCharSequence.add(type.compile)
+			var fmus = newArrayList();		
+			for (fmu : type.inner.eAllContents.toIterable.filter(InnerFMU)) {
+				//TODO: Merge this with ModelDescriptionCreator somehow
+				var md = new ModelDescription(fmu.name, new File(fmu.path.replace('\"', '')));
+				fmus.add(fmu.name);
+				this.scalars.putAll(md.scalars);
+			}
+			
+			var defines = newArrayList();
+			for(scalar : this.scalars.entrySet){
+				val pair = scalar.value;
+				defines.add("#define " + pair.key + " " + pair.value);
+			}
+			
+			var String generatedDefines = defines.join("\n");
+			fsa.generateFile("defines.cpp", generatedDefines);
+			
+			var String generatedCpp;
+			
+			//This generates all the inrules
+			this.inrules = new InRulesConditionSwitch(type.name, scalars);
+			for (inRules : adaptation.eAllContents.toIterable.filter(InRulesBlock)) {
+				for (dataRule : inRules.eAllContents.toIterable.filter(DataRule)) {
+					this.inrules.incrementCount;
+					generatedCpp+=this.inrules.doSwitch(dataRule);
+				}
+			}
+			
+			//This generates all the outrules
+			var outrules = new OutRulesConditionSwitch(type.name, scalars);
+			for(outRules : adaptation.eAllContents.toIterable.filter(OutRulesBlock)){
+				for(dataRule : outRules.eAllContents.toIterable.filter(DataRule)){
+					outrules.incrementCount;
+					generatedCpp+=outrules.doSwitch(dataRule);
+				}
+			}
+			
+			var controlrule = new ControlConditionSwitch(type.name,	 scalars);
+			for(controlRule : adaptation.eAllContents.toIterable.filter(ControlRuleBlock)){
+				for(crtlRule : controlRule.eAllContents.toIterable.filter(ControlRule)){
+					generatedCpp += controlrule.doSwitch(crtlRule);
+				}
+			}
+
+			fsa.generateFile(type.name+".cpp", generatedCpp);
+			
+			var String header = 
+			'''
+			class «type.name» : SemanticAdaptation<«type.name»>{
+				public:
+					«type.name»();
+					virtual ~«type.name»();
+					
+					void setFmiValue(int id, int value);
+					void setFmiValue(int id, bool value);
+					void setFmiValue(int id, double value);
+				
+					int getFmiValueInteger(int id);
+					bool getFmiValueBoolean(int id);
+					double getFmiValueDouble(int id);
+				private:
+					shared_ptr<std::list<Rule<«type.name»>>>createInputRules();
+					shared_ptr<std::list<Rule<«type.name»>>> createOutputRules();
+					
+					/*in rules*/
+					«inrules.functionSignatures.join("\n")»
+					
+					/*out rules*/
+					«outrules.functionSignatures.join("\n")»
+					
+					«controlrule.functionSignatures.join("\n")»
+					
+					«FOR fmu : fmus»
+						shared_ptr<Fmu> «fmu»;
+					«ENDFOR»
+					
+					«FOR sv : scalars.entrySet»
+						
+					«ENDFOR»
+			}
+			'''
+			fsa.generateFile(type.name+".h", header);
+			
 		}
 
-		return adaptationCharSequence.join('''\n''');
 	}
 
 	def CharSequence compile(Adaptation adaptation) {
-		
 		return '''compiling «adaptation.toString»''';
 	}
 }

+ 157 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/InOutRulesConditionSwitch.xtend

@@ -0,0 +1,157 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
+
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Assignment
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BoolLiteral
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CompositeOutputFunction
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.If
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IsSet
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.LValueDeclaration
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RealLiteral
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RuleCondition
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleVarDeclaration
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StateTransitionFunction
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.util.SemanticAdaptationSwitch
+import java.util.LinkedHashMap
+import java.util.List
+import org.eclipse.emf.ecore.EObject
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Multi
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IntLiteral
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Neg
+
+abstract class InOutRulesConditionSwitch extends SemanticAdaptationSwitch<String> {
+
+	protected final String adaptationName;
+	protected final LinkedHashMap<String, Pair<String, Integer>> scalars;
+	protected Integer count = 0;
+	private final String functionPrefix;
+	protected List<String> functionSignatures = newArrayList();
+	protected String externalVariableOwner;
+
+	new(String adaptationName, LinkedHashMap<String, Pair<String, Integer>> scalars, String functionPrefix) {
+		this.adaptationName = adaptationName;
+		this.scalars = scalars;
+		this.functionPrefix = functionPrefix;
+	}
+
+	/**
+	 * This function adds a header style function signature to the list <i>functionsignatures</i> 
+	 * and returns the source style function signature
+	 */
+	protected def String createFunctionSignature(String functionName, String type) {
+		val functionSignature = this.functionPrefix + functionName + this.count + "()";
+		this.functionSignatures.add(type + " " + functionSignature);
+		return type + " " + this.adaptationName + "::" + functionSignature;
+	}
+
+	def void incrementCount() {
+		this.count++;
+	}
+
+	override String caseBoolLiteral(BoolLiteral object) {
+		return '''«object.value»''';
+	}
+
+	override String caseRealLiteral(RealLiteral object) {
+		return '''«object.value»''';
+	}
+
+	override String caseRuleCondition(RuleCondition object) {
+		val functionSignature = createFunctionSignature("condition","bool");
+		'''«functionSignature»{
+			return «doSwitch(object.condition)»;
+		}''';
+	}
+
+	override String caseStateTransitionFunction(StateTransitionFunction object) {
+		val functionSig = createFunctionSignature("body","void");
+		'''«functionSig»{
+			«IF object.expression !== null»
+			«doSwitch(object.expression)»
+			«ENDIF»
+			«IF object.statements !== null»
+				«FOR stm : object.statements»
+				«doSwitch(stm)»
+				«ENDFOR»
+			«ENDIF»			
+			«IF object.assignment !== null»
+			«doSwitch(object.assignment)»
+			«ENDIF»
+		}
+		''';
+	}
+
+	override String caseDataRule(DataRule object) {
+		return '''			
+			«doSwitch(object.condition)»
+				«doSwitch(object.statetransitionfunction)»
+				«doSwitch(object.outputfunction)»
+		'''
+	}
+
+	override String defaultCase(EObject object) {
+		return '''[«object.class»]''';
+	}
+
+	override String caseIf(If object) {
+		'''
+			if(«doSwitch(object.ifcondition)»){
+				«FOR stm : object.ifstatements»
+					«doSwitch(stm)»
+				«ENDFOR»
+			}
+		''';
+	}
+
+	override String caseLValueDeclaration(LValueDeclaration object) {
+		return '''«object.name»'''
+	}
+
+	override String caseAssignment(Assignment object) {
+		return '''«doSwitch(object.lvalue)» = «doSwitch(object.expr)»;'''
+	}
+
+	override String caseIsSet(IsSet object) {
+		return '''this->isSet«(object.args as Variable).ref.name»'''
+	}
+
+	override String caseMulti(Multi object) {
+		return '''«doSwitch(object.left)» * «doSwitch(object.right)»''';
+	}
+
+	override String caseIntLiteral(IntLiteral object) {
+		return '''«object.value»''';
+	}
+
+	override String caseNeg(Neg object) {
+		return '''-«doSwitch(object.right)»'''
+	}
+
+	override String caseVariable(Variable object) {
+		if (object.owner === null || object.owner.name == this.adaptationName) {
+			return '''this->«object.ref.name»''';
+		} else {
+			this.externalVariableOwner = object.owner.name;
+			return '''«doSwitch(object.ref)»''';
+		}
+	}
+
+	override String caseSingleVarDeclaration(SingleVarDeclaration object) {
+		var returnVal = '''«object.name»'''
+		return returnVal;
+	}
+
+	override String caseCompositeOutputFunction(CompositeOutputFunction object) {
+		val functionSig = createFunctionSignature("flush","void");
+		val returnVal = '''
+			«functionSig»{
+				«FOR stm : object.statements»
+					«doSwitch(stm)»
+				«ENDFOR»
+				}
+		''';
+		return returnVal;
+	}
+
+}

+ 31 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/InRulesConditionSwitch.xtend

@@ -0,0 +1,31 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
+
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Assignment
+import java.util.LinkedHashMap
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CompositeOutputFunction
+
+class InRulesConditionSwitch<CharSequence> extends InOutRulesConditionSwitch {
+
+	private Boolean inOutput = false;
+
+	new(String adaptationName, LinkedHashMap<String, Pair<String, Integer>> scalars) {
+		super(adaptationName, scalars, "in_rule_");
+	}
+
+	override String caseCompositeOutputFunction(CompositeOutputFunction object) {
+		this.inOutput = true;
+		val returnVal = super.caseCompositeOutputFunction(object);
+		this.inOutput = false;
+		return returnVal;
+	}
+
+	override String caseAssignment(Assignment object) {
+		if (inOutput) {	'''
+		setValue(«object.lvalue.owner.name»,«scalars.get(object.lvalue.owner.name+object.lvalue.ref.name).key»,«doSwitch(object.expr)»);
+		''';
+		} else {
+			super.caseAssignment(object);
+		}
+	}
+
+}

+ 79 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescription.xtend

@@ -0,0 +1,79 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
+
+import java.io.File
+import java.util.zip.ZipFile
+import java.util.Enumeration
+import java.util.zip.ZipEntry
+import org.w3c.dom.Document
+import javax.xml.parsers.DocumentBuilderFactory
+import javax.xml.parsers.DocumentBuilder
+import javax.xml.xpath.XPathExpression
+import javax.xml.xpath.XPathFactory
+import javax.xml.xpath.XPath
+import javax.xml.soap.Node
+import javax.xml.xpath.XPathConstants
+import org.w3c.dom.NodeList
+import java.util.LinkedHashMap
+import javax.lang.model.element.Element
+
+class ModelDescription {
+	private final Document md;
+	private final String name;
+	private var LinkedHashMap<String,Pair<String,Integer>> scalarDefinitions = newLinkedHashMap();
+	private var LinkedHashMap<String,SVType> scalarWithTypes = newLinkedHashMap();
+
+	new(String name, File path) {
+		this.name = name;
+
+		var ZipFile fmu = new ZipFile(path);
+		var Enumeration<? extends ZipEntry> entries = fmu.entries();
+		var boolean entryFound = false;
+		var ZipEntry locatedEntry;
+
+		while (!entryFound && entries.hasMoreElements()) {
+			var ZipEntry entry = entries.nextElement();
+			if (entry.name.equalsIgnoreCase("modelDescription.xml"))
+				locatedEntry = entry;
+		}
+		var DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance();
+		var DocumentBuilder builder = fac.newDocumentBuilder();
+		val is = fmu.getInputStream(locatedEntry)
+		this.md = builder.parse(is);
+		is.close();
+		calcScalars();
+	}
+
+	private def calcScalars() {
+		val XPathFactory xPathfactory = XPathFactory.newInstance();
+		val XPath xpath = xPathfactory.newXPath();
+		val XPathExpression expr = xpath.compile("/fmiModelDescription/ModelVariables/ScalarVariable");
+		val NodeList nl = expr.evaluate(this.md, XPathConstants.NODESET) as NodeList;
+		for (var int i = 0; i < nl.length; i++) {
+			val node = nl.item(i);
+			val nodeName = node.attributes.getNamedItem("name").nodeValue;
+			val name = this.name + nodeName;
+			val define = name.toUpperCase; 
+			this.scalarDefinitions.put(name,define -> i+1);
+			
+			for(var j = 0; j < node.childNodes.length; j++)
+			{
+				val subNode = node.childNodes.item(i);
+				if(subNode.nodeType == Node.ELEMENT_NODE)
+				{
+					val type = SVType.valueOf(subNode.nodeName);
+					this.scalarWithTypes.put(nodeName, type);
+					//Alternative break, as break is not allowed
+					j = node.childNodes.length;
+				}
+			}
+		}
+	}
+	
+	public def getName(){
+		return this.name;
+	}
+	
+	public def getScalars() {
+		return this.scalarDefinitions;
+	}
+}

+ 1 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescriptionBuilder.java

@@ -37,7 +37,7 @@ public class ModelDescriptionBuilder {
 		rootElement.setAttribute("fmiVersion", "2.0");
 		rootElement.setAttribute("modelName", modelName);
 		rootElement.setAttribute("guid", guid);
-		rootElement.setAttribute("variableNamingConvention", "structured");
+		rootElement.setAttribute("variableNamingConvention", "flat");
 
 		modelVariables = doc.createElement("ModelVariables");
 		rootElement.appendChild(modelVariables);

+ 4 - 1
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/ModelDescriptionCreator.xtend

@@ -42,8 +42,11 @@ public class ModelDescriptionCreator {
 		mdName = name;
 	}
 	
+	public def List<ScalarVariable> getScalars(){
+		return this.sVars;
+	}
+	
 	private def Document getModelDescription(File path) {
-		System.out.println(path.absolutePath);
 		var ZipFile fmu = new ZipFile(path);
 		var Enumeration<? extends ZipEntry> entries = fmu.entries();
 		var boolean entryFound = false;

+ 23 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/OutRulesConditionSwitch.xtend

@@ -0,0 +1,23 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp;
+
+import java.util.LinkedHashMap;
+
+import org.eclipse.xtext.xbase.lib.Pair;
+
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Assignment;
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StateTransitionFunction
+
+public class OutRulesConditionSwitch extends InOutRulesConditionSwitch {
+
+
+	private boolean inBody = false;
+
+	new(String adaptationName, LinkedHashMap<String, Pair<String, Integer>> scalars) {
+		super(adaptationName, scalars, "out_rule_");
+	}
+	
+	override String casePort(Port object){
+		return '''getValue(«this.externalVariableOwner»,«this.scalars.get(this.externalVariableOwner+object.name).key»)'''
+	}
+}

+ 22 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.cg.cpp/src/be/uantwerpen/ansymo/semanticadaptation/cg/cpp/Visitor.xtend

@@ -0,0 +1,22 @@
+package be.uantwerpen.ansymo.semanticadaptation.cg.cpp
+
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.util.SemanticAdaptationSwitch
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
+import org.eclipse.xtext.xbase.interpreter.impl.XbaseInterpreter
+import com.google.inject.Inject
+import com.google.inject.Provider
+import org.eclipse.xtext.xbase.interpreter.IEvaluationContext
+import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Expression
+import org.eclipse.xtext.xbase.interpreter.IEvaluationResult
+
+class Visitor<CharSequence> extends SemanticAdaptationSwitch<String> {
+	
+	override String caseSemanticAdaptation(SemanticAdaptation adaptatoin) {
+		return '''a''';		
+	}
+	
+	override String caseExpression(Expression object){
+		return '''object''';
+	}
+	
+}

+ 69 - 0
DSL_SemanticAdaptation/be.uantwerpen.ansymo.semanticadaptation.tests/testInputs/single_folder_spec/windowKEL/window_sa_canonical.BASE.sa

@@ -0,0 +1,69 @@
+module Window_SA
+
+semantic adaptation mealy reactive window_sa
+
+for fmu Window window
+at "./path/to/Window.fmu"
+input ports displacement (rad), speed (rad/s), reaction_force (N)
+
+
+/*
+In the originial version, no input ports where declared, so all dangling inputs of the original fmus are bound to the input ports of the adapted FMU.
+In the canonical version, the input and output ports are all declared explicitly, and their bindings are implemented in the in/out rules.
+*/
+
+input ports 	reaction_force,
+				displacement,
+				speed;
+
+output ports	disp;
+				tau;
+
+in var 	stored_windowsa_reaction_force,
+		stored_windowsa_displacement,
+		stored_windowsa_speed;
+
+out var stored_window_reaction_torque,
+		stored_window_height;
+
+in rules {
+	true -> {
+		/*
+		is_set checks whether the input value is given in the setValues call of the adapted FMU.
+		Notice that in the canonical version, all ports are prefixed.
+		*/
+		if (is_set(window_sa.reaction_force))
+			stored_windowsa_reaction_force := window_sa.reaction_force;
+	} --> {
+		window.reaction_force := stored_windowsa_reaction_force;
+	};
+    true -> {
+		if (is_set(window_sa.displacement))
+			stored_windowsa_displacement := window_sa.displacement;
+	} --> {
+		window.displacement := stored_windowsa_displacement; 
+	};
+    true -> {
+		if (is_set(window_sa.speed))
+			stored_windowsa_speed := window_sa.speed;
+	} --> {
+		window.speed := stored_windowsa_speed;
+	};
+}
+
+control rules {
+	do_step(window, t, H); // includes update_in rules and update_out (update-in rules do not update state)
+}
+
+out rules {
+	true => {
+		stored_window_reaction_torque := window.reaction_torque;
+	} -> {
+		window_sa.tau := - stored_window_reaction_torque;
+	}
+	true => {
+		stored_window_height := window.height;
+	} -> {
+		window_sa.disp := stored_window_height * 100;
+	}
+}