123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527 |
- /*
- * generated by Xtext 2.10.0
- */
- package be.uantwerpen.ansymo.semanticadaptation.cg.canonical
- import be.uantwerpen.ansymo.semanticadaptation.cg.canonical.graph.DirectedGraph
- import be.uantwerpen.ansymo.semanticadaptation.cg.canonical.graph.FMUGraph
- import be.uantwerpen.ansymo.semanticadaptation.cg.canonical.graph.TopologicalSort
- import be.uantwerpen.ansymo.semanticadaptation.log.Log
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Adaptation
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.Assignment
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.AtomicUnity
- 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.DivideUnity
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DoStep
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.DoStepFun
- 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.MultiplyUnity
- 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.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.common.util.EList
- import org.eclipse.emf.common.util.URI
- import org.eclipse.emf.ecore.EObject
- import org.eclipse.xtext.EcoreUtil2
- import org.eclipse.xtext.generator.IFileSystemAccess2
- import be.uantwerpen.ansymo.semanticadaptation.semanticAdaptation.CurrentTime
- /**
- * Generates code from your model files on save.
- *
- * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
- */
- class SemanticAdaptationCanonicalGenerator {
-
- String CANONICAL_SUFIX = "_canonical"
-
- def Adaptation doGenerate(Adaptation adaptation, IFileSystemAccess2 fsa, URI mainFile) {
- Log.push("Generating canonical semantic adaptation for file...")
-
- Log.println(prettyprint_model(adaptation, "File Read"))
-
- // Create file name for the canonical sa file
- var fileNameWithoutExt = mainFile.trimFileExtension().lastSegment()
-
- Log.println("Checking if file is already a canonical version...")
- if (fileNameWithoutExt.indexOf(CANONICAL_SUFIX) == -1){
-
- Log.println("It is not.")
- var canonicalFileName = fileNameWithoutExt + CANONICAL_SUFIX + ".sa"
- Log.println("canonicalFileName = " + canonicalFileName)
-
- 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... DONE")
-
- return adaptation
- }
-
- 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)
-
- if (sa.outports.size==0){
- addOutPorts(sa)
- }
-
- val outputPort2parameterDeclaration = addOutParams(sa)
-
- val internalOutputPort2OutVarDeclaration = addOutVars(sa, outputPort2parameterDeclaration)
-
- val internalOutputPort2ExternalPortBindings = findAllInternalPort2ExternalOutputPort_Bindings(sa)
- //val internalOutputPort2OutVarDeclaration = transitiveStep(internalOutputPort2ExternalPortBindings, internalOutputPort2OutVarDeclaration)
- 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)
- }
-
- createInternalBindingAssignments(sa)
-
- Log.push("Replace port refs in input rules")
- for (rule : sa.in.rules){
- check(rule.outputfunction instanceof CompositeOutputFunction, "Only CompositeOutputFunction are supported in DataRules.")
- replacePortRefsByVarDecl((rule.outputfunction as CompositeOutputFunction).statements, externalInputPort2InVarDeclaration)
- }
- Log.pop("Replace port refs in input rules")
-
- Log.push("Replace port refs in control rule")
- if (sa.control.rule instanceof CustomControlRule){
- replacePortRefsByVarDecl((sa.control.rule as CustomControlRule).controlRulestatements,internalOutputPort2OutVarDeclaration)
- }
- Log.pop("Replace port refs in control rule")
-
- Log.push("Replace port refs in output rule")
- for (rule : sa.out.rules){
- check(rule.outputfunction instanceof CompositeOutputFunction, "Only CompositeOutputFunction are supported in DataRules.")
- replacePortRefsByVarDecl((rule.outputfunction as CompositeOutputFunction).statements, internalOutputPort2OutVarDeclaration)
- }
- Log.pop("Replace port refs in output rule")
-
- Log.pop("Canonicalize")
- }
-
- def replacePortRefsByVarDecl(EList<Statement> statements, HashMap<Port, SingleVarDeclaration> port2VarDecl) {
- Log.push("replacePortRefsByVarDecl")
-
- for(statement : statements){
- val vars = statement.eAllContents.filter[v | v instanceof Variable]
- var Variable v
-
- while (vars.hasNext) {
- v = vars.next as Variable
- if (port2VarDecl.containsKey(v.ref)){
- val port = v.ref as Port
- v.owner = null
- val varDecl = port2VarDecl.get(v.ref)
- v.ref = varDecl
- Log.println("Replaced ref to " + port.qualifiedName + " by " + varDecl.name)
- } else {
- Log.println("Var ref not substituted: " + v.ref)
- }
- }
- }
-
- Log.pop("replacePortRefsByVarDecl")
- }
-
- def createInternalBindingAssignments(Adaptation sa) {
- Log.push("createInternalBindingAssignments")
-
- val scenario = (sa.inner as InnerFMUDeclarationFull)
-
- for (connection : scenario.connection){
- val trgFMU = connection.tgt.port.eContainer as InnerFMU
- val ctrlRule = sa.control.rule as CustomControlRule
-
- val doStepIndex = findDoStepStatementIndex(ctrlRule, trgFMU)
-
- if (doStepIndex < 0){
- throw new IllegalArgumentException("DoStep instruction for FMU " + trgFMU.name + " not found in control rule block.")
- }
-
- if (! existsAssignmentToPort_BeforeIndex(connection.tgt.port, doStepIndex, ctrlRule)){
- Log.println("Creating assignment to port " + connection.tgt.port.qualifiedName + " at position " + doStepIndex)
- addPortAssignment(ctrlRule.controlRulestatements, connection.tgt.port, connection.src.port, doStepIndex, true)
- } else {
- Log.println("There is already an assignment to port " + connection.tgt.port.qualifiedName + " before position " + doStepIndex)
- }
- }
-
- Log.pop("createInternalBindingAssignments")
- }
-
- def existsAssignmentToPort_BeforeIndex(Port port, int index, CustomControlRule rule) {
-
- val assignmentsToPort = rule.controlRulestatements.indexed
- .filter[s | s.value instanceof Assignment &&
- (s.value as Assignment).lvalue.ref == port
- ]
-
- check(assignmentsToPort.size <= 1, "Multiple assignments to the same port are not supported yet. Use a loop with a single call.")
-
- return assignmentsToPort.size == 1
- }
-
- def findDoStepStatementIndex(CustomControlRule rule, InnerFMU fmu) {
- Log.push("findDoStepStatementIndex")
-
- var result = -1
-
- val doStepProcedures = rule.controlRulestatements.indexed.filter[s | s.value instanceof DoStep && (s.value as DoStep).fmu == fmu]
-
- check(doStepProcedures.size <= 1, "Multiple calls to the doStep function for the same FMU are not supported yet. Use a loop with a single call.")
-
- if (doStepProcedures.size == 1){
- Log.println("Found a doStep procedure for fmu " + fmu.name + " at position " + doStepProcedures.head.key)
- result = doStepProcedures.head.key
- }
-
- // Warning: this does not support instructions such as:
- // var someVar = 10, h = doStep(f), etc...
- // Only single declarations are supported, such as:
- // var h = doStep(f)
- // FIXME: This needs to look into hirarchical statements (like for loops).
- val doStepAssignments = rule.controlRulestatements.indexed
- .filter[s | s.value instanceof Declaration &&
- (s.value as Declaration).declarations.size == 1 &&
- (s.value as Declaration).declarations.head instanceof SingleVarDeclaration &&
- (s.value as Declaration).declarations.head.expr instanceof DoStepFun &&
- ((s.value as Declaration).declarations.head.expr as DoStepFun).fmu == fmu
- ]
-
- check(doStepAssignments.size <= 1, "Multiple calls to the doStep function for the same FMU are not supported yet. Use a loop with a single call.")
-
- if (doStepAssignments.size == 1){
- check(result==-1, "Multiple calls to the doStep function for the same FMU are not supported yet. Use a loop with a single call.")
- Log.println("Found a doStep function for fmu " + fmu.name + " at position " + doStepAssignments.head.key)
- result = doStepAssignments.head.key
- }
-
- Log.pop("findDoStepStatementIndex")
- return result
- }
-
- 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()){
- 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)){
- 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)
- check((dataRule.outputfunction instanceof CompositeOutputFunction), "Only CompositeOutputFunction is supported for now.")
- val outFunction = dataRule.outputfunction as CompositeOutputFunction
- addPortAssignment(outFunction.statements, internalPort, externalPort, 0, true)
- }
-
- 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)
-
- check((dataRule.outputfunction instanceof CompositeOutputFunction), "Only CompositeOutputFunction is supported for now.")
- val outFunction = dataRule.outputfunction as CompositeOutputFunction
- addPortAssignment(outFunction.statements, externalPort, internalPort, 0, true)
- }
-
- Log.pop("addOutRules_Internal2External_Assignments")
- }
-
- def addPortAssignment(List<Statement> statements, Port toPort, Port fromPort, int position, boolean convertUnits) {
- Log.push("addPortAssignment")
-
- val assignment = SemanticAdaptationFactory.eINSTANCE.createAssignment()
- assignment.lvalue = SemanticAdaptationFactory.eINSTANCE.createVariable()
- assignment.lvalue.owner = toPort.eContainer as FMU
- assignment.lvalue.ref = toPort
- val varRef = SemanticAdaptationFactory.eINSTANCE.createVariable()
- varRef.owner = fromPort.eContainer as FMU
- varRef.ref = fromPort
-
- if (convertUnits && compatibleUnits(toPort.unity, fromPort.unity) && !unitsEqual(toPort.unity, fromPort.unity)){
- Log.println("Converting units " + fromPort.unity + " to " + toPort.unity)
- assignment.expr = getConversionExpression(toPort.unity, fromPort.unity, varRef)
- } else {
- assignment.expr = varRef
- Log.println("Assignment " + toPort.qualifiedName + " := " + fromPort.qualifiedName + " created.")
- }
-
- statements.add(position, assignment)
-
-
- Log.pop("addPortAssignment")
- }
-
- def getConversionExpression(Unity toUnits, Unity fromUnit, Variable varFrom) {
- check(toUnits instanceof AtomicUnity && fromUnit instanceof AtomicUnity, "Conversion between units is only supported for AtomicUnits.")
- var toAtomic = toUnits as AtomicUnity
- var fromAtomic = fromUnit as AtomicUnity
- check(fromAtomic.name == "cm" && toAtomic.name == "m", "Conversion only possible between cm and m... Not very usefull :)")
- var division = SemanticAdaptationFactory.eINSTANCE.createDiv()
- division.left = varFrom
- var hundred = SemanticAdaptationFactory.eINSTANCE.createRealLiteral()
- hundred.value=100f
- division.right = hundred
- return division
- }
-
- def dispatch boolean unitsEqual(DivideUnity u1, DivideUnity u2) {
- return unitsEqual(u1.left, u2.left) && unitsEqual(u1.right, u2.right)
- }
-
- def dispatch boolean unitsEqual(Void u1, Void u2) {
- return true
- }
-
- def dispatch boolean unitsEqual(MultiplyUnity u1, MultiplyUnity u2) {
- return unitsEqual(u1.left, u2.left) && unitsEqual(u1.right, u2.right)
- }
-
- def dispatch boolean unitsEqual(AtomicUnity u1, AtomicUnity u2) {
- return u1.name == u2.name && u1.power == u2.power
- }
-
- def compatibleUnits(Unity u1, Unity u2) {
- if ((u1 === null && u2===null) ||
- (u1 !== null && u2!==null)
- ){
- // TODO What makes two units compatible?
- return true
- } else {
- return false
- }
- }
-
- 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 = addNewVarDeclaration(port, paramDecl, varDeclarations)
-
- port2VarDeclaration.put(port, varDeclaration)
- } else {
- Log.println("Input variable declaration " + varDeclarationName + " already exists.")
- }
- }
-
- Log.pop("addStorageVars")
- return port2VarDeclaration
- }
-
- def addNewVarDeclaration(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
- 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 if (expression instanceof CurrentTime) {
- 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, or connect it to an internal fmu port, 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 = addParamForPortDeclarations(sa, sa.inports)
- Log.pop("Adding input parameters... DONE")
- return result
- }
-
- def addOutParams(Adaptation sa) {
- Log.push("Adding output parameters...")
-
- val result = addParamForPortDeclarations(sa, getAllInnerFMUOutputPortDeclarations(sa))
-
- Log.pop("Adding output parameters... DONE")
- return result
- }
-
- def addParamForPortDeclarations(Adaptation sa, List<Port> ports){
- Log.push("addParamForPortDeclarations")
-
- val PARAM_PREFIX = "INIT_"
-
- var port2parameterDeclaration = new HashMap<Port, SingleParamDeclaration>(ports.size)
-
- for (externalPortDecl : ports) {
- 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)
- port2parameterDeclaration.put(externalPortDecl, paramDeclaration)
- }
- }
-
- Log.pop("addParamForPortDeclarations")
- return port2parameterDeclaration
- }
-
- 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, or connect it to an internal fmu port, to avoid clashes.")
- }
- } else {
- Log.println("Port " + port.qualifiedName + " has an incoming connection.")
- }
- }
-
- Log.pop("Adding output ports... DONE")
- }
-
- }
|