RulesConditionSwitch.xtend 13 KB

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