OMCompiler/Compiler/Script/Binding.mo
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of OpenModelica. | ||
| 3 | * | ||
| 4 | * Copyright (c) 1998-2026, Open Source Modelica Consortium (OSMC), | ||
| 5 | * c/o Linköpings universitet, Department of Computer and Information Science, | ||
| 6 | * SE-58183 Linköping, Sweden. | ||
| 7 | * | ||
| 8 | * All rights reserved. | ||
| 9 | * | ||
| 10 | * THIS PROGRAM IS PROVIDED UNDER THE TERMS OF AGPL VERSION 3 LICENSE OR | ||
| 11 | * THIS OSMC PUBLIC LICENSE (OSMC-PL) VERSION 1.8. | ||
| 12 | * ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS PROGRAM CONSTITUTES | ||
| 13 | * RECIPIENT'S ACCEPTANCE OF THE OSMC PUBLIC LICENSE OR THE GNU AGPL | ||
| 14 | * VERSION 3, ACCORDING TO RECIPIENTS CHOICE. | ||
| 15 | * | ||
| 16 | * The OpenModelica software and the OSMC (Open Source Modelica Consortium) | ||
| 17 | * Public License (OSMC-PL) are obtained from OSMC, either from the above | ||
| 18 | * address, from the URLs: | ||
| 19 | * http://www.openmodelica.org or | ||
| 20 | * https://github.com/OpenModelica/ or | ||
| 21 | * http://www.ida.liu.se/projects/OpenModelica, | ||
| 22 | * and in the OpenModelica distribution. | ||
| 23 | * | ||
| 24 | * GNU AGPL version 3 is obtained from: | ||
| 25 | * https://www.gnu.org/licenses/licenses.html#GPL | ||
| 26 | * | ||
| 27 | * This program is distributed WITHOUT ANY WARRANTY; without | ||
| 28 | * even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 29 | * FOR A PARTICULAR PURPOSE, EXCEPT AS EXPRESSLY SET FORTH | ||
| 30 | * IN THE BY RECIPIENT SELECTED SUBSIDIARY LICENSE CONDITIONS OF OSMC-PL. | ||
| 31 | * | ||
| 32 | * See the full OSMC Public License conditions for more details. | ||
| 33 | * | ||
| 34 | */ | ||
| 35 | |||
| 36 | encapsulated package Binding "Binding generation support." | ||
| 37 | |||
| 38 | // Imports | ||
| 39 | public import Absyn; | ||
| 40 | import ProgramUtil; | ||
| 41 | public import AbsynUtil; | ||
| 42 | public import SCode; | ||
| 43 | public import SCodeDump; | ||
| 44 | public import Dump; | ||
| 45 | |||
| 46 | protected import AbsynToSCode; | ||
| 47 | protected import Parser; | ||
| 48 | protected import GlobalScript; | ||
| 49 | protected import System; | ||
| 50 | |||
| 51 | // Aliases | ||
| 52 | public type Ident = Absyn.Ident; | ||
| 53 | public type Path = Absyn.Path; | ||
| 54 | public type TypeSpec = Absyn.TypeSpec; | ||
| 55 | |||
| 56 | // Types | ||
| 57 | public uniontype Mediator | ||
| 58 | record MEDIATOR | ||
| 59 | String mType; | ||
| 60 | String template; | ||
| 61 | list<Client> clients; | ||
| 62 | list<Provider> providers; | ||
| 63 | list<Preferred> preferred; | ||
| 64 | end MEDIATOR; | ||
| 65 | end Mediator; | ||
| 66 | |||
| 67 | public uniontype Client | ||
| 68 | record CLIENT | ||
| 69 | String modelID ; | ||
| 70 | String component; | ||
| 71 | String template; | ||
| 72 | Boolean isMandatory; | ||
| 73 | end CLIENT; | ||
| 74 | end Client; | ||
| 75 | |||
| 76 | public uniontype Provider | ||
| 77 | record PROVIDER | ||
| 78 | String modelID ; | ||
| 79 | String component; | ||
| 80 | String template; | ||
| 81 | end PROVIDER; | ||
| 82 | end Provider; | ||
| 83 | |||
| 84 | public uniontype Preferred | ||
| 85 | record PREFERRED | ||
| 86 | String clientInstancePath; | ||
| 87 | String providerInstancePath; | ||
| 88 | end PREFERRED; | ||
| 89 | end Preferred; | ||
| 90 | |||
| 91 | protected uniontype Client_e "internal client list representation" | ||
| 92 | record CLIENT_E | ||
| 93 | list<Absyn.ComponentItem> components; | ||
| 94 | TypeSpec typeSpec; //specification of the client element type | ||
| 95 | TypeSpec rootType; //specification of the top level type of element including the lower level client | ||
| 96 | Absyn.Class def; | ||
| 97 | list<list<String>> instance; | ||
| 98 | Client_e predecessors; | ||
| 99 | list<Mediator> mediator; | ||
| 100 | end CLIENT_E; | ||
| 101 | |||
| 102 | record NO_PRED end NO_PRED; | ||
| 103 | end Client_e; | ||
| 104 | |||
| 105 | public function inferBindings "@autor lenab : root function called from API " | ||
| 106 | input Path model_path "Model for which the bindings will be computed"; | ||
| 107 | input Absyn.Program env "All loaded models"; | ||
| 108 | output Absyn.Program out_model_def "Updated environment"; | ||
| 109 | protected | ||
| 110 | list<Mediator> ms; | ||
| 111 | Absyn.Class model_def, out_vmodel; | ||
| 112 | list<SCode.Element> scode_def; | ||
| 113 | list<Client_e> client_list; | ||
| 114 | algorithm | ||
| 115 | ✗ | model_def := ProgramUtil.getPathedClassInProgram(model_path, env); | |
| 116 | ✗ | scode_def := AbsynToSCode.translateAbsyn2SCode(env); | |
| 117 | // print(SCodeDump.programStr(scode_def)); | ||
| 118 | ✗ | ms := getMediatorDefsElements(scode_def, {}); | |
| 119 | ✗ | client_list := buildInstList(model_def, env, NO_PRED(), ms, {}, {}); | |
| 120 | ✗ | out_vmodel := inferBindingClientList(client_list, model_def, env); | |
| 121 | ✗ | print(Dump.unparseClassStr(out_vmodel) + "\n"); | |
| 122 | ✗ | out_model_def := ProgramUtil.updateProgram(Absyn.PROGRAM({out_vmodel}, ProgramUtil.buildWithin(model_path)), env); | |
| 123 | end inferBindings; | ||
| 124 | |||
| 125 | public function generateVerificationScenarios "@autor lenab : root function called from API " | ||
| 126 | input Path package_path "The package where the bindings will be generated"; | ||
| 127 | input Absyn.Program in_env "All loaded models"; | ||
| 128 | output Absyn.Program out_env "Updated environment containing autogenerated models"; | ||
| 129 | |||
| 130 | protected | ||
| 131 | list<Mediator> ms; | ||
| 132 | Absyn.Class package_def, out_vmodel, autogen_class, autogen_class2; | ||
| 133 | list<SCode.Element> scode_def; | ||
| 134 | List<tuple<SCode.Element, String>> design_alts, reqs, scenarios; | ||
| 135 | list<Client_e> client_list; | ||
| 136 | list<Absyn.ElementItem> ag_elems, autogen_model_list; | ||
| 137 | Absyn.ElementItem autogen_model; | ||
| 138 | Integer i; | ||
| 139 | algorithm | ||
| 140 | 1 | scode_def := AbsynToSCode.translateAbsyn2SCode(in_env); | |
| 141 | // get all design alternatives | ||
| 142 | 1 | design_alts := getAllElementsOfType(scode_def, "VVDRlib.Verification.Design", "", {}); | |
| 143 | // get all requirements | ||
| 144 | 1 | reqs := getAllElementsOfType(scode_def, "VVDRlib.Verification.Requirement", "", {}); | |
| 145 | // get all scenarios | ||
| 146 | 1 | scenarios := getAllElementsOfType(scode_def, "VVDRlib.Verification.Scenario", "", {}); | |
| 147 | // get mediators | ||
| 148 | 1 | ms := getMediatorDefsElements(scode_def, {}); | |
| 149 | 1 | package_def := ProgramUtil.getPathedClassInProgram(package_path, in_env); | |
| 150 | autogen_model_list := {}; | ||
| 151 | i:=0; | ||
| 152 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
|
3 | for s in scenarios loop |
| 153 |
2/2✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
|
4 | for d in design_alts loop |
| 154 | |||
| 155 | 2 | ag_elems := populateModel(s::d::reqs, 0 , {}); | |
| 156 | ag_elems := Absyn.ELEMENTITEM(Absyn.ELEMENT(false, NONE(), Absyn.NOT_INNER_OUTER(), | ||
| 157 | Absyn.EXTENDS(Absyn.QUALIFIED("VVDRlib",Absyn.QUALIFIED("Verification",Absyn.IDENT("VerificationModel"))), {}, NONE()), | ||
| 158 | Absyn.dummyInfo, NONE()))::ag_elems; | ||
| 159 | 4 | autogen_class := Absyn.CLASS("verif_model_autogen_" + intString(i), | |
| 160 | false, false, false, Absyn.R_MODEL(), | ||
| 161 | Absyn.PARTS({}, {}, {Absyn.PUBLIC(ag_elems)},{}, | ||
| 162 | SOME("Autogenerated verification model")), {}, {}, {}, Absyn.dummyInfo); | ||
| 163 | 2 | print("*** Autogenerated class: " + "verif_model_autogen_" + intString(i) + "\n"); | |
| 164 | 2 | client_list := buildInstList(autogen_class, in_env, NO_PRED(), ms, {}, {}); | |
| 165 | 2 | autogen_class2 := inferBindingClientList(client_list, autogen_class, in_env); | |
| 166 | // print(Dump.unparseClassStr(autogen_class2) + "\n"); | ||
| 167 | |||
| 168 | 2 | autogen_model := Absyn.ELEMENTITEM(Absyn.ELEMENT(false, NONE(), Absyn.NOT_INNER_OUTER(), | |
| 169 | Absyn.CLASSDEF(false, autogen_class2), Absyn.dummyInfo, NONE())); | ||
| 170 | autogen_model_list := autogen_model::autogen_model_list; | ||
| 171 | 2 | i:= i+1; | |
| 172 | end for; | ||
| 173 | end for; | ||
| 174 | 1 | out_vmodel := updatePackage(package_def, autogen_model_list); | |
| 175 | 1 | print("******** Autogenerated classes:\n"+ Dump.unparseClassStr(out_vmodel) + "\n"); | |
| 176 | 1 | out_env := ProgramUtil.updateProgram(Absyn.PROGRAM({out_vmodel}, ProgramUtil.buildWithin(package_path)), in_env); | |
| 177 | end generateVerificationScenarios; | ||
| 178 | |||
| 179 | public function updatePackage | ||
| 180 | input Absyn.Class in_class; | ||
| 181 | input list<Absyn.ElementItem> ag_elems; | ||
| 182 | output Absyn.Class out_class; | ||
| 183 | algorithm | ||
| 184 | out_class := match in_class | ||
| 185 | local | ||
| 186 | Absyn.ClassDef body; | ||
| 187 | list<String> typeVars ; | ||
| 188 | list<Absyn.NamedArg> classAttrs ; | ||
| 189 | list<Absyn.Annotation> ann ; | ||
| 190 | Option<String> comment; | ||
| 191 | case out_class as Absyn.CLASS(body=Absyn.PARTS(typeVars, classAttrs, _, ann, comment)) | ||
| 192 | algorithm | ||
| 193 | 3 | out_class.body := Absyn.PARTS(typeVars, classAttrs, {Absyn.PUBLIC(ag_elems)}, ann, comment); | |
| 194 | then | ||
| 195 | out_class; | ||
| 196 | end match; | ||
| 197 | end updatePackage; | ||
| 198 | |||
| 199 | protected function populateModel | ||
| 200 | input List<tuple<SCode.Element, String>> element_defs; | ||
| 201 | input Integer autoVal; | ||
| 202 | input List<Absyn.ElementItem> elements_in; | ||
| 203 | output List<Absyn.ElementItem> elements_out; | ||
| 204 | algorithm | ||
| 205 | elements_out := match element_defs | ||
| 206 | local | ||
| 207 | List<tuple<SCode.Element, String>> rest; | ||
| 208 | Absyn.Element el; | ||
| 209 | Absyn.Ident cname; | ||
| 210 | String nName; | ||
| 211 | String p_path; | ||
| 212 | case {} then elements_in; | ||
| 213 | case (SCode.CLASS(cname, _, _, _, _, _, _, _), p_path)::rest | ||
| 214 | algorithm | ||
| 215 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
8 | nName := if(p_path=="")then cname else p_path+"."+cname; |
| 216 | 16 | el := Absyn.ELEMENT(false, NONE(), Absyn.NOT_INNER_OUTER(), Absyn.COMPONENTS( | |
| 217 | Absyn.ATTR(false, false, Absyn.NON_PARALLEL(), Absyn.VAR(), Absyn.BIDIR(), Absyn.NONFIELD(), {}), | ||
| 218 | Absyn.TPATH(AbsynUtil.stringPath(nName), NONE()), {Absyn.COMPONENTITEM( | ||
| 219 | Absyn.COMPONENT("_agen_" + cname + intString(autoVal), {}, NONE()), NONE(), NONE())}), Absyn.dummyInfo, NONE()); | ||
| 220 | 16 | then populateModel(rest, autoVal+1, Absyn.ELEMENTITEM(el)::elements_in); | |
| 221 | end match; | ||
| 222 | end populateModel; | ||
| 223 | |||
| 224 | |||
| 225 | |||
| 226 | protected function getAllElementsOfType | ||
| 227 | input list<SCode.Element> element_defs; | ||
| 228 | input Ident typeName; | ||
| 229 | input String pathInProg; | ||
| 230 | input List<tuple<SCode.Element, String>> elements_in; | ||
| 231 | output List<tuple<SCode.Element, String>> elements_out; | ||
| 232 | algorithm | ||
| 233 | elements_out := match element_defs | ||
| 234 | local | ||
| 235 | list<SCode.Element> rest; | ||
| 236 | List<tuple<SCode.Element, String>> m; | ||
| 237 | SCode.Element el; | ||
| 238 | case {} then elements_in; | ||
| 239 | case el::rest | ||
| 240 | algorithm | ||
| 241 | 90 | m := listAppend(getAllElementsOfType2(el, typeName, pathInProg), elements_in); | |
| 242 | 90 | then getAllElementsOfType(rest, typeName, pathInProg, m); | |
| 243 | end match; | ||
| 244 | end getAllElementsOfType; | ||
| 245 | |||
| 246 | protected function getAllElementsOfType2 | ||
| 247 | input SCode.Element el; | ||
| 248 | input Ident typeName; | ||
| 249 | input String pathInProg; | ||
| 250 | output List<tuple<SCode.Element, String>> res_elem; | ||
| 251 | algorithm | ||
| 252 | res_elem := match el | ||
| 253 | local | ||
| 254 | list<SCode.Element> elist; | ||
| 255 | String name, nName; | ||
| 256 | case SCode.CLASS("Modelica", _, _, _, SCode.R_PACKAGE(), SCode.PARTS(_, _,_,_,_,_,_,_), _, _) | ||
| 257 | algorithm | ||
| 258 | ✗ | print("**** Ignoring Standard Modelica library\n"); | |
| 259 | then {}; | ||
| 260 | case SCode.CLASS("OpenModelica", _, _, _, SCode.R_PACKAGE(), SCode.PARTS(_, _,_,_,_,_,_,_), _, _) | ||
| 261 | algorithm | ||
| 262 | ✗ | print("**** Ignoring Open Modelica library\n"); | |
| 263 | then {}; | ||
| 264 | case SCode.CLASS("Complex", _, _, _, SCode.R_PACKAGE(), SCode.PARTS(_, _,_,_,_,_,_,_), _, _) | ||
| 265 | algorithm | ||
| 266 | ✗ | print("**** Ignoring Complex library\n"); | |
| 267 | then {}; | ||
| 268 | case SCode.CLASS(name, _, _, _, SCode.R_PACKAGE(), SCode.PARTS(elist, _,_,_,_,_,_,_), _, _) | ||
| 269 | algorithm | ||
| 270 |
3/4✓ Branch 0 taken 3 times.
✓ Branch 1 taken 24 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
|
27 | nName := if(pathInProg=="")then name else pathInProg+"."+name; |
| 271 | 27 | then getAllElementsOfType(elist, typeName, nName, {}); | |
| 272 | case SCode.CLASS(_, _, _, _, _, SCode.PARTS(elist, _,_,_,_,_,_,_), _, _) guard isOfType(elist, typeName) | ||
| 273 | algorithm | ||
| 274 | 5 | print ("*** Found a " + typeName + "\n"); | |
| 275 | 5 | then {(el,pathInProg)}; | |
| 276 | case _ | ||
| 277 | algorithm | ||
| 278 | //print("not of right type " + typeName + "\n"); | ||
| 279 | //print(SCodeDump.unparseElementStr(el) + "\n"); | ||
| 280 | then {}; | ||
| 281 | end match; | ||
| 282 | end getAllElementsOfType2; | ||
| 283 | |||
| 284 | |||
| 285 | protected function isOfType | ||
| 286 | input list<SCode.Element> elems; | ||
| 287 | input String typeName; | ||
| 288 | output Boolean result; | ||
| 289 | algorithm | ||
| 290 | result := matchcontinue elems | ||
| 291 | local | ||
| 292 | list<SCode.Element> rest; | ||
| 293 | Absyn.Path p; | ||
| 294 | |||
| 295 | case {} then (false); | ||
| 296 | case SCode.EXTENDS(p, _, _, _, _)::_ | ||
| 297 | algorithm | ||
| 298 |
3/4✓ Branch 1 taken 5 times.
✓ Branch 2 taken 22 times.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
27 | true := (AbsynUtil.pathString(p) == typeName); |
| 299 | then (true); | ||
| 300 | case _::rest | ||
| 301 | 129 | then isOfType(rest, typeName); | |
| 302 | end matchcontinue; | ||
| 303 | end isOfType; | ||
| 304 | |||
| 305 | protected function inferBindingClientList | ||
| 306 | input list<Client_e> client_list "list of nodes for which the binding is inferred"; | ||
| 307 | input Absyn.Class vmodel; | ||
| 308 | input Absyn.Program env; | ||
| 309 | output Absyn.Class out_vmodel; | ||
| 310 | algorithm | ||
| 311 | out_vmodel := match client_list | ||
| 312 | local | ||
| 313 | Client_e ce; | ||
| 314 | list<Client_e> rest; | ||
| 315 | Absyn.Class upd_vmodel; | ||
| 316 | case {} then vmodel; | ||
| 317 | case ce::rest | ||
| 318 | algorithm | ||
| 319 | 6 | upd_vmodel := inferBindingClient(ce, vmodel, env); | |
| 320 | 6 | then inferBindingClientList(rest, upd_vmodel, env); | |
| 321 | end match; | ||
| 322 | end inferBindingClientList; | ||
| 323 | |||
| 324 | protected function inferBindingClient | ||
| 325 | input Client_e client_e; | ||
| 326 | input Absyn.Class vmodel; | ||
| 327 | input Absyn.Program env; | ||
| 328 | output Absyn.Class out_vmodel; | ||
| 329 | algorithm | ||
| 330 | out_vmodel := match client_e | ||
| 331 | local | ||
| 332 | TypeSpec typeSpec, rootType; | ||
| 333 | list<list<String>> iname; | ||
| 334 | String template; | ||
| 335 | list<Provider> providers; | ||
| 336 | list<Preferred> preferred; | ||
| 337 | list<tuple<Absyn.Exp, String>> out_es; | ||
| 338 | Absyn.Exp exp, new_exp; | ||
| 339 | Absyn.Class out_class; | ||
| 340 | case CLIENT_E(_, typeSpec, rootType, _, iname, _, | ||
| 341 | MEDIATOR(_, template, _, providers, {})::_) /* no preferred bindings indicated */ | ||
| 342 | algorithm | ||
| 343 | 6 | print("... infer binding " + Dump.unparseTypeSpec(typeSpec) + " " + Dump.unparseTypeSpec(rootType) + "\n"); | |
| 344 | |||
| 345 | 6 | out_es := getProviders(providers, vmodel, env, {}); | |
| 346 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 4 not taken.
|
6 | if (template == "") then |
| 347 | 6 | out_class := updateClass(vmodel, typeSpec, rootType, out_es, iname, env, false, {}, ""); | |
| 348 | else | ||
| 349 | ✗ | GlobalScript.ISTMTS({GlobalScript.IEXP(exp, _)}, _) := Parser.parsestringexp(template); | |
| 350 | ✗ | new_exp := parseAggregator(exp, Absyn.FUNCTIONARGS({Absyn.LIST(toExpList(out_es, {}))}, {})); | |
| 351 | // print("new TEMPLATE : " + Dump.dumpExpStr(new_exp) + "\n"); | ||
| 352 | ✗ | out_class := updateClass(vmodel, typeSpec, rootType, {(new_exp, "")}, iname, env, false, {}, ""); | |
| 353 | end if; | ||
| 354 | then out_class; | ||
| 355 | |||
| 356 | case CLIENT_E(_, typeSpec, rootType, _, iname, _, | ||
| 357 | MEDIATOR(_, _, _, providers, preferred)::_) /* preferred bindings indicated */ | ||
| 358 | algorithm | ||
| 359 | ✗ | out_es := getProviders(providers, vmodel, env, {}); | |
| 360 | ✗ | out_class := updateClass(vmodel, typeSpec, rootType, out_es, iname, env, true, preferred, ""); | |
| 361 | |||
| 362 | then out_class; | ||
| 363 | case NO_PRED() | ||
| 364 | algorithm | ||
| 365 | // print("NO_PRED\n"); | ||
| 366 | then vmodel; | ||
| 367 | end match; | ||
| 368 | end inferBindingClient; | ||
| 369 | |||
| 370 | public function toExpList | ||
| 371 | input list<tuple<Absyn.Exp, String>> e_list; | ||
| 372 | input list<Absyn.Exp> in_es; | ||
| 373 | output list<Absyn.Exp> out_es; | ||
| 374 | algorithm | ||
| 375 | out_es := match e_list | ||
| 376 | local | ||
| 377 | list<tuple<Absyn.Exp, String>> rest; | ||
| 378 | Absyn.Exp exp; | ||
| 379 | case {} then in_es; | ||
| 380 | case (exp, _)::rest | ||
| 381 | ✗ | then toExpList(rest, exp::in_es); | |
| 382 | end match; | ||
| 383 | end toExpList; | ||
| 384 | |||
| 385 | public function updateClass | ||
| 386 | input Absyn.Class in_class; | ||
| 387 | input TypeSpec typeSpec; | ||
| 388 | input TypeSpec rootType; | ||
| 389 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 390 | input list<list<String>> instance_name; | ||
| 391 | input Absyn.Program defs; | ||
| 392 | input Boolean hasPreferred; | ||
| 393 | input list<Preferred> preferred; | ||
| 394 | input String path; | ||
| 395 | output Absyn.Class out_class; | ||
| 396 | algorithm | ||
| 397 | out_class as Absyn.CLASS() := in_class; | ||
| 398 | 12 | out_class.body := parseClassDef(out_class.body, defs, typeSpec, rootType, exp, instance_name, hasPreferred, preferred, path + out_class.name + "."); | |
| 399 | end updateClass; | ||
| 400 | |||
| 401 | protected function parseClassDef | ||
| 402 | input Absyn.ClassDef in_def; | ||
| 403 | input Absyn.Program defs; | ||
| 404 | input TypeSpec typeSpec; | ||
| 405 | input TypeSpec rootType; | ||
| 406 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 407 | input list<list<String>> instance_name; | ||
| 408 | input Boolean hasPreferred; | ||
| 409 | input list<Preferred> preferred; | ||
| 410 | input String path; | ||
| 411 | output Absyn.ClassDef out_def; | ||
| 412 | algorithm | ||
| 413 | out_def := match in_def | ||
| 414 | local | ||
| 415 | list<String> typeVars ; | ||
| 416 | list<Absyn.NamedArg> classAttrs ; | ||
| 417 | list<Absyn.ClassPart> classParts, nclsp; | ||
| 418 | list<Absyn.Annotation> ann ; | ||
| 419 | Option<String> comment; | ||
| 420 | case Absyn.PARTS(typeVars, classAttrs, classParts, ann, comment) | ||
| 421 | algorithm | ||
| 422 | 6 | nclsp := parseClassParts(classParts, defs, typeSpec, rootType, exp, instance_name, hasPreferred, preferred, path); | |
| 423 | 6 | then | |
| 424 | Absyn.PARTS(typeVars, classAttrs, nclsp, ann, comment); | ||
| 425 | end match; | ||
| 426 | end parseClassDef; | ||
| 427 | |||
| 428 | protected function parseClassParts | ||
| 429 | input list<Absyn.ClassPart> classes; | ||
| 430 | input Absyn.Program defs; | ||
| 431 | input TypeSpec typeSpec; | ||
| 432 | input TypeSpec rootType; | ||
| 433 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 434 | input list<list<String>> instance_name; | ||
| 435 | input Boolean hasPreferred; | ||
| 436 | input list<Preferred> preferred; | ||
| 437 | input String path; | ||
| 438 | output list<Absyn.ClassPart> out_classes; | ||
| 439 | |||
| 440 | algorithm | ||
| 441 | out_classes := match classes | ||
| 442 | local | ||
| 443 | list<Absyn.ClassPart> r_classes, nr_classes; | ||
| 444 | Absyn.ClassPart cls, n_cls; | ||
| 445 | case {} then ({}); | ||
| 446 | case cls :: r_classes | ||
| 447 | algorithm | ||
| 448 | 6 | n_cls := parseClassPart(cls, defs, typeSpec, rootType, exp, instance_name, hasPreferred, preferred, path); | |
| 449 | 6 | nr_classes := parseClassParts(r_classes, defs, typeSpec, rootType, exp, instance_name, hasPreferred, preferred, path); | |
| 450 | then | ||
| 451 | (n_cls :: nr_classes); | ||
| 452 | end match; | ||
| 453 | end parseClassParts; | ||
| 454 | |||
| 455 | protected function parseClassPart | ||
| 456 | input Absyn.ClassPart in_def; | ||
| 457 | input Absyn.Program defs; | ||
| 458 | input TypeSpec typeSpec; | ||
| 459 | input TypeSpec rootType; | ||
| 460 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 461 | input list<list <String>> instance_name; | ||
| 462 | input Boolean hasPreferred; | ||
| 463 | input list<Preferred> preferred; | ||
| 464 | input String path; | ||
| 465 | output Absyn.ClassPart out_def; | ||
| 466 | |||
| 467 | algorithm | ||
| 468 | out_def := match in_def | ||
| 469 | local | ||
| 470 | list<Absyn.ElementItem> elems; | ||
| 471 | list<Absyn.ElementItem> elems1; | ||
| 472 | case Absyn.PUBLIC(elems) | ||
| 473 | algorithm | ||
| 474 | 6 | elems1 := parseElems(elems, defs, typeSpec, rootType, exp, instance_name, hasPreferred, preferred, path); | |
| 475 | 6 | then | |
| 476 | (Absyn.PUBLIC(elems1)); | ||
| 477 | /* case(Absyn.PROTECTED(elems)) //TODO | ||
| 478 | then | ||
| 479 | (Absyn.PROTECTED(elems), {}, {}, instNo); //TODO */ | ||
| 480 | case _ | ||
| 481 | then | ||
| 482 | (in_def); | ||
| 483 | end match; | ||
| 484 | end parseClassPart; | ||
| 485 | |||
| 486 | protected function parseElems | ||
| 487 | input list<Absyn.ElementItem> in_elems; | ||
| 488 | input Absyn.Program defs; | ||
| 489 | input TypeSpec typeSpec; | ||
| 490 | input TypeSpec rootType; | ||
| 491 | input list<tuple<Absyn.Exp, String>> exp2; | ||
| 492 | input list<list<String>> instance_name; | ||
| 493 | input Boolean hasPreferred; | ||
| 494 | input list<Preferred> preferred; | ||
| 495 | input String pathInClass; | ||
| 496 | output list<Absyn.ElementItem> out_elems; | ||
| 497 | algorithm | ||
| 498 | out_elems := matchcontinue in_elems | ||
| 499 | local | ||
| 500 | Boolean finalPrefix; | ||
| 501 | Option<Absyn.RedeclareKeywords> redeclareKeywords "replaceable, redeclare" ; | ||
| 502 | Absyn.InnerOuter innerOuter "inner/outer" ; | ||
| 503 | Absyn.Info info "File name the class is defined in + line no + column no" ; | ||
| 504 | Option<Absyn.ConstrainClass> constrainClass "only valid for classdef and component" ; | ||
| 505 | Absyn.ElementAttributes attributes; | ||
| 506 | Absyn.ElementItem e_item; | ||
| 507 | list<Absyn.ElementItem> rest, e_list; | ||
| 508 | list<Absyn.ComponentItem> components; | ||
| 509 | TypeSpec tSpec; | ||
| 510 | Boolean newName; | ||
| 511 | case {} | ||
| 512 | then in_elems; | ||
| 513 | case Absyn.ELEMENTITEM(Absyn.ELEMENT(finalPrefix,redeclareKeywords,innerOuter, | ||
| 514 | Absyn.COMPONENTS(attributes, tSpec, components), info , constrainClass))::rest | ||
| 515 | algorithm | ||
| 516 | //print ("**** Finding clients ... " + Dump.unparseTypeSpec(typeSpec) + " + " +Dump.unparseTypeSpec(tSpec)+ " + "+Dump.unparseTypeSpec(rootType) + "...\n"); | ||
| 517 | //if Interactive.isPrimitive(path, defs) then fail(); end if; | ||
| 518 | // TODO: add generation error for is mandatory | ||
| 519 |
4/6✓ Branch 2 taken 6 times.
✓ Branch 3 taken 24 times.
✓ Branch 7 taken 6 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 6 times.
✗ Branch 10 not taken.
|
30 | if ((AbsynUtil.typeSpecPathString(rootType) == AbsynUtil.typeSpecPathString(tSpec)) and not(listEmpty(exp2))) then |
| 520 | 6 | print("... found instance provider " + Dump.unparseTypeSpec(tSpec) + "\n"); | |
| 521 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if(hasPreferred) then //handle preferred bindings |
| 522 | ✗ | e_list := applyModifiersPreferred(components, exp2, instance_name, pathInClass, finalPrefix, redeclareKeywords ,innerOuter, info , constrainClass, attributes, tSpec, preferred); | |
| 523 | else | ||
| 524 | 6 | newName := listLength(exp2) <> 1; | |
| 525 | 6 | e_list := applyModifiers(components, exp2, instance_name, 0, finalPrefix, redeclareKeywords ,innerOuter, info , constrainClass, attributes, tSpec, newName); | |
| 526 | end if; | ||
| 527 | else | ||
| 528 | //print("*** NOT Found provider" + Dump.unparseTypeSpec(typeSpec) + "\n"); | ||
| 529 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
48 | e_list := {Absyn.ELEMENTITEM(Absyn.ELEMENT(finalPrefix,redeclareKeywords ,innerOuter, Absyn.COMPONENTS(attributes,tSpec, components), info , constrainClass))}; |
| 530 | |||
| 531 | end if; | ||
| 532 | 30 | then listAppend(e_list, parseElems(rest, defs, typeSpec, rootType, exp2, instance_name, hasPreferred, preferred, pathInClass)); | |
| 533 | case e_item::rest | ||
| 534 | 6 | then e_item::parseElems(rest, defs, typeSpec, rootType, exp2, instance_name, hasPreferred, preferred, pathInClass); | |
| 535 | end matchcontinue; | ||
| 536 | end parseElems; | ||
| 537 | |||
| 538 | protected function applyModifiersPreferred | ||
| 539 | input list<Absyn.ComponentItem> comps; | ||
| 540 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 541 | input list<list<String>> instance_name; | ||
| 542 | input String typeSp; | ||
| 543 | input Boolean finalPrefix; | ||
| 544 | input Option<Absyn.RedeclareKeywords> redeclareKeywords "replaceable, redeclare" ; | ||
| 545 | input Absyn.InnerOuter innerOuter "inner/outer" ; | ||
| 546 | input Absyn.Info info "File name the class is defined in + line no + column no" ; | ||
| 547 | input Option<Absyn.ConstrainClass> constrainClass "only valid for classdef and component" ; | ||
| 548 | input Absyn.ElementAttributes attributes; | ||
| 549 | input TypeSpec tSpec; | ||
| 550 | input list<Preferred> preferred; | ||
| 551 | output list<Absyn.ElementItem> out_elems; | ||
| 552 | algorithm | ||
| 553 | out_elems := matchcontinue exp | ||
| 554 | local | ||
| 555 | list<tuple<Absyn.Exp, String>> rest; | ||
| 556 | list<Absyn.ComponentItem> cnew; | ||
| 557 | Absyn.Exp e; | ||
| 558 | String ename, client_pref; | ||
| 559 | Absyn.ElementItem enew; | ||
| 560 | case {} then {}; | ||
| 561 | case (e, ename)::rest | ||
| 562 | algorithm | ||
| 563 | ✗ | client_pref := getPreferredBinding(ename, preferred); | |
| 564 | ✗ | cnew := applyModifierPreferred(comps, e, client_pref, instance_name, ename); | |
| 565 | ✗ | enew := Absyn.ELEMENTITEM(Absyn.ELEMENT(finalPrefix,redeclareKeywords ,innerOuter, Absyn.COMPONENTS(attributes,tSpec, cnew), info , constrainClass)); | |
| 566 | |||
| 567 | ✗ | then enew::applyModifiersPreferred(comps, rest, instance_name, typeSp, finalPrefix,redeclareKeywords ,innerOuter, info , constrainClass, attributes,tSpec, preferred); | |
| 568 | case _::rest | ||
| 569 | ✗ | then applyModifiersPreferred(comps, rest, instance_name, typeSp, finalPrefix, redeclareKeywords ,innerOuter, info , constrainClass, attributes,tSpec, preferred); | |
| 570 | end matchcontinue; | ||
| 571 | end applyModifiersPreferred; | ||
| 572 | |||
| 573 | protected function getPreferredBinding | ||
| 574 | input String ename; | ||
| 575 | input list<Preferred> elems; | ||
| 576 | output String cl_name; | ||
| 577 | algorithm | ||
| 578 | cl_name := matchcontinue elems | ||
| 579 | local | ||
| 580 | list<Preferred> rest; | ||
| 581 | String c_id, p_id; | ||
| 582 | case {} then fail(); | ||
| 583 | case PREFERRED(c_id, p_id)::_ | ||
| 584 | algorithm | ||
| 585 | ✗ | true := (p_id == ename); | |
| 586 | then c_id; | ||
| 587 | case _::rest | ||
| 588 | ✗ | then getPreferredBinding(ename, rest); | |
| 589 | end matchcontinue; | ||
| 590 | end getPreferredBinding; | ||
| 591 | |||
| 592 | protected function applyModifierPreferred | ||
| 593 | input list<Absyn.ComponentItem> comps; | ||
| 594 | input Absyn.Exp exp; | ||
| 595 | input String typeSp; | ||
| 596 | input list<list <String>> instance_name; | ||
| 597 | input String ename; | ||
| 598 | output list<Absyn.ComponentItem> out_comps; | ||
| 599 | algorithm | ||
| 600 | out_comps := matchcontinue comps | ||
| 601 | local | ||
| 602 | list<Absyn.ComponentItem> rest; | ||
| 603 | Absyn.ComponentItem cnew; | ||
| 604 | Option<Absyn.ComponentCondition> condition "condition" ; | ||
| 605 | Option<Absyn.Comment> comment "comment" ; | ||
| 606 | Ident name "name" ; | ||
| 607 | Absyn.ArrayDim arrayDim "Array dimensions, if any" ; | ||
| 608 | case {} then {}; | ||
| 609 | case Absyn.COMPONENTITEM(Absyn.COMPONENT(name, arrayDim, _), condition, comment)::_ | ||
| 610 | algorithm | ||
| 611 | ✗ | true := (typeSp == name); | |
| 612 | ✗ | cnew := Absyn.COMPONENTITEM(Absyn.COMPONENT(name, arrayDim, | |
| 613 | SOME(Absyn.CLASSMOD(buildComponentModifiers(instance_name,exp), Absyn.NOMOD()))), condition, comment); | ||
| 614 | then {cnew}; | ||
| 615 | case _::rest | ||
| 616 | ✗ | then applyModifierPreferred(rest, exp, typeSp, instance_name, ename); | |
| 617 | end matchcontinue; | ||
| 618 | end applyModifierPreferred; | ||
| 619 | |||
| 620 | protected function applyModifiers | ||
| 621 | input list<Absyn.ComponentItem> comps; | ||
| 622 | input list<tuple<Absyn.Exp, String>> exp; | ||
| 623 | input list<list<String>> instance_name; | ||
| 624 | input Integer counter; | ||
| 625 | input Boolean finalPrefix; | ||
| 626 | input Option<Absyn.RedeclareKeywords> redeclareKeywords "replaceable, redeclare" ; | ||
| 627 | input Absyn.InnerOuter innerOuter "inner/outer" ; | ||
| 628 | input Absyn.Info info "File name the class is defined in + line no + column no" ; | ||
| 629 | input Option<Absyn.ConstrainClass> constrainClass "only valid for classdef and component" ; | ||
| 630 | input Absyn.ElementAttributes attributes; | ||
| 631 | input TypeSpec tSpec; | ||
| 632 | input Boolean newName; | ||
| 633 | output list<Absyn.ElementItem> out_elems; | ||
| 634 | algorithm | ||
| 635 | out_elems := match exp | ||
| 636 | local | ||
| 637 | list<tuple<Absyn.Exp, String>> rest; | ||
| 638 | list<Absyn.ComponentItem> cnew; | ||
| 639 | Absyn.Exp e; | ||
| 640 | Absyn.ElementItem enew; | ||
| 641 | case {} then {}; | ||
| 642 | case (e, _)::rest | ||
| 643 | algorithm | ||
| 644 | 10 | cnew := applyModifier(comps, e, instance_name, counter, newName); | |
| 645 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | enew := Absyn.ELEMENTITEM(Absyn.ELEMENT(finalPrefix,redeclareKeywords ,innerOuter, Absyn.COMPONENTS(attributes,tSpec, cnew), info , constrainClass)); |
| 646 | 10 | then enew::applyModifiers(comps, rest, instance_name, counter+1, finalPrefix,redeclareKeywords ,innerOuter, info , constrainClass, attributes,tSpec, newName); | |
| 647 | case _::rest | ||
| 648 | ✗ | then applyModifiers(comps, rest, instance_name, counter, finalPrefix,redeclareKeywords ,innerOuter, info , constrainClass, attributes,tSpec, newName); | |
| 649 | end match; | ||
| 650 | end applyModifiers; | ||
| 651 | |||
| 652 | protected function applyModifier | ||
| 653 | input list<Absyn.ComponentItem> comps; | ||
| 654 | input Absyn.Exp exp; | ||
| 655 | input list<list<String>> instance_name; | ||
| 656 | input Integer counter; | ||
| 657 | input Boolean newName; | ||
| 658 | output list<Absyn.ComponentItem> out_comps; | ||
| 659 | algorithm | ||
| 660 | out_comps := matchcontinue comps | ||
| 661 | local | ||
| 662 | list<Absyn.ComponentItem> rest; | ||
| 663 | Absyn.ComponentItem cnew; | ||
| 664 | Option<Absyn.ComponentCondition> condition "condition" ; | ||
| 665 | Option<Absyn.Comment> comment "comment" ; | ||
| 666 | Absyn.Ident name, new_name ; | ||
| 667 | |||
| 668 | Absyn.ArrayDim arrayDim "Array dimensions, if any" ; | ||
| 669 | case {} then {}; | ||
| 670 | case Absyn.COMPONENTITEM(Absyn.COMPONENT(name, arrayDim, _), condition, comment)::_ | ||
| 671 | algorithm | ||
| 672 | //print("**** Applying modifier\n"); | ||
| 673 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 2 times.
|
10 | new_name := if(newName) then name + "_autogen_bind_" + intString(counter) else name; |
| 674 | 10 | print("**** Applying modifier " + new_name +"\n"); | |
| 675 | 20 | cnew := Absyn.COMPONENTITEM(Absyn.COMPONENT(new_name, arrayDim, | |
| 676 | SOME(Absyn.CLASSMOD(buildComponentModifiers(instance_name,exp), Absyn.NOMOD()))), condition, comment); | ||
| 677 | then {cnew}; | ||
| 678 | case _::rest | ||
| 679 | ✗ | then applyModifier(rest, exp, instance_name, counter, newName); | |
| 680 | end matchcontinue; | ||
| 681 | end applyModifier; | ||
| 682 | |||
| 683 | protected function buildComponentModifiers | ||
| 684 | input list<list<String>> name_list; | ||
| 685 | input Absyn.Exp exp; | ||
| 686 | output list<Absyn.ElementArg> out_modifiers; | ||
| 687 | protected | ||
| 688 | list<String> parsed_names; | ||
| 689 | algorithm | ||
| 690 | 10 | parsed_names := buildAllComponentModifiers(name_list); | |
| 691 | 10 | out_modifiers := buildComponentModifiers2(parsed_names, exp); | |
| 692 | end buildComponentModifiers; | ||
| 693 | |||
| 694 | protected function buildComponentModifiers2 | ||
| 695 | input list<String> name_list; | ||
| 696 | input Absyn.Exp exp; | ||
| 697 | output list<Absyn.ElementArg> out_modifiers; | ||
| 698 | algorithm | ||
| 699 | out_modifiers := match name_list | ||
| 700 | local | ||
| 701 | list<String> rest; | ||
| 702 | String name; | ||
| 703 | case {} then {}; | ||
| 704 | 20 | case name::rest then Absyn.MODIFICATION(false, Absyn.NON_EACH(), | |
| 705 | AbsynUtil.stringPath(name), SOME(Absyn.CLASSMOD({}, Absyn.EQMOD(exp, Absyn.dummyInfo))), NONE(), Absyn.dummyInfo)::buildComponentModifiers2(rest, exp); | ||
| 706 | end match; | ||
| 707 | end buildComponentModifiers2; | ||
| 708 | |||
| 709 | |||
| 710 | protected function buildAllComponentModifiers | ||
| 711 | input list<list<String>> name_list; | ||
| 712 | output list<String> out_names; | ||
| 713 | algorithm | ||
| 714 | out_names := match name_list | ||
| 715 | local | ||
| 716 | list<String> l, tmp_names; | ||
| 717 | list<list<String>> rest; | ||
| 718 | case {} then {}; | ||
| 719 | case l::rest | ||
| 720 | algorithm | ||
| 721 | 12 | tmp_names := buildAllComponentModifiers(rest); | |
| 722 | 12 | then buildAllComponentModifiers2(l, tmp_names); | |
| 723 | end match; | ||
| 724 | end buildAllComponentModifiers; | ||
| 725 | |||
| 726 | protected function buildAllComponentModifiers2 | ||
| 727 | input list<String> name_list; | ||
| 728 | input list<String> name_list2; | ||
| 729 | output list<String> out_names; | ||
| 730 | algorithm | ||
| 731 | out_names := match name_list | ||
| 732 | local | ||
| 733 | String s; | ||
| 734 | list<String> tmp_names; | ||
| 735 | list<String> rest; | ||
| 736 | case {} then {}; | ||
| 737 | case s::rest | ||
| 738 | algorithm | ||
| 739 | 12 | tmp_names := buildAllComponentModifiers2(rest, name_list2); | |
| 740 | 12 | then listAppend(buildAllComponentModifiers3(s, name_list2), tmp_names); | |
| 741 | end match; | ||
| 742 | end buildAllComponentModifiers2; | ||
| 743 | |||
| 744 | protected function buildAllComponentModifiers3 | ||
| 745 | input String prefix; | ||
| 746 | input list<String> name_list2; | ||
| 747 | output list<String> out_names; | ||
| 748 | algorithm | ||
| 749 | out_names := match name_list2 | ||
| 750 | local | ||
| 751 | String s; | ||
| 752 | list<String> rest; | ||
| 753 | case {} then {prefix}; | ||
| 754 | case s::rest | ||
| 755 | algorithm | ||
| 756 | 2 | then (s+ "." + prefix )::buildAllComponentModifiers2(rest, name_list2); | |
| 757 | end match; | ||
| 758 | end buildAllComponentModifiers3; | ||
| 759 | |||
| 760 | |||
| 761 | protected function parseAggregator | ||
| 762 | input Absyn.Exp in_eq; | ||
| 763 | input Absyn.FunctionArgs fargs; | ||
| 764 | output Absyn.Exp out_eq; | ||
| 765 | algorithm | ||
| 766 | out_eq := match in_eq | ||
| 767 | local | ||
| 768 | Absyn.ComponentRef crf; | ||
| 769 | Absyn.Exp exp1, exp2, nexp1, nexp2, ife, nife; | ||
| 770 | Absyn.Operator op; | ||
| 771 | list<tuple<Absyn.Exp, Absyn.Exp>> elif; | ||
| 772 | |||
| 773 | case Absyn.BINARY(exp1, op, exp2) | ||
| 774 | algorithm | ||
| 775 | ✗ | nexp1 := parseAggregator(exp1, fargs); | |
| 776 | ✗ | nexp2 := parseAggregator(exp2, fargs); | |
| 777 | ✗ | then Absyn.BINARY(nexp1, op, nexp2); | |
| 778 | |||
| 779 | case Absyn.LBINARY(exp1, op, exp2) | ||
| 780 | algorithm | ||
| 781 | ✗ | nexp1 := parseAggregator(exp1, fargs); | |
| 782 | ✗ | nexp2 := parseAggregator(exp2, fargs); | |
| 783 | ✗ | then (Absyn.LBINARY(nexp1, op, nexp2)); | |
| 784 | case Absyn.RELATION(exp1, op, exp2) | ||
| 785 | algorithm | ||
| 786 | ✗ | nexp1 := parseAggregator(exp1, fargs); | |
| 787 | ✗ | nexp2 := parseAggregator(exp2, fargs); | |
| 788 | ✗ | then (Absyn.RELATION(nexp1, op, nexp2)); | |
| 789 | case Absyn.UNARY(op, exp2) | ||
| 790 | algorithm | ||
| 791 | ✗ | nexp1 := parseAggregator(exp2, fargs); | |
| 792 | ✗ | then (Absyn.UNARY(op, nexp1)); | |
| 793 | |||
| 794 | case Absyn.LUNARY(op, exp2) | ||
| 795 | algorithm | ||
| 796 | ✗ | nexp1 := parseAggregator(exp2, fargs); | |
| 797 | ✗ | then (Absyn.LUNARY(op, nexp1)); | |
| 798 | |||
| 799 | case Absyn.IFEXP(ife, exp1, exp2, elif) | ||
| 800 | algorithm | ||
| 801 | ✗ | nife := parseAggregator(ife, fargs); | |
| 802 | ✗ | nexp1 := parseAggregator(exp1, fargs); | |
| 803 | ✗ | nexp2 := parseAggregator(exp2, fargs); | |
| 804 | //(nelif, eqs4, elems4, count4) = parseExpressionTuple(elif, defs, eqs3, elems3, count3); | ||
| 805 | ✗ | then (Absyn.IFEXP(nife, nexp1, nexp2, elif)); | |
| 806 | case Absyn.CALL(crf, _) | ||
| 807 | algorithm | ||
| 808 | //print("CALL...." + "\n"); | ||
| 809 | //print(Dump.dumpExpStr(Absyn.CALL(crf, fargs)) + "\n"); | ||
| 810 | ✗ | then (Absyn.CALL(crf, fargs, in_eq.typeVars)); | |
| 811 | case _ | ||
| 812 | algorithm | ||
| 813 | //print(Dump.dumpExpStr(in_eq) + "\n"); | ||
| 814 | then (in_eq); | ||
| 815 | end match; | ||
| 816 | end parseAggregator; | ||
| 817 | |||
| 818 | |||
| 819 | public function getProviders | ||
| 820 | input list<Provider> providers; | ||
| 821 | input Absyn.Class vmodel; | ||
| 822 | input Absyn.Program env; | ||
| 823 | input list<tuple<Absyn.Exp, String>> in_es; | ||
| 824 | output list<tuple<Absyn.Exp, String>> out_es; | ||
| 825 | algorithm | ||
| 826 | out_es := match providers | ||
| 827 | local | ||
| 828 | list<Provider> rest; | ||
| 829 | String className, template; | ||
| 830 | list<tuple<list<Absyn.ComponentItem>, String>> comps; | ||
| 831 | list<tuple<Absyn.Exp, String>> exps, new_es; | ||
| 832 | list<Absyn.ElementItem> mlist; | ||
| 833 | Absyn.Exp exp; | ||
| 834 | case {} then in_es; | ||
| 835 | case PROVIDER(className, _, template)::rest // TODO fix handling instance | ||
| 836 | algorithm | ||
| 837 | 8 | mlist := AbsynUtil.getElementItemsInClass(vmodel); | |
| 838 | 8 | comps := getAllProviderInstances(className, template, mlist, env, {}, ""); | |
| 839 | //print("WILL parse provider: "+ className + " with template: " + template + "\n"); | ||
| 840 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8 times.
|
8 | GlobalScript.ISTMTS({GlobalScript.IEXP(exp, _)}, _) := Parser.parsestringexp(template); |
| 841 | //print(Dump.dumpExpStr(exp) + "\n"); | ||
| 842 | 8 | exps := applyTemplate(exp, comps, {}); | |
| 843 | //print("Updated expression ... " + Dump.dumpExpStr(exp) + "\n"); | ||
| 844 | 8 | new_es := listAppend(exps, in_es); | |
| 845 | 8 | then getProviders(rest, vmodel, env, new_es); | |
| 846 | end match; | ||
| 847 | end getProviders; | ||
| 848 | |||
| 849 | protected function applyTemplate | ||
| 850 | input Absyn.Exp exp; | ||
| 851 | input list<tuple<list<Absyn.ComponentItem>, String>> comps; | ||
| 852 | input list<tuple<Absyn.Exp, String>> in_es; | ||
| 853 | output list<tuple<Absyn.Exp, String>> out_es; | ||
| 854 | algorithm | ||
| 855 | out_es := match comps | ||
| 856 | local | ||
| 857 | list<Absyn.ComponentItem> clist; | ||
| 858 | list<tuple<list<Absyn.ComponentItem>, String>> rest; | ||
| 859 | list<tuple<Absyn.Exp, String>> new_es; | ||
| 860 | String pathInClass; | ||
| 861 | case {} | ||
| 862 | then in_es; | ||
| 863 | case (clist, pathInClass)::rest | ||
| 864 | algorithm | ||
| 865 | 10 | new_es := applyTemplate2(exp, clist, in_es, pathInClass); | |
| 866 | 10 | then applyTemplate(exp, rest, new_es); | |
| 867 | case _::rest | ||
| 868 | algorithm | ||
| 869 | ✗ | then applyTemplate(exp, rest, in_es); | |
| 870 | end match; | ||
| 871 | end applyTemplate; | ||
| 872 | |||
| 873 | protected function applyTemplate2 | ||
| 874 | input Absyn.Exp exp; | ||
| 875 | input list<Absyn.ComponentItem> comps; | ||
| 876 | input list<tuple<Absyn.Exp, String>> in_es; | ||
| 877 | input String pathInClass; | ||
| 878 | output list<tuple<Absyn.Exp, String>> out_es; | ||
| 879 | algorithm | ||
| 880 | out_es := match comps | ||
| 881 | local | ||
| 882 | list<Absyn.ComponentItem> rest; | ||
| 883 | Absyn.Ident name, newName; | ||
| 884 | case {} | ||
| 885 | algorithm | ||
| 886 | then in_es; | ||
| 887 | case Absyn.COMPONENTITEM(Absyn.COMPONENT(name, _, _), _, _)::rest | ||
| 888 | algorithm | ||
| 889 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
10 | newName := if(pathInClass == "") then name else pathInClass + "." + name; |
| 890 | // print("Applying template to" + newName + "\n"); | ||
| 891 | 20 | then applyTemplate2(exp, rest, (parseExpression(exp, newName), newName)::in_es, pathInClass); | |
| 892 | case _::rest | ||
| 893 | algorithm | ||
| 894 | ✗ | then applyTemplate2(exp, rest, in_es, pathInClass); | |
| 895 | end match; | ||
| 896 | end applyTemplate2; | ||
| 897 | |||
| 898 | protected function parseExpression | ||
| 899 | input Absyn.Exp in_eq; | ||
| 900 | input Absyn.Ident fargs; | ||
| 901 | output Absyn.Exp out_eq; | ||
| 902 | algorithm | ||
| 903 | out_eq := match in_eq | ||
| 904 | local | ||
| 905 | Absyn.ComponentRef crf, new_crf; | ||
| 906 | Absyn.Exp exp1, exp2, nexp1, nexp2, ife, nife; | ||
| 907 | Absyn.Operator op; | ||
| 908 | list<tuple<Absyn.Exp, Absyn.Exp>> elif; | ||
| 909 | |||
| 910 | case Absyn.BINARY(exp1, op, exp2) | ||
| 911 | algorithm | ||
| 912 | ✗ | nexp1 := parseExpression(exp1, fargs); | |
| 913 | ✗ | nexp2 := parseExpression(exp2, fargs); | |
| 914 | ✗ | then Absyn.BINARY(nexp1, op, nexp2); | |
| 915 | |||
| 916 | case Absyn.LBINARY(exp1, op, exp2) | ||
| 917 | algorithm | ||
| 918 | ✗ | nexp1 := parseExpression(exp1, fargs); | |
| 919 | ✗ | nexp2 := parseExpression(exp2, fargs); | |
| 920 | ✗ | then (Absyn.LBINARY(nexp1, op, nexp2)); | |
| 921 | case Absyn.RELATION(exp1, op, exp2) | ||
| 922 | algorithm | ||
| 923 | ✗ | nexp1 := parseExpression(exp1, fargs); | |
| 924 | ✗ | nexp2 := parseExpression(exp2, fargs); | |
| 925 | ✗ | then (Absyn.RELATION(nexp1, op, nexp2)); | |
| 926 | case Absyn.UNARY(op, exp2) | ||
| 927 | algorithm | ||
| 928 | ✗ | nexp1 := parseExpression(exp2, fargs); | |
| 929 | ✗ | then (Absyn.UNARY(op, nexp1)); | |
| 930 | |||
| 931 | case Absyn.LUNARY(op, exp2) | ||
| 932 | algorithm | ||
| 933 | ✗ | nexp1 := parseExpression(exp2, fargs); | |
| 934 | ✗ | then (Absyn.LUNARY(op, nexp1)); | |
| 935 | |||
| 936 | case Absyn.IFEXP(ife, exp1, exp2, elif) | ||
| 937 | algorithm | ||
| 938 | ✗ | nife := parseExpression(ife, fargs); | |
| 939 | ✗ | nexp1 := parseExpression(exp1, fargs); | |
| 940 | ✗ | nexp2 := parseExpression(exp2, fargs); | |
| 941 | //(nelif, eqs4, elems4, count4) = parseExpressionTuple(elif, defs, eqs3, elems3, count3); | ||
| 942 | ✗ | then (Absyn.IFEXP(nife, nexp1, nexp2, elif)); | |
| 943 | case Absyn.CREF(crf) | ||
| 944 | algorithm | ||
| 945 | 10 | new_crf := updateCRF(crf, fargs); | |
| 946 | 10 | then (Absyn.CREF(new_crf)); | |
| 947 | case _ | ||
| 948 | algorithm | ||
| 949 | //print(Dump.dumpExpStr(in_eq) + "\n"); | ||
| 950 | then (in_eq); | ||
| 951 | end match; | ||
| 952 | end parseExpression; | ||
| 953 | |||
| 954 | protected function updateCRF | ||
| 955 | input Absyn.ComponentRef componentRef; | ||
| 956 | input Absyn.Ident name; | ||
| 957 | output Absyn.ComponentRef out_componentRef; | ||
| 958 | algorithm | ||
| 959 | out_componentRef := match componentRef | ||
| 960 | local | ||
| 961 | Absyn.ComponentRef cRef, new_cRef; | ||
| 962 | list<Absyn.Subscript> subscripts; | ||
| 963 | Absyn.Ident id; | ||
| 964 | ✗ | case Absyn.CREF_FULLYQUALIFIED(cRef) then updateCRF(cRef, name); | |
| 965 | case Absyn.CREF_QUAL("getPath", subscripts, cRef) | ||
| 966 | 10 | then Absyn.CREF_QUAL(name, subscripts, cRef); | |
| 967 | case Absyn.CREF_QUAL(id, subscripts, cRef) | ||
| 968 | algorithm | ||
| 969 | ✗ | new_cRef := updateCRF(cRef, name); | |
| 970 | ✗ | then Absyn.CREF_QUAL(id, subscripts, new_cRef); | |
| 971 | ✗ | case Absyn.CREF_IDENT("getPath", subscripts) then Absyn.CREF_IDENT(name, subscripts); | |
| 972 | case _ then componentRef; | ||
| 973 | end match; | ||
| 974 | end updateCRF; | ||
| 975 | |||
| 976 | protected function getAllProviderInstances | ||
| 977 | input String className; | ||
| 978 | input String template; | ||
| 979 | input list<Absyn.ElementItem> e_items; | ||
| 980 | input Absyn.Program env; | ||
| 981 | input list<tuple<list<Absyn.ComponentItem>, String>> in_components; | ||
| 982 | input String pathInClass; | ||
| 983 | output list<tuple<list<Absyn.ComponentItem>, String>> out_components; | ||
| 984 | algorithm | ||
| 985 | out_components := matchcontinue e_items | ||
| 986 | local | ||
| 987 | list<Absyn.ElementItem> rest, re_items; | ||
| 988 | list<Absyn.ComponentItem> components; | ||
| 989 | list<tuple<list<Absyn.ComponentItem>, String>> cnew, cnew2; | ||
| 990 | TypeSpec typeSpec; | ||
| 991 | Path path; | ||
| 992 | Absyn.Class def; | ||
| 993 | case {} | ||
| 994 | then in_components; | ||
| 995 | case Absyn.ELEMENTITEM(Absyn.ELEMENT(_,_,_, Absyn.COMPONENTS(_,typeSpec, components), _, _))::rest | ||
| 996 | algorithm | ||
| 997 | 338 | path := AbsynUtil.typeSpecPath(typeSpec); | |
| 998 | //print ("TESTING PROVIDERS ... "); | ||
| 999 | //print(Dump.unparseTypeSpec(typeSpec)); | ||
| 1000 | //print(" VS " +className); | ||
| 1001 | //print ("...\n"); | ||
| 1002 | // if Interactive.isPrimitive(path, env) then fail(); end if; | ||
| 1003 | 338 | def := ProgramUtil.getPathedClassInProgram(path,env); // load the element | |
| 1004 |
3/4✓ Branch 1 taken 10 times.
✓ Branch 2 taken 144 times.
✓ Branch 5 taken 10 times.
✗ Branch 6 not taken.
|
154 | if (AbsynUtil.typeSpecPathString(typeSpec) == className) then |
| 1005 | 10 | print("... found provider " + className + "\n"); | |
| 1006 | 10 | cnew := (components, pathInClass)::in_components; | |
| 1007 | |||
| 1008 | else | ||
| 1009 | //print("... NOT found provider " + AbsynUtil.typeSpecPathString(typeSpec) + "\n"); | ||
| 1010 | cnew := in_components; | ||
| 1011 | end if; | ||
| 1012 | |||
| 1013 | 154 | re_items := AbsynUtil.getElementItemsInClass(def); // if the provider is an element from the class | |
| 1014 | 154 | cnew2 := parseComponents(className, template, re_items, env, components, cnew, pathInClass); | |
| 1015 | 154 | then getAllProviderInstances(className, template, rest, env, cnew2, pathInClass); | |
| 1016 | case _::rest | ||
| 1017 | 250 | then getAllProviderInstances(className, template, rest, env, in_components, pathInClass); | |
| 1018 | end matchcontinue; | ||
| 1019 | end getAllProviderInstances; | ||
| 1020 | |||
| 1021 | |||
| 1022 | protected function parseComponents | ||
| 1023 | input String className; | ||
| 1024 | input String template; | ||
| 1025 | input list<Absyn.ElementItem> e_items; | ||
| 1026 | input Absyn.Program env; | ||
| 1027 | input list<Absyn.ComponentItem> components; | ||
| 1028 | input list<tuple<list<Absyn.ComponentItem>, String>> in_components; | ||
| 1029 | input String pathInClass; | ||
| 1030 | output list<tuple<list<Absyn.ComponentItem>, String>> out_components; | ||
| 1031 | algorithm | ||
| 1032 | out_components:= match components | ||
| 1033 | local | ||
| 1034 | list<Absyn.ComponentItem> rest; | ||
| 1035 | Absyn.Ident name ; | ||
| 1036 | list<tuple<list<Absyn.ComponentItem>, String>> tmp; | ||
| 1037 | String newName; | ||
| 1038 | case {} then in_components; | ||
| 1039 | case Absyn.COMPONENTITEM(Absyn.COMPONENT(name, _, _), _, _)::rest | ||
| 1040 | algorithm | ||
| 1041 |
3/4✓ Branch 0 taken 42 times.
✓ Branch 1 taken 112 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 42 times.
|
154 | newName := if(pathInClass == "") then name else pathInClass + "." + name; |
| 1042 | 154 | tmp := getAllProviderInstances(className, template, e_items, env, in_components, newName); | |
| 1043 | 154 | then parseComponents(className, template, e_items, env, rest, tmp, pathInClass); | |
| 1044 | case _::rest | ||
| 1045 | ✗ | then parseComponents(className, template, e_items, env, rest, in_components, pathInClass); | |
| 1046 | end match; | ||
| 1047 | end parseComponents; | ||
| 1048 | |||
| 1049 | |||
| 1050 | protected function buildInstList "mark all the clients and providers in the model" | ||
| 1051 | input Absyn.Class clazz; | ||
| 1052 | input Absyn.Program env; | ||
| 1053 | input Client_e predecessors; | ||
| 1054 | input list<Mediator> mediators; | ||
| 1055 | input list<Client_e> client_list_in; | ||
| 1056 | input list<list<String>> instance_list; | ||
| 1057 | |||
| 1058 | //input list<Provider> providers; | ||
| 1059 | output list<Client_e> client_list; | ||
| 1060 | protected | ||
| 1061 | list<Absyn.ElementItem> e_items; | ||
| 1062 | algorithm | ||
| 1063 | // print("Building instance list\n"); | ||
| 1064 | // print("" + Dump.unparseClassStr(clazz) + "\n"); | ||
| 1065 | 2 | e_items := AbsynUtil.getElementItemsInClass(clazz); | |
| 1066 | 2 | client_list := parseElementInstList(e_items, env, NO_PRED(), mediators, client_list_in, instance_list); | |
| 1067 | // print("DONE Building instance list\n"); | ||
| 1068 | end buildInstList; | ||
| 1069 | |||
| 1070 | protected function buildInstList2 "mark all the clients and providers in the model" | ||
| 1071 | input Absyn.Class clazz; | ||
| 1072 | input Absyn.Program env; | ||
| 1073 | input Client_e predecessors; | ||
| 1074 | input list<Mediator> mediators; | ||
| 1075 | input list<Client_e> client_list_in; | ||
| 1076 | input list<list<String>> instance_list; | ||
| 1077 | input TypeSpec rootType; | ||
| 1078 | |||
| 1079 | //input list<Provider> providers; | ||
| 1080 | output list<Client_e> client_list; | ||
| 1081 | protected | ||
| 1082 | list<Absyn.ElementItem> e_items; | ||
| 1083 | algorithm | ||
| 1084 | // print("Building instance list\n"); | ||
| 1085 | // print("" + Dump.unparseClassStr(clazz) + "\n"); | ||
| 1086 | 36 | e_items := AbsynUtil.getElementItemsInClass(clazz); | |
| 1087 | 36 | client_list := parseElementInstList2(e_items, env, NO_PRED(), mediators, client_list_in, instance_list, rootType); | |
| 1088 | // print("DONE Building instance list\n"); | ||
| 1089 | end buildInstList2; | ||
| 1090 | |||
| 1091 | protected function isAlreadyInList | ||
| 1092 | input Absyn.TypeSpec ts; | ||
| 1093 | input list<Client_e> predecessors; | ||
| 1094 | output Boolean val; | ||
| 1095 | algorithm | ||
| 1096 | val := match predecessors | ||
| 1097 | local | ||
| 1098 | list<Client_e> rest; | ||
| 1099 | Absyn.TypeSpec ots; | ||
| 1100 | case {} then false; | ||
| 1101 | case CLIENT_E(_, _, ots, _, _, _, _):: rest | ||
| 1102 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | then if AbsynUtil.typeSpecEqual(ts, ots) then true else isAlreadyInList(ts, rest); |
| 1103 | end match; | ||
| 1104 | end isAlreadyInList; | ||
| 1105 | |||
| 1106 | protected function parseElementInstList | ||
| 1107 | input list<Absyn.ElementItem> e_items; | ||
| 1108 | input Absyn.Program env; | ||
| 1109 | input Client_e predecessors; | ||
| 1110 | input list<Mediator> mediators; | ||
| 1111 | input list<Client_e> in_client_list; | ||
| 1112 | input list<list<String>> instance_list; | ||
| 1113 | //input list<Provider> providers; | ||
| 1114 | output list<Client_e> client_list; | ||
| 1115 | |||
| 1116 | algorithm | ||
| 1117 | client_list := matchcontinue e_items | ||
| 1118 | local | ||
| 1119 | list<Absyn.ElementItem> rest; | ||
| 1120 | list<Absyn.ComponentItem> components; | ||
| 1121 | TypeSpec typeSpec; | ||
| 1122 | Path path; | ||
| 1123 | String iname; | ||
| 1124 | Client_e new_predecessors; | ||
| 1125 | Absyn.Class def; | ||
| 1126 | list<Client_e> l1, l2; | ||
| 1127 | Boolean isCl; | ||
| 1128 | List<Mediator> m; | ||
| 1129 | case {} | ||
| 1130 | then in_client_list; | ||
| 1131 | case Absyn.ELEMENTITEM(Absyn.ELEMENT(_,_,_, Absyn.COMPONENTS(_,typeSpec, components), _, _))::rest | ||
| 1132 | algorithm | ||
| 1133 | 8 | path := AbsynUtil.typeSpecPath(typeSpec); | |
| 1134 | //print ("TESTING in parseElementList ... "); | ||
| 1135 | //print(Dump.unparseTypeSpec(typeSpec)); | ||
| 1136 | //print ("...\n"); | ||
| 1137 | |||
| 1138 | //if Interactive.isPrimitive(path, env) then fail(); end if; | ||
| 1139 | 8 | def := ProgramUtil.getPathedClassInProgram(path, env); // load the element | |
| 1140 | |||
| 1141 | 8 | (isCl, iname, m) := isClient(AbsynUtil.typeSpecPathString(typeSpec), mediators, {}); | |
| 1142 | // TODO: check if it was not already added to the list | ||
| 1143 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
8 | if(isCl and not isAlreadyInList(typeSpec, in_client_list)) then |
| 1144 | 8 | new_predecessors := CLIENT_E(components, typeSpec, typeSpec, def, {iname}::instance_list, predecessors, m); | |
| 1145 | l2 := new_predecessors::in_client_list; | ||
| 1146 | else | ||
| 1147 | new_predecessors := predecessors; | ||
| 1148 | l2 := in_client_list; | ||
| 1149 | end if; | ||
| 1150 | 8 | l1 := buildInstList2(def, env, new_predecessors, mediators, l2, instance_list, typeSpec); | |
| 1151 | 8 | then parseElementInstList(rest, env, predecessors, mediators, l1, instance_list); | |
| 1152 | case _::rest | ||
| 1153 | algorithm | ||
| 1154 | //print("parseElementInstList unmatched pattern\n"); | ||
| 1155 | 2 | then parseElementInstList(rest, env, predecessors, mediators, in_client_list, instance_list); | |
| 1156 | end matchcontinue; | ||
| 1157 | end parseElementInstList; | ||
| 1158 | |||
| 1159 | protected function getComponentNames | ||
| 1160 | input list<Absyn.ComponentItem> l; | ||
| 1161 | output list<String> res; | ||
| 1162 | algorithm | ||
| 1163 | res := match l | ||
| 1164 | local | ||
| 1165 | Absyn.ComponentItem ci; | ||
| 1166 | list<Absyn.ComponentItem> r; | ||
| 1167 | case {} then {}; | ||
| 1168 | 30 | case ci::r then AbsynUtil.componentName(ci)::getComponentNames(r); | |
| 1169 | end match; | ||
| 1170 | |||
| 1171 | end getComponentNames; | ||
| 1172 | |||
| 1173 | protected function parseElementInstList2 | ||
| 1174 | input list<Absyn.ElementItem> e_items; | ||
| 1175 | input Absyn.Program env; | ||
| 1176 | input Client_e predecessors; | ||
| 1177 | input list<Mediator> mediators; | ||
| 1178 | input list<Client_e> in_client_list; | ||
| 1179 | input list<list<String>> instance_list; | ||
| 1180 | //input list<Provider> providers; | ||
| 1181 | input TypeSpec rootType; | ||
| 1182 | output list<Client_e> client_list; | ||
| 1183 | |||
| 1184 | algorithm | ||
| 1185 | client_list := matchcontinue e_items | ||
| 1186 | local | ||
| 1187 | list<Absyn.ElementItem> rest; | ||
| 1188 | list<Absyn.ComponentItem> components; | ||
| 1189 | TypeSpec typeSpec; | ||
| 1190 | Path path; | ||
| 1191 | String iname; | ||
| 1192 | Client_e new_predecessors; | ||
| 1193 | Absyn.Class def; | ||
| 1194 | list<Client_e> l1, l2; | ||
| 1195 | Boolean isCl; | ||
| 1196 | List<Mediator> m; | ||
| 1197 | case {} | ||
| 1198 | then in_client_list; | ||
| 1199 | case Absyn.ELEMENTITEM(Absyn.ELEMENT(_,_,_, Absyn.COMPONENTS(_,typeSpec, components), _, _))::rest | ||
| 1200 | algorithm | ||
| 1201 | 70 | path := AbsynUtil.typeSpecPath(typeSpec); | |
| 1202 | //print ("TESTING in parseElementList ... "); | ||
| 1203 | //print(Dump.unparseTypeSpec(typeSpec)); | ||
| 1204 | //print ("...\n"); | ||
| 1205 | //if Interactive.isPrimitive(path, env) then fail(); end if; | ||
| 1206 | 70 | def := ProgramUtil.getPathedClassInProgram(path, env); // load the element | |
| 1207 | 28 | (isCl, iname, m) := isClient(AbsynUtil.typeSpecPathString(typeSpec), mediators, {}); | |
| 1208 | // TODO: check if it was not already added to the list | ||
| 1209 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 26 times.
|
28 | if(isCl) then |
| 1210 | 4 | new_predecessors := CLIENT_E(components, typeSpec, rootType, def, {iname}::getComponentNames(components)::instance_list, predecessors, m); | |
| 1211 | l2 := new_predecessors::in_client_list; | ||
| 1212 | else | ||
| 1213 | new_predecessors := predecessors; | ||
| 1214 | l2 := in_client_list; | ||
| 1215 | end if; | ||
| 1216 | //print("---------------> L1" + AbsynUtil.pathString(path) + "\n"); | ||
| 1217 | //print("" + Dump.unparseClassStr(def) + "\n"); | ||
| 1218 | 56 | l1 := buildInstList2(def, env, new_predecessors, mediators, l2, getComponentNames(components)::instance_list, rootType); | |
| 1219 | 28 | then parseElementInstList2(rest, env, predecessors, mediators, l1, instance_list, rootType); | |
| 1220 | case _::rest | ||
| 1221 | algorithm | ||
| 1222 | //print("parseElementInstList unmatched pattern\n"); | ||
| 1223 | 54 | then parseElementInstList2(rest, env, predecessors, mediators, in_client_list, instance_list, rootType); | |
| 1224 | end matchcontinue; | ||
| 1225 | end parseElementInstList2; | ||
| 1226 | |||
| 1227 | protected function isClient | ||
| 1228 | input String ci_name ; | ||
| 1229 | input list<Mediator> mediators; | ||
| 1230 | input List<Mediator> in_m; | ||
| 1231 | output Boolean isClient; | ||
| 1232 | output String iname; | ||
| 1233 | output List<Mediator> m; | ||
| 1234 | algorithm | ||
| 1235 | (isClient, iname, m) := matchcontinue mediators | ||
| 1236 | local | ||
| 1237 | String nm; | ||
| 1238 | String mType; | ||
| 1239 | String template; | ||
| 1240 | list<Client> clients; | ||
| 1241 | list<Provider> providers; | ||
| 1242 | list<Mediator> rest; | ||
| 1243 | list<Preferred> preferred; | ||
| 1244 | 30 | case {} then (false, "", in_m); | |
| 1245 | case MEDIATOR(mType, template, clients, providers, preferred)::_ | ||
| 1246 | algorithm | ||
| 1247 | //print("Testing mediator : " + mType + "\n"); | ||
| 1248 | //print("... testing client : "+ ci_name +"\n"); | ||
| 1249 |
2/2✓ Branch 1 taken 96 times.
✓ Branch 2 taken 6 times.
|
102 | (true, nm) := isClientInMediator(ci_name, clients); |
| 1250 | 6 | print("... found client : "+ ci_name +"\n"); | |
| 1251 | 12 | then (true, nm, MEDIATOR(mType, template, clients, providers, preferred)::in_m); | |
| 1252 | case _::rest | ||
| 1253 | algorithm | ||
| 1254 | // print("REST\n"); | ||
| 1255 | 96 | then isClient(ci_name, rest, in_m); | |
| 1256 | end matchcontinue; | ||
| 1257 | end isClient; | ||
| 1258 | |||
| 1259 | protected function isClientInMediator | ||
| 1260 | input String ci_name ; | ||
| 1261 | input list<Client> clients; | ||
| 1262 | output Boolean isClient; | ||
| 1263 | output String iname; | ||
| 1264 | algorithm | ||
| 1265 | |||
| 1266 | (isClient, iname) := matchcontinue clients | ||
| 1267 | local | ||
| 1268 | String name, inst; | ||
| 1269 | list<Client> rest; | ||
| 1270 | 96 | case {} then (false, ""); | |
| 1271 | case CLIENT(name, inst, _, _)::_ | ||
| 1272 | algorithm | ||
| 1273 | // print("Testing mediator for names: " + name + " " + ci_name + "\n"); | ||
| 1274 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 90 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 6 times.
|
102 | true := (name == ci_name); |
| 1275 | 6 | then (true, inst); | |
| 1276 | case _::rest | ||
| 1277 | algorithm | ||
| 1278 | // print("REST\n"); | ||
| 1279 | 96 | then isClientInMediator(ci_name, rest); | |
| 1280 | end matchcontinue; | ||
| 1281 | end isClientInMediator; | ||
| 1282 | |||
| 1283 | |||
| 1284 | protected function getMediatorDefsElements "extracts the mediator infomration from SCODE" | ||
| 1285 | input list<SCode.Element> mediator_defs; | ||
| 1286 | input List<Mediator> mediators_in; | ||
| 1287 | output List<Mediator> mediators_out; | ||
| 1288 | algorithm | ||
| 1289 | mediators_out := match mediator_defs | ||
| 1290 | local | ||
| 1291 | list<SCode.Element> rest; | ||
| 1292 | SCode.Element el; | ||
| 1293 | List<Mediator> m; | ||
| 1294 | case {} then mediators_in; | ||
| 1295 | case el::rest | ||
| 1296 | algorithm | ||
| 1297 | 30 | m := listAppend(getMediatorDefsElement(el), mediators_in); | |
| 1298 | 30 | then getMediatorDefsElements(rest, m); | |
| 1299 | end match; | ||
| 1300 | end getMediatorDefsElements; | ||
| 1301 | |||
| 1302 | protected function getMediatorDefsElement | ||
| 1303 | input SCode.Element el; | ||
| 1304 | output List<Mediator> mediator; | ||
| 1305 | algorithm | ||
| 1306 | mediator := matchcontinue el | ||
| 1307 | local | ||
| 1308 | list<SCode.Element> elist; | ||
| 1309 | SCode.Mod mod; | ||
| 1310 | list<Absyn.Exp> cMod, pMod, prMod; | ||
| 1311 | String template, mType, str1, str2; | ||
| 1312 | list<Client> cls; | ||
| 1313 | list<Provider> prvs; | ||
| 1314 | list<Preferred> pref; | ||
| 1315 | case SCode.CLASS(_, _, _, _, SCode.R_PACKAGE(), SCode.PARTS(elist, _,_,_,_,_,_,_), _, _) | ||
| 1316 | 9 | then getMediatorDefsElements(elist, {}); | |
| 1317 | case SCode.CLASS(_, _, _, _, SCode.R_RECORD(_), SCode.PARTS(elist, _,_,_,_,_,_,_), _, _) | ||
| 1318 | algorithm | ||
| 1319 |
3/6✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
|
3 | (true, SOME(mod)) := extendsType(elist, "Mediator"); |
| 1320 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | Absyn.STRING(template) := getValue(mod, "template", "string"); |
| 1321 | 3 | str1 := System.stringReplace(template, "%", ""); | |
| 1322 | 3 | str2 := System.stringReplace(str1, ":", "all"); | |
| 1323 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | Absyn.STRING(mType) := getValue(mod, "mType", "string"); |
| 1324 | |||
| 1325 | // build clients | ||
| 1326 | //print("************ Build clients\n"); | ||
| 1327 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | Absyn.ARRAY(cMod) := getValue(mod, "clients", "array"); |
| 1328 | 3 | cls := getClientList(cMod, {}); | |
| 1329 | // build providers | ||
| 1330 | //print("************ Build providers\n"); | ||
| 1331 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | Absyn.ARRAY(pMod) := getValue(mod, "providers", "array"); |
| 1332 | 3 | prvs := getProviderList(pMod, {}); | |
| 1333 | |||
| 1334 | // build preferred | ||
| 1335 | //print("************ Build preferred\n"); | ||
| 1336 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
|
3 | Absyn.ARRAY(prMod) := getValue(mod, "preferred", "array"); |
| 1337 | 3 | pref := getPreferredList(prMod, {}); | |
| 1338 | |||
| 1339 | 3 | then {MEDIATOR(mType,str2, cls, prvs, pref)}; | |
| 1340 | case _ | ||
| 1341 | algorithm //print("noName\n"); | ||
| 1342 | //print(SCodeDump.unparseElementStr(el)); | ||
| 1343 | then {}; | ||
| 1344 | end matchcontinue; | ||
| 1345 | end getMediatorDefsElement; | ||
| 1346 | |||
| 1347 | protected function getPreferredList | ||
| 1348 | input list<Absyn.Exp> e; | ||
| 1349 | input list<Preferred> val; | ||
| 1350 | output list<Preferred> n_val; | ||
| 1351 | algorithm | ||
| 1352 | n_val := match e | ||
| 1353 | local | ||
| 1354 | list<Absyn.NamedArg> argNames; | ||
| 1355 | list<Absyn.Exp> rest; | ||
| 1356 | String clientInstancePath; | ||
| 1357 | String providerInstancePath; | ||
| 1358 | case {} | ||
| 1359 | then val; | ||
| 1360 | case Absyn.CALL(_, Absyn.FUNCTIONARGS(_, argNames))::rest | ||
| 1361 | algorithm | ||
| 1362 | ✗ | clientInstancePath := getArg(argNames, "clientInstancePath"); | |
| 1363 | //print ("clientInstancePath " + clientInstancePath + "\n"); | ||
| 1364 | ✗ | providerInstancePath := getArg(argNames, "providerInstancePath"); | |
| 1365 | // print ("providerInstancePath " + providerInstancePath + "\n"); | ||
| 1366 | ✗ | then getPreferredList(rest, PREFERRED(clientInstancePath, providerInstancePath)::val); | |
| 1367 | end match; | ||
| 1368 | end getPreferredList; | ||
| 1369 | |||
| 1370 | protected function getClientList | ||
| 1371 | input list<Absyn.Exp> e; | ||
| 1372 | input list<Client> val; | ||
| 1373 | output list<Client> n_val; | ||
| 1374 | algorithm | ||
| 1375 | n_val := match e | ||
| 1376 | local | ||
| 1377 | list<Absyn.NamedArg> argNames; | ||
| 1378 | list<Absyn.Exp> rest; | ||
| 1379 | String className, instance, template, isM; | ||
| 1380 | Boolean isMandatory; | ||
| 1381 | case {} | ||
| 1382 | then val; | ||
| 1383 | case Absyn.CALL(_, Absyn.FUNCTIONARGS(_, argNames))::rest | ||
| 1384 | algorithm | ||
| 1385 | // print ("gettingClients\n"); | ||
| 1386 | 3 | className := getArg(argNames, "modelID"); | |
| 1387 | // print ("className " + className + "\n"); | ||
| 1388 | 3 | instance := getArg(argNames, "component"); | |
| 1389 | // print ("instance " + instance + "\n"); | ||
| 1390 | 3 | template := getArg(argNames, "template"); | |
| 1391 | // print ("providerTemplate " + template + "\n"); | ||
| 1392 | 3 | isM := getArg(argNames, "isMandatory"); | |
| 1393 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
3 | if(isM == "true") |
| 1394 | then isMandatory := true; else isMandatory := false; end if; | ||
| 1395 | 6 | then getClientList(rest, CLIENT(className, instance, template, isMandatory)::val); | |
| 1396 | end match; | ||
| 1397 | end getClientList; | ||
| 1398 | |||
| 1399 | protected function getProviderList | ||
| 1400 | input list<Absyn.Exp> e; | ||
| 1401 | input list<Provider> val; | ||
| 1402 | output list<Provider> n_val; | ||
| 1403 | algorithm | ||
| 1404 | n_val := match e | ||
| 1405 | local | ||
| 1406 | list<Absyn.NamedArg> argNames; | ||
| 1407 | list<Absyn.Exp> rest; | ||
| 1408 | String className, providerTemplate, instance; | ||
| 1409 | |||
| 1410 | case {} | ||
| 1411 | then val; | ||
| 1412 | case Absyn.CALL(_, Absyn.FUNCTIONARGS(_, argNames))::rest | ||
| 1413 | algorithm | ||
| 1414 | 4 | className := getArg(argNames, "modelID"); | |
| 1415 | // print ("className " + className + "\n"); | ||
| 1416 | 4 | instance := getArg(argNames, "component"); | |
| 1417 | //print ("instance " + instance + "\n"); | ||
| 1418 | 4 | providerTemplate := getArg(argNames, "template"); | |
| 1419 | // print ("providerTemplate " + providerTemplate + "\n"); | ||
| 1420 | 8 | then getProviderList(rest, PROVIDER(className, instance, providerTemplate)::val); | |
| 1421 | end match; | ||
| 1422 | end getProviderList; | ||
| 1423 | |||
| 1424 | protected function getArg | ||
| 1425 | input list<Absyn.NamedArg> argNames; | ||
| 1426 | input String name; | ||
| 1427 | output String val; | ||
| 1428 | algorithm | ||
| 1429 | val := matchcontinue argNames | ||
| 1430 | local | ||
| 1431 | String str, nname, str1, str2; | ||
| 1432 | list<Absyn.NamedArg> rest; | ||
| 1433 | case {} | ||
| 1434 | then ""; | ||
| 1435 | case Absyn.NAMEDARG(nname, Absyn.STRING(str))::_ | ||
| 1436 | algorithm | ||
| 1437 | // print("Comparing: " + name + " " +nname + "\n"); | ||
| 1438 | 41 | str1 := System.stringReplace(str, "%", ""); | |
| 1439 | 41 | str2 := System.stringReplace(str1, ":", "all"); | |
| 1440 | //print("Updated string from " + str + " to " + str2 + "\n"); | ||
| 1441 |
3/4✓ Branch 0 taken 14 times.
✓ Branch 1 taken 27 times.
✓ Branch 3 taken 14 times.
✗ Branch 4 not taken.
|
41 | true := (nname == name); |
| 1442 | then str2; | ||
| 1443 | case _::rest | ||
| 1444 | 27 | then getArg(rest, name); | |
| 1445 | end matchcontinue; | ||
| 1446 | end getArg; | ||
| 1447 | |||
| 1448 | |||
| 1449 | protected function extendsType | ||
| 1450 | input list<SCode.Element> elems; | ||
| 1451 | input String typeName; | ||
| 1452 | output Boolean result; | ||
| 1453 | output Option<SCode.Mod> mods; | ||
| 1454 | algorithm | ||
| 1455 | |||
| 1456 | (result, mods) := match elems | ||
| 1457 | local | ||
| 1458 | list<SCode.Element> rest; | ||
| 1459 | SCode.Mod mod; | ||
| 1460 | String tName; | ||
| 1461 | case {} then (false, NONE()); | ||
| 1462 | case SCode.EXTENDS(Absyn.IDENT(tName), _, mod, _, _)::_ guard (tName == typeName) | ||
| 1463 | then (true, SOME(mod)); | ||
| 1464 | case _::rest | ||
| 1465 | ✗ | then extendsType(rest, typeName); | |
| 1466 | end match; | ||
| 1467 | end extendsType; | ||
| 1468 | |||
| 1469 | protected function getValue | ||
| 1470 | input SCode.Mod mod; | ||
| 1471 | input Ident name "name of argument"; | ||
| 1472 | input String retype "type of argument"; | ||
| 1473 | output Absyn.Exp val; | ||
| 1474 | algorithm | ||
| 1475 | val := match mod | ||
| 1476 | local | ||
| 1477 | list<SCode.SubMod> smod; | ||
| 1478 | case SCode.MOD(_,_, smod, _, _) | ||
| 1479 | 15 | then getValueR(smod, name, retype); | |
| 1480 | end match; | ||
| 1481 | end getValue; | ||
| 1482 | |||
| 1483 | protected function getValueR | ||
| 1484 | input list<SCode.SubMod> smod; | ||
| 1485 | input Ident name; | ||
| 1486 | input String retype "type of argument"; | ||
| 1487 | output Absyn.Exp val; | ||
| 1488 | algorithm | ||
| 1489 | val := matchcontinue(smod, retype) | ||
| 1490 | local | ||
| 1491 | Absyn.Exp eval; | ||
| 1492 | Ident n; | ||
| 1493 | list<SCode.SubMod> rest; | ||
| 1494 | case ({}, "bool") | ||
| 1495 | then Absyn.BOOL(false); // client not mandatory by default | ||
| 1496 | case ({}, "array") | ||
| 1497 | then Absyn.ARRAY({}); | ||
| 1498 | case ({}, "string") | ||
| 1499 | then Absyn.STRING(""); | ||
| 1500 | case (SCode.NAMEMOD(n, SCode.MOD(_,_,_, SOME((eval)), _))::_, _) | ||
| 1501 | algorithm | ||
| 1502 |
4/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 24 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 9 times.
|
36 | if(n <> name) then fail(); end if; |
| 1503 | then eval; | ||
| 1504 | case (_::rest, _) | ||
| 1505 | 27 | then getValueR(rest, name, retype); | |
| 1506 | end matchcontinue; | ||
| 1507 | end getValueR; | ||
| 1508 | |||
| 1509 | annotation(__OpenModelica_Interface="backend_tools"); | ||
| 1510 | end Binding; | ||
| 1511 |