RulesConditionSwitch.xtend 15 KB

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