Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 67.1% 153 / 0 / 228
Functions: -% 0 / 1 / 1
Branches: 56.4% 62 / 0 / 110

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