RulesConditionSwitch.xtend 17 KB

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