1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360 |
- /*
- * generated by Xtext 2.10.0
- */
- package be.uantwerpen.ansymo.semanticadaptation.generator
- import be.uantwerpen.ansymo.semanticadaptation.generator.graph.DirectedGraph
- import be.uantwerpen.ansymo.semanticadaptation.generator.graph.FMUGraph
- import be.uantwerpen.ansymo.semanticadaptation.generator.graph.TopologicalSort
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BoolLiteral
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.BuiltinFunction
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Close
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CompositeOutputFunction
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Connection
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CustomControlRule
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DataRule
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Declaration
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DeclaredParameter
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Expression
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.FMU
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMU
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclaration
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.InnerFMUDeclarationFull
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IntLiteral
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.IsSet
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.MooreOrMealy
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.OutputFunction
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Port
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.ReactiveOrDelayed
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.RealLiteral
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptation
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SemanticAdaptationFactory
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleParamDeclaration
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.SingleVarDeclaration
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Statement
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.StringLiteral
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Unity
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Variable
- import java.io.ByteArrayOutputStream
- import java.util.HashMap
- import java.util.LinkedList
- import java.util.List
- import java.util.Map
- import org.eclipse.emf.ecore.EObject
- import org.eclipse.emf.ecore.resource.Resource
- import org.eclipse.xtext.EcoreUtil2
- import org.eclipse.xtext.generator.AbstractGenerator
- import org.eclipse.xtext.generator.IFileSystemAccess2
- import org.eclipse.xtext.generator.IGeneratorContext
- /**
- * Generates code from your model files on save.
- *
- * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
- */
- class SemanticAdaptationCanonicalGenerator extends AbstractGenerator {
-
- String CANONICAL_EXT = ".BASE.sa"
- String NAME_SUFFIX = "_BASE"
-
- override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
- Log.push("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "...")
-
- Log.println("Resource URI information:")
- Log.println("\t resource.URI.lastSegment = " + resource.URI.lastSegment())
- Log.println("\t resource.URI.trimFileExtension = " + resource.URI.trimFileExtension())
-
- // Create in memory representation of canonical SA file
- var adaptations = resource.allContents.toIterable.filter(SemanticAdaptation).last.elements.filter(Adaptation);
- if (adaptations.size > 1){
- throw new Exception("Only one semantic adaptation is supported per .sa file")
- }
- var adaptation = adaptations.head
-
- Log.println(prettyprint_model(adaptation, "File Read"))
-
- // Create file name for the canonical sa file
- var fileNameWithoutExt = resource.URI.trimFileExtension().lastSegment()
- var canonicalFileName = fileNameWithoutExt + CANONICAL_EXT
- Log.println("canonicalFileName = " + canonicalFileName)
-
- Log.println("Checking if file is already a canonical version...")
- if (adaptation.name.indexOf(NAME_SUFFIX) == -1){
- Log.println("It is not.")
-
- adaptation.name = adaptation.name + NAME_SUFFIX
-
- canonicalize(adaptation)
-
- Log.println(prettyprint_model(adaptation, "Generated File"))
-
- fsa.generateFile(canonicalFileName, adaptation.serialize_model)
- Log.println("File " + canonicalFileName + " written.")
-
-
- } else {
- Log.println("It is already a canonical version.")
- Log.println("Nothing to do.")
- }
-
- Log.pop("Generating canonical semantic adaptation for file " + resource.URI.toFileString() + "... DONE.")
- }
-
- def prettyprint_model(Adaptation sa, String title){
- var outputByteArray = new ByteArrayOutputStream()
- sa.eResource.save(outputByteArray,null)
- return "______________________________" + title + "______________________________\n" +
- sa.serialize_model +
- "\n__________________________________________________________________________"
- }
-
- def serialize_model(Adaptation sa){
- var outputByteArray = new ByteArrayOutputStream()
- sa.eResource.save(outputByteArray,null)
- return outputByteArray.toString()
- }
-
- def inferUnits(Adaptation sa){
- // Unit inference
- var unitlessElements = genericDeclarationInferenceAlgorithm(sa ,
- [// getField
- element | {
- var DUMMY_UNIT = "Dips"
- if (element instanceof SingleParamDeclaration) {
- return DUMMY_UNIT
- } else if (element instanceof Port){
- return element.unity
- } else if (element instanceof SingleVarDeclaration){
- return DUMMY_UNIT
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ],
- [// setField
- element, value | {
- if (element instanceof SingleParamDeclaration) {
-
- } else if (element instanceof Port){
- element.unity = EcoreUtil2.copy(value as Unity)
- } else if (element instanceof SingleVarDeclaration){
-
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ],
- [// inferField
- element | {
- var DUMMY_UNIT = "Dips"
- if (element instanceof SingleParamDeclaration) {
- return DUMMY_UNIT
- } else if (element instanceof Port){
- return getPortUnit(element)
- } else if (element instanceof SingleVarDeclaration){
- return DUMMY_UNIT
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ]
- )
-
- if (unitlessElements > 0){
- Log.println("Could not infer all element units. There are " + unitlessElements + " unitless elements.")
- }
- }
-
- def inferTypes(Adaptation sa){
- // Type inference
- var untypedElements = genericDeclarationInferenceAlgorithm(sa ,
- [// getField
- element | {
- if (element instanceof SingleParamDeclaration) {
- return element.type
- } else if (element instanceof Port){
- return element.type
- } else if (element instanceof SingleVarDeclaration){
- return element.type
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ],
- [// setField
- element, value | {
- if (element instanceof SingleParamDeclaration) {
- element.type = value as String
- } else if (element instanceof Port){
- element.type = value as String
- } else if (element instanceof SingleVarDeclaration){
- element.type = value as String
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ],
- [// inferField
- element | {
- if (element instanceof SingleParamDeclaration) {
- return extractTypeFromExpression(element.expr, element.name)
- } else if (element instanceof Port){
- return getPortType(element)
- } else if (element instanceof SingleVarDeclaration){
- return extractTypeFromExpression(element.expr, element.name)
- } else {
- throw new Exception("Unexpected element type: " + element)
- }
- }
- ]
- )
-
- if (untypedElements > 0){
-
- Log.println("Error: Could not infer all types. There are " + untypedElements + " untyped elements.")
-
- Log.println(prettyprint_model(sa, "Current File"))
-
- throw new Exception("Could not infer all types. There are " + untypedElements + " untyped elements.")
- }
- }
-
- def canonicalize(Adaptation sa){
- Log.push("Canonicalize")
-
- inferUnits(sa)
-
- inferTypes(sa)
-
- addInPorts(sa)
-
- val inputPort2parameterDeclaration = addInParams(sa)
-
- val externalInputPort2InVarDeclaration = addInVars(sa, inputPort2parameterDeclaration)
-
- addInRules_External2Stored_Assignments(sa, externalInputPort2InVarDeclaration)
-
- val internalPort2ExternalPortBindings = findAllExternalPort2InputPort_Bindings(sa)
-
- addInRules_External2Internal_Assignments(sa, internalPort2ExternalPortBindings)
-
- removeBindings(internalPort2ExternalPortBindings, sa)
-
- addOutPorts(sa)
-
- val outputPort2parameterDeclaration = addOutParams(sa)
-
- val externalOutputPort2OutVarDeclaration = addOutVars(sa, outputPort2parameterDeclaration)
-
- val internalOutputPort2ExternalPortBindings = findAllInternalPort2ExternalOutputPort_Bindings(sa)
- val internalOutputPort2OutVarDeclaration = transitiveStep(internalOutputPort2ExternalPortBindings, externalOutputPort2OutVarDeclaration)
- addOutRules_Internal2Stored_Assignments(sa, internalOutputPort2OutVarDeclaration)
-
- addOutRules_Internal2External_Assignments(sa, internalOutputPort2ExternalPortBindings)
-
- removeBindings(internalOutputPort2ExternalPortBindings, sa)
-
- if (sa.control === null){
- sa.control = SemanticAdaptationFactory.eINSTANCE.createControlRuleBlock()
- sa.control.rule = SemanticAdaptationFactory.eINSTANCE.createCustomControlRule()
-
- createCoSimStepInstructions(sa)
- }
-
- Log.pop("Canonicalize")
- }
-
- def createCoSimStepInstructions(Adaptation sa) {
- check((sa.inner as InnerFMUDeclarationFull).fmus.size > 0, "At least one internal FMU is expected...")
- if (onlyOneInternalFMU(sa)){
- createCosimStepForOneFMU(sa)
- } else {
- createCosimStepForMultipleFMUs(sa)
- }
- }
-
- def createCosimStepForOneFMU(Adaptation sa) {
- Log.push("createCosimStepForOneFMU")
- val fmu = (sa.inner as InnerFMUDeclarationFull).fmus.head
- val controlRule = sa.control.rule as CustomControlRule
- val returnedStepVar = controlRule.appendDoStep(fmu)
- val stepVarSingleton = new LinkedList()
- stepVarSingleton.add(returnedStepVar)
- controlRule.appendReturnCosimStep(stepVarSingleton)
- Log.pop("createCosimStepForOneFMU")
- }
-
- def appendReturnCosimStep(CustomControlRule rule, LinkedList<SingleVarDeclaration> stepVariables) {
- Log.push("appendReturnCosimStep")
-
- if (stepVariables.size == 0){
- throw new Exception("Does not make sense. At least one inner FMU is expected.")
- }
-
- val minExpression = SemanticAdaptationFactory.eINSTANCE.createMin()
-
- Log.println("Creating min(...) expression with the following arguments:")
-
- for(varDecl : stepVariables){
- val varRef = SemanticAdaptationFactory.eINSTANCE.createVariable()
- varRef.ref = varDecl
- minExpression.args.add(varRef)
- Log.println(varDecl.name)
- }
-
- rule.returnstatement = SemanticAdaptationFactory.eINSTANCE.createReturnStatement()
- rule.returnstatement.expr = minExpression
-
- Log.pop("appendReturnCosimStep")
- }
-
- def appendDoStep(CustomControlRule rule, InnerFMU fmu) {
- Log.push("appendDoStep")
- val t = SemanticAdaptationFactory.eINSTANCE.createCurrentTime()
- val H = SemanticAdaptationFactory.eINSTANCE.createStepSize()
-
- val doStep = SemanticAdaptationFactory.eINSTANCE.createDoStepFun()
- doStep.t = t
- doStep.h = H
- doStep.fmu = fmu
-
- val step_var = SemanticAdaptationFactory.eINSTANCE.createSingleVarDeclaration()
- step_var.name = "H_" + fmu.name
- step_var.expr = doStep
-
- val step_decl = SemanticAdaptationFactory.eINSTANCE.createDeclaration()
- step_decl.declarations.add(step_var)
-
- rule.controlRulestatements.add(step_decl)
-
- Log.println("Added var " + step_var.name + " := doStep(t, H, " + fmu.name + ")")
-
- Log.pop("appendDoStep")
- return step_var
- }
-
- def createCosimStepForMultipleFMUs(Adaptation sa) {
- Log.push("createCosimStepForMultipleFMUs")
- val innerDeclaration = (sa.inner as InnerFMUDeclarationFull)
- val controlRule = sa.control.rule as CustomControlRule
-
- val stepVarSingleton = new LinkedList()
- for (fmu : innerDeclaration.topologicalSort()){
- // TODO: Maybe add the setting of inputs and outputs here.
- val returnedStepVar = controlRule.appendDoStep(fmu)
- stepVarSingleton.add(returnedStepVar)
- }
-
- controlRule.appendReturnCosimStep(stepVarSingleton)
- Log.pop("createCosimStepForMultipleFMUs")
- }
-
- def topologicalSort(InnerFMUDeclarationFull scenario){
- Log.push("topologicalSort")
-
- val DirectedGraph<InnerFMU> inner_fmu_graph = createFMUGraph(scenario)
-
- val result = TopologicalSort.sort(inner_fmu_graph)
-
- Log.println("Sorting: " + result)
-
- Log.pop("topologicalSort")
- return result
- }
-
- def createFMUGraph(InnerFMUDeclarationFull scenario) {
- Log.push("createFMUGraph")
-
- val graph = new FMUGraph()
-
- for (fmu : scenario.fmus){
- graph.addNode(fmu)
- }
-
- for (connection : scenario.connection){
- check(connection.src.port.eContainer instanceof InnerFMU &&
- connection.tgt.port.eContainer instanceof InnerFMU, "Weird connection found: " + connection)
- if (reactiveMealyFMU(connection.tgt.port.eContainer as InnerFMU)){
- graph.addEdge(connection.src.port.eContainer as InnerFMU, connection.tgt.port.eContainer as InnerFMU)
- } else {
- Log.println("FMU " + (connection.tgt.port.eContainer as InnerFMU).name + " is not reactive mealy, so it has no algebraic dependencies.")
- }
- }
-
- Log.println(graph.toString())
-
- Log.pop("createFMUGraph")
- return graph
- }
-
- def reactiveMealyFMU(InnerFMU fmu) {
- return fmu.reactiveness == ReactiveOrDelayed.REACTIVE && fmu.machine == MooreOrMealy.MEALY
- }
-
- def check(Boolean condition, String msg){
- if (! condition){
- throw new Exception("Assertion error: " + msg)
- }
- }
-
- def onlyOneInternalFMU(Adaptation sa) {
- if(sa.inner instanceof InnerFMUDeclarationFull){
- return (sa.inner as InnerFMUDeclarationFull).fmus.size == 1
- } else {
- throw new Exception('This kind of internal scenario is not supported yet.')
- }
- }
-
-
- def transitiveStep(HashMap<Port, Port> internalOutputPort2ExternalPortBindings, HashMap<Port, SingleVarDeclaration> externalOutputPort2OutVarDeclaration) {
- Log.push("transitiveStep")
-
- val internalOutputPort2OutVarDeclaration = new HashMap<Port, SingleVarDeclaration>()
-
- for(internalOutputPort : internalOutputPort2ExternalPortBindings.keySet){
- val externalOutputPort = internalOutputPort2ExternalPortBindings.get(internalOutputPort)
- if (externalOutputPort2OutVarDeclaration.containsKey(externalOutputPort)){
- val outVar = externalOutputPort2OutVarDeclaration.get(externalOutputPort)
- Log.println("Found binding: " + internalOutputPort.qualifiedName + "->" + externalOutputPort.qualifiedName + " to be stored in " + outVar.name)
- internalOutputPort2OutVarDeclaration.put(internalOutputPort, outVar)
- }
- }
-
- Log.pop("transitiveStep")
- return internalOutputPort2OutVarDeclaration
- }
-
- def String qualifiedName(Port port){
- if (port.eContainer instanceof FMU){
- return (port.eContainer as FMU).name + "." + port.name
- }
- return port.name
- }
-
- def removeBindings(HashMap<Port, Port> internalPort2ExternalPortBindings, Adaptation sa) {
- Log.push("removeBindings")
-
- for (internalPort : internalPort2ExternalPortBindings.keySet){
- val externalPort = internalPort2ExternalPortBindings.get(internalPort)
- Log.println("Removing binding " + externalPort.qualifiedName + "->" + internalPort.qualifiedName)
- externalPort.targetdependency = null
- Log.println("Removing binding " + externalPort.qualifiedName + "<-" + internalPort.qualifiedName)
- externalPort.sourcedependency = null
- }
-
- Log.pop("removeBindings")
- }
-
- def findAllExternalPort2InputPort_Bindings(Adaptation sa) {
- Log.push("findAllExternalPort2InputPort_Bindings")
-
- val internalPort2ExternalPortBindings = new HashMap<Port, Port>()
-
- for (port : getAllInnerFMUInputPortDeclarations(sa)){
- var parentFMU = port.eContainer as InnerFMU
- Log.println("Checking if port " + port.qualifiedName + " is bound to an external port.")
- val externalPort = findExternalPortByTargetDependency(sa.inports, port)
- if (externalPort !== null){
- Log.println("Port " + port.qualifiedName + " is bound to an external port: " + externalPort.qualifiedName)
- internalPort2ExternalPortBindings.put(port, externalPort)
- } else {
- Log.println("Port " + port.qualifiedName + " is not bound to an external port.")
- }
- }
-
- Log.pop("findAllExternalPort2InputPort_Bindings")
-
- return internalPort2ExternalPortBindings
- }
-
- def findAllInternalPort2ExternalOutputPort_Bindings(Adaptation sa) {
- Log.push("findAllInternalPort2ExternalOutputPort_Bindings")
-
- val internalPort2ExternalPortBindings = new HashMap<Port, Port>()
-
- for (port : getAllInnerFMUOutputPortDeclarations(sa)){
- Log.println("Checking if port " + port.qualifiedName + " is bound to an external port.")
- val externalPort = findExternalPortBySourceDependency(sa.outports, port)
- if (externalPort !== null){
- Log.println("Port " + externalPort.qualifiedName + " is bound to an internal port: " + port.qualifiedName
- )
- internalPort2ExternalPortBindings.put(port, externalPort)
- } else {
- Log.println("Port " + port.qualifiedName + " is not bound to an external port.")
- }
- }
-
-
- Log.pop("findAllInternalPort2ExternalOutputPort_Bindings")
-
- return internalPort2ExternalPortBindings
- }
-
- def createExternalPortNameFromInternalPort(String parentFMUName, String internalPortName) {
- //return parentFMUName + "__" + internalPortName // Violates transparency
- return internalPortName
- }
-
- def addInRules_External2Internal_Assignments(Adaptation sa, HashMap<Port, Port> internalPort2ExternalPort) {
- Log.push("addInRules_External2Internal_Assignments")
-
- val dataRule = getOrPrependTrueRule(sa.in.rules)
-
- for(internalPort : internalPort2ExternalPort.keySet){
- val externalPort = internalPort2ExternalPort.get(internalPort)
- addPortAssignment(dataRule.outputfunction, internalPort, externalPort)
- }
-
- Log.pop("addInRules_External2Internal_Assignments")
- }
-
- def addOutRules_Internal2External_Assignments(Adaptation sa, HashMap<Port, Port> internalPort2ExternalPort){
- Log.push("addOutRules_Internal2External_Assignments")
-
- val dataRule = getOrPrependTrueRule(sa.out.rules)
-
- for(internalPort : internalPort2ExternalPort.keySet){
- val externalPort = internalPort2ExternalPort.get(internalPort)
- addPortAssignment(dataRule.outputfunction, externalPort, internalPort)
- }
-
- Log.pop("addOutRules_Internal2External_Assignments")
- }
-
- def addPortAssignment(OutputFunction function, Port toPort, Port fromPort) {
- Log.push("addPortAssignment")
-
- if(! (function instanceof CompositeOutputFunction) ){
- throw new Exception("Only CompositeOutputFunction is supported for now.")
- }
-
- // TODO: Unit conversion is done here.
-
- val assignment = SemanticAdaptationFactory.eINSTANCE.createAssignment()
- assignment.lvalue = SemanticAdaptationFactory.eINSTANCE.createVariable()
- (assignment.lvalue as Variable).owner = toPort.eContainer as FMU
- (assignment.lvalue as Variable).ref = toPort
- assignment.expr = SemanticAdaptationFactory.eINSTANCE.createVariable()
- (assignment.expr as Variable).owner = fromPort.eContainer as FMU
- (assignment.expr as Variable).ref = fromPort
-
- val outFunction = function as CompositeOutputFunction
- outFunction.statements.add(0, assignment)
-
- Log.println("Assignment " + toPort.qualifiedName + " := " + fromPort.qualifiedName + " created.")
-
- Log.pop("addPortAssignment")
- }
-
- def addInRules_External2Stored_Assignments(Adaptation sa, HashMap<Port, SingleVarDeclaration> inputPort2InVarDeclaration) {
- Log.push("addInRules_External2Stored_Assignments")
-
- if (sa.in === null){
- sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
- }
-
- addRules_Port2Stored_Assignments(sa.in.rules, inputPort2InVarDeclaration)
-
- Log.pop("addInRules_External2Stored_Assignments")
- }
-
- def addOutRules_Internal2Stored_Assignments(Adaptation sa, HashMap<Port, SingleVarDeclaration> internalOutputPort2OutVarDeclaration) {
- Log.push("addOutRules_Internal2Stored_Assignments")
-
- if (sa.out === null){
- sa.out = SemanticAdaptationFactory.eINSTANCE.createOutRulesBlock()
- }
-
- addRules_Port2Stored_Assignments(sa.out.rules, internalOutputPort2OutVarDeclaration)
-
- Log.pop("addOutRules_Internal2Stored_Assignments")
- }
-
- def addRules_Port2Stored_Assignments(List<DataRule> rules, HashMap<Port, SingleVarDeclaration> port2VarDeclaration) {
- Log.push("addRules_External2Stored_Assignments")
-
- val dataRule = getOrPrependTrueRule(rules)
-
- if (dataRule.statetransitionfunction.expression !== null){
- throw new Exception("Expressions in rules are not supported yet.")
- // This and the one below are asily solved with a syntactic sugar substitution.
- }
- if (dataRule.statetransitionfunction.assignment !== null){
- throw new Exception("Assignment in rules are not supported yet.")
- }
-
- for(port : port2VarDeclaration.keySet){
- val storedVarDecl = port2VarDeclaration.get(port)
- addAssignmentToStoredVar(dataRule.statetransitionfunction.statements, port, storedVarDecl)
- }
-
- Log.pop("addRules_External2Stored_Assignments")
- }
-
- def addAssignmentToStoredVar(List<Statement> statements, Port internalPort, SingleVarDeclaration storedVarDecl) {
- Log.push("addAssignmentToStoredVar")
-
- val assignment = SemanticAdaptationFactory.eINSTANCE.createAssignment()
- assignment.lvalue = SemanticAdaptationFactory.eINSTANCE.createVariable()
- assignment.lvalue.ref = storedVarDecl
- assignment.expr = SemanticAdaptationFactory.eINSTANCE.createVariable()
- (assignment.expr as Variable).owner = internalPort.eContainer as FMU
- (assignment.expr as Variable).ref = internalPort
-
- statements.add(0, assignment)
-
- Log.println("Assignment " + storedVarDecl.name + " := " + internalPort.qualifiedName + " created.")
-
- Log.pop("addAssignmentToStoredVar")
- }
-
- def getOrPrependTrueRule(List<DataRule> rules) {
- var DataRule rule = null
- if (rules.size == 0 || !isTrueRule(rules.head)){
- Log.println("No existing rule found with true condition. Creating one.")
- val trueRule = SemanticAdaptationFactory.eINSTANCE.createDataRule()
- trueRule.condition = SemanticAdaptationFactory.eINSTANCE.createRuleCondition()
- val trueExpr = SemanticAdaptationFactory.eINSTANCE.createBoolLiteral()
- trueExpr.value = "true"
- trueRule.condition.condition = trueExpr
-
- trueRule.statetransitionfunction = SemanticAdaptationFactory.eINSTANCE.createStateTransitionFunction()
-
- trueRule.outputfunction = SemanticAdaptationFactory.eINSTANCE.createCompositeOutputFunction()
-
- rules.add(0, trueRule)
- rule = trueRule
- } else {
- Log.println("Existing rule with true condition found.")
- rule = rules.head
- }
- return rule
- }
-
- def isTrueRule(DataRule rule){
- if (rule.condition.condition instanceof BoolLiteral){
- return (rule.condition.condition as BoolLiteral).value == "true"
- }
- return false
- }
-
- def addInVars(Adaptation sa, Map<Port, SingleParamDeclaration> inputPort2parameterDeclaration){
- Log.push("addInVars")
-
- if (sa.in === null){
- sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
- }
-
- val inputPort2InVarDeclaration = addStorageVars(sa.in.globalInVars, inputPort2parameterDeclaration)
-
- Log.pop("addInVars")
- return inputPort2InVarDeclaration
- }
-
- def addOutVars(Adaptation sa, Map<Port, SingleParamDeclaration> outputPort2parameterDeclaration){
- Log.push("addOutVars")
-
- if (sa.out === null){
- sa.out = SemanticAdaptationFactory.eINSTANCE.createOutRulesBlock()
- }
-
- val outputPort2InVarDeclaration = addStorageVars(sa.out.globalOutVars, outputPort2parameterDeclaration)
-
- Log.pop("addOutVars")
- return outputPort2InVarDeclaration
- }
-
- def addStorageVars(List<Declaration> varDeclarations, Map<Port, SingleParamDeclaration> port2parameterDeclaration){
- Log.push("addStorageVars")
-
- var port2VarDeclaration = new HashMap<Port, SingleVarDeclaration>()
-
- for(port : port2parameterDeclaration.keySet){
- Log.println("Processing port " + port.qualifiedName)
- val paramDecl = port2parameterDeclaration.get(port)
-
- val varDeclarationName = getStorageVarDeclarationName(port)
- if (!varDeclarationExists(varDeclarationName, varDeclarations) ){
- Log.println("Creating new variable declaration " + varDeclarationName)
-
- val varDeclaration = addNewInputVarDeclaration(port, paramDecl, varDeclarations)
-
- port2VarDeclaration.put(port, varDeclaration)
- } else {
- Log.println("Input variable declaration " + varDeclarationName + " already exists.")
- }
- }
-
- Log.pop("addStorageVars")
- return port2VarDeclaration
- }
-
- def addNewInputVarDeclaration(Port externalInputPort, SingleParamDeclaration paramDecl, List<Declaration> varDeclarations) {
- /*
- if (sa.in === null){
- sa.in = SemanticAdaptationFactory.eINSTANCE.createInRulesBlock()
- }
- */
- if (varDeclarations.size == 0){
- varDeclarations.add(SemanticAdaptationFactory.eINSTANCE.createDeclaration())
- }
-
- val newSingleVarDecl = SemanticAdaptationFactory.eINSTANCE.createSingleVarDeclaration()
- newSingleVarDecl.name = getStorageVarDeclarationName(externalInputPort)
- newSingleVarDecl.type = externalInputPort.type
- val initValue = SemanticAdaptationFactory.eINSTANCE.createVariable()
- initValue.ref = paramDecl
- newSingleVarDecl.expr = initValue
-
- varDeclarations.head.declarations.add(newSingleVarDecl)
-
- Log.println("New variable declaration created: " + newSingleVarDecl.name + " := " + paramDecl.name)
- return newSingleVarDecl
- }
-
- def varDeclarationExists(String invarName, List<Declaration> varDeclarations) {
- for (declarations : varDeclarations){ // sa.in.globalInVars
- for (decl : declarations.declarations){
- if (decl.name == invarName){
- return true
- }
- }
- }
- return false
- }
-
- def getStorageVarDeclarationName(Port externalInputPort) {
- return "stored__" + externalInputPort.name;
- }
-
- def genericDeclarationInferenceAlgorithm(Adaptation sa,
- (EObject)=>Object getField,
- (EObject, Object)=>void setField,
- (EObject)=>Object inferField
- ){
- Log.push("Running generic inference algorithm...")
-
- /*
- * Dumbest (and simplest) algorithm for this is a fixed point computation:
- * 1. Look for every var/port declaration
- * 2. If that var has a XXX already, nothing else to be done.
- * 3. If that var has no XXX declared, then
- * 3.1 If var/port has an initial value or connection, then
- * 3.1.1 If the initial_value/connection has a XXX declared, then var gets that XXX.
- * 3.1.2 Otherwise, nothing else to be done.
- * 3.2 If var/port has no initial value or connection then this either is a missing feature, or an error.
- * 3.3 If something has changed, go to 1. Otherwise, end.
- *
- * An extra set of instructions is there to push the element field information using connections and bindings.
- */
- var fixedPoint = false
- var unfieldedElementsCounter = 0
- while (! fixedPoint){
- fixedPoint = true
- unfieldedElementsCounter = 0
-
- Log.println("Inferring parameter fields...")
-
- for (paramDeclarations : sa.params) {
- for (paramDeclaration : paramDeclarations.declarations) {
- Log.println("Computing field for param " + paramDeclaration.name)
- if(getField.apply(paramDeclaration) !== null){
- Log.println("Already has been inferred: " + getField.apply(paramDeclaration))
- } else {
- Log.println("Has not been inferred yet.")
- if (tryInferAndAssignField(paramDeclaration, getField, setField, inferField)){
- fixedPoint = false
- } else {
- unfieldedElementsCounter++
- }
- }
- }
- }
-
- if(sa.inner !== null){
- if(sa.inner instanceof InnerFMUDeclarationFull){
- var innerFMUFull = sa.inner as InnerFMUDeclarationFull
- for(fmu : innerFMUFull.fmus){
- Log.println("Inferring port fields of FMU " + fmu.name)
- for (port : EcoreUtil2.getAllContentsOfType(fmu, Port)) {
- if(getField.apply(port) !== null){
- Log.println("Already has a field: " + getField.apply(port))
- } else {
- if (tryInferAndAssignField(port, getField, setField, inferField)){
- fixedPoint = false
- } else {
- unfieldedElementsCounter++
- }
- }
- }
- }
-
- if (innerFMUFull.connection.size > 0){
- Log.println("Inferring port fields using internal scenario bindings.")
- for (binding : innerFMUFull.connection){
- if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
- Log.println("Both ports have fields already.")
- } else {
- var inferredFieldAttempt = inferPortFieldViaConnection(binding, getField, setField, inferField)
- if (inferredFieldAttempt !== null){
- if (getField.apply(binding.src.port) === null){
- setField.apply(binding.src.port, inferredFieldAttempt)
- } else if (getField.apply(binding.tgt.port) === null){
- setField.apply(binding.tgt.port, inferredFieldAttempt)
- }
- fixedPoint = false
- unfieldedElementsCounter--
- Log.println("Got new field: " + inferredFieldAttempt)
- } else {
- Log.println("Cannot infer field from binding now.")
- }
- }
- }
- }
- } else {
- throw new Exception("Field inference only supported for InnerFMUDeclarationFull.")
- }
- }
-
- Log.println("Inferring external port fields...")
-
- var externalPorts = new LinkedList(sa.inports)
- externalPorts.addAll(sa.outports)
-
- for (port : externalPorts) {
- if (getField.apply(port) !== null){
- Log.println("Already has a field: " + getField.apply(port))
- if (pushPortField(port, getField, setField, inferField)){
- fixedPoint = false
- unfieldedElementsCounter--
- }
- } else {
- if (tryInferAndAssignField(port, getField, setField, inferField)){
- fixedPoint = false
- } else {
- unfieldedElementsCounter++
- }
- }
- }
-
- Log.println("Inferring all other declaration fields...")
-
- for (varDeclaration : EcoreUtil2.getAllContentsOfType(sa, SingleVarDeclaration)) {
- Log.println("Computing field for declaration " + varDeclaration.name)
- if(getField.apply(varDeclaration) !== null){
- Log.println("Already has a field: " + getField.apply(varDeclaration))
- } else {
- if (tryInferAndAssignField(varDeclaration, getField, setField, inferField)){
- fixedPoint = false
- } else {
- unfieldedElementsCounter++
- }
- }
- }
-
- Log.println("Ended iteration with unfielded elements remaining: " + unfieldedElementsCounter)
- } // while (! fixedPoint)
-
-
- Log.pop("Running generic inference algorithm... DONE")
-
- return unfieldedElementsCounter
- }
-
- def tryInferAndAssignField(EObject element,
- (EObject)=>Object getField,
- (EObject, Object)=>void setField,
- (EObject)=>Object inferField) {
- var inferredFieldAttempt = inferField.apply(element)
- if (inferredFieldAttempt !== null){
- setField.apply(element, inferredFieldAttempt)
- Log.println("Got new field: " + inferredFieldAttempt)
- return true
- } else {
- Log.println("Cannot infer field now.")
- return false
- }
- }
-
- def extractTypeFromExpression(Expression expression, String declarationName){
- if (expression instanceof IntLiteral){
- return "Integer"
- } else if (expression instanceof RealLiteral){
- return "Real"
- } else if (expression instanceof BoolLiteral){
- return "Bool"
- } else if (expression instanceof StringLiteral){
- return "String"
- } else if (expression instanceof Variable){
- var varRef = expression as Variable
- if (varRef.ref instanceof Port){
- var decl = varRef.ref as Port
- if (decl.type !== null){
- return decl.type
- }
- } else if(varRef.ref instanceof SingleParamDeclaration){
- var decl = varRef.ref as SingleParamDeclaration
- if (decl.type !== null){
- return decl.type
- }
- } else if(varRef.ref instanceof SingleVarDeclaration){
- var decl = varRef.ref as SingleVarDeclaration
- if (decl.type !== null){
- return decl.type
- }
- } else if(varRef.ref instanceof DeclaredParameter){
- throw new Exception("Type cannot be inferred for references to DeclaredParameter (for now). Please specify the explicit type of declaration " + declarationName)
- } else {
- throw new Exception("Unexpected kind of Variable expression found.")
- }
- } else if(expression instanceof BuiltinFunction){
- if (expression instanceof IsSet || expression instanceof Close){
- return "Bool"
- } else {
- return "Real"
- }
- } else {
- 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.")
- }
- return null
- }
-
- def inferPortFieldViaConnection(Connection binding,
- (EObject)=>Object getField,
- (EObject, Object)=>void setField,
- (EObject)=>Object inferField
- ){
- var Object resultField = null
- if (getField.apply(binding.src.port) !== null && getField.apply(binding.tgt.port) !== null){
- throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
- } else if (getField.apply(binding.src.port) !== null){
- resultField = getField.apply(binding.src.port)
- Log.println("Target port "+ binding.tgt.port.qualifiedName +" got new type: " + resultField)
- } else if (getField.apply(binding.tgt.port) !== null){
- resultField = getField.apply(binding.tgt.port)
- Log.println("Target port "+ binding.src.port.qualifiedName +" got new type: " + resultField)
- }
-
- return resultField
- }
-
- def pushPortField(Port port,
- (EObject)=>Object getField,
- (EObject, Object)=>void setField,
- (EObject)=>Object inferField){
- var fieldInferred = false
- Log.println("Pushing field of port " + port.qualifiedName + " to its bindings.")
-
- if(getField.apply(port) === null){
- Log.println("Has no field to be pushed.")
- throw new Exception("Wrong way of using this function. It assumes field is already inferred.")
- } else {
- Log.println("Pushing field: " + getField.apply(port))
- if(port.sourcedependency !== null){
- Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
- if(getField.apply(port.sourcedependency.port) === null){
- setField.apply(port.sourcedependency.port, getField.apply(port))
- Log.println("Port " + port.sourcedependency.port.qualifiedName + " got new type: " + getField.apply(port.sourcedependency.port))
- fieldInferred = true
- } else {
- Log.println("Source port already has field.")
- }
- } else {
- Log.println("Has no source dependency.")
- }
-
- if (port.targetdependency !== null) {
- Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
- if(getField.apply(port.targetdependency.port) === null){
- Log.println("Dependency has no field yet.")
- setField.apply(port.targetdependency.port, getField.apply(port))
- Log.println("Port " + port.targetdependency.port.qualifiedName + " got new type: " + getField.apply(port.targetdependency.port))
- fieldInferred = true
- } else {
- Log.println("Target port already has field.")
- }
- } else {
- Log.println("Has no target dependency.")
- }
- }
-
- return fieldInferred
- }
-
- def getPortUnit(Port port){
- var unitInferred = false
-
- Log.println("Computing unit for port " + port.qualifiedName)
-
- var Unity returnUnit = null
-
- if(port.unity !== null){
- throw new Exception("Wrong way of using this function. It assumes unit is not inferred yet.")
- } else {
- Log.println("Has no unit.")
-
- Log.println("Attempting to infer unit from bindings.")
- if(port.sourcedependency !== null){
- Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
- if(port.sourcedependency.port.unity === null){
- Log.println("Dependency has no unit yet.")
- } else {
- returnUnit = port.sourcedependency.port.unity
- Log.println("Got new unit: " + returnUnit)
- unitInferred = true
- }
- } else {
- Log.println("Has no source dependency.")
- }
-
- if (port.targetdependency !== null && !unitInferred) {
- Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
- if(port.targetdependency.port.unity === null){
- Log.println("Dependency has no unit yet.")
- } else {
- returnUnit = port.targetdependency.port.unity
- Log.println("Got new unit: " + returnUnit)
- unitInferred = true
- }
- } else {
- Log.println("Has no target dependency, or unit has already been inferred from source dependency.")
- }
- }
-
- return returnUnit
- }
-
- def getPortType(Port port){
- var typeInferred = false
-
- Log.println("Computing type for port " + port.qualifiedName)
-
- var String returnType = null
-
- if(port.type !== null){
- throw new Exception("Wrong way of using this function. It assumes type is not inferred yet.")
- } else {
- Log.println("Has no type.")
-
- Log.println("Attempting to infer type from units.")
- if (port.unity !== null){
- returnType = "Real"
- Log.println("Got new type: " + returnType)
- typeInferred = true
- } else {
- Log.println("Attempting to infer type from bindings.")
- if(port.sourcedependency !== null){
- Log.println("Has a source dependency: " + port.sourcedependency.port.qualifiedName)
- if(port.sourcedependency.port.type === null){
- Log.println("Dependency has no type yet.")
- } else {
- returnType = port.sourcedependency.port.type
- Log.println("Got new type: " + returnType)
- typeInferred = true
- }
- } else {
- Log.println("Has no source dependency.")
- }
-
- if (port.targetdependency !== null && !typeInferred) {
- Log.println("Has a target dependency: " + port.targetdependency.port.qualifiedName)
- if(port.targetdependency.port.type === null){
- //println("Port object: " + port.targetdependency.port)
- Log.println("Dependency has no type yet.")
- } else {
- returnType = port.targetdependency.port.type
- Log.println("Got new type: " + returnType)
- typeInferred = true
- }
- } else {
- Log.println("Has no target dependency, or type has already been inferred from source dependency.")
- }
- }
- }
-
- return returnType
- }
-
- def addInPorts(Adaptation sa) {
- Log.push("Adding input ports...")
- for (port : getAllInnerFMUInputPortDeclarations(sa)){
- var parentFMU = port.eContainer as InnerFMU
- Log.println("Checking if port " + port.qualifiedName + " has incoming connections"
- )
- if (! hasConnection(port, sa, true)){
- Log.println("Port " + port.qualifiedName + " has no incoming connections.")
- val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
- if (findExternalPortByName(sa, externalPortName) === null){
- var newExternalPort = createExternalInputPortDeclarationFromInnerPort(port, parentFMU, sa)
- Log.println("External port " + newExternalPort.qualifiedName + " created.")
- newExternalPort.bindExternalInputPortTo(parentFMU, port)
- Log.println("External port " + newExternalPort.qualifiedName + " bound to port " + port.qualifiedName)
- } else {
- Log.println("Error: External port " + externalPortName + " already declared.")
- throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
- }
- } else {
- Log.println("Port " + port.qualifiedName + " has an incoming connection.")
- }
- }
-
- Log.pop("Adding input ports... DONE")
- }
-
- def bindExternalInputPortTo(Port externalInputPort, InnerFMU internalPortParent, Port internalPort) {
- externalInputPort.targetdependency = SemanticAdaptationFactory.eINSTANCE.createSpecifiedPort()
- externalInputPort.targetdependency.owner = internalPortParent
- externalInputPort.targetdependency.port = internalPort
- }
-
- def bindExternalOutputPortTo(Port externalOutputPort, InnerFMU internalPortParent, Port internalPort) {
- externalOutputPort.sourcedependency = SemanticAdaptationFactory.eINSTANCE.createSpecifiedPort()
- externalOutputPort.sourcedependency.owner = internalPortParent
- externalOutputPort.sourcedependency.port = internalPort
- }
-
- def createExternalInputPortDeclarationFromInnerPort(Port port, FMU parent, Adaptation sa) {
- var externalInputPort = createExternalPortDeclarationFromInnerPort(port, parent)
- sa.inports.add(externalInputPort)
- return externalInputPort
- }
-
- def createExternalOutputPortDeclarationFromInnerPort(Port port, FMU parent, Adaptation sa) {
- var externalOutputPort = createExternalPortDeclarationFromInnerPort(port, parent)
- sa.outports.add(externalOutputPort)
- return externalOutputPort
- }
-
- def createExternalPortDeclarationFromInnerPort(Port port, FMU parent) {
- var externalInputPort = SemanticAdaptationFactory.eINSTANCE.createPort()
- externalInputPort.name = createExternalPortNameFromInternalPort(parent.name, port.name)
- externalInputPort.type = port.type
- externalInputPort.unity = EcoreUtil2.copy(port.unity)
- return externalInputPort
- }
-
- def findExternalPortByName(Adaptation adaptation, String name) {
- for (externalInputPort : adaptation.inports){
- if (externalInputPort.name == name){
- return externalInputPort
- }
- }
- return null
- }
-
-
- def findExternalPortByTargetDependency(List<Port> ports, Port targetDependency) {
- for (externalInputPort : ports){
- if (externalInputPort.targetdependency !== null && externalInputPort.targetdependency.port == targetDependency){
- return externalInputPort
- }
- }
- return null
- }
-
- def findExternalPortBySourceDependency(List<Port> ports, Port sourceDependency) {
- for (externalInputPort : ports){
- if (externalInputPort.sourcedependency !== null && externalInputPort.sourcedependency.port == sourceDependency){
- return externalInputPort
- }
- }
- return null
- }
-
-
- def hasConnection(Port port, Adaptation adaptation, Boolean checkForIncomming) {
-
- var result = false
-
- if ( (checkForIncomming && port.sourcedependency !== null) ||
- (! checkForIncomming && port.targetdependency !== null)
- ){
- result = true
- } else {
- if (port.eContainer instanceof InnerFMU){
-
- var innerScenarioDeclaration = EcoreUtil2.getContainerOfType(port, InnerFMUDeclaration)
-
- if (innerScenarioDeclaration instanceof InnerFMUDeclarationFull){
- var innerScenarioWithCoupling = innerScenarioDeclaration as InnerFMUDeclarationFull
- if (innerScenarioWithCoupling.connection.size > 0){
- for (connection : innerScenarioWithCoupling.connection ){
- if ( (checkForIncomming && connection.tgt.port == port)){
- Log.println("Port " + port.qualifiedName + " has an incoming connection from internal port " + connection.src.port.qualifiedName)
- result = true
- } else if (!checkForIncomming && connection.src.port == port) {
- Log.println("Port " + port.qualifiedName + " has an outgoing connection to internal port " + connection.tgt.port.qualifiedName)
- result = true
- }
- }
- }
- }
-
- for (externalInputPort : adaptation.inports.filter[p | (checkForIncomming && p.targetdependency !== null) || (!checkForIncomming && p.sourcedependency !== null) ]){
- if (checkForIncomming && externalInputPort.targetdependency.port == port){
- Log.println("Port " + port.qualifiedName + " has an incoming connection from external port " + externalInputPort.qualifiedName)
- result = true
- } else if ( !checkForIncomming && externalInputPort.sourcedependency.port == port){
- Log.println("Port " + port.qualifiedName + " has an outgoing connection to external port " + externalInputPort.qualifiedName)
- result = true
- }
- }
- }
- }
-
- return result
- }
-
- def getAllInnerFMUInputPortDeclarations(Adaptation sa){
- return mapAllInnerFMUs(sa, [fmu | fmu.inports]);
- }
-
- def getAllInnerFMUOutputPortDeclarations(Adaptation sa){
- return mapAllInnerFMUs(sa, [fmu | fmu.outports]);
- }
-
- def <T> List<T> mapAllInnerFMUs(Adaptation sa, (InnerFMU)=>List<T> map){
- var result = new LinkedList()
-
- if(sa.inner !== null){
- if(sa.inner instanceof InnerFMUDeclarationFull){
- var innerFMUFull = sa.inner as InnerFMUDeclarationFull
- for(fmu : innerFMUFull.fmus){
- result.addAll(map.apply(fmu))
- }
- } else {
- throw new Exception("Only support for InnerFMUDeclarationFull.")
- }
- }
-
- return result;
- }
-
-
- def addInParams(Adaptation sa) {
- Log.push("Adding input parameters...")
- val result = addParamForExternalPortDeclarations(sa, sa.inports)
- Log.pop("Adding input parameters... DONE")
- return result
- }
-
- def addOutParams(Adaptation sa) {
- Log.push("Adding output parameters...")
- val result = addParamForExternalPortDeclarations(sa, sa.outports)
- Log.pop("Adding output parameters... DONE")
- return result
- }
-
- def addParamForExternalPortDeclarations(Adaptation sa, List<Port> externalPortList){
- Log.push("addParamForExternalPortDeclarations")
-
- val PARAM_PREFIX = "INIT_"
-
- var externalPort2parameterDeclaration = new HashMap<Port, SingleParamDeclaration>(externalPortList.size)
-
- for (externalPortDecl : externalPortList) {
- Log.println("Generating parameter for port " + externalPortDecl.qualifiedName)
- var paramname = PARAM_PREFIX + externalPortDecl.name.toUpperCase()
-
- if (paramAlreadyDeclared(paramname, sa)){
- Log.println("Parameter " + paramname + " already declared for port " + externalPortDecl.qualifiedName)
- } else {
- Log.println("Declaring new parameter " + paramname + " for port " + externalPortDecl.qualifiedName)
- var paramDeclaration = addNewParamDeclaration(paramname, externalPortDecl, sa)
- externalPort2parameterDeclaration.put(externalPortDecl, paramDeclaration)
- }
- }
-
- Log.pop("addParamForExternalPortDeclarations")
- return externalPort2parameterDeclaration
- }
-
- def addNewParamDeclaration(String name, Port fromPort, Adaptation sa) {
- var factory = SemanticAdaptationFactory.eINSTANCE
- var paramDeclaration = factory.createSingleParamDeclaration()
-
- paramDeclaration.name = name
- paramDeclaration.type = fromPort.type
- paramDeclaration.expr = getDefaultTypeExpression(paramDeclaration.type)
-
- if (sa.params.size == 0){
- sa.params.add(factory.createParamDeclarations())
- }
-
- sa.params.head.declarations.add(paramDeclaration)
- return paramDeclaration
- }
-
- def getDefaultTypeExpression(String type) {
- switch (type) {
- case "Integer": {
- val result = SemanticAdaptationFactory.eINSTANCE.createIntLiteral
- result.value = 0
- return result
- }
- case "Real": {
- val result = SemanticAdaptationFactory.eINSTANCE.createRealLiteral
- result.value = 0.0f
- return result
- }
- case "Bool": {
- val result = SemanticAdaptationFactory.eINSTANCE.createBoolLiteral
- result.value = "false"
- return result
- }
- case "String": {
- val result = SemanticAdaptationFactory.eINSTANCE.createStringLiteral
- result.value = " "
- return result
- }
- default: {
- throw new Exception("Unexpected type.")
- }
- }
- }
-
- def paramAlreadyDeclared(String name, Adaptation sa) {
- for(paramDeclarations : sa.params){
- for(paramDeclaration : paramDeclarations.declarations){
- if(paramDeclaration.name == name){
- return true
- }
- }
- }
- return false
- }
-
-
- def addOutPorts(Adaptation sa) {
- Log.push("Adding output ports...")
- for (port : getAllInnerFMUOutputPortDeclarations(sa)){
- var parentFMU = port.eContainer as InnerFMU
- Log.println("Checking if port " + port.qualifiedName + " has outgoing connections")
- if (! hasConnection(port, sa, false)){
- Log.println("Port " + port.qualifiedName + " has no outgoing connections.")
-
- val externalPortName = createExternalPortNameFromInternalPort(parentFMU.name, port.name)
- if (findExternalPortByName(sa, externalPortName) === null){
- var newExternalPort = createExternalOutputPortDeclarationFromInnerPort(port, parentFMU, sa)
- Log.println("External port " + newExternalPort.qualifiedName + " created.")
- newExternalPort.bindExternalOutputPortTo(parentFMU, port)
- Log.println("External port " + newExternalPort.qualifiedName + " bound to port " + port.qualifiedName)
- } else {
- Log.println("Error: External port " + externalPortName + " already declared.")
- throw new Exception("Error: External port " + externalPortName + " already declared. Please rename it to avoid clashes.")
- }
- } else {
- Log.println("Port " + port.qualifiedName + " has an incoming connection.")
- }
- }
-
- Log.pop("Adding output ports... DONE")
- }
-
- }
|