InOutRulesConditionSwitch.xtend 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  1. package be.uantwerpen.ansymo.semanticadaptation.cg.cpp.generation
  2. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.util.SemanticAdaptationSwitch
  3. import java.util.LinkedHashMap
  4. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.SVType
  5. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.GlobalInOutVariable
  6. import java.util.List
  7. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.MappedScalarVariable
  8. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.SAScalarVariable
  9. import be.uantwerpen.ansymo.semanticadaptation.cg.cpp.data.ReturnInformation
  10. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Literal
  11. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RealLiteral
  12. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IntLiteral
  13. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BoolLiteral
  14. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutRulesBlock
  15. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
  16. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InRulesBlock
  17. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RuleCondition
  18. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StateTransitionFunction
  19. import org.eclipse.emf.ecore.EObject
  20. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Assignment
  21. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Multi
  22. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Neg
  23. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleVarDeclaration
  24. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.If
  25. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CompositeOutputFunction
  26. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
  27. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.LValueDeclaration
  28. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Declaration
  29. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IsSet
  30. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Div
  31. import org.eclipse.emf.common.util.EList
  32. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InOutRules
  33. abstract class InOutRulesConditionSwitch extends SemanticAdaptationSwitch<ReturnInformation> {
  34. // Global in and out variables
  35. protected var LinkedHashMap<String, GlobalInOutVariable> gVars = newLinkedHashMap();
  36. // Global params
  37. protected var LinkedHashMap<String, GlobalInOutVariable> params;
  38. protected final String adaptationName;
  39. protected final String adaptationClassName;
  40. private Integer count = 0;
  41. /** See the method {@link #createFunctionSignature(String, String)} and subclasses */
  42. private final String functionPrefix;
  43. protected List<String> functionSignatures = newArrayList();
  44. /*
  45. * Intermediate variable used for referencing external FMU.
  46. * It is necessary because of parsing error
  47. */
  48. protected String externalVariableOwner;
  49. protected final LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars;
  50. protected final LinkedHashMap<String, SAScalarVariable> SASVs;
  51. protected boolean inRuleCondition;
  52. protected boolean inRuleTransition;
  53. protected boolean inRuleOutput;
  54. protected boolean inControlRule;
  55. // This is used for storing initialization information for global declarations.
  56. protected String constructorInitialization = "";
  57. // Flag to signal whether the declarations to be processed are global or local.
  58. protected boolean globalDeclaration = false;
  59. // Add scope information to this.
  60. protected var LinkedHashMap<String, SVType> localDeclarations = newLinkedHashMap();
  61. new(
  62. String adaptationClassName,
  63. String adaptationName,
  64. String functionPrefix,
  65. LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars,
  66. LinkedHashMap<String, SAScalarVariable> SASVs,
  67. LinkedHashMap<String, GlobalInOutVariable> params
  68. ) {
  69. this.params = params;
  70. this.SASVs = SASVs;
  71. this.adaptationName = adaptationName;
  72. this.adaptationClassName = adaptationClassName;
  73. this.functionPrefix = functionPrefix;
  74. this.mSVars = mSVars;
  75. }
  76. /*
  77. * UTILITY FUNCTIONS
  78. */
  79. override ReturnInformation defaultCase(EObject object) {
  80. var retVal = new ReturnInformation();
  81. retVal.code = '''[«object.class»]''';
  82. return retVal;
  83. }
  84. private def Object convertTypeToObject(SVType type, Literal object) {
  85. switch (type) {
  86. case Real: {
  87. return (object as RealLiteral).value.doubleValue;
  88. }
  89. case Integer: {
  90. return (object as IntLiteral).value;
  91. }
  92. case Boolean: {
  93. return Boolean.parseBoolean((object as BoolLiteral).value);
  94. }
  95. default: {
  96. }
  97. }
  98. }
  99. public def getGlobalVars() { return this.gVars; }
  100. public def getConstructorInitialization() { return this.constructorInitialization; }
  101. /**
  102. * This function adds a header style function signature to the list <i>functionsignatures</i>
  103. * and returns the source style function signature
  104. */
  105. protected def String createFunctionSignature(String functionName, String type) {
  106. val functionSignature = this.functionPrefix + functionName + this.count + "()";
  107. this.functionSignatures.add(type + " " + functionSignature);
  108. return type + " " + this.adaptationClassName + "::" + functionSignature;
  109. }
  110. def void incrementCount() {
  111. this.count++;
  112. }
  113. /*
  114. * COMPILATION FUNCTIONS
  115. */
  116. protected def ReturnInformation doSwitch(EList<Declaration> gVars, InOutRules object) {
  117. this.globalDeclaration = true;
  118. var retVal = new ReturnInformation();
  119. // Get the global variables added to globalVars
  120. for (gVar : gVars) {
  121. constructorInitialization += doSwitch(gVar).code;
  122. }
  123. this.globalDeclaration = false;
  124. for (dataRule : object.eAllContents.toIterable.filter(DataRule)) {
  125. this.incrementCount;
  126. retVal.appendCode(doSwitch(dataRule).code);
  127. }
  128. return retVal;
  129. }
  130. override ReturnInformation caseInRulesBlock(InRulesBlock object) {
  131. return this.doSwitch(object.globalInVars, object);
  132. }
  133. override ReturnInformation caseOutRulesBlock(OutRulesBlock object) {
  134. return this.doSwitch(object.globalOutVars, object);
  135. }
  136. override ReturnInformation caseDataRule(DataRule object) {
  137. var retVal = new ReturnInformation();
  138. inRuleCondition = true;
  139. val conditionSwitch = doSwitch(object.condition);
  140. inRuleCondition = false;
  141. inRuleTransition = true;
  142. val transitionSwitch = doSwitch(object.statetransitionfunction);
  143. inRuleTransition = false;
  144. inRuleOutput = true;
  145. val outputSwitch = doSwitch(object.outputfunction);
  146. inRuleOutput = false;
  147. retVal.code = '''
  148. «conditionSwitch.code»
  149. «transitionSwitch.code»
  150. «outputSwitch.code»
  151. '''
  152. return retVal;
  153. }
  154. override ReturnInformation caseRuleCondition(RuleCondition object) {
  155. var retVal = new ReturnInformation();
  156. val functionSignature = createFunctionSignature("condition", "bool");
  157. retVal.code = '''
  158. «functionSignature»{
  159. return «doSwitch(object.condition).code»;
  160. }
  161. ''';
  162. return retVal;
  163. }
  164. override ReturnInformation caseStateTransitionFunction(StateTransitionFunction object) {
  165. var retVal = new ReturnInformation();
  166. val functionSig = createFunctionSignature("body", "void");
  167. retVal.code = '''
  168. «functionSig»{
  169. «IF object.expression !== null»
  170. «doSwitch(object.expression).code»
  171. «ENDIF»
  172. «IF object.statements !== null»
  173. «FOR stm : object.statements»
  174. «doSwitch(stm).code»
  175. «ENDFOR»
  176. «ENDIF»
  177. «IF object.assignment !== null»
  178. «doSwitch(object.assignment).code»
  179. «ENDIF»
  180. }
  181. ''';
  182. return retVal;
  183. }
  184. override ReturnInformation caseIf(If object) {
  185. var retVal = new ReturnInformation();
  186. retVal.code = '''
  187. if(«doSwitch(object.ifcondition).code»){
  188. «FOR stm : object.ifstatements»
  189. «doSwitch(stm).code»
  190. «ENDFOR»
  191. }
  192. ''';
  193. return retVal;
  194. }
  195. private def calcConSaSvData(SAScalarVariable SASV, ReturnInformation rI) {
  196. if (SASV !== null) {
  197. if (rI.typeIsSet) {
  198. SASV.type = rI.type;
  199. SASV.variability = Conversions.fmiTypeToFmiVariability(rI.type);
  200. return;
  201. } else if (rI.conGlobVar !== null) {
  202. SASV.type = rI.conGlobVar.type;
  203. SASV.variability = Conversions.fmiTypeToFmiVariability(rI.conGlobVar.type);
  204. return;
  205. }
  206. }
  207. throw new Exception("Not enough information to determine content of the SASV: " + SASV.name);
  208. }
  209. override ReturnInformation caseAssignment(Assignment object) {
  210. var retVal = new ReturnInformation();
  211. var lValSwitch = doSwitch(object.lvalue);
  212. var rValSwitch = doSwitch(object.expr);
  213. // Here we set the information necessary to create a scalar variables in the model description for the SA.
  214. if (inRuleTransition) {
  215. if (rValSwitch.conSaSv !== null) {
  216. calcConSaSvData(rValSwitch.conSaSv, lValSwitch);
  217. }
  218. } else if (inRuleOutput) {
  219. calcConSaSvData(lValSwitch.conSaSv, rValSwitch);
  220. }
  221. retVal.code = '''«lValSwitch.code» = «rValSwitch.code»;''';
  222. return retVal;
  223. }
  224. override ReturnInformation caseMulti(Multi object) {
  225. val doSwitchLeft = doSwitch(object.left);
  226. val doSwitchRight = doSwitch(object.right);
  227. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  228. retVal.code = '''«doSwitchLeft.code» * «doSwitchRight.code»''';
  229. return retVal;
  230. }
  231. override ReturnInformation caseDiv(Div object) {
  232. val doSwitchLeft = doSwitch(object.left);
  233. val doSwitchRight = doSwitch(object.right);
  234. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  235. retVal.code = '''«doSwitchLeft.code» / «doSwitchRight.code»''';
  236. retVal.type = SVType.Real;
  237. retVal.forceType = true;
  238. return retVal;
  239. }
  240. override ReturnInformation caseNeg(Neg object) {
  241. var doSwitch = doSwitch(object.right);
  242. var retVal = new ReturnInformation(doSwitch);
  243. retVal.code = doSwitch.code;
  244. return retVal;
  245. }
  246. override ReturnInformation caseSingleVarDeclaration(SingleVarDeclaration object) {
  247. var retVal = new ReturnInformation();
  248. retVal.code = '''«object.name»''';
  249. return retVal;
  250. }
  251. override ReturnInformation caseCompositeOutputFunction(CompositeOutputFunction object) {
  252. var retVal = new ReturnInformation();
  253. val functionSig = createFunctionSignature("flush", "void");
  254. retVal.code = '''
  255. «functionSig»{
  256. «FOR stm : object.statements»
  257. «doSwitch(stm).code»
  258. «ENDFOR»
  259. }
  260. ''';
  261. return retVal;
  262. }
  263. override ReturnInformation caseVariable(Variable object) {
  264. var retVal = new ReturnInformation();
  265. if (object.owner === null || object.owner.name == this.adaptationName) {
  266. if (SASVs.containsKey(object.ref.name) || gVars.containsKey(object.ref.name) ||
  267. params.containsKey(object.ref.name)) {
  268. retVal.code = '''this->«object.ref.name»''';
  269. if (SASVs.containsKey(object.ref.name)) {
  270. retVal.conSaSv = SASVs.get(object.ref.name);
  271. } else if (gVars.containsKey(object.ref.name)) {
  272. retVal.conGlobVar = gVars.get(object.ref.name);
  273. } else if (params.containsKey(object.ref.name)) {
  274. retVal.conGlobVar = params.get(object.ref.name);
  275. }
  276. } else if (localDeclarations.containsKey(object.ref.name)) {
  277. retVal.code = '''«object.ref.name»'''
  278. retVal.type = localDeclarations.get(object.ref.name);
  279. }
  280. } else {
  281. this.externalVariableOwner = object.owner.name;
  282. retVal.code = '''«doSwitch(object.ref).code»''';
  283. }
  284. return retVal;
  285. }
  286. override ReturnInformation caseLValueDeclaration(LValueDeclaration object) {
  287. var retVal = new ReturnInformation();
  288. retVal.code = '''«object.name»''';
  289. return retVal;
  290. }
  291. override ReturnInformation caseDeclaration(Declaration object) {
  292. var retVal = new ReturnInformation();
  293. for (SingleVarDeclaration decl : object.declarations) {
  294. var doSwitchRes = doSwitch(decl.expr);
  295. var String code = "";
  296. if (globalDeclaration) {
  297. // This is an in var or out var declaration
  298. code = '''
  299. this->«decl.name» = «doSwitchRes.code»;
  300. '''
  301. var globVar = new GlobalInOutVariable();
  302. globVar.name = decl.name;
  303. globVar.value = doSwitchRes.value;
  304. globVar.type = doSwitchRes.type;
  305. gVars.put(decl.name, globVar);
  306. } else {
  307. // This is a local declaration.
  308. val String type = Conversions.fmiTypeToCppType(doSwitchRes.type)
  309. code = '''«type» «decl.name» = «doSwitchRes.code»''';
  310. this.localDeclarations.put(decl.name, doSwitchRes.type);
  311. }
  312. retVal.appendCode = code;
  313. }
  314. return retVal;
  315. }
  316. override ReturnInformation caseIsSet(IsSet object) {
  317. var retInfo = new ReturnInformation();
  318. retInfo.code = '''this->isSet«(object.args as Variable).ref.name»''';
  319. return retInfo;
  320. }
  321. override ReturnInformation caseRealLiteral(RealLiteral object) {
  322. var retInfo = new ReturnInformation();
  323. retInfo.type = SVType.Real;
  324. retInfo.value = convertTypeToObject(retInfo.type, object);
  325. retInfo.code = '''«object.value»''';
  326. return retInfo;
  327. }
  328. override ReturnInformation caseIntLiteral(IntLiteral object) {
  329. var retInfo = new ReturnInformation();
  330. retInfo.type = SVType.Integer;
  331. retInfo.value = convertTypeToObject(retInfo.type, object);
  332. retInfo.code = '''«object.value»''';
  333. return retInfo;
  334. }
  335. override ReturnInformation caseBoolLiteral(BoolLiteral object) {
  336. var retInfo = new ReturnInformation();
  337. retInfo.type = SVType.Boolean;
  338. retInfo.value = convertTypeToObject(retInfo.type, object);
  339. retInfo.code = '''«object.value»''';
  340. return retInfo;
  341. }
  342. }