SemanticAdaptationCanonicalGenerator.xtend 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205
  1. /*
  2. * generated by Xtext 2.10.0
  3. */
  4. package be.uantwerpen.ansymo.semanticadaptation.generator
  5. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
  6. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BoolLiteral
  7. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BuiltinFunction
  8. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Close
  9. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CompositeOutputFunction
  10. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Connection
  11. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
  12. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Declaration
  13. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DeclaredParameter
  14. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Expression
  15. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.FMU
  16. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMU
  17. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclaration
  18. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclarationFull
  19. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IntLiteral
  20. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IsSet
  21. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutputFunction
  22. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
  23. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RealLiteral
  24. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
  25. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptationFactory
  26. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleParamDeclaration
  27. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleVarDeclaration
  28. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StateTransitionFunction
  29. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StringLiteral
  30. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Unity
  31. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
  32. import java.io.ByteArrayOutputStream
  33. import java.util.HashMap
  34. import java.util.LinkedList
  35. import java.util.List
  36. import java.util.Map
  37. import org.eclipse.emf.ecore.EObject
  38. import org.eclipse.emf.ecore.resource.Resource
  39. import org.eclipse.xtext.EcoreUtil2
  40. import org.eclipse.xtext.generator.AbstractGenerator
  41. import org.eclipse.xtext.generator.IFileSystemAccess2
  42. import org.eclipse.xtext.generator.IGeneratorContext
  43. import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Statement
  44. /**
  45. * Generates code from your model files on save.
  46. *
  47. * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
  48. */
  49. class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
  50. String CANONICAL_EXT = ".BASE.sa"
  51. String NAME_SUFFIX = "_BASE"
  52. override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
  53. Log.push("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "...")
  54. Log.println("Resource URI information:")
  55. Log.println("\t resource.URI.lastSegment = " + resource.URI.lastSegment())
  56. Log.println("\t resource.URI.trimFileExtension = " + resource.URI.trimFileExtension())
  57. // Create in memory representation of canonical SA file
  58. var adaptations = resource.allContents.toIterable.filter(SemanticAdaptation).last.elements.filter(Adaptation);
  59. if (adaptations.size > 1){
  60. throw new Exception("Only one semantic adaptation is supported per .sa file")
  61. }
  62. var adaptation = adaptations.head
  63. Log.println(prettyprint_model(adaptation, "File Read"))
  64. // Create file name for the canonical sa file
  65. var fileNameWithoutExt = resource.URI.trimFileExtension().lastSegment()
  66. var canonicalFileName = fileNameWithoutExt + CANONICAL_EXT
  67. Log.println("canonicalFileName = " + canonicalFileName)
  68. Log.println("Checking if file is already a canonical version...")
  69. if (adaptation.name.indexOf(NAME_SUFFIX) == -1){
  70. Log.println("It is not.")
  71. adaptation.name = adaptation.name + NAME_SUFFIX
  72. canonicalize(adaptation)
  73. Log.println(prettyprint_model(adaptation, "Generated File"))
  74. fsa.generateFile(canonicalFileName, adaptation.serialize_model)
  75. Log.println("File " + canonicalFileName + " written.")
  76. } else {
  77. Log.println("It is already a canonical version.")
  78. Log.println("Nothing to do.")
  79. }
  80. Log.pop("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "... DONE.")
  81. }
  82. def prettyprint_model(Adaptation sa, String title){
  83. var outputByteArray = new ByteArrayOutputStream()
  84. sa.eResource.save(outputByteArray,null)
  85. return "______________________________" + title + "______________________________\n" +
  86. sa.serialize_model +
  87. "\n__________________________________________________________________________"
  88. }
  89. def serialize_model(Adaptation sa){
  90. var outputByteArray = new ByteArrayOutputStream()
  91. sa.eResource.save(outputByteArray,null)
  92. return outputByteArray.toString()
  93. }
  94. def inferUnits(Adaptation sa){
  95. // Unit inference
  96. var unitlessElements = genericDeclarationInferenceAlgorithm(sa ,
  97. [// getField
  98. element | {
  99. var DUMMY_UNIT = "Dips"
  100. if (element instanceof SingleParamDeclaration) {
  101. return DUMMY_UNIT
  102. } else if (element instanceof Port){
  103. return element.unity
  104. } else if (element instanceof SingleVarDeclaration){
  105. return DUMMY_UNIT
  106. } else {
  107. throw new Exception("Unexpected element type: " + element)
  108. }
  109. }
  110. ],
  111. [// setField
  112. element, value | {
  113. if (element instanceof SingleParamDeclaration) {
  114. } else if (element instanceof Port){
  115. element.unity = EcoreUtil2.copy(value as Unity)
  116. } else if (element instanceof SingleVarDeclaration){
  117. } else {
  118. throw new Exception("Unexpected element type: " + element)
  119. }
  120. }
  121. ],
  122. [// inferField
  123. element | {
  124. var DUMMY_UNIT = "Dips"
  125. if (element instanceof SingleParamDeclaration) {
  126. return DUMMY_UNIT
  127. } else if (element instanceof Port){
  128. return getPortUnit(element)
  129. } else if (element instanceof SingleVarDeclaration){
  130. return DUMMY_UNIT
  131. } else {
  132. throw new Exception("Unexpected element type: " + element)
  133. }
  134. }
  135. ]
  136. )
  137. if (unitlessElements > 0){
  138. Log.println("Could not infer all element units. There are " + unitlessElements + " unitless elements.")
  139. }
  140. }
  141. def inferTypes(Adaptation sa){
  142. // Type inference
  143. var untypedElements = genericDeclarationInferenceAlgorithm(sa ,
  144. [// getField
  145. element | {
  146. if (element instanceof SingleParamDeclaration) {
  147. return element.type
  148. } else if (element instanceof Port){
  149. return element.type
  150. } else if (element instanceof SingleVarDeclaration){
  151. return element.type
  152. } else {
  153. throw new Exception("Unexpected element type: " + element)
  154. }
  155. }
  156. ],
  157. [// setField
  158. element, value | {
  159. if (element instanceof SingleParamDeclaration) {
  160. element.type = value as String
  161. } else if (element instanceof Port){
  162. element.type = value as String
  163. } else if (element instanceof SingleVarDeclaration){
  164. element.type = value as String
  165. } else {
  166. throw new Exception("Unexpected element type: " + element)
  167. }
  168. }
  169. ],
  170. [// inferField
  171. element | {
  172. if (element instanceof SingleParamDeclaration) {
  173. return extractTypeFromExpression(element.expr, element.name)
  174. } else if (element instanceof Port){
  175. return getPortType(element)
  176. } else if (element instanceof SingleVarDeclaration){
  177. return extractTypeFromExpression(element.expr, element.name)
  178. } else {
  179. throw new Exception("Unexpected element type: " + element)
  180. }
  181. }
  182. ]
  183. )
  184. if (untypedElements > 0){
  185. Log.println("Error: Could not infer all types. There are " + untypedElements + " untyped elements.")
  186. Log.println(prettyprint_model(sa, "Current File"))
  187. throw new Exception("Could not infer all types. There are " + untypedElements + " untyped elements.")
  188. }
  189. }
  190. def canonicalize(Adaptation sa){
  191. Log.push("Canonicalize")
  192. inferUnits(sa)
  193. inferTypes(sa)
  194. addInPorts(sa)
  195. val inputPort2parameterDeclaration = addInParams(sa)
  196. val externalInputPort2InVarDeclaration = addInVars(sa, inputPort2parameterDeclaration)
  197. addInRules_External2Stored_Assignments(sa, externalInputPort2InVarDeclaration)
  198. val internalPort2ExternalPortBindings = findAllExternalPort2InputPort_Bindings(sa)
  199. addInRules_External2Internal_Assignments(sa, internalPort2ExternalPortBindings)
  200. removeBindings(internalPort2ExternalPortBindings, sa)
  201. addOutPorts(sa)
  202. val outputPort2parameterDeclaration = addOutParams(sa)
  203. val externalOutputPort2OutVarDeclaration = addOutVars(sa, outputPort2parameterDeclaration)
  204. val internalOutputPort2ExternalPortBindings = findAllInternalPort2ExternalOutputPort_Bindings(sa)
  205. val internalOutputPort2OutVarDeclaration = transitiveStep(internalOutputPort2ExternalPortBindings, externalOutputPort2OutVarDeclaration)
  206. addOutRules_Internal2Stored_Assignments(sa, internalOutputPort2OutVarDeclaration)
  207. addOutRules_Internal2External_Assignments(sa, internalOutputPort2ExternalPortBindings)
  208. removeBindings(internalOutputPort2ExternalPortBindings, sa)
  209. Log.pop("Canonicalize")
  210. }
  211. def transitiveStep(HashMap<Port, Port> internalOutputPort2ExternalPortBindings, HashMap<Port, SingleVarDeclaration> externalOutputPort2OutVarDeclaration) {
  212. Log.push("transitiveStep")
  213. val internalOutputPort2OutVarDeclaration = new HashMap<Port, SingleVarDeclaration>()
  214. for(internalOutputPort : internalOutputPort2ExternalPortBindings.keySet){
  215. val externalOutputPort = internalOutputPort2ExternalPortBindings.get(internalOutputPort)
  216. if (externalOutputPort2OutVarDeclaration.containsKey(externalOutputPort)){
  217. val outVar = externalOutputPort2OutVarDeclaration.get(externalOutputPort)
  218. Log.println("Found binding: " + internalOutputPort.qualifiedName + "->" + externalOutputPort.qualifiedName + " to be stored in " + outVar.name)
  219. internalOutputPort2OutVarDeclaration.put(internalOutputPort, outVar)
  220. }
  221. }
  222. Log.pop("transitiveStep")
  223. return internalOutputPort2OutVarDeclaration
  224. }
  225. def String qualifiedName(Port port){
  226. if (port.eContainer instanceof FMU){
  227. return (port.eContainer as FMU).name + "." + port.name
  228. }
  229. return port.name
  230. }
  231. def removeBindings(HashMap<Port, Port> internalPort2ExternalPortBindings, Adaptation sa) {
  232. Log.push("removeBindings")
  233. for (internalPort : internalPort2ExternalPortBindings.keySet){
  234. val externalPort = internalPort2ExternalPortBindings.get(internalPort)
  235. Log.println("Removing binding " + externalPort.qualifiedName + "->" + internalPort.qualifiedName)
  236. externalPort.targetdependency = null
  237. Log.println("Removing binding " + externalPort.qualifiedName + "<-" + internalPort.qualifiedName)
  238. externalPort.sourcedependency = null
  239. }
  240. Log.pop("removeBindings")
  241. }
  242. def findAllExternalPort2InputPort_Bindings(Adaptation sa) {
  243. Log.push("findAllExternalPort2InputPort_Bindings")
  244. val internalPort2ExternalPortBindings = new HashMap<Port, Port>()
  245. for (port : getAllInnerFMUInputPortDeclarations(sa)){
  246. var parentFMU = port.eContainer as InnerFMU
  247. Log.println("Checking if port " + port.qualifiedName + " is bound to an external port.")
  248. val externalPort = findExternalPortByTargetDependency(sa.inports, port)
  249. if (externalPort !== null){
  250. Log.println("Port " + port.qualifiedName + " is bound to an external port: " + externalPort.qualifiedName)
  251. internalPort2ExternalPortBindings.put(port, externalPort)
  252. } else {
  253. Log.println("Port " + port.qualifiedName + " is not bound to an external port.")
  254. }
  255. }
  256. Log.pop("findAllExternalPort2InputPort_Bindings")
  257. return internalPort2ExternalPortBindings
  258. }
  259. def findAllInternalPort2ExternalOutputPort_Bindings(Adaptation sa) {
  260. Log.push("findAllInternalPort2ExternalOutputPort_Bindings")
  261. val internalPort2ExternalPortBindings = new HashMap<Port, Port>()
  262. for (port : getAllInnerFMUOutputPortDeclarations(sa)){
  263. Log.println("Checking if port " + port.qualifiedName + " is bound to an external port.")
  264. val externalPort = findExternalPortBySourceDependency(sa.outports, port)
  265. if (externalPort !== null){
  266. Log.println("Port " + externalPort.qualifiedName + " is bound to an internal port: " + port.qualifiedName
  267. )
  268. internalPort2ExternalPortBindings.put(port, externalPort)
  269. } else {
  270. Log.println("Port " + port.qualifiedName + " is not bound to an external port.")
  271. }
  272. }
  273. Log.pop("findAllInternalPort2ExternalOutputPort_Bindings")
  274. return internalPort2ExternalPortBindings
  275. }
  276. def createExternalPortNameFromInternalPort(String parentFMUName, String internalPortName) {
  277. //return parentFMUName + "__" + internalPortName // Violates transparency
  278. return internalPortName
  279. }
  280. def addInRules_External2Internal_Assignments(Adaptation sa, HashMap<Port, Port> internalPort2ExternalPort) {
  281. Log.push("addInRules_External2Internal_Assignments")
  282. val dataRule = getOrPrependTrueRule(sa.in.rules)
  283. for(internalPort : internalPort2ExternalPort.keySet){
  284. val externalPort = internalPort2ExternalPort.get(internalPort)
  285. addPortAssignment(dataRule.outputfunction, internalPort, externalPort)
  286. }
  287. Log.pop("addInRules_External2Internal_Assignments")
  288. }
  289. def addOutRules_Internal2External_Assignments(Adaptation sa, HashMap<Port, Port> internalPort2ExternalPort){
  290. Log.push("addOutRules_Internal2External_Assignments")
  291. val dataRule = getOrPrependTrueRule(sa.out.rules)
  292. for(internalPort : internalPort2ExternalPort.keySet){
  293. val externalPort = internalPort2ExternalPort.get(internalPort)
  294. addPortAssignment(dataRule.outputfunction, externalPort, internalPort)
  295. }
  296. Log.pop("addOutRules_Internal2External_Assignments")
  297. }
  298. def addPortAssignment(OutputFunction function, Port toPort, Port fromPort) {
  299. Log.push("addPortAssignment")
  300. if(! (function instanceof CompositeOutputFunction) ){
  301. throw new Exception("Only CompositeOutputFunction is supported for now.")
  302. }
  303. val assignment = SemanticAdaptationFactory.eINSTANCE.createAssignment()
  304. assignment.lvalue = SemanticAdaptationFactory.eINSTANCE.createVariable()
  305. (assignment.lvalue as Variable).owner = toPort.eContainer as FMU
  306. (assignment.lvalue as Variable).ref = toPort
  307. assignment.expr = SemanticAdaptationFactory.eINSTANCE.createVariable()
  308. (assignment.expr as Variable).owner = fromPort.eContainer as FMU
  309. (assignment.expr as Variable).ref = fromPort
  310. val outFunction = function as CompositeOutputFunction
  311. outFunction.statements.add(0, assignment)
  312. Log.println("Assignment " + toPort.qualifiedName + " := " + fromPort.qualifiedName + " created.")
  313. Log.pop("addPortAssignment")
  314. }
  315. def addInRules_External2Stored_Assignments(Adaptation sa, HashMap<Port, SingleVarDeclaration> inputPort2InVarDeclaration) {
  316. Log.push("addInRules_External2Stored_Assignments")
  317. if (sa.in === null){
  318. sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
  319. }
  320. addRules_Port2Stored_Assignments(sa.in.rules, inputPort2InVarDeclaration)
  321. Log.pop("addInRules_External2Stored_Assignments")
  322. }
  323. def addOutRules_Internal2Stored_Assignments(Adaptation sa, HashMap<Port, SingleVarDeclaration> internalOutputPort2OutVarDeclaration) {
  324. Log.push("addOutRules_Internal2Stored_Assignments")
  325. if (sa.out === null){
  326. sa.out = SemanticAdaptationFactory.eINSTANCE.createOutRulesBlock()
  327. }
  328. addRules_Port2Stored_Assignments(sa.out.rules, internalOutputPort2OutVarDeclaration)
  329. Log.pop("addOutRules_Internal2Stored_Assignments")
  330. }
  331. def addRules_Port2Stored_Assignments(List<DataRule> rules, HashMap<Port, SingleVarDeclaration> port2VarDeclaration) {
  332. Log.push("addRules_External2Stored_Assignments")
  333. val dataRule = getOrPrependTrueRule(rules)
  334. if (dataRule.statetransitionfunction.expression !== null){
  335. throw new Exception("Expressions in rules are not supported yet.")
  336. // This and the one below are asily solved with a syntactic sugar substitution.
  337. }
  338. if (dataRule.statetransitionfunction.assignment !== null){
  339. throw new Exception("Assignment in rules are not supported yet.")
  340. }
  341. for(port : port2VarDeclaration.keySet){
  342. val storedVarDecl = port2VarDeclaration.get(port)
  343. addAssignmentToStoredVar(dataRule.statetransitionfunction.statements, port, storedVarDecl)
  344. }
  345. Log.pop("addRules_External2Stored_Assignments")
  346. }
  347. def addAssignmentToStoredVar(List<Statement> statements, Port internalPort, SingleVarDeclaration storedVarDecl) {
  348. Log.push("addAssignmentToStoredVar")
  349. val assignment = SemanticAdaptationFactory.eINSTANCE.createAssignment()
  350. assignment.lvalue = SemanticAdaptationFactory.eINSTANCE.createVariable()
  351. assignment.lvalue.ref = storedVarDecl
  352. assignment.expr = SemanticAdaptationFactory.eINSTANCE.createVariable()
  353. (assignment.expr as Variable).owner = internalPort.eContainer as FMU
  354. (assignment.expr as Variable).ref = internalPort
  355. statements.add(0, assignment)
  356. Log.println("Assignment " + storedVarDecl.name + " := " + internalPort.qualifiedName + " created.")
  357. Log.pop("addAssignmentToStoredVar")
  358. }
  359. def getOrPrependTrueRule(List<DataRule> rules) {
  360. var DataRule rule = null
  361. if (rules.size == 0 || !isTrueRule(rules.head)){
  362. Log.println("No existing rule found with true condition. Creating one.")
  363. val trueRule = SemanticAdaptationFactory.eINSTANCE.createDataRule()
  364. trueRule.condition = SemanticAdaptationFactory.eINSTANCE.createRuleCondition()
  365. val trueExpr = SemanticAdaptationFactory.eINSTANCE.createBoolLiteral()
  366. trueExpr.value = "true"
  367. trueRule.condition.condition = trueExpr
  368. trueRule.statetransitionfunction = SemanticAdaptationFactory.eINSTANCE.createStateTransitionFunction()
  369. trueRule.outputfunction = SemanticAdaptationFactory.eINSTANCE.createCompositeOutputFunction()
  370. rules.add(0, trueRule)
  371. rule = trueRule
  372. } else {
  373. Log.println("Existing rule with true condition found.")
  374. rule = rules.head
  375. }
  376. return rule
  377. }
  378. def isTrueRule(DataRule rule){
  379. if (rule.condition.condition instanceof BoolLiteral){
  380. return (rule.condition.condition as BoolLiteral).value == "true"
  381. }
  382. return false
  383. }
  384. def addInVars(Adaptation sa, Map<Port, SingleParamDeclaration> inputPort2parameterDeclaration){
  385. Log.push("addInVars")
  386. if (sa.in === null){
  387. sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
  388. }
  389. val inputPort2InVarDeclaration = addStorageVars(sa.in.globalInVars, inputPort2parameterDeclaration)
  390. Log.pop("addInVars")
  391. return inputPort2InVarDeclaration
  392. }
  393. def addOutVars(Adaptation sa, Map<Port, SingleParamDeclaration> outputPort2parameterDeclaration){
  394. Log.push("addOutVars")
  395. if (sa.out === null){
  396. sa.out = SemanticAdaptationFactory.eINSTANCE.createOutRulesBlock()
  397. }
  398. val outputPort2InVarDeclaration = addStorageVars(sa.out.globalOutVars, outputPort2parameterDeclaration)
  399. Log.pop("addOutVars")
  400. return outputPort2InVarDeclaration
  401. }
  402. def addStorageVars(List<Declaration> varDeclarations, Map<Port, SingleParamDeclaration> port2parameterDeclaration){
  403. Log.push("addStorageVars")
  404. var port2VarDeclaration = new HashMap<Port, SingleVarDeclaration>()
  405. for(port : port2parameterDeclaration.keySet){
  406. Log.println("Processing port " + port.qualifiedName)
  407. val paramDecl = port2parameterDeclaration.get(port)
  408. val varDeclarationName = getStorageVarDeclarationName(port)
  409. if (!varDeclarationExists(varDeclarationName, varDeclarations) ){
  410. Log.println("Creating new variable declaration " + varDeclarationName)
  411. val varDeclaration = addNewInputVarDeclaration(port, paramDecl, varDeclarations)
  412. port2VarDeclaration.put(port, varDeclaration)
  413. } else {
  414. Log.println("Input variable declaration " + varDeclarationName + " already exists.")
  415. }
  416. }
  417. Log.pop("addStorageVars")
  418. return port2VarDeclaration
  419. }
  420. def addNewInputVarDeclaration(Port externalInputPort, SingleParamDeclaration paramDecl, List<Declaration> varDeclarations) {
  421. /*
  422. if (sa.in === null){
  423. sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
  424. }
  425. */
  426. if (varDeclarations.size == 0){
  427. varDeclarations.add(SemanticAdaptationFactory.eINSTANCE.createDeclaration())
  428. }
  429. val newSingleVarDecl = SemanticAdaptationFactory.eINSTANCE.createSingleVarDeclaration()
  430. newSingleVarDecl.name = getStorageVarDeclarationName(externalInputPort)
  431. newSingleVarDecl.type = externalInputPort.type
  432. val initValue = SemanticAdaptationFactory.eINSTANCE.createVariable()
  433. initValue.ref = paramDecl
  434. newSingleVarDecl.expr = initValue
  435. varDeclarations.head.declarations.add(newSingleVarDecl)
  436. Log.println("New variable declaration created: " + newSingleVarDecl.name + " := " + paramDecl.name)
  437. return newSingleVarDecl
  438. }
  439. def varDeclarationExists(String invarName, List<Declaration> varDeclarations) {
  440. for (declarations : varDeclarations){ // sa.in.globalInVars
  441. for (decl : declarations.declarations){
  442. if (decl.name == invarName){
  443. return true
  444. }
  445. }
  446. }
  447. return false
  448. }
  449. def getStorageVarDeclarationName(Port externalInputPort) {
  450. return "stored__" + externalInputPort.name;
  451. }
  452. def genericDeclarationInferenceAlgorithm(Adaptation sa,
  453. (EObject)=>Object getField,
  454. (EObject, Object)=>void setField,
  455. (EObject)=>Object inferField
  456. ){
  457. Log.push("Running generic inference algorithm...")
  458. /*
  459. * Dumbest (and simplest) algorithm for this is a fixed point computation:
  460. * 1. Look for every var/port declaration
  461. * 2. If that var has a XXX already, nothing else to be done.
  462. * 3. If that var has no XXX declared, then
  463. * 3.1 If var/port has an initial value or connection, then
  464. * 3.1.1 If the initial_value/connection has a XXX declared, then var gets that XXX.
  465. * 3.1.2 Otherwise, nothing else to be done.
  466. * 3.2 If var/port has no initial value or connection then this either is a missing feature, or an error.
  467. * 3.3 If something has changed, go to 1. Otherwise, end.
  468. *
  469. * An extra set of instructions is there to push the element field information using connections and bindings.
  470. */
  471. var fixedPoint = false
  472. var unfieldedElementsCounter = 0
  473. while (! fixedPoint){
  474. fixedPoint = true
  475. unfieldedElementsCounter = 0
  476. Log.println("Inferring parameter fields...")
  477. for (paramDeclarations : sa.params) {
  478. for (paramDeclaration : paramDeclarations.declarations) {
  479. Log.println("Computing field for param " + paramDeclaration.name)
  480. if(getField.apply(paramDeclaration) !== null){
  481. Log.println("Already has been inferred: " + getField.apply(paramDeclaration))
  482. } else {
  483. Log.println("Has not been inferred yet.")
  484. if (tryInferAndAssignField(paramDeclaration, getField, setField, inferField)){
  485. fixedPoint = false
  486. } else {
  487. unfieldedElementsCounter++
  488. }
  489. }
  490. }
  491. }
  492. if(sa.inner !== null){
  493. if(sa.inner instanceof InnerFMUDeclarationFull){
  494. var innerFMUFull = sa.inner as InnerFMUDeclarationFull
  495. for(fmu : innerFMUFull.fmus){
  496. Log.println("Inferring port fields of FMU " + fmu.name)
  497. for (port : EcoreUtil2.getAllContentsOfType(fmu, Port)) {
  498. if(getField.apply(port) !== null){
  499. Log.println("Already has a field: " + getField.apply(port))
  500. } else {
  501. if (tryInferAndAssignField(port, getField, setField, inferField)){
  502. fixedPoint = false
  503. } else {
  504. unfieldedElementsCounter++
  505. }
  506. }
  507. }
  508. }
  509. if (innerFMUFull.connection.size > 0){
  510. Log.println("Inferring port fields using internal scenario bindings.")
  511. for (binding : innerFMUFull.connection){
  512. if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
  513. Log.println("Both ports have fields already.")
  514. } else {
  515. var inferredFieldAttempt = inferPortFieldViaConnection(binding, getField, setField, inferField)
  516. if (inferredFieldAttempt !== null){
  517. if (getField.apply(binding.src.port) === null){
  518. setField.apply(binding.src.port, inferredFieldAttempt)
  519. } else if (getField.apply(binding.tgt.port) === null){
  520. setField.apply(binding.tgt.port, inferredFieldAttempt)
  521. }
  522. fixedPoint = false
  523. unfieldedElementsCounter--
  524. Log.println("Got new field: " + inferredFieldAttempt)
  525. } else {
  526. Log.println("Cannot infer field from binding now.")
  527. }
  528. }
  529. }
  530. }
  531. } else {
  532. throw new Exception("Field inference only supported for InnerFMUDeclarationFull.")
  533. }
  534. }
  535. Log.println("Inferring external port fields...")
  536. var externalPorts = new LinkedList(sa.inports)
  537. externalPorts.addAll(sa.outports)
  538. for (port : externalPorts) {
  539. if (getField.apply(port) !== null){
  540. Log.println("Already has a field: " + getField.apply(port))
  541. if (pushPortField(port, getField, setField, inferField)){
  542. fixedPoint = false
  543. unfieldedElementsCounter--
  544. }
  545. } else {
  546. if (tryInferAndAssignField(port, getField, setField, inferField)){
  547. fixedPoint = false
  548. } else {
  549. unfieldedElementsCounter++
  550. }
  551. }
  552. }
  553. Log.println("Inferring all other declaration fields...")
  554. for (varDeclaration : EcoreUtil2.getAllContentsOfType(sa, SingleVarDeclaration)) {
  555. Log.println("Computing field for declaration " + varDeclaration.name)
  556. if(getField.apply(varDeclaration) !== null){
  557. Log.println("Already has a field: " + getField.apply(varDeclaration))
  558. } else {
  559. if (tryInferAndAssignField(varDeclaration, getField, setField, inferField)){
  560. fixedPoint = false
  561. } else {
  562. unfieldedElementsCounter++
  563. }
  564. }
  565. }
  566. Log.println("Ended iteration with unfielded elements remaining: " + unfieldedElementsCounter)
  567. } // while (! fixedPoint)
  568. Log.pop("Running generic inference algorithm... DONE")
  569. return unfieldedElementsCounter
  570. }
  571. def tryInferAndAssignField(EObject element,
  572. (EObject)=>Object getField,
  573. (EObject, Object)=>void setField,
  574. (EObject)=>Object inferField) {
  575. var inferredFieldAttempt = inferField.apply(element)
  576. if (inferredFieldAttempt !== null){
  577. setField.apply(element, inferredFieldAttempt)
  578. Log.println("Got new field: " + inferredFieldAttempt)
  579. return true
  580. } else {
  581. Log.println("Cannot infer field now.")
  582. return false
  583. }
  584. }
  585. def extractTypeFromExpression(Expression expression, String declarationName){
  586. if (expression instanceof IntLiteral){
  587. return "Integer"
  588. } else if (expression instanceof RealLiteral){
  589. return "Real"
  590. } else if (expression instanceof BoolLiteral){
  591. return "Bool"
  592. } else if (expression instanceof StringLiteral){
  593. return "String"
  594. } else if (expression instanceof Variable){
  595. var varRef = expression as Variable
  596. if (varRef.ref instanceof Port){
  597. var decl = varRef.ref as Port
  598. if (decl.type !== null){
  599. return decl.type
  600. }
  601. } else if(varRef.ref instanceof SingleParamDeclaration){
  602. var decl = varRef.ref as SingleParamDeclaration
  603. if (decl.type !== null){
  604. return decl.type
  605. }
  606. } else if(varRef.ref instanceof SingleVarDeclaration){
  607. var decl = varRef.ref as SingleVarDeclaration
  608. if (decl.type !== null){
  609. return decl.type
  610. }
  611. } else if(varRef.ref instanceof DeclaredParameter){
  612. throw new Exception("Type cannot be inferred for references to DeclaredParameter (for now). Please specify the explicit type of declaration " + declarationName)
  613. } else {
  614. throw new Exception("Unexpected kind of Variable expression found.")
  615. }
  616. } else if(expression instanceof BuiltinFunction){
  617. if (expression instanceof IsSet || expression instanceof Close){
  618. return "Bool"
  619. } else {
  620. return "Real"
  621. }
  622. } else {
  623. throw new Exception("Initial value for declaration " + declarationName + " must be literal or var ref for now. Got instead " + expression + ". If you want complex expressions, give it an explicit type.")
  624. }
  625. return null
  626. }
  627. def inferPortFieldViaConnection(Connection binding,
  628. (EObject)=>Object getField,
  629. (EObject, Object)=>void setField,
  630. (EObject)=>Object inferField
  631. ){
  632. var Object resultField = null
  633. if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
  634. throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
  635. } else if (getField.apply(binding.src.port) !== null){
  636. resultField = getField.apply(binding.src.port)
  637. Log.println("Target port "+ binding.tgt.port.qualifiedName +" got new type: " + resultField)
  638. } else if (getField.apply(binding.tgt.port) !== null){
  639. resultField = getField.apply(binding.tgt.port)
  640. Log.println("Target port "+ binding.src.port.qualifiedName +" got new type: " + resultField)
  641. }
  642. return resultField
  643. }
  644. def pushPortField(Port port,
  645. (EObject)=>Object getField,
  646. (EObject, Object)=>void setField,
  647. (EObject)=>Object inferField){
  648. var fieldInferred = false
  649. Log.println("Pushing field of port " + port.qualifiedName + " to its bindings.")
  650. if(getField.apply(port) === null){
  651. Log.println("Has no field to be pushed.")
  652. throw new Exception("Wrong way of using this function. It assumes field is already inferred.")
  653. } else {
  654. Log.println("Pushing field: " + getField.apply(port))
  655. if(port.sourcedependency !== null){
  656. Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
  657. if(getField.apply(port.sourcedependency.port) === null){
  658. setField.apply(port.sourcedependency.port, getField.apply(port))
  659. Log.println("Port " + port.sourcedependency.port.qualifiedName + " got new type: " + getField.apply(port.sourcedependency.port))
  660. fieldInferred = true
  661. } else {
  662. Log.println("Source port already has field.")
  663. }
  664. } else {
  665. Log.println("Has no source dependency.")
  666. }
  667. if (port.targetdependency !== null) {
  668. Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
  669. if(getField.apply(port.targetdependency.port) === null){
  670. Log.println("Dependency has no field yet.")
  671. setField.apply(port.targetdependency.port, getField.apply(port))
  672. Log.println("Port " + port.targetdependency.port.qualifiedName + " got new type: " + getField.apply(port.targetdependency.port))
  673. fieldInferred = true
  674. } else {
  675. Log.println("Target port already has field.")
  676. }
  677. } else {
  678. Log.println("Has no target dependency.")
  679. }
  680. }
  681. return fieldInferred
  682. }
  683. def getPortUnit(Port port){
  684. var unitInferred = false
  685. Log.println("Computing unit for port " + port.qualifiedName)
  686. var Unity returnUnit = null
  687. if(port.unity !== null){
  688. throw new Exception("Wrong way of using this function. It assumes unit is not inferred yet.")
  689. } else {
  690. Log.println("Has no unit.")
  691. Log.println("Attempting to infer unit from bindings.")
  692. if(port.sourcedependency !== null){
  693. Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
  694. if(port.sourcedependency.port.unity === null){
  695. Log.println("Dependency has no unit yet.")
  696. } else {
  697. returnUnit = port.sourcedependency.port.unity
  698. Log.println("Got new unit: " + returnUnit)
  699. unitInferred = true
  700. }
  701. } else {
  702. Log.println("Has no source dependency.")
  703. }
  704. if (port.targetdependency !== null && !unitInferred) {
  705. Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
  706. if(port.targetdependency.port.unity === null){
  707. Log.println("Dependency has no unit yet.")
  708. } else {
  709. returnUnit = port.targetdependency.port.unity
  710. Log.println("Got new unit: " + returnUnit)
  711. unitInferred = true
  712. }
  713. } else {
  714. Log.println("Has no target dependency, or unit has already been inferred from source dependency.")
  715. }
  716. }
  717. return returnUnit
  718. }
  719. def getPortType(Port port){
  720. var typeInferred = false
  721. Log.println("Computing type for port " + port.qualifiedName)
  722. var String returnType = null
  723. if(port.type !== null){
  724. throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
  725. } else {
  726. Log.println("Has no type.")
  727. Log.println("Attempting to infer type from units.")
  728. if (port.unity !== null){
  729. returnType = "Real"
  730. Log.println("Got new type: " + returnType)
  731. typeInferred = true
  732. } else {
  733. Log.println("Attempting to infer type from bindings.")
  734. if(port.sourcedependency !== null){
  735. Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
  736. if(port.sourcedependency.port.type === null){
  737. Log.println("Dependency has no type yet.")
  738. } else {
  739. returnType = port.sourcedependency.port.type
  740. Log.println("Got new type: " + returnType)
  741. typeInferred = true
  742. }
  743. } else {
  744. Log.println("Has no source dependency.")
  745. }
  746. if (port.targetdependency !== null && !typeInferred) {
  747. Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
  748. if(port.targetdependency.port.type === null){
  749. //println("Port object: " + port.targetdependency.port)
  750. Log.println("Dependency has no type yet.")
  751. } else {
  752. returnType = port.targetdependency.port.type
  753. Log.println("Got new type: " + returnType)
  754. typeInferred = true
  755. }
  756. } else {
  757. Log.println("Has no target dependency, or type has already been inferred from source dependency.")
  758. }
  759. }
  760. }
  761. return returnType
  762. }
  763. def addInPorts(Adaptation sa) {
  764. Log.push("Adding input ports...")
  765. for (port : getAllInnerFMUInputPortDeclarations(sa)){
  766. var parentFMU = port.eContainer as InnerFMU
  767. Log.println("Checking if port " + port.qualifiedName + " has incoming connections"
  768. )
  769. if (! hasConnection(port, sa, true)){
  770. Log.println("Port " + port.qualifiedName + " has no incoming connections.")
  771. val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
  772. if (findExternalPortByName(sa, externalPortName) === null){
  773. var newExternalPort = createExternalInputPortDeclarationFromInnerPort(port, parentFMU, sa)
  774. Log.println("External port " + newExternalPort.qualifiedName + " created.")
  775. newExternalPort.bindExternalInputPortTo(parentFMU, port)
  776. Log.println("External port " + newExternalPort.qualifiedName + " bound to port " + port.qualifiedName)
  777. } else {
  778. Log.println("Error: External port " + externalPortName + " already declared.")
  779. throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
  780. }
  781. } else {
  782. Log.println("Port " + port.qualifiedName + " has an incoming connection.")
  783. }
  784. }
  785. Log.pop("Adding input ports... DONE")
  786. }
  787. def bindExternalInputPortTo(Port externalInputPort, InnerFMU internalPortParent, Port internalPort) {
  788. externalInputPort.targetdependency = SemanticAdaptationFactory.eINSTANCE.createSpecifiedPort()
  789. externalInputPort.targetdependency.owner = internalPortParent
  790. externalInputPort.targetdependency.port = internalPort
  791. }
  792. def bindExternalOutputPortTo(Port externalOutputPort, InnerFMU internalPortParent, Port internalPort) {
  793. externalOutputPort.sourcedependency = SemanticAdaptationFactory.eINSTANCE.createSpecifiedPort()
  794. externalOutputPort.sourcedependency.owner = internalPortParent
  795. externalOutputPort.sourcedependency.port = internalPort
  796. }
  797. def createExternalInputPortDeclarationFromInnerPort(Port port, FMU parent, Adaptation sa) {
  798. var externalInputPort = createExternalPortDeclarationFromInnerPort(port, parent)
  799. sa.inports.add(externalInputPort)
  800. return externalInputPort
  801. }
  802. def createExternalOutputPortDeclarationFromInnerPort(Port port, FMU parent, Adaptation sa) {
  803. var externalOutputPort = createExternalPortDeclarationFromInnerPort(port, parent)
  804. sa.outports.add(externalOutputPort)
  805. return externalOutputPort
  806. }
  807. def createExternalPortDeclarationFromInnerPort(Port port, FMU parent) {
  808. var externalInputPort = SemanticAdaptationFactory.eINSTANCE.createPort()
  809. externalInputPort.name = createExternalPortNameFromInternalPort(parent.name, port.name)
  810. externalInputPort.type = port.type
  811. externalInputPort.unity = EcoreUtil2.copy(port.unity)
  812. return externalInputPort
  813. }
  814. def findExternalPortByName(Adaptation adaptation, String name) {
  815. for (externalInputPort : adaptation.inports){
  816. if (externalInputPort.name == name){
  817. return externalInputPort
  818. }
  819. }
  820. return null
  821. }
  822. def findExternalPortByTargetDependency(List<Port> ports, Port targetDependency) {
  823. for (externalInputPort : ports){
  824. if (externalInputPort.targetdependency !== null && externalInputPort.targetdependency.port == targetDependency){
  825. return externalInputPort
  826. }
  827. }
  828. return null
  829. }
  830. def findExternalPortBySourceDependency(List<Port> ports, Port sourceDependency) {
  831. for (externalInputPort : ports){
  832. if (externalInputPort.sourcedependency !== null && externalInputPort.sourcedependency.port == sourceDependency){
  833. return externalInputPort
  834. }
  835. }
  836. return null
  837. }
  838. def hasConnection(Port port, Adaptation adaptation, Boolean checkForIncomming) {
  839. var result = false
  840. if ( (checkForIncomming && port.sourcedependency !== null) ||
  841. (! checkForIncomming && port.targetdependency !== null)
  842. ){
  843. result = true
  844. } else {
  845. if (port.eContainer instanceof InnerFMU){
  846. var innerScenarioDeclaration = EcoreUtil2.getContainerOfType(port, InnerFMUDeclaration)
  847. if (innerScenarioDeclaration instanceof InnerFMUDeclarationFull){
  848. var innerScenarioWithCoupling = innerScenarioDeclaration as InnerFMUDeclarationFull
  849. if (innerScenarioWithCoupling.connection.size > 0){
  850. for (connection : innerScenarioWithCoupling.connection ){
  851. if ( (checkForIncomming && connection.tgt.port == port)){
  852. Log.println("Port " + port.qualifiedName + " has an incoming connection from internal port " + connection.src.port.qualifiedName)
  853. result = true
  854. } else if (!checkForIncomming && connection.src.port == port) {
  855. Log.println("Port " + port.qualifiedName + " has an outgoing connection to internal port " + connection.tgt.port.qualifiedName)
  856. result = true
  857. }
  858. }
  859. }
  860. }
  861. for (externalInputPort : adaptation.inports.filter[p | (checkForIncomming && p.targetdependency !== null) || (!checkForIncomming && p.sourcedependency !== null) ]){
  862. if (checkForIncomming && externalInputPort.targetdependency.port == port){
  863. Log.println("Port " + port.qualifiedName + " has an incoming connection from external port " + externalInputPort.qualifiedName)
  864. result = true
  865. } else if ( !checkForIncomming && externalInputPort.sourcedependency.port == port){
  866. Log.println("Port " + port.qualifiedName + " has an outgoing connection to external port " + externalInputPort.qualifiedName)
  867. result = true
  868. }
  869. }
  870. }
  871. }
  872. return result
  873. }
  874. def getAllInnerFMUInputPortDeclarations(Adaptation sa){
  875. return mapAllInnerFMUs(sa, [fmu | fmu.inports]);
  876. }
  877. def getAllInnerFMUOutputPortDeclarations(Adaptation sa){
  878. return mapAllInnerFMUs(sa, [fmu | fmu.outports]);
  879. }
  880. def <T> List<T> mapAllInnerFMUs(Adaptation sa, (InnerFMU)=>List<T> map){
  881. var result = new LinkedList()
  882. if(sa.inner !== null){
  883. if(sa.inner instanceof InnerFMUDeclarationFull){
  884. var innerFMUFull = sa.inner as InnerFMUDeclarationFull
  885. for(fmu : innerFMUFull.fmus){
  886. result.addAll(map.apply(fmu))
  887. }
  888. } else {
  889. throw new Exception("Only support for InnerFMUDeclarationFull.")
  890. }
  891. }
  892. return result;
  893. }
  894. def addInParams(Adaptation sa) {
  895. Log.push("Adding input parameters...")
  896. val result = addParamForExternalPortDeclarations(sa, sa.inports)
  897. Log.pop("Adding input parameters... DONE")
  898. return result
  899. }
  900. def addOutParams(Adaptation sa) {
  901. Log.push("Adding output parameters...")
  902. val result = addParamForExternalPortDeclarations(sa, sa.outports)
  903. Log.pop("Adding output parameters... DONE")
  904. return result
  905. }
  906. def addParamForExternalPortDeclarations(Adaptation sa, List<Port> externalPortList){
  907. Log.push("addParamForExternalPortDeclarations")
  908. val PARAM_PREFIX = "INIT_"
  909. var externalPort2parameterDeclaration = new HashMap<Port, SingleParamDeclaration>(externalPortList.size)
  910. for (externalPortDecl : externalPortList) {
  911. Log.println("Generating parameter for port " + externalPortDecl.qualifiedName)
  912. var paramname = PARAM_PREFIX + externalPortDecl.name.toUpperCase()
  913. if (paramAlreadyDeclared(paramname, sa)){
  914. Log.println("Parameter " + paramname + " already declared for port " + externalPortDecl.qualifiedName)
  915. } else {
  916. Log.println("Declaring new parameter " + paramname + " for port " + externalPortDecl.qualifiedName)
  917. var paramDeclaration = addNewParamDeclaration(paramname, externalPortDecl, sa)
  918. externalPort2parameterDeclaration.put(externalPortDecl, paramDeclaration)
  919. }
  920. }
  921. Log.pop("addParamForExternalPortDeclarations")
  922. return externalPort2parameterDeclaration
  923. }
  924. def addNewParamDeclaration(String name, Port fromPort, Adaptation sa) {
  925. var factory = SemanticAdaptationFactory.eINSTANCE
  926. var paramDeclaration = factory.createSingleParamDeclaration()
  927. paramDeclaration.name = name
  928. paramDeclaration.type = fromPort.type
  929. paramDeclaration.expr = getDefaultTypeExpression(paramDeclaration.type)
  930. if (sa.params.size == 0){
  931. sa.params.add(factory.createParamDeclarations())
  932. }
  933. sa.params.head.declarations.add(paramDeclaration)
  934. return paramDeclaration
  935. }
  936. def getDefaultTypeExpression(String type) {
  937. switch (type) {
  938. case "Integer": {
  939. val result = SemanticAdaptationFactory.eINSTANCE.createIntLiteral
  940. result.value = 0
  941. return result
  942. }
  943. case "Real": {
  944. val result = SemanticAdaptationFactory.eINSTANCE.createRealLiteral
  945. result.value = 0.0f
  946. return result
  947. }
  948. case "Bool": {
  949. val result = SemanticAdaptationFactory.eINSTANCE.createBoolLiteral
  950. result.value = "false"
  951. return result
  952. }
  953. case "String": {
  954. val result = SemanticAdaptationFactory.eINSTANCE.createStringLiteral
  955. result.value = " "
  956. return result
  957. }
  958. default: {
  959. throw new Exception("Unexpected type.")
  960. }
  961. }
  962. }
  963. def paramAlreadyDeclared(String name, Adaptation sa) {
  964. for(paramDeclarations : sa.params){
  965. for(paramDeclaration : paramDeclarations.declarations){
  966. if(paramDeclaration.name == name){
  967. return true
  968. }
  969. }
  970. }
  971. return false
  972. }
  973. def addOutPorts(Adaptation sa) {
  974. Log.push("Adding output ports...")
  975. for (port : getAllInnerFMUOutputPortDeclarations(sa)){
  976. var parentFMU = port.eContainer as InnerFMU
  977. Log.println("Checking if port " + port.qualifiedName + " has outgoing connections")
  978. if (! hasConnection(port, sa, false)){
  979. Log.println("Port " + port.qualifiedName + " has no outgoing connections.")
  980. val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
  981. if (findExternalPortByName(sa, externalPortName) === null){
  982. var newExternalPort = createExternalOutputPortDeclarationFromInnerPort(port, parentFMU, sa)
  983. Log.println("External port " + newExternalPort.qualifiedName + " created.")
  984. newExternalPort.bindExternalOutputPortTo(parentFMU, port)
  985. Log.println("External port " + newExternalPort.qualifiedName + " bound to port " + port.qualifiedName)
  986. } else {
  987. Log.println("Error: External port " + externalPortName + " already declared.")
  988. throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
  989. }
  990. } else {
  991. Log.println("Port " + port.qualifiedName + " has an incoming connection.")
  992. }
  993. }
  994. Log.pop("Adding output ports... DONE")
  995. }
  996. }