RulesConditionSwitch.xtend 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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. class RulesConditionSwitch extends SemanticAdaptationSwitch<ReturnInformation> {
  47. // Global params
  48. protected var LinkedHashMap<String, GlobalInOutVariable> params;
  49. protected final String adaptationName;
  50. protected final String adaptationClassName;
  51. private Integer count = 0;
  52. /** See the method {@link #createFunctionSignature(String, String)} and subclasses */
  53. private final String functionPrefix;
  54. protected List<String> functionSignatures = newArrayList();
  55. /*
  56. * Intermediate variable used for referencing external FMU.
  57. * Currently only used by OutRulesConditionSwitch.
  58. */
  59. protected String externalVariableOwner;
  60. protected final LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars;
  61. protected final LinkedHashMap<String, SAScalarVariable> SASVs;
  62. // Global in and out variables
  63. protected var LinkedHashMap<String, GlobalInOutVariable> gVars = newLinkedHashMap();
  64. LinkedHashMap<String, GlobalInOutVariable> inVars;
  65. LinkedHashMap<String, GlobalInOutVariable> outVars;
  66. LinkedHashMap<String, GlobalInOutVariable> crtlVars;
  67. protected boolean inRuleCondition;
  68. protected boolean inRuleTransition;
  69. protected boolean inRuleOutput;
  70. protected boolean inControlRule;
  71. // Flag to signal whether the declarations to be processed are global or local.
  72. protected boolean globalDeclaration = false;
  73. // Add scope information to this.
  74. protected var LinkedHashMap<String, SVType> localDeclarations = newLinkedHashMap();
  75. protected String forLoopIterVar;
  76. protected boolean forLoopIterVarIsSet = false;
  77. new(
  78. String adaptationClassName,
  79. String adaptationName,
  80. String functionPrefix,
  81. LinkedHashMap<String, LinkedHashMap<String, MappedScalarVariable>> mSVars,
  82. LinkedHashMap<String, SAScalarVariable> SASVs,
  83. LinkedHashMap<String, GlobalInOutVariable> params,
  84. LinkedHashMap<String, GlobalInOutVariable> inVars,
  85. LinkedHashMap<String, GlobalInOutVariable> outVars,
  86. LinkedHashMap<String, GlobalInOutVariable> crtlVars
  87. ) {
  88. this.params = params;
  89. this.SASVs = SASVs;
  90. this.adaptationName = adaptationName;
  91. this.adaptationClassName = adaptationClassName;
  92. this.functionPrefix = functionPrefix;
  93. this.mSVars = mSVars;
  94. this.outVars = outVars;
  95. this.inVars = inVars;
  96. this.crtlVars = crtlVars;
  97. }
  98. /*
  99. * UTILITY FUNCTIONS
  100. */
  101. override ReturnInformation defaultCase(EObject object) {
  102. var retVal = new ReturnInformation();
  103. retVal.code = '''[«object.class»]''';
  104. return retVal;
  105. }
  106. private def Object convertTypeToObject(SVType type, Literal object) {
  107. switch (type) {
  108. case Real: {
  109. return (object as RealLiteral).value.doubleValue;
  110. }
  111. case Integer: {
  112. return (object as IntLiteral).value;
  113. }
  114. case Boolean: {
  115. return Boolean.parseBoolean((object as BoolLiteral).value);
  116. }
  117. default: {
  118. }
  119. }
  120. }
  121. public def getGlobalVars() { return this.gVars; }
  122. public def getConstructorInitialization() { return this.constructorInitialization; }
  123. /**
  124. * This function adds a header style function signature to the list <i>functionsignatures</i>
  125. * and returns the source style function signature
  126. */
  127. protected def String createFunctionSignature(String functionName, String type) {
  128. val functionSignature = this.functionPrefix + functionName + this.count + "()";
  129. this.functionSignatures.add(type + " " + functionSignature);
  130. return type + " " + this.adaptationClassName + "::" + functionSignature;
  131. }
  132. def void incrementCount() {
  133. this.count++;
  134. }
  135. /*
  136. * COMPILATION FUNCTIONS
  137. */
  138. public def Pair<String, LinkedHashMap<String, GlobalInOutVariable>> getGlobalVars(EList<Declaration> gVars)
  139. {
  140. var String constructorInitialisation= "";
  141. // Get the global variables added to globalVars
  142. this.globalDeclaration = true;
  143. for (gVar : gVars) {
  144. constructorInitialisation += doSwitch(gVar).code;
  145. }
  146. this.globalDeclaration = false;
  147. return constructorInitialisation -> this.gVars;
  148. }
  149. protected def ReturnInformation doSwitch(EList<Declaration> gVars, InOutRules object) {
  150. var retVal = new ReturnInformation();
  151. // // Get the global variables added to globalVars
  152. // this.globalDeclaration = true;
  153. // for (gVar : gVars) {
  154. // constructorInitialization += doSwitch(gVar).code;
  155. // }
  156. // this.globalDeclaration = false;
  157. for (dataRule : object.eAllContents.toIterable.filter(DataRule)) {
  158. this.incrementCount;
  159. retVal.appendCode(doSwitch(dataRule).code);
  160. }
  161. return retVal;
  162. }
  163. override ReturnInformation caseDataRule(DataRule object) {
  164. var retVal = new ReturnInformation();
  165. inRuleCondition = true;
  166. val conditionSwitch = doSwitch(object.condition);
  167. inRuleCondition = false;
  168. inRuleTransition = true;
  169. val transitionSwitch = doSwitch(object.statetransitionfunction);
  170. inRuleTransition = false;
  171. inRuleOutput = true;
  172. val outputSwitch = doSwitch(object.outputfunction);
  173. inRuleOutput = false;
  174. retVal.code = '''
  175. «conditionSwitch.code»
  176. «transitionSwitch.code»
  177. «outputSwitch.code»
  178. '''
  179. return retVal;
  180. }
  181. override ReturnInformation caseRuleCondition(RuleCondition object) {
  182. var retVal = new ReturnInformation();
  183. val functionSignature = createFunctionSignature("condition", "bool");
  184. retVal.code = '''
  185. «functionSignature»{
  186. return «doSwitch(object.condition).code»;
  187. }
  188. ''';
  189. return retVal;
  190. }
  191. override ReturnInformation caseStateTransitionFunction(StateTransitionFunction object) {
  192. var retVal = new ReturnInformation();
  193. val functionSig = createFunctionSignature("body", "void");
  194. retVal.code = '''
  195. «functionSig»{
  196. «IF object.expression !== null»
  197. «val result = doSwitch(object.expression)»
  198. «result.code»«if (!result.isExpression) ";"»
  199. «ENDIF»
  200. «IF object.statements !== null»
  201. «FOR stm : object.statements»
  202. «val result = doSwitch(stm)»
  203. «result.code»«if (!result.isExpression) ";"»
  204. «ENDFOR»
  205. «ENDIF»
  206. «IF object.assignment !== null»
  207. «val result = doSwitch(object.assignment)»
  208. «result.code»«if (!result.isExpression) ";"»
  209. «ENDIF»
  210. }
  211. ''';
  212. return retVal;
  213. }
  214. override ReturnInformation caseIf(If object) {
  215. var retVal = new ReturnInformation();
  216. retVal.isExpression = true;
  217. retVal.code = '''
  218. if(«doSwitch(object.ifcondition).code»){
  219. «FOR stm : object.ifstatements»
  220. «val result = doSwitch(stm)»
  221. «result.code»«if (!result.isExpression) ";"»
  222. «ENDFOR»
  223. }
  224. ''';
  225. if (object.elsestatements.length > 0) {
  226. retVal.appendCode('''
  227. else {
  228. «FOR stm : object.elsestatements»
  229. «doSwitch(stm).code»;
  230. «ENDFOR»
  231. }
  232. ''')
  233. }
  234. return retVal;
  235. }
  236. private def calcConSaSvData(SAScalarVariable SASV, ReturnInformation rI) {
  237. if (SASV !== null) {
  238. if (rI.typeIsSet) {
  239. SASV.type = rI.type;
  240. SASV.variability = Conversions.fmiTypeToFmiVariability(rI.type);
  241. return;
  242. } else if (rI.conGlobVar !== null) {
  243. SASV.type = rI.conGlobVar.type;
  244. SASV.variability = Conversions.fmiTypeToFmiVariability(rI.conGlobVar.type);
  245. return;
  246. }
  247. }
  248. throw new Exception("Not enough information to determine content of the SASV: " + SASV.name);
  249. }
  250. override ReturnInformation caseAssignment(Assignment object) {
  251. var retVal = new ReturnInformation();
  252. var lValSwitch = doSwitch(object.lvalue);
  253. var rValSwitch = doSwitch(object.expr);
  254. // Here we set the information necessary to create a scalar variables in the model description for the SA.
  255. if (inRuleTransition) {
  256. if (rValSwitch.conSaSv !== null) {
  257. calcConSaSvData(rValSwitch.conSaSv, lValSwitch);
  258. }
  259. } else if (inRuleOutput) {
  260. calcConSaSvData(lValSwitch.conSaSv, rValSwitch);
  261. }
  262. retVal.code = '''«lValSwitch.code» = «rValSwitch.code»''';
  263. return retVal;
  264. }
  265. override ReturnInformation caseMulti(Multi object) {
  266. val doSwitchLeft = doSwitch(object.left);
  267. val doSwitchRight = doSwitch(object.right);
  268. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  269. retVal.code = '''«doSwitchLeft.code» * «doSwitchRight.code»''';
  270. return retVal;
  271. }
  272. override ReturnInformation caseDiv(Div object) {
  273. val doSwitchLeft = doSwitch(object.left);
  274. val doSwitchRight = doSwitch(object.right);
  275. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  276. retVal.code = '''«doSwitchLeft.code» / «doSwitchRight.code»''';
  277. retVal.type = SVType.Real;
  278. retVal.forceType = true;
  279. return retVal;
  280. }
  281. override ReturnInformation caseNeg(Neg object) {
  282. var doSwitch = doSwitch(object.right);
  283. var retVal = new ReturnInformation(doSwitch);
  284. retVal.code = doSwitch.code;
  285. return retVal;
  286. }
  287. override ReturnInformation caseSingleVarDeclaration(SingleVarDeclaration object) {
  288. var retVal = new ReturnInformation();
  289. retVal.code = '''«object.name»''';
  290. return retVal;
  291. }
  292. override ReturnInformation caseCompositeOutputFunction(CompositeOutputFunction object) {
  293. var retVal = new ReturnInformation();
  294. val functionSig = createFunctionSignature("flush", "void");
  295. retVal.code = '''
  296. «functionSig»{
  297. «FOR stm : object.statements»
  298. «val result = doSwitch(stm)»
  299. «result.code»«if(!result.isExpression) ";"»
  300. «ENDFOR»
  301. }
  302. ''';
  303. return retVal;
  304. }
  305. override ReturnInformation caseVariable(Variable object) {
  306. var retVal = new ReturnInformation();
  307. if (object.owner === null || object.owner.name == this.adaptationName) {
  308. if ((SASVs !== null && SASVs.containsKey(object.ref.name)) ||
  309. params.containsKey(object.ref.name) ||
  310. (outVars !== null && outVars.containsKey(object.ref.name)) ||
  311. (inVars !== null && inVars.containsKey(object.ref.name)) ||
  312. (crtlVars !== null && crtlVars.containsKey(object.ref.name))) {
  313. retVal.code = '''this->«object.ref.name»''';
  314. if (SASVs !== null && SASVs.containsKey(object.ref.name)) {
  315. retVal.conSaSv = SASVs.get(object.ref.name);
  316. } else if (crtlVars !== null && crtlVars.containsKey(object.ref.name)) {
  317. retVal.conGlobVar = crtlVars.get(object.ref.name);
  318. } else if (params.containsKey(object.ref.name)) {
  319. retVal.conGlobVar = params.get(object.ref.name);
  320. } else if (outVars !== null && outVars.containsKey(object.ref.name)) {
  321. retVal.conGlobVar = outVars.get(object.ref.name);
  322. } else if (inVars !== null && inVars.containsKey(object.ref.name)) {
  323. retVal.conGlobVar = inVars.get(object.ref.name);
  324. }
  325. } else if (localDeclarations.containsKey(object.ref.name)) {
  326. retVal.code = '''«object.ref.name»'''
  327. retVal.type = localDeclarations.get(object.ref.name);
  328. } else {
  329. throw new Exception("Variable not found: " + object.ref.name);
  330. }
  331. } else {
  332. this.externalVariableOwner = object.owner.name;
  333. retVal.code = '''«doSwitch(object.ref).code»''';
  334. }
  335. return retVal;
  336. }
  337. override ReturnInformation caseLValueDeclaration(LValueDeclaration object) {
  338. var retVal = new ReturnInformation();
  339. retVal.code = '''«object.name»''';
  340. return retVal;
  341. }
  342. override ReturnInformation caseVar(Var object) {
  343. var retVal = new ReturnInformation();
  344. return retVal;
  345. }
  346. override ReturnInformation caseDeclaration(Declaration object) {
  347. var retVal = new ReturnInformation();
  348. for (SingleVarDeclaration decl : object.declarations) {
  349. var doSwitchRes = doSwitch(decl.expr);
  350. var String code = "";
  351. if (globalDeclaration) {
  352. // This is an in var, out var or crtl var declaration
  353. code = '''
  354. this->«decl.name» = «doSwitchRes.code»;
  355. '''
  356. var globVar = new GlobalInOutVariable(decl.name, doSwitchRes.type);
  357. gVars.put(decl.name, globVar);
  358. } else {
  359. // This is a local declaration.
  360. val String type = Conversions.fmiTypeToCppType(doSwitchRes.type)
  361. code = '''
  362. «type» «decl.name» = «doSwitchRes.code»;
  363. ''';
  364. this.localDeclarations.put(decl.name, doSwitchRes.type);
  365. }
  366. retVal.appendCode = code;
  367. }
  368. return retVal;
  369. }
  370. override ReturnInformation caseIsSet(IsSet object) {
  371. var retInfo = new ReturnInformation();
  372. retInfo.code = '''this->isSet«(object.args as Variable).ref.name»''';
  373. return retInfo;
  374. }
  375. override ReturnInformation caseRealLiteral(RealLiteral object) {
  376. var retInfo = new ReturnInformation();
  377. retInfo.type = SVType.Real;
  378. retInfo.value = convertTypeToObject(retInfo.type, object);
  379. retInfo.code = '''«object.value»''';
  380. return retInfo;
  381. }
  382. override ReturnInformation caseIntLiteral(IntLiteral object) {
  383. var retInfo = new ReturnInformation();
  384. retInfo.type = SVType.Integer;
  385. retInfo.value = convertTypeToObject(retInfo.type, object);
  386. retInfo.code = '''«object.value»''';
  387. return retInfo;
  388. }
  389. override ReturnInformation caseBoolLiteral(BoolLiteral object) {
  390. var retInfo = new ReturnInformation();
  391. retInfo.type = SVType.Boolean;
  392. retInfo.value = convertTypeToObject(retInfo.type, object);
  393. retInfo.code = '''«object.value»''';
  394. return retInfo;
  395. }
  396. override ReturnInformation caseMin(Min object) {
  397. var retInfo = new ReturnInformation();
  398. var doSwitchResCode = newArrayList();
  399. for (expr : object.args) {
  400. val doSwitchRes_ = this.doSwitch(expr);
  401. doSwitchResCode.add(doSwitchRes_.code);
  402. retInfo = new ReturnInformation(retInfo, doSwitchRes_);
  403. }
  404. retInfo.code = '''
  405. min({«doSwitchResCode.join(",")»})
  406. '''
  407. return retInfo;
  408. }
  409. override ReturnInformation caseMinus(Minus object) {
  410. val doSwitchLeft = doSwitch(object.left);
  411. val doSwitchRight = doSwitch(object.right);
  412. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  413. retVal.code = '''«doSwitchLeft.code» - «doSwitchRight.code»''';
  414. return retVal;
  415. }
  416. override ReturnInformation casePlus(Plus object) {
  417. val doSwitchLeft = doSwitch(object.left);
  418. val doSwitchRight = doSwitch(object.right);
  419. var retVal = new ReturnInformation(doSwitchLeft, doSwitchRight);
  420. retVal.code = '''«doSwitchLeft.code» + «doSwitchRight.code»''';
  421. return retVal;
  422. }
  423. override ReturnInformation caseFor(For object) {
  424. {
  425. var retVal = new ReturnInformation();
  426. retVal.isExpression = true;
  427. val iterator = doSwitch(object.iterator);
  428. forLoopIterVar = iterator.code;
  429. forLoopIterVarIsSet = true;
  430. val iterable = doSwitch(object.iterable);
  431. retVal.appendCode('''
  432. for (int «forLoopIterVar» = «iterable.code»){
  433. «FOR stm : object.statements»
  434. «val result = doSwitch(stm)»
  435. «result.code»«if (!result.isExpression) ";"»
  436. «ENDFOR»
  437. }
  438. ''')
  439. forLoopIterVarIsSet = false;
  440. return retVal;
  441. }
  442. }
  443. override ReturnInformation caseRange(Range object) {
  444. var retVal = new ReturnInformation();
  445. val left = doSwitch(object.left);
  446. val right = doSwitch(object.right);
  447. retVal.appendCode('''«left.code»; «forLoopIterVar»<=«right.code»; «forLoopIterVar»++''')
  448. return retVal;
  449. }
  450. }