Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 66.4% 299 / 0 / 450
Functions: -% 0 / 1 / 1
Branches: 50.0% 133 / 0 / 266

OMCompiler/Compiler/FrontEnd/Mod.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 Mod
37 " file: Mod.mo
38 package: Mod
39 description: Modification handling
40
41
42 Modifications are simply the same kind of modifications used in the Absyn module.
43
44 This module contains functions for handling DAE.Mod, which is very similar to
45 SCode.Mod. The main difference is that it uses DAE.Exp for the expressions.
46 Expressions stored here are prefixed and typechecked.
47 "
48
49
50 public import Absyn;
51 public import AbsynUtil;
52 public import DAE;
53 public import FCore;
54 public import FGraph;
55 public import SCode;
56 public import InnerOuter;
57 public import ComponentReference;
58 protected import ComponentReferenceBasics;
59
60 protected type InstanceHierarchy = InnerOuter.InstHierarchy "an instance hierarchy";
61
62 protected import Ceval;
63 protected import ClassInf;
64 protected import Config;
65 protected import Dump;
66 protected import Debug;
67 protected import Error;
68 protected import Expression;
69 protected import ExpressionBasics;
70 protected import ExpressionDump;
71 protected import ExpressionSimplify;
72 protected import Flags;
73 protected import Inst;
74 protected import InstUtil;
75 protected import List;
76 protected import PrefixUtil;
77 protected import Print;
78 import SCodeInstUtil;
79 import SCodeUtil;
80 protected import Static;
81 protected import Types;
82 protected import Util;
83 protected import Values;
84 protected import ValuesDump;
85 protected import ValuesUtil;
86 protected import System;
87 protected import SCodeDump;
88 protected import Lookup;
89
90 public uniontype ModScope
91 "Used to know where a modifier came from, for error reporting."
92 record COMPONENT
93 String name;
94 end COMPONENT;
95
96 record EXTENDS
97 Absyn.Path path;
98 end EXTENDS;
99
100 record DERIVED
101 Absyn.Path path;
102 end DERIVED;
103 end ModScope;
104
105 protected
106 uniontype FullMod "used for error reporting"
107 record MOD "the fully qualified cref and the mod, only used for redeclare"
108 DAE.ComponentRef cref;
109 DAE.Mod mod;
110 end MOD;
111
112 record SUB_MOD "the fully qualified cref and the sub mod for all other mods"
113 DAE.ComponentRef cref;
114 DAE.SubMod subMod;
115 end SUB_MOD;
116 end FullMod;
117
118 protected type SubMod = DAE.SubMod;
119 protected type EqMod = DAE.EqMod;
120
121 public function elabMod "
122 This function elaborates on the expressions in a modification and
123 turns them into global expressions. This is done because the
124 expressions in modifications must be elaborated on in the context
125 they are provided in, and not the context they are used in."
126 input FCore.Cache inCache;
127 input FCore.Graph inEnv;
128 input InnerOuter.InstHierarchy inIH;
129 input DAE.Prefix inPrefix;
130 input SCode.Mod inMod;
131 input Boolean inBoolean;
132 input ModScope inModScope;
133 input SourceInfo inInfo;
134 output FCore.Cache outCache;
135 output DAE.Mod outMod;
136 protected
137 SCode.Mod mod;
138 algorithm
139 1921321 mod := SCodeInstUtil.expandEnumerationMod(inMod);
140 (outCache,outMod) := match(inCache, inEnv, inIH, inPrefix, mod, inBoolean, inInfo)
141 local
142 Boolean impl;
143 SCode.Final finalPrefix;
144 list<DAE.SubMod> subs_1;
145 FCore.Graph env;
146 DAE.Prefix pre;
147 SCode.Each each_;
148 list<SCode.SubMod> subs;
149 DAE.Exp e_1,e_2;
150 DAE.Properties prop;
151 Option<Values.Value> e_val;
152 Absyn.Exp e;
153 SCode.Element elem;
154 DAE.Mod dm;
155 FCore.Cache cache;
156 InstanceHierarchy ih;
157 SourceInfo info;
158
159 // no modifications
160 case (cache, _, _, _, SCode.NOMOD(), _, _) then (cache,DAE.NOMOD());
161
162 // no top binding
163 case (cache, env, ih, pre, SCode.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = NONE(), info = info), impl, _)
164 algorithm
165 324122 (cache,subs_1) := elabSubmods(cache, env, ih, pre, subs, impl, inModScope, info);
166 324119 then
167 (cache,DAE.MOD(finalPrefix,each_,subs_1,NONE(),info));
168
169 // Only elaborate expressions with non-delayed type checking, see SCode.MOD.
170 case (cache, env, ih, pre, (SCode.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = SOME(e), info=info)), impl, _)
171 algorithm
172 1060762 (cache,subs_1) := elabSubmods(cache, env, ih, pre, subs, impl, inModScope, info);
173 // print("Mod.elabMod: calling elabExp on mod exp: " + Dump.printExpStr(e) + " in env: " + FGraph.printGraphPathStr(env) + "\n");
174 1060762 (cache,e_1,prop) := Static.elabExp(cache, env, e, impl, Config.splitArrays(), pre, info); // Vectorize only if arrays are expanded
175 // Modifiers always apply to single components, so if the expression is
176 // a tuple (i.e. from a function call) select the first tuple element.
177 1060704 (e_1, prop) := Expression.tupleHead(e_1, prop);
178 1060704 (cache, e_1, prop) := Ceval.cevalIfConstant(cache, env, e_1, prop, impl, info);
179 1060704 (e_val, cache) := elabModValue(cache, env, e_1, prop, impl, info);
180 1060704 (cache,e_2) := PrefixUtil.prefixExp(cache, env, ih, e_1, pre)
181 "Bug: will cause elaboration of parameters without value to fail,
182 But this can be ok, since a modifier is present, giving it a value from outer modifications.." ;
183 2121408 then
184 (cache,DAE.MOD(finalPrefix,each_,subs_1,SOME(DAE.TYPED(e_2,e_val,prop,e,info)),info));
185
186 // Delayed type checking
187 case (cache, env, ih, pre, (SCode.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = SOME(e), info = info)), impl, _)
188 algorithm
189 // print("Mod.elabMod: delayed mod : " + Dump.printExpStr(e) + " in env: " + FGraph.printGraphPathStr(env) + "\n");
190 ✗ (cache,subs_1) := elabSubmods(cache, env, ih, pre, subs, impl, inModScope, info);
191 ✗ then
192 (cache,DAE.MOD(finalPrefix,each_,subs_1,SOME(DAE.UNTYPED(e)),info));
193
194 // redeclarations
195 case (cache, env, ih, pre, (SCode.REDECL(finalPrefix = finalPrefix, eachPrefix = each_, element = elem)), impl, info)
196 algorithm
197 //elist_1 = Inst.addNomod(elist);
198 199 (elem, dm) := elabModRedeclareElement(cache,env,ih,pre,finalPrefix,elem,impl,inModScope,info);
199 199 then
200 (cache,DAE.REDECL(finalPrefix,each_,elem,dm));
201
202 /*/ failure
203 case (cache,env,ih,pre,m,impl,info)
204 algorithm
205 str = "- Mod.elabMod failed: " +
206 SCodeDump.printModStr(m) +
207 " in env: " +
208 FGraph.printGraphStr(env);
209 fprintln(Flags.FAILTRACE, str);
210 then
211 fail();*/
212 end match;
213 end elabMod;
214
215 public function isInvariantMod "Is the modification one that does not depend on the scope it is evaluated in?"
216 input SCode.Mod mod;
217 output Boolean b;
218 protected
219 Absyn.Exp e;
220 SCode.Mod mods;
221 algorithm
222 b := match mod
223 case SCode.NOMOD() then true;
224 case SCode.MOD(binding=NONE())
225 algorithm
226 b := match mod.binding
227 case SOME(e)
228 algorithm
229 (_, b) := AbsynUtil.traverseExp(e, AbsynUtil.isInvariantExpNoTraverse, true);
230 then b;
231 else true;
232 end match;
233 if not b then
234 return;
235 end if;
236
1/2
✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
44 for sm in mod.subModLst loop
237
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 if not isInvariantMod(sm.mod) then
238 b := false;
239 44 return;
240 end if;
241 end for;
242 then true;
243 // operator record ComplexCurrent = Complex(redeclare Modelica.SIunits.Current re, redeclare Modelica.SIunits.Current im)
244 case SCode.Mod.REDECL(element=SCode.Element.COMPONENT(modifications=mods,typeSpec=Absyn.TypeSpec.TPATH(path=Absyn.Path.FULLYQUALIFIED(),arrayDim=NONE())))
245 ✗ then isInvariantMod(mods);
246 else false; // Redeclarations, etc
247 end match;
248 end isInvariantMod;
249
250 public function isInvariantDAEMod "Is the modification one that does not depend on the scope it is evaluated in?"
251 input DAE.Mod mod;
252 output Boolean b;
253 protected
254 DAE.Exp e;
255 Absyn.Exp exp;
256 SCode.Mod mods;
257 algorithm
258 b := match mod
259 case DAE.NOMOD() then true;
260 case DAE.MOD(binding=NONE())
261 algorithm
262 b := match mod.binding
263 case SOME(DAE.TYPED(modifierAsExp = e))
264 algorithm
265 (_, b) := Expression.traverseExpBottomUp(e, Expression.isInvariantExpNoTraverse, true);
266 then b;
267 case SOME(DAE.UNTYPED(exp))
268 algorithm
269 (_, b) := AbsynUtil.traverseExp(exp, AbsynUtil.isInvariantExpNoTraverse, true);
270 then b;
271 else true;
272 end match;
273 if not b then
274 return;
275 end if;
276
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 for sm in mod.subModLst loop
277
1/2
✓ Branch 1 taken 18 times.
✗ Branch 2 not taken.
18 if not isInvariantDAEMod(sm.mod) then
278 b := false;
279 18 return;
280 end if;
281 end for;
282 then true;
283 // operator record ComplexCurrent = Complex(redeclare Modelica.SIunits.Current re, redeclare Modelica.SIunits.Current im)
284 case DAE.Mod.REDECL(element=SCode.Element.COMPONENT(modifications=mods,typeSpec=Absyn.TypeSpec.TPATH(path=Absyn.Path.FULLYQUALIFIED(),arrayDim=NONE())))
285 ✗ then isInvariantMod(mods);
286 else false; // Redeclarations, etc
287 end match;
288 end isInvariantDAEMod;
289
290 public function elabModForBasicType "
291 Same as elabMod, but if a named Mod is not part of a basic type, fail instead."
292 input FCore.Cache inCache;
293 input FCore.Graph inEnv;
294 input InnerOuter.InstHierarchy inIH;
295 input DAE.Prefix inPrefix;
296 input SCode.Mod inMod;
297 input Boolean inBoolean;
298 input ModScope inModScope;
299 input SourceInfo info;
300 output FCore.Cache outCache;
301 output DAE.Mod outMod;
302 algorithm
303 16592 checkIfModsAreBasicTypeMods(inMod);
304 16583 (outCache,outMod) := elabMod(inCache,inEnv,inIH,inPrefix,inMod,inBoolean,inModScope,info);
305 end elabModForBasicType;
306
307 protected function checkIfModsAreBasicTypeMods "
308 Verifies that a list of submods only have named modifications that could be
309 used for basic types."
310 input SCode.Mod mod;
311 algorithm
312 () := match mod
313 local
314 list<SCode.SubMod> subs;
315 case SCode.NOMOD() then ();
316 case SCode.MOD(subModLst = subs)
317 algorithm
318 19 checkIfSubmodsAreBasicTypeMods(subs);
319 then ();
320 end match;
321 end checkIfModsAreBasicTypeMods;
322
323 protected function checkIfSubmodsAreBasicTypeMods "
324 Verifies that a list of submods only have named modifications that could be
325 used for basic types."
326 input list<SCode.SubMod> inSubs;
327 algorithm
328 () := match inSubs
329 local
330 String ident;
331 list<SCode.SubMod> subs;
332
333 case {} then ();
334 case SCode.NAMEMOD(ident = ident)::subs
335 algorithm
336
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 20 times.
29 true := ClassInfUtil.isBasicTypeComponentName(ident);
337 20 checkIfSubmodsAreBasicTypeMods(subs);
338 then ();
339 end match;
340 end checkIfSubmodsAreBasicTypeMods;
341
342 protected function elabModRedeclareElement
343 input FCore.Cache inCache;
344 input FCore.Graph inEnv;
345 input InnerOuter.InstHierarchy inIH;
346 input DAE.Prefix inPrefix;
347 input SCode.Final finalPrefix;
348 input SCode.Element inElt;
349 input Boolean impl;
350 input ModScope inModScope;
351 input SourceInfo info;
352 output SCode.Element outElement;
353 output DAE.Mod outMod;
354 algorithm
355 (outElement, outMod) := matchcontinue inElt
356 local
357 FCore.Cache cache; SCode.Final fi;
358 SCode.Replaceable repl;
359 SCode.Partial p;
360 SCode.Encapsulated enc;
361 SCode.Visibility vis;
362 SCode.Redeclare redecl;
363 Absyn.InnerOuter io;
364 SCode.Ident cn,compname;
365 SCode.Restriction restr;
366 Absyn.TypeSpec tp,tp1;
367 DAE.Mod emod;
368 SCode.Attributes attr;
369 SCode.Mod mod;
370 Option<Absyn.Exp> cond;
371 SourceInfo i;
372 SCode.Attributes attr1;
373 SCode.Comment cmt;
374 SCode.Element element;
375 SCode.Prefixes prefixes;
376
377 /*/ search for target class locally and if it is a derived with no modifications, use it
378 // replaceable package Medium = Modelica.Media.Air.MoistAir constrainedby Modelica.Media.Interfaces.PartialMedium;
379 // modifier: redeclare Medium = Medium
380 case SCode.CLASS(cn, prefixes as SCode.PREFIXES(vis,redecl,fi,io,repl), enc, p, restr, SCode.DERIVED(Absyn.TPATH(Absyn.IDENT(bcn), NONE()),mod,attr1), cmt, i)
381 algorithm
382 true = stringEq(cn, bcn);
383 (c, _) = Lookup.lookupClassLocal(inEnv, bcn);
384 tp = SCodeUtil.getDerivedTypeSpec(c);
385 c = SCodeUtil.mergeWithOriginal(SCode.CLASS(cn,SCode.PREFIXES(vis,redecl,fi,io,repl),enc,p,restr,SCode.DERIVED(tp,mod,attr1),cmt,i), c);
386 SCode.CLASS(cn,SCode.PREFIXES(vis,redecl,fi,io,repl),enc,p,restr,SCode.DERIVED(tp,mod,attr1),cmt,i) = c;
387 (cache, emod) = elabMod(inCache, inEnv, inIH, inPrefix, mod, impl, inModScope, info);
388 (cache, tp1) = elabModQualifyTypespec(cache, inEnv, inIH, inPrefix, impl, info, cn, tp);
389 // unelab mod so we get constant evaluation of parameters
390 mod = unelabMod(emod);
391 then
392 (SCode.CLASS(cn,SCode.PREFIXES(vis,redecl,fi,io,repl),enc,p,restr,SCode.DERIVED(tp1,mod,attr1),cmt,i), emod);*/
393
394 // Only derived classdefinitions supported in redeclares for now.
395 // TODO: What is allowed according to spec? adrpo: 2011-06-28: is not decided yet,
396 // but i think only derived even if in the Modelica.Media we have redeclare-as-element
397 // replacing entire functions with PARTS and everything, so i added the case below
398 case SCode.CLASS(cn, prefixes as SCode.PREFIXES(vis,redecl,fi,io,repl), enc, p, restr, SCode.DERIVED(tp,mod,attr1), cmt, i)
399 algorithm
400 // merge modifers from the component to the modifers from the constrained by
401 185 mod := SCodeUtil.mergeModifiers(mod, SCodeUtil.getConstrainedByModifiers(prefixes));
402 185 (cache, emod) := elabMod(inCache, inEnv, inIH, inPrefix, mod, impl, inModScope, info);
403 185 (_, tp1) := elabModQualifyTypespec(cache, inEnv, inIH, inPrefix, impl, info, cn, tp);
404 // unelab mod so we get constant evaluation of parameters
405 185 mod := unelabMod(emod);
406 185 then
407 (SCode.CLASS(cn, SCode.PREFIXES(vis,redecl,fi,io,repl), enc, p, restr, SCode.DERIVED(tp1,mod,attr1), cmt, i), emod);
408
409 // replaceable type E=enumeration(e1,...,en), E=enumeration(:)
410 case SCode.CLASS(restriction=SCode.R_ENUMERATION())
411 then
412 (inElt, DAE.NOMOD());
413 case SCode.CLASS(classDef=SCode.ENUMERATION())
414 then
415 (inElt, DAE.NOMOD());
416
417 // redeclare of component declaration
418 case SCode.COMPONENT(compname,prefixes as SCode.PREFIXES(vis,redecl,fi,io,repl),attr,tp,mod,cmt,cond,i)
419 algorithm
420 // merge modifers from the component to the modifers from the constrained by
421 13 mod := SCodeUtil.mergeModifiers(mod, SCodeUtil.getConstrainedByModifiers(prefixes));
422 13 (cache,emod) := elabMod(inCache, inEnv, inIH, inPrefix, mod, impl, inModScope, info);
423 13 (_, tp1) := elabModQualifyTypespec(cache, inEnv, inIH, inPrefix, impl, info, compname, tp);
424 // unelab mod so we get constant evaluation of parameters
425 13 mod := unelabMod(emod);
426 13 then
427 (SCode.COMPONENT(compname, SCode.PREFIXES(vis,redecl,fi,io,repl), attr, tp1, mod, cmt, cond, i), emod);
428
429 // redeclare failure?
430 case element
431 algorithm
432 ✗ print("Unhandled element redeclare (we keep it as it is!): " + SCodeDump.unparseElementStr(element,SCodeDump.defaultOptions) + "\n");
433 then
434 (element, DAE.NOMOD());
435
436 end matchcontinue;
437 end elabModRedeclareElement;
438
439 protected function elabModQualifyTypespec
440 "Help function to elabModRedeclareElements.
441 This function makes sure that type specifiers, i.e. class names, in redeclarations are looked up in the correct environment.
442 This is achieved by making them fully qualified."
443 input FCore.Cache inCache;
444 input FCore.Graph inEnv;
445 input InnerOuter.InstHierarchy inIH;
446 input DAE.Prefix inPrefix;
447 input Boolean impl;
448 input SourceInfo info;
449 input Absyn.Ident name;
450 input Absyn.TypeSpec tp;
451 output FCore.Cache outCache;
452 output Absyn.TypeSpec outTp;
453 algorithm
454 (outCache,outTp) := match(inCache, inEnv, inIH, inPrefix, tp)
455 local
456 FCore.Cache cache; FCore.Graph env;
457 Absyn.ArrayDim dims;
458 Absyn.Path p,p1;
459 Absyn.ComponentRef cref;
460 DAE.Dimensions edims;
461 InnerOuter.InstHierarchy ih;
462 DAE.Prefix pre;
463
464 // no array dimensions
465 case (cache, env, _, _, Absyn.TPATH(p,NONE()))
466 algorithm
467 196 (cache,p1) := Inst.makeFullyQualified(cache,env,p);
468 196 then
469 (cache,Absyn.TPATH(p1,NONE()));
470
471 // some array dimensions, elaborate them!
472 case (cache, env, ih, pre, Absyn.TPATH(p,SOME(dims)))
473 algorithm
474 2 cref := Absyn.CREF_IDENT(name,{});
475 2 (cache,edims) := InstUtil.elabArraydim(cache, env, cref, p, dims, NONE(), impl, true, false, pre, info, {});
476 2 (cache,edims) := PrefixUtil.prefixDimensions(cache, env, ih, pre, edims);
477 2 dims := List.map(edims, Expression.unelabDimension);
478 2 (cache,p1) := Inst.makeFullyQualified(cache,env,p);
479 2 then
480 (cache,Absyn.TPATH(p1,SOME(dims)));
481
482 end match;
483 end elabModQualifyTypespec;
484
485 protected function elabModValue
486 "Helper function to elabMod. Tries to constant evaluate a modifier expression."
487 input FCore.Cache inCache;
488 input FCore.Graph inEnv;
489 input DAE.Exp inExp;
490 input DAE.Properties inProp;
491 input Boolean inImpl;
492 input SourceInfo inInfo;
493 output Option<Values.Value> outValue = NONE();
494 output FCore.Cache outCache = inCache;
495 protected
496 Integer err_count;
497 Absyn.Msg msg;
498 DAE.Const c;
499 Values.Value v;
500 algorithm
501 1079270 c := Types.propAllConst(inProp);
502
503 // If the expression is a parameter or constant expression:
504
2/2
✓ Branch 1 taken 1074207 times.
✓ Branch 2 taken 5063 times.
1079270 if not Types.constIsVariable(c) then
505 // Show error messages from ceval only if the expression is constant.
506
4/4
✓ Branch 1 taken 1056804 times.
✓ Branch 2 taken 17403 times.
✓ Branch 3 taken 475903 times.
✓ Branch 4 taken 580901 times.
1567513 msg := AbsynUtil.optMsg(Types.constIsConst(c) and not inImpl, inInfo);
507 1074207 err_count := Error.getNumErrorMessages();
508
509 try
510 1074207 (_, v) := Ceval.ceval(inCache, inEnv, inExp, false, msg, 0);
511
512
2/2
✓ Branch 1 taken 8417 times.
✓ Branch 2 taken 1065628 times.
1074045 if ValuesUtil.isRecord(v) then
513 8417 v := ValuesUtil.typeConvertRecord(v, Expression.typeof(inExp));
514 end if;
515
516 1074045 outValue := SOME(v);
517 else
518 // Fail if ceval gave an error. Except if the expression contains a
519 // function call, because we don't handle function parameter modifiers
520 // correctly which causes issues with CevalFunction.
521
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 162 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
162 if err_count <> Error.getNumErrorMessages() and not
522 Expression.containsAnyCall(inExp) then
523 ✗ fail();
524 end if;
525 end try;
526 end if;
527 end elabModValue;
528
529 public function unelabMod
530 "Transforms Mod back to SCode.Mod, loosing type information."
531 input DAE.Mod inMod;
532 output SCode.Mod outMod;
533 algorithm
534 outMod := matchcontinue inMod
535 local
536 list<SCode.SubMod> subs_1;
537 DAE.Mod mod;
538 SCode.Final finalPrefix;
539 SCode.Each each_;
540 list<DAE.SubMod> subs;
541 Absyn.Exp e,e_1,absynExp;
542 SCode.Element elem;
543 String str;
544 SourceInfo info;
545 Values.Value v;
546
547 case DAE.NOMOD() then SCode.NOMOD();
548 case DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = NONE(), info = info)
549 algorithm
550 2119 subs_1 := unelabSubmods(subs);
551 2119 then
552 SCode.MOD(finalPrefix,each_,subs_1,NONE(),NONE(),info);
553
554 case DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = SOME(DAE.UNTYPED(e)), info = info)
555 algorithm
556 17534 subs_1 := unelabSubmods(subs);
557 17534 then
558 SCode.MOD(finalPrefix,each_,subs_1,SOME(e),NONE(),info);
559
560 // use the constant first!
561 case DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,
562 binding = SOME(DAE.TYPED(modifierAsValue = SOME(v))), info = info)
563 algorithm
564 //es = ExpressionBasics.printExpStr(e);
565 22761 subs_1 := unelabSubmods(subs);
566 22761 e_1 := Expression.unelabExp(ValuesUtil.valueExp(v));
567 22760 then
568 SCode.MOD(finalPrefix,each_,subs_1,SOME(e_1),NONE(),info); // default typechecking non-delayed
569
570 /* / use the expression second
571 case ((DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,
572 binding = SOME(DAE.TYPED(modifierAsExp = dexp, info = info)))))
573 algorithm
574 //es = ExpressionBasics.printExpStr(e);
575 subs_1 = unelabSubmods(subs);
576 e_1 = Expression.unelabExp(dexp);
577 then
578 SCode.MOD(finalPrefix,each_,subs_1,SOME((e_1,false)),info); // default typechecking non-delayed */
579
580 case DAE.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,
581 binding = SOME(DAE.TYPED(_,_,_,absynExp)),info = info)
582 algorithm
583 //es = ExpressionBasics.printExpStr(e);
584 4288 subs_1 := unelabSubmods(subs);
585 e_1 := absynExp; //Expression.unelabExp(e);
586 4288 then
587 SCode.MOD(finalPrefix,each_,subs_1,SOME(e_1),NONE(),info);
588
589 case DAE.REDECL(finalPrefix = finalPrefix,eachPrefix = each_,element = elem)
590 4532 then
591 SCode.REDECL(finalPrefix,each_,elem);
592
593 case mod
594 algorithm
595 ✗ str := "Mod.elabUntypedMod failed: " + printModStr(mod) + "\n";
596 ✗ Error.addMessage(Error.INTERNAL_ERROR, {str});
597 ✗ then
598 fail();
599 end matchcontinue;
600 end unelabMod;
601
602 protected function unelabSubmods
603 "Helper function to unelabMod."
604 input list<DAE.SubMod> inTypesSubModLst;
605 output list<SCode.SubMod> outSCodeSubModLst;
606 algorithm
607
4/4
✓ Branch 0 taken 5028 times.
✓ Branch 1 taken 46702 times.
✓ Branch 2 taken 5028 times.
✓ Branch 3 taken 46702 times.
51730 outSCodeSubModLst := list(match x
608 local
609 SCode.Mod m_1;
610 String i;
611 DAE.Mod m;
612 case DAE.NAMEMOD(ident = i,mod = m)
613 algorithm
614 5028 m_1 := unelabMod(m);
615 5028 then
616 SCode.NAMEMOD(i,m_1);
617 end match for x in inTypesSubModLst);
618 end unelabSubmods;
619
620 protected function unelabSubscript
621 input list<Integer> inIntegerLst;
622 output list<SCode.Subscript> outSCodeSubscriptLst;
623 algorithm
624 ✗ outSCodeSubscriptLst := list(Absyn.SUBSCRIPT(Absyn.INTEGER(i)) for i in inIntegerLst);
625 end unelabSubscript;
626
627 public function updateMod
628 "This function updates an untyped modification to a typed one, by looking
629 up the type of the modifier in the environment and update it."
630 input FCore.Cache inCache;
631 input FCore.Graph inEnv;
632 input InnerOuter.InstHierarchy inIH;
633 input DAE.Prefix inPrefix;
634 input DAE.Mod inMod;
635 input Boolean inBoolean;
636 input SourceInfo inInfo;
637 output FCore.Cache outCache;
638 output DAE.Mod outMod;
639 algorithm
640 (outCache,outMod) := matchcontinue (inCache, inEnv, inIH, inPrefix, inMod, inBoolean)
641 local
642 Boolean impl;
643 SCode.Final f;
644 DAE.Mod m;
645 list<DAE.SubMod> subs_1,subs;
646 DAE.Exp e_1,e_2;
647 DAE.Properties prop,p;
648 Option<Values.Value> e_val;
649 FCore.Graph env;
650 DAE.Prefix pre;
651 SCode.Each each_;
652 Absyn.Exp e;
653 FCore.Cache cache;
654 InstanceHierarchy ih;
655 String str;
656 SourceInfo info;
657
658 case (cache, _, _, _, DAE.NOMOD(), _) then (cache,DAE.NOMOD());
659
660 case (cache, _, _, _, (m as DAE.REDECL()), _) then (cache,m);
661
662 case (cache, env, ih, pre, (DAE.MOD(finalPrefix = f,eachPrefix = each_,subModLst = subs,binding = SOME(DAE.UNTYPED(e)), info = info)), impl)
663 algorithm
664 18566 (cache,subs_1) := updateSubmods(cache, env, ih, pre, subs, impl, info);
665 18566 (cache,e_1,prop) := Static.elabExp(cache, env, e, impl, true, pre, info);
666 18566 (cache, e_1, prop) := Ceval.cevalIfConstant(cache, env, e_1, prop, impl, info);
667 18566 (e_val, cache) := elabModValue(cache,env,e_1,prop,impl,info);
668 18566 (cache,e_2) := PrefixUtil.prefixExp(cache, env, ih, e_1, pre);
669
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18566 times.
18566 if Flags.isSet(Flags.UPDMOD) then
670 ✗ Debug.trace("Updated mod: ");
671 ✗ Debug.traceln(printModStr(DAE.MOD(f,each_,subs_1,SOME(DAE.TYPED(e_2,NONE(),prop,e,info)),info)));
672 end if;
673 37132 then
674 (cache,DAE.MOD(f,each_,subs_1,SOME(DAE.TYPED(e_2,e_val,prop,e,info)),info));
675
676 case (cache, env, ih, pre, DAE.MOD(finalPrefix = f,eachPrefix = each_,subModLst = subs,binding = SOME(DAE.TYPED(e_1,e_val,p,e)),info = info), impl)
677 algorithm
678 660532 (cache,subs_1) := updateSubmods(cache, env, ih, pre, subs, impl, info);
679 1321064 then
680 (cache,DAE.MOD(f,each_,subs_1,SOME(DAE.TYPED(e_1,e_val,p,e,info)),info));
681
682 case (cache, env, ih, pre, DAE.MOD(finalPrefix = f,eachPrefix = each_,subModLst = subs,binding = NONE(), info = info), impl)
683 algorithm
684 62936 (cache,subs_1) := updateSubmods(cache, env, ih, pre, subs, impl, info);
685 62936 then
686 (cache,DAE.MOD(f,each_,subs_1,NONE(), info));
687
688 case (_, _, _, _, m, _)
689 algorithm
690 ✗ true := Flags.isSet(Flags.FAILTRACE);
691 ✗ str := printModStr(m);
692 ✗ Debug.traceln("- Mod.updateMod failed mod: " + str);
693 ✗ then fail();
694 end matchcontinue;
695 end updateMod;
696
697 protected function updateSubmods ""
698 input FCore.Cache inCache;
699 input FCore.Graph inEnv;
700 input InnerOuter.InstHierarchy inIH;
701 input DAE.Prefix inPrefix;
702 input list<DAE.SubMod> inTypesSubModLst;
703 input Boolean inBoolean;
704 input SourceInfo info;
705 output FCore.Cache outCache = inCache;
706 output list<DAE.SubMod> outTypesSubModLst;
707 algorithm
708
4/4
✓ Branch 0 taken 162718 times.
✓ Branch 1 taken 742034 times.
✓ Branch 2 taken 162718 times.
✓ Branch 3 taken 742034 times.
904752 outTypesSubModLst := list(match x
709 local
710 DAE.Mod m_1,m;
711 String i;
712
713 case DAE.NAMEMOD(ident = i,mod = m)
714 algorithm
715 162718 (outCache,m_1) := updateMod(outCache, inEnv, inIH, inPrefix, m, inBoolean, info);
716 162718 then
717 DAE.NAMEMOD(i,m_1);
718 end match for x in inTypesSubModLst);
719 end updateSubmods;
720
721 public function elabUntypedMod "This function is used to convert SCode.Mod into Mod, without
722 adding correct type information. Instead, a undefined type will be
723 given to the modification. This is used when modifications of e.g.
724 elements in base classes used. For instance,
725 model test extends A(x=y); end test; // both x and y are defined in A
726 The modifier x=y must be merged with outer modifiers, thus it needs
727 to be converted to Mod.
728 Notice that the correct type information must be updated later on."
729 input SCode.Mod inMod;
730 input ModScope inModScope;
731 output DAE.Mod outMod;
732 algorithm
733 outMod := matchcontinue inMod
734 local
735 list<DAE.SubMod> subs_1;
736 SCode.Final finalPrefix;
737 SCode.Each each_;
738 list<SCode.SubMod> subs;
739 Absyn.Exp e;
740 SCode.Element elem;
741 String s;
742 SourceInfo info;
743 case SCode.NOMOD() then DAE.NOMOD();
744 case SCode.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = NONE(), info = info)
745 algorithm
746 2965 subs_1 := elabUntypedSubmods(subs, inModScope);
747 2963 then
748 DAE.MOD(finalPrefix,each_,subs_1,NONE(),info);
749 case SCode.MOD(finalPrefix = finalPrefix,eachPrefix = each_,subModLst = subs,binding = SOME(e),info = info)
750 algorithm
751 9674 subs_1 := elabUntypedSubmods(subs, inModScope);
752 19348 then
753 DAE.MOD(finalPrefix,each_,subs_1,SOME(DAE.UNTYPED(e)),info);
754 case SCode.REDECL(finalPrefix = finalPrefix,eachPrefix = each_, element = elem)
755 3813 then
756 DAE.REDECL(finalPrefix,each_,elem, DAE.NOMOD());
757 else
758 algorithm
759 2 print("- elab_untyped_mod ");
760 2 s := SCodeDump.printModStr(inMod,SCodeDump.defaultOptions);
761 2 print(s);
762 2 print(" failed\n");
763 2 then
764 fail();
765 end matchcontinue;
766 end elabUntypedMod;
767
768 protected function elabSubmods
769 "This function helps elabMod by recursively elaborating on a list of submodifications."
770 input FCore.Cache inCache;
771 input FCore.Graph inEnv;
772 input InnerOuter.InstHierarchy inIH;
773 input DAE.Prefix inPrefix;
774 input list<SCode.SubMod> inSCodeSubModLst;
775 input Boolean inBoolean;
776 input ModScope inModScope;
777 input SourceInfo info;
778 output FCore.Cache outCache;
779 output list<DAE.SubMod> outTypesSubModLst;
780 protected
781 list<SCode.SubMod> submods;
782 algorithm
783 1384884 submods := compactSubMods(inSCodeSubModLst, inModScope);
784 1384881 (outCache, outTypesSubModLst) := elabSubmods2(inCache, inEnv, inIH, inPrefix, submods, inBoolean, info, {});
785 end elabSubmods;
786
787 protected function elabSubmods2
788 "This function elaborates a list of submodifications."
789 input FCore.Cache inCache;
790 input FCore.Graph inEnv;
791 input InnerOuter.InstHierarchy inIH;
792 input DAE.Prefix inPrefix;
793 input list<SCode.SubMod> inSubMods;
794 input Boolean inImpl;
795 input SourceInfo inInfo;
796 input list<DAE.SubMod> inAccumMods;
797 output FCore.Cache outCache;
798 output list<DAE.SubMod> outSubMods;
799 algorithm
800 (outCache, outSubMods) :=
801 match(inCache, inSubMods)
802 local
803 FCore.Cache cache;
804 SCode.SubMod smod;
805 list<SCode.SubMod> rest_smods;
806 DAE.SubMod dmod;
807 list<DAE.SubMod> accum_mods;
808
809 case (cache, smod :: rest_smods)
810 algorithm
811 912401 (cache, dmod) := elabSubmod(cache, inEnv, inIH, inPrefix, smod, inImpl, inInfo);
812 912401 (cache, accum_mods) := elabSubmods2(cache, inEnv, inIH, inPrefix,
813 rest_smods, inImpl, inInfo, dmod :: inAccumMods);
814 then
815 (cache, accum_mods);
816
817 1384881 else (inCache, listReverse(inAccumMods));
818
819 end match;
820 end elabSubmods2;
821
822 protected function compactSubMods
823 "This function merges the submodifiers in a modifier so that each submodifier
824 only occurs once. Ex:
825
826 compactMod({x.start = 2.0, y = 4.0, x(min = 1.0, max = 3.0)}) =>
827 {x(start = 2.0, min = 1.0, max = 3.0), y = 4.0}
828
829 "
830 input list<SCode.SubMod> inSubMods;
831 input ModScope inModScope;
832 output list<SCode.SubMod> outSubMods;
833 protected
834 list<SCode.SubMod> submods;
835 algorithm
836 1397523 submods := List.fold2(inSubMods, compactSubMod, inModScope, {}, {});
837 1397518 outSubMods := listReverse(submods);
838 end compactSubMods;
839
840 protected function compactSubMod
841 "Helper function to compactSubMods. Tries to merge the given modifier with an
842 existing modifier in the accumulation list. If a matching modifier is not
843 found in the list it's added instead."
844 input SCode.SubMod inSubMod;
845 input ModScope inModScope;
846 input list<String> inName;
847 input list<SCode.SubMod> inAccumMods;
848 output list<SCode.SubMod> outSubMods;
849 protected
850 list<SCode.SubMod> submods;
851 Boolean found;
852 algorithm
853 926850 (submods, found) := List.findMap(inAccumMods,
854 function compactSubMod2(inNewMod = inSubMod, inModScope = inModScope, inName = inName));
855 926844 outSubMods := List.consOnTrue(not found, inSubMod, submods);
856 end compactSubMod;
857
858 protected function compactSubMod2
859 "Helper function to compactSubMod. Merges the given modifier with the existing
860 modifier if they have the same name, otherwise does nothing."
861 input SCode.SubMod inExistingMod;
862 input SCode.SubMod inNewMod;
863 input ModScope inModScope;
864 input list<String> inName;
865 output SCode.SubMod outMod;
866 output Boolean outFound;
867 algorithm
868 (outMod, outFound) := match(inExistingMod, inNewMod)
869 local
870 String name1, name2;
871 SCode.SubMod submod;
872
873 case (SCode.NAMEMOD(ident = name1), SCode.NAMEMOD(ident = name2))
874 guard
875 not stringEqual(name1, name2)
876 then
877 (inExistingMod, false);
878
879 case (SCode.NAMEMOD(ident = name1), _)
880 algorithm
881 10 submod := mergeSubModsInSameScope(inExistingMod, inNewMod, name1 :: inName, inModScope);
882 then
883 (submod, true);
884
885 end match;
886 end compactSubMod2;
887
888 protected function mergeSubModsInSameScope
889 "Merges two submodifiers in the same scope, i.e. they have the same priority.
890 It's thus an error if the modifiers modify the same element."
891 input SCode.SubMod inMod1;
892 input SCode.SubMod inMod2;
893 input list<String> inElementName;
894 input ModScope inModScope;
895 output SCode.SubMod outMod;
896 protected
897 String scope, name;
898 list<SCode.SubMod> submods;
899 SourceInfo info1, info2;
900 SCode.Mod mod1 = inMod1.mod, mod2 = inMod2.mod;
901 algorithm
902 outMod := match(mod1, mod2)
903 // The second modifier has no binding, use the binding from the first.
904 case (SCode.MOD(), SCode.MOD(binding = NONE()))
905 algorithm
906 5 submods := List.fold2(mod1.subModLst, compactSubMod, inModScope, inElementName, mod2.subModLst);
907 4 then
908 SCode.NAMEMOD(inMod1.ident, SCode.MOD(mod1.finalPrefix, mod1.eachPrefix,
909 submods, mod1.binding, mod1.comment, mod1.info));
910
911 // The first modifier has no binding, use the binding from the second.
912 case (SCode.MOD(binding = NONE()), SCode.MOD())
913 algorithm
914 ✗ submods := List.fold2(mod1.subModLst, compactSubMod, inModScope, inElementName, mod2.subModLst);
915 ✗ then
916 SCode.NAMEMOD(inMod2.ident, SCode.MOD(mod2.finalPrefix, mod2.eachPrefix,
917 submods, mod2.binding, mod2.comment, mod2.info));
918
919 // Both modifiers have a binding.
920 else
921 algorithm
922 5 info1 := SCodeUtil.getModifierInfo(mod1);
923 5 info2 := SCodeUtil.getModifierInfo(mod2);
924 5 scope := printModScope(inModScope);
925 5 name := stringDelimitList(listReverse(inElementName), ".");
926 5 Error.addMultiSourceMessage(Error.DUPLICATE_MODIFICATIONS,
927 {name, scope}, {info2, info1});
928 5 then
929 fail();
930
931 end match;
932 end mergeSubModsInSameScope;
933
934 protected function printModScope
935 input ModScope inModScope;
936 output String outString;
937 algorithm
938 outString := match inModScope
939 local
940 String name;
941 Absyn.Path path;
942
943 3 case COMPONENT(name = name) then "component " + name;
944 2 case EXTENDS(path = path) then "extends " + AbsynUtil.pathString(path);
945 ✗ case DERIVED(path = path) then "inherited class " + AbsynUtil.pathString(path);
946
947 end match;
948 end printModScope;
949
950 protected function elabSubmod
951 "This function elaborates on a submodification, turning an
952 SCode.SubMod into a DAE.SubMod."
953 input FCore.Cache inCache;
954 input FCore.Graph inEnv;
955 input InnerOuter.InstHierarchy inIH;
956 input DAE.Prefix inPrefix;
957 input SCode.SubMod inSubMod;
958 input Boolean inBoolean;
959 input SourceInfo info;
960 output FCore.Cache outCache;
961 output DAE.SubMod outSubMod;
962 protected
963 SCode.Mod smod;
964 DAE.Mod dmod;
965 String i;
966 algorithm
967 912401 SCode.NAMEMOD(ident = i, mod = smod) := inSubMod;
968 912401 (outCache, dmod) := elabMod(inCache, inEnv, inIH, inPrefix, smod, inBoolean, COMPONENT(i), info);
969 912401 outSubMod := DAE.NAMEMOD(i, dmod);
970 end elabSubmod;
971
972 protected function elabUntypedSubmods
973 input list<SCode.SubMod> inSubMods;
974 input ModScope inModScope;
975 output list<DAE.SubMod> outSubMods;
976 protected
977 list<SCode.SubMod> submods;
978 algorithm
979 12639 submods := compactSubMods(inSubMods, inModScope);
980
4/4
✓ Branch 1 taken 14430 times.
✓ Branch 2 taken 12637 times.
✓ Branch 3 taken 14430 times.
✓ Branch 4 taken 12637 times.
27067 outSubMods := listAppend(elabUntypedSubmod(m) for m in listReverse(submods));
981 end elabUntypedSubmods;
982
983 protected function elabUntypedSubmod "
984 This function elaborates on a submodification, turning an
985 `SCode.SubMod\' into one or more `DAE.SubMod\'s, wihtout type information.
986 "
987 input SCode.SubMod inSubMod;
988 output list<DAE.SubMod> outTypesSubModLst;
989 algorithm
990 outTypesSubModLst:= match inSubMod
991 local
992 DAE.Mod m_1;
993 String i;
994 SCode.Mod m;
995
996 case SCode.NAMEMOD(ident = i, mod = m)
997 algorithm
998 14430 m_1 := elabUntypedMod(m, COMPONENT(""));
999 14430 then
1000 {DAE.NAMEMOD(i,m_1)};
1001 end match;
1002 end elabUntypedSubmod;
1003
1004 // - Lookup
1005 public function lookupModificationP "This function extracts a modification from inside another
1006 modification, using a name to look up submodifications."
1007 input DAE.Mod inMod;
1008 input Absyn.Path inPath;
1009 output DAE.Mod outMod;
1010 algorithm
1011 outMod := matchcontinue (inMod,inPath)
1012 local
1013 DAE.Mod mod,m,mod_1;
1014 String n;
1015 Absyn.Path p;
1016 case (m,Absyn.IDENT(name = n))
1017 algorithm
1018 1242343 mod := lookupCompModification(m, n);
1019 then
1020 mod;
1021 255814 case (m,Absyn.FULLYQUALIFIED(p)) then lookupModificationP(m,p);
1022 case (m,Absyn.QUALIFIED(name = n,path = p))
1023 algorithm
1024 756653 mod := lookupCompModification(m, n);
1025 756653 mod_1 := lookupModificationP(mod, p);
1026 then
1027 mod_1;
1028 else
1029 algorithm
1030 ✗ Print.printBuf("- Mod.lookupModificationP failed\n");
1031 ✗ then
1032 fail();
1033 end matchcontinue;
1034 end lookupModificationP;
1035
1036 public function lookupCompModification "This function is used to look up an identifier in a modification."
1037 input DAE.Mod inMod;
1038 input Absyn.Ident inIdent;
1039 output DAE.Mod outMod;
1040 algorithm
1041 outMod := match(inMod,inIdent)
1042 local
1043 DAE.Mod mod1,mod2;
1044 list<DAE.SubMod> subs;
1045 String n;
1046 Option<DAE.EqMod> eqMod;
1047 SCode.Each e;
1048 SCode.Final f;
1049 SourceInfo info;
1050
1051 case (DAE.MOD(finalPrefix = f,eachPrefix = e,subModLst = subs,binding = eqMod,info = info),n)
1052 algorithm
1053 27576891 mod1 := lookupCompModification2(subs, n);
1054 27576891 mod2 := lookupComplexCompModification(eqMod,n,f,e,info);
1055 27576891 then
1056 checkDuplicateModifications(mod1,mod2,n);
1057
1058 else DAE.NOMOD();
1059 end match;
1060 end lookupCompModification;
1061
1062 public function getModifs
1063 "return the modifications from mod
1064 which is named inName or which
1065 is named name if name is inside
1066 inSMod(xxx = name)"
1067 input DAE.Mod inMods;
1068 input SCode.Ident inName;
1069 input SCode.Mod inSMod;
1070 output DAE.Mod outMod;
1071 algorithm
1072 outMod := matchcontinue inSMod
1073 local
1074 DAE.Mod m;
1075
1076 case _
1077 algorithm
1078 ✗ m := lookupCompModification(inMods, inName);
1079 ✗ m := mergeModifiers(inMods, m, inSMod);
1080 then
1081 m;
1082
1083 else
1084 algorithm
1085 ✗ m := mergeModifiers(inMods, DAE.NOMOD(), inSMod);
1086 then
1087 m;
1088 end matchcontinue;
1089 end getModifs;
1090
1091 protected function mergeModifiers
1092 input DAE.Mod inMods;
1093 input DAE.Mod inMod;
1094 input SCode.Mod inSMod;
1095 output DAE.Mod outMod;
1096 algorithm
1097 outMod := match inSMod
1098 local
1099 DAE.Mod m;
1100 list<SCode.SubMod> sl;
1101 SCode.Final f;
1102 SCode.Each e;
1103
1104 case SCode.MOD(f, e, sl, _, _)
1105 algorithm
1106 ✗ m := mergeSubMods(inMods, inMod, f, e, sl);
1107 then
1108 m;
1109
1110 else inMod;
1111
1112 end match;
1113 end mergeModifiers;
1114
1115 protected function mergeSubMods
1116 input DAE.Mod inMods;
1117 input DAE.Mod inMod;
1118 input SCode.Final f;
1119 input SCode.Each e;
1120 input list<SCode.SubMod> inSMods;
1121 output DAE.Mod outMod;
1122 algorithm
1123 outMod := matchcontinue inSMods
1124 local
1125 DAE.Mod m;
1126 SCode.Ident id, n;
1127 list<SCode.SubMod> rest;
1128 SourceInfo info;
1129
1130 case {} then inMod;
1131
1132 case SCode.NAMEMOD(n, SCode.MOD(binding = SOME(Absyn.CREF(Absyn.CREF_IDENT(id, _))),info = info))::rest
1133 algorithm
1134 ✗ m := lookupCompModification(inMods, id);
1135 ✗ m := DAE.MOD(f, e, {DAE.NAMEMOD(n, m)}, NONE(), info);
1136 ✗ m := merge(inMod, m);
1137 ✗ m := mergeSubMods(inMods, m, f, e, rest);
1138 then
1139 m;
1140
1141 case _::rest
1142 algorithm
1143 ✗ m := mergeSubMods(inMods, inMod, f, e, rest);
1144 then
1145 m;
1146
1147 end matchcontinue;
1148 end mergeSubMods;
1149
1150 public function lookupCompModificationFromEqu "This function is used to look up an identifier in a modification."
1151 input DAE.Mod inMod;
1152 input Absyn.Ident inIdent;
1153 output DAE.Mod outMod;
1154 algorithm
1155 outMod := match (inMod,inIdent)
1156 local
1157 DAE.Mod mod,mod1,mod2;
1158 list<DAE.SubMod> subs;
1159 String n;
1160 Option<DAE.EqMod> eqMod;
1161 SCode.Each e;
1162 SCode.Final f;
1163 SourceInfo info;
1164
1165 case (DAE.NOMOD(),_) then DAE.NOMOD();
1166 case (DAE.REDECL(),_) then DAE.NOMOD();
1167 case (DAE.MOD(finalPrefix=f,eachPrefix=e,subModLst = subs,binding=eqMod,info = info),n)
1168 algorithm
1169 117809 mod1 := lookupCompModification2(subs, n);
1170 117809 mod2 := lookupComplexCompModification(eqMod,n,f,e,info);
1171 117809 mod := selectEqMod(mod1, mod2, n);
1172 then
1173 mod;
1174 end match;
1175 end lookupCompModificationFromEqu;
1176
1177 protected function selectEqMod
1178 "@adrpo:
1179 This function selects the eqmod modifier if is not DAE.NOMOD! AND IS TYPED!
1180 Otherwise check for duplicates"
1181 input DAE.Mod subMod;
1182 input DAE.Mod eqMod;
1183 input String n;
1184 output DAE.Mod mod;
1185 algorithm
1186 mod := match eqMod
1187 // eqmod is nomod!
1188 case DAE.NOMOD() then subMod;
1189 case DAE.MOD(binding = SOME(DAE.TYPED())) then eqMod;
1190 else
1191 algorithm
1192 ✗ mod := checkDuplicateModifications(subMod,eqMod,n);
1193 then
1194 mod;
1195 end match;
1196 end selectEqMod;
1197
1198 protected function lookupComplexCompModification
1199 "Looks up a component modification from a complex constructor (e.g. record
1200 constructor) by name."
1201 input Option<DAE.EqMod> inEqMod;
1202 input Absyn.Ident inName;
1203 input SCode.Final inFinal;
1204 input SCode.Each inEach;
1205 input SourceInfo inInfo;
1206 output DAE.Mod outMod = DAE.NOMOD();
1207 protected
1208 list<Values.Value> values;
1209 list<String> names;
1210 Values.Value v;
1211 String name;
1212 DAE.Exp e;
1213 Absyn.Exp ae;
1214 DAE.Type ty;
1215 DAE.EqMod eq_mod;
1216 SourceInfo info;
1217 algorithm
1218 try
1219
11/14
✗ Branch 0 not taken.
✓ Branch 1 taken 27694700 times.
✓ Branch 2 taken 4775146 times.
✓ Branch 3 taken 22919554 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 22919554 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 22919554 times.
✓ Branch 8 taken 1174441 times.
✓ Branch 9 taken 21745113 times.
✓ Branch 10 taken 21604624 times.
✓ Branch 11 taken 140489 times.
✓ Branch 12 taken 28247 times.
✓ Branch 13 taken 112242 times.
27694700 SOME(DAE.TYPED(modifierAsValue =
1220 SOME(Values.RECORD(orderd = values, comp = names, index = -1)), info=info)) := inEqMod;
1221
1222
2/2
✓ Branch 0 taken 1750873 times.
✓ Branch 1 taken 41020 times.
1791893 for name in names loop
1223
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1750873 times.
1750873 v :: values := values;
1224
1225
4/4
✓ Branch 0 taken 146286 times.
✓ Branch 1 taken 1604587 times.
✓ Branch 3 taken 71222 times.
✓ Branch 4 taken 75064 times.
1750873 if name == inName then
1226 71222 e := ValuesUtil.valueExp(v);
1227 71222 ae := Expression.unelabExp(e);
1228 71216 ty := Types.complicateType(Expression.typeof(e));
1229 142432 eq_mod := DAE.TYPED(e, SOME(v), DAE.PROP(ty, DAE.C_CONST()), ae, info);
1230 71216 outMod := DAE.MOD(inFinal, inEach, {}, SOME(eq_mod), inInfo);
1231 break;
1232 end if;
1233 end for;
1234 else
1235 end try;
1236 end lookupComplexCompModification;
1237
1238 protected function checkDuplicateModifications "Checks if two modifiers are present, and in that case
1239 print error of duplicate modifications, if not, the one modification having a value is returned"
1240 input DAE.Mod mod1;
1241 input DAE.Mod mod2;
1242 input String n;
1243 output DAE.Mod outMod;
1244 algorithm
1245 outMod := match(mod1, mod2)
1246 local
1247 list<DAE.SubMod> submods;
1248
1249 case (DAE.NOMOD(), _) then mod2;
1250 case (_, DAE.NOMOD()) then mod1;
1251
1252 case (DAE.REDECL(), DAE.MOD())
1253 ✗ then mergeRedeclareWithBinding(mod1, mod2);
1254
1255 case (DAE.MOD(), DAE.REDECL())
1256 ✗ then mergeRedeclareWithBinding(mod2, mod1);
1257
1258 case (DAE.MOD(binding = NONE()), DAE.MOD())
1259 algorithm
1260 8 submods := checkDuplicateModifications2(mod1.subModLst, mod2.subModLst, n);
1261 8 then
1262 DAE.MOD(mod2.finalPrefix, mod2.eachPrefix, submods, mod2.binding, mod2.info);
1263
1264 case (DAE.MOD(), DAE.MOD(binding = NONE()))
1265 algorithm
1266 ✗ submods := checkDuplicateModifications2(mod1.subModLst, mod2.subModLst, n);
1267 ✗ then
1268 DAE.MOD(mod1.finalPrefix, mod1.eachPrefix, submods, mod1.binding, mod1.info);
1269
1270 case (DAE.MOD(), DAE.MOD())
1271 algorithm
1272 ✗ Error.addMultiSourceMessage(Error.DUPLICATE_MODIFICATIONS, {n, ""},
1273 {getModInfo(mod1), getModInfo(mod2)});
1274 then
1275 mod2;
1276
1277 end match;
1278 end checkDuplicateModifications;
1279
1280 protected function checkDuplicateModifications2
1281 input list<DAE.SubMod> inSubMods1;
1282 input list<DAE.SubMod> inSubMods2;
1283 input String inName;
1284 output list<DAE.SubMod> outSubMods;
1285 protected
1286 list<DAE.SubMod> submods = inSubMods2;
1287 Option<DAE.SubMod> osubmod;
1288 DAE.SubMod submod;
1289 SourceInfo info1, info2;
1290 algorithm
1291
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 8 times.
16 for s in inSubMods1 loop
1292 8 (submods, osubmod) :=
1293 List.deleteMemberOnTrue(subModName(s), submods, isSubModNamed);
1294
1295
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 if isSome(osubmod) then
1296 ✗ SOME(submod) := osubmod;
1297
1298 ✗ info1 := subModInfo(s);
1299 ✗ info2 := subModInfo(submod);
1300 ✗ Error.addMultiSourceMessage(Error.MULTIPLE_MODIFIER, {inName}, {info1, info2});
1301 end if;
1302 end for;
1303
1304 8 outSubMods := listAppend(inSubMods1, inSubMods2);
1305 end checkDuplicateModifications2;
1306
1307 protected function mergeRedeclareWithBinding
1308 "Merges two modifiers where the first is a redeclare and the second a binding
1309 modifier. This is to handle the case where an extended record redeclares a
1310 component, and then the component gets a binding when the record type is used.
1311
1312 E.g. record ER = R(redeclare SomeType x);
1313 ER er = ER(1.0);
1314 "
1315 input DAE.Mod inRedeclare;
1316 input DAE.Mod inBinding;
1317 output DAE.Mod outMod = inRedeclare;
1318 algorithm
1319 outMod := match(outMod, inBinding)
1320 case (DAE.REDECL(),
1321 DAE.MOD(subModLst = {}, binding = SOME(_)))
1322 algorithm
1323 ✗ outMod.mod := merge(inBinding, outMod.mod);
1324 then
1325 outMod;
1326
1327 end match;
1328 end mergeRedeclareWithBinding;
1329
1330 protected function modEqualNoPrefix
1331 input DAE.Mod mod1;
1332 input DAE.Mod mod2;
1333 output DAE.Mod outMod;
1334 output Boolean equal;
1335 algorithm
1336 (outMod, equal) := match(mod1, mod2)
1337 case (DAE.MOD(), DAE.MOD())
1338 algorithm
1339 ✗ true := subModsEqual(mod1.subModLst, mod2.subModLst);
1340 ✗ true := eqModEqual(mod1.binding, mod2.binding);
1341 then
1342 (mod2, true);
1343
1344 // two exactly the same mod, return just one! (used when it is REDECL or a submod is REDECL)
1345 case(DAE.REDECL(), DAE.REDECL())
1346 algorithm
1347 ✗ true := SCodeUtil.elementEqual(mod1.element, mod2.element);
1348 then
1349 (mod2, true);
1350
1351 case(DAE.NOMOD(),DAE.NOMOD()) then (DAE.NOMOD(), true);
1352
1353 // adrpo: do not fail, return false!
1354 else (mod2, false);
1355 end match;
1356 end modEqualNoPrefix;
1357
1358 protected function lookupNamedSubMod
1359 input list<DAE.SubMod> inSubMods;
1360 input Absyn.Ident inIdent;
1361 output DAE.SubMod outSubMod;
1362 algorithm
1363 6308733 outSubMod := List.getMemberOnTrue(inIdent, inSubMods, isSubModNamed);
1364 end lookupNamedSubMod;
1365
1366 protected function isSubModNamed
1367 input Absyn.Ident inIdent;
1368 input DAE.SubMod inSubMod;
1369 output Boolean outIsNamed;
1370 protected
1371 String ident;
1372 algorithm
1373 16931891 DAE.NAMEMOD(ident = ident) := inSubMod;
1374
4/4
✓ Branch 0 taken 1341420 times.
✓ Branch 1 taken 15590471 times.
✓ Branch 3 taken 1015016 times.
✓ Branch 4 taken 326404 times.
16931891 outIsNamed := stringEq(inIdent, ident);
1375 end isSubModNamed;
1376
1377 public function printSubsStr
1378 "@author: adrpo
1379 Prints sub-mods in a string with format (sub1, sub2, sub3)"
1380 input list<DAE.SubMod> inSubMods;
1381 input Boolean addParan;
1382 output String s;
1383 algorithm
1384 ✗ s := stringDelimitList(List.map(inSubMods, prettyPrintSubmod), ", ");
1385 ✗ s := (if addParan then "(" else "") + s + (if addParan then ")" else "");
1386 end printSubsStr;
1387
1388 protected function lookupCompModification2
1389 input list<DAE.SubMod> inSubModLst;
1390 input Absyn.Ident inIdent;
1391 output DAE.Mod outMod;
1392 algorithm
1393 outMod := matchcontinue inSubModLst
1394 local
1395 DAE.Mod mod;
1396
1397 case {} then DAE.NOMOD();
1398
1399 case _
1400 algorithm
1401 6308733 DAE.NAMEMOD(mod = mod) := lookupNamedSubMod(inSubModLst, inIdent);
1402 then
1403 mod;
1404
1405 else DAE.NOMOD();
1406
1407 end matchcontinue;
1408 end lookupCompModification2;
1409
1410 public function lookupIdxModification
1411 "This function extracts modifications to an array element, using a subscript
1412 expression to index the modification."
1413 input DAE.Mod inMod;
1414 input DAE.Exp inIndex;
1415 output DAE.Mod outMod;
1416 algorithm
1417 outMod := matchcontinue inMod
1418 local
1419 DAE.Mod mod1, mod2;
1420 list<DAE.SubMod> subs;
1421 Option<DAE.EqMod> eq;
1422
1423 case DAE.NOMOD() then DAE.NOMOD();
1424 case DAE.REDECL() then DAE.NOMOD();
1425 case DAE.MOD()
1426 algorithm
1427 220792 (mod1, subs) := lookupIdxModification2(inMod.subModLst, inIndex);
1428 220792 mod2 := DAE.MOD(inMod.finalPrefix, inMod.eachPrefix, subs, NONE(), inMod.info);
1429 220792 mod2 := merge(mod2, mod1);
1430
1431 220792 eq := indexEqmod(inMod.binding, {inIndex}, inMod.info);
1432 220792 mod1 := DAE.MOD(SCode.NOT_FINAL(), inMod.eachPrefix, {}, eq, inMod.info);
1433 220792 mod2 := merge(mod2, mod1);
1434 then
1435 mod2;
1436
1437 else
1438 algorithm
1439 ✗ true := Flags.isSet(Flags.FAILTRACE);
1440 ✗ Debug.trace("- Mod.lookupIdxModification(");
1441 ✗ Debug.trace(printModStr(inMod));
1442 ✗ Debug.traceln(", " + ExpressionBasics.printExpStr(inIndex) + ") failed");
1443 ✗ then
1444 fail();
1445
1446 end matchcontinue;
1447 end lookupIdxModification;
1448
1449 protected function lookupIdxModification2
1450 "This function does part of the job for lookupIdxModification."
1451 input list<DAE.SubMod> inSubMods;
1452 input DAE.Exp inIndex;
1453 output DAE.Mod outMod = DAE.NOMOD();
1454 output list<DAE.SubMod> outSubMods = {};
1455 protected
1456 DAE.Mod mod;
1457 String name;
1458 algorithm
1459
2/2
✓ Branch 0 taken 32880 times.
✓ Branch 1 taken 234921 times.
267801 for submod in inSubMods loop
1460 32880 DAE.NAMEMOD(name, mod) := submod;
1461 32880 mod := lookupIdxModification3(mod, inIndex);
1462
1463 // isEmptyMod should be used instead, but the Modification13 test case
1464 // breaks if empty submods are filtered out...
1465
1/2
✓ Branch 1 taken 32880 times.
✗ Branch 2 not taken.
32880 if not isNoMod(mod) then
1466 32880 outSubMods := DAE.NAMEMOD(name, mod) :: outSubMods;
1467 end if;
1468 end for;
1469
1470 234921 outSubMods := listReverse(outSubMods);
1471 end lookupIdxModification2;
1472
1473 protected function lookupIdxModification3
1474 "Helper function to lookupIdxModification2.
1475 When lookup up the index of a named mod, e.g. y = {1, 2, 3}, it should
1476 subscript the expression {1, 2, 3} to the corresponding index."
1477 input DAE.Mod inMod;
1478 input DAE.Exp inIndex;
1479 output DAE.Mod outMod;
1480 algorithm
1481 outMod := match inMod
1482 local
1483 list<DAE.SubMod> subs;
1484 Option<DAE.EqMod> eq;
1485
1486 case DAE.NOMOD() then DAE.NOMOD();
1487 case DAE.REDECL() then inMod;
1488
1489 case DAE.MOD(eachPrefix = SCode.NOT_EACH())
1490 algorithm
1491 14129 (_, subs) := lookupIdxModification2(inMod.subModLst, inIndex);
1492 14129 eq := indexEqmod(inMod.binding, {inIndex}, inMod.info);
1493 14129 then
1494 DAE.MOD(inMod.finalPrefix, inMod.eachPrefix, subs, eq, inMod.info);
1495
1496 case DAE.MOD(eachPrefix = SCode.EACH())
1497 then inMod;
1498
1499 end match;
1500 end lookupIdxModification3;
1501
1502 protected function indexEqmod
1503 "If there is an equation modification, this function can subscript it using
1504 the provided indexing expressions. This is used when a modification equates
1505 an array variable with an array expression. This expression will be expanded
1506 to produce one equation expression per array component."
1507 input Option<DAE.EqMod> inBinding;
1508 input list<DAE.Exp> inIndices;
1509 input SourceInfo inInfo;
1510 output Option<DAE.EqMod> outBinding = inBinding;
1511 protected
1512 DAE.Exp exp;
1513 Option<Values.Value> oval;
1514 Values.Value val;
1515 DAE.Type ty;
1516 DAE.Const c;
1517 Absyn.Exp aexp;
1518 DAE.EqMod eq;
1519 SourceInfo info;
1520 algorithm
1521
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 234921 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 225231 times.
✓ Branch 5 taken 9690 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 225231 times.
234921 if isNone(inBinding) or listEmpty(inIndices) then
1522 9690 return;
1523 end if;
1524
1525
2/4
✓ Branch 0 taken 225231 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 225231 times.
225231 SOME(eq) := inBinding;
1526
1527 outBinding := matchcontinue eq
1528 // Subscripting empty array gives no value. This is needed in e.g. fill(1.0, 0, 2).
1529 case DAE.TYPED(modifierAsValue = SOME(Values.ARRAY(valueLst = {}))) then NONE();
1530
1531 // A normal typed binding.
1532 case DAE.TYPED(exp, oval, DAE.PROP(ty, c), aexp, info)
1533 algorithm
1534 // Subscript the expression with the indices.
1535
2/2
✓ Branch 0 taken 225231 times.
✓ Branch 1 taken 225215 times.
450446 for i in inIndices loop
1536
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 225215 times.
225231 if not Types.isArray(ty) then
1537 // Check that we're not trying to apply a non-array modifier to an
1538 // array, which isn't really allowed but working anyway. Some
1539 // standard Modelica libraries are missing the 'each' keyword
1540 // though (e.g. the DoublePendulum example), and therefore relying
1541 // on this behaviour, so just print a warning here.
1542 32 Error.addSourceMessage(Error.MODIFIER_NON_ARRAY_TYPE_WARNING,
1543 {ExpressionBasics.printExpStr(exp)}, inInfo);
1544 16 return;
1545 end if;
1546
1547 225215 ty := Types.unliftArray(ty);
1548 225215 exp := ExpressionSimplify.simplify1(Expression.makeASUB(exp, {i}));
1549 end for;
1550
1551 // If the modifier has a value, retrieve the indexed elements.
1552
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 225215 times.
✓ Branch 2 taken 211770 times.
✓ Branch 3 taken 13445 times.
225215 if isSome(oval) then
1553 211770 SOME(val) := oval;
1554
1555
2/2
✓ Branch 0 taken 211770 times.
✓ Branch 1 taken 211770 times.
423540 for i in inIndices loop
1556 211770 val := ValuesUtil.nthArrayelt(val, ExpressionBasics.expArrayIndex(i));
1557 end for;
1558
1559 oval := SOME(val);
1560 end if;
1561 225215 then
1562 SOME(DAE.TYPED(exp, oval, DAE.PROP(ty, c), aexp, info));
1563
1564 else
1565 algorithm
1566 ✗ true := Flags.isSet(Flags.FAILTRACE);
1567 ✗ Debug.traceln("- Mod.indexEqmod failed for mod:\n " +
1568 TypesDump.unparseEqMod(eq) + "\n indices: " +
1569 ExpressionDump.printExpListStr(inIndices));
1570 ✗ then
1571 fail();
1572
1573 end matchcontinue;
1574 end indexEqmod;
1575
1576 public function merge
1577 "Merges two modifiers, where the outer modifiers overrides the inner one."
1578 input DAE.Mod inModOuter "The outer mod which should override the inner mod.";
1579 input DAE.Mod inModInner "The inner mod.";
1580 input String inElementName = "";
1581 input Boolean inCheckFinal = true;
1582 output DAE.Mod outMod;
1583 protected
1584 String mod_str;
1585 algorithm
1586
2/2
✓ Branch 1 taken 1380679 times.
✓ Branch 2 taken 4148257 times.
5528936 if isEmptyMod(inModOuter) then
1587 outMod := inModInner;
1588 elseif isEmptyMod(inModInner) then
1589 outMod := inModOuter;
1590 elseif inCheckFinal and isFinalMod(inModInner) and
1591 not merge_isEqual(inModOuter, inModInner) and
1592 not isRedeclareMod(inModOuter) then
1593 8 mod_str := unparseModStr(inModOuter);
1594 24 Error.addMultiSourceMessage(Error.FINAL_COMPONENT_OVERRIDE,
1595 {inElementName, mod_str}, {getModInfo(inModInner), getModInfo(inModOuter)});
1596 8 fail();
1597 else
1598 469777 outMod := doMerge(inModOuter, inModInner, inCheckFinal);
1599 end if;
1600 end merge;
1601
1602 protected function merge_isEqual
1603 input DAE.Mod inMod1;
1604 input DAE.Mod inMod2;
1605 output Boolean outIsEqual;
1606 protected
1607 SourceInfo info1, info2;
1608 algorithm
1609
2/2
✓ Branch 0 taken 1941 times.
✓ Branch 1 taken 1235 times.
3176 if referenceEq(inMod1, inMod2) then
1610 outIsEqual := true;
1611 else
1612 1941 info1 := getModInfo(inMod1);
1613 1941 info2 := getModInfo(inMod2);
1614
1615
4/6
✓ Branch 1 taken 1941 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1941 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 8 times.
✓ Branch 8 taken 1933 times.
1941 outIsEqual := not (Util.sourceInfoIsEmpty(info1) or
1616 Util.sourceInfoIsEmpty(info2)) and
1617 Util.sourceInfoIsEqual(info1, info2);
1618 end if;
1619 end merge_isEqual;
1620
1621 public function isFinalMod
1622 "Returns whether a modifier is declared final or not."
1623 input DAE.Mod inMod1;
1624 output Boolean outMod;
1625 algorithm
1626 outMod:= match inMod1
1627 case DAE.MOD(finalPrefix = SCode.FINAL()) then true;
1628
1629 case DAE.REDECL(element =
1630 SCode.COMPONENT(prefixes=SCode.PREFIXES(finalPrefix=SCode.FINAL())))
1631 then true;
1632
1633 else false;
1634 end match;
1635 end isFinalMod;
1636
1637 protected function doMerge
1638 "Merges two DAE.Mod into one. The first argument is the outer modification
1639 that should take precedence over the inner modification."
1640 input DAE.Mod inModOuter "The outer mod which should overwrite the inner mod.";
1641 input DAE.Mod inModInner "The inner mod.";
1642 input Boolean inCheckFinal;
1643 output DAE.Mod outMod = inModOuter;
1644 algorithm
1645 outMod := match (outMod, inModInner)
1646 local
1647 SCode.Element el1, el2;
1648 SCode.Mod smod1, smod2;
1649 DAE.Mod emod1, emod2, emod, dmod1, dmod2, dmod;
1650 SCode.Restriction res;
1651 SourceInfo info;
1652 DAE.EqMod eqmod;
1653 list<Values.Value> vals;
1654 Values.Value val;
1655 list<String> names;
1656 String name;
1657 list<DAE.SubMod> submods;
1658 DAE.SubMod submod;
1659
1660 // Redeclaration of component with no constraining class on the inner modifier.
1661 case (DAE.REDECL(element = SCode.COMPONENT()),
1662 DAE.REDECL(element = SCode.COMPONENT(prefixes =
1663 SCode.PREFIXES(replaceablePrefix = SCode.REPLACEABLE(cc = NONE())))))
1664 then inModOuter;
1665
1666 // Redeclaration of component with constraining class on the inner modifier.
1667 case (DAE.REDECL(element = el1 as SCode.COMPONENT(), mod = emod1),
1668 DAE.REDECL(element = el2 as SCode.COMPONENT(), mod = emod2))
1669 algorithm
1670 135 smod1 := SCodeUtil.getConstrainedByModifiers(el1.prefixes);
1671 135 smod1 := SCodeUtil.mergeModifiers(el1.modifications, smod1);
1672 135 dmod1 := elabUntypedMod(smod1, COMPONENT(el1.name));
1673
1674 135 smod2 := SCodeUtil.getConstrainedByModifiers(el2.prefixes);
1675 135 smod2 := SCodeUtil.mergeModifiers(el2.modifications, smod2);
1676 135 dmod2 := elabUntypedMod(smod2, COMPONENT(el2.name));
1677
1678 135 dmod := merge(dmod1, dmod2, el1.name, inCheckFinal);
1679 135 emod := merge(emod1, emod2, el1.name, inCheckFinal);
1680 // If we have a constraining class we don't need the mod.
1681 135 el1.modifications := unelabMod(dmod);
1682
1683 135 el1.prefixes := SCodeUtil.propagatePrefixes(el2.prefixes, el1.prefixes);
1684 135 el1.attributes := SCodeUtil.propagateAttributes(el2.attributes, el1.attributes);
1685 135 outMod.element := el1;
1686 135 outMod.mod := emod;
1687 then
1688 outMod;
1689
1690 // Redeclaration of class with no constraining class on the inner modifier.
1691 case (DAE.REDECL(element = SCode.CLASS()),
1692 DAE.REDECL(element = SCode.CLASS(prefixes =
1693 SCode.PREFIXES(replaceablePrefix = SCode.REPLACEABLE(cc = NONE())))))
1694 then inModOuter;
1695
1696 // Redeclaration of class with constraining class on the inner modifier.
1697 case (DAE.REDECL(element = el1 as SCode.CLASS(), mod = emod1),
1698 DAE.REDECL(element = el2 as SCode.CLASS(), mod = emod2))
1699 algorithm
1700 188 smod1 := SCodeUtil.getConstrainedByModifiers(el1.prefixes);
1701 188 dmod1 := elabUntypedMod(smod1, COMPONENT(el1.name));
1702 188 emod1 := merge(emod1, dmod1, el1.name, inCheckFinal);
1703
1704 188 smod2 := SCodeUtil.getConstrainedByModifiers(el2.prefixes);
1705 188 dmod2 := elabUntypedMod(smod2, COMPONENT(el2.name));
1706 188 emod2 := merge(emod2, dmod2, el1.name, inCheckFinal);
1707
1708 188 emod := merge(emod1, emod2, el1.name, inCheckFinal);
1709 188 el1.prefixes := SCodeUtil.propagatePrefixes(el2.prefixes, el2.prefixes);
1710 188 (res, info) := SCodeUtil.checkSameRestriction(
1711 el1.restriction, el2.restriction, el1.info, el2.info);
1712 188 el1.restriction := res;
1713 188 el1.info := info;
1714
1715 188 outMod.element := el1;
1716 188 outMod.mod := emod;
1717 then
1718 outMod;
1719
1720 case (DAE.REDECL(element = el1, mod = emod),
1721 DAE.MOD())
1722 algorithm
1723 73 emod := merge(emod, inModInner, "", inCheckFinal);
1724 73 outMod.element := el1;
1725 73 outMod.mod := emod;
1726 then
1727 outMod;
1728
1729 case (DAE.MOD(),
1730 DAE.REDECL(element = el2, mod = emod))
1731 algorithm
1732 7 emod := merge(inModOuter, emod, "", inCheckFinal);
1733 7 then
1734 DAE.REDECL(inModInner.finalPrefix, inModInner.eachPrefix, el2, emod);
1735
1736 // The outer modifier has a record binding, while the inner consists of submodifiers.
1737 case (DAE.MOD(binding = SOME(eqmod as DAE.TYPED(modifierAsValue =
1738 SOME(val as Values.RECORD()))), subModLst = {}),
1739 DAE.MOD(binding = NONE(), subModLst = submods as _ :: _))
1740 algorithm
1741 3 names := val.comp;
1742 vals := {};
1743
1744
2/2
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 3 times.
101 for v in val.orderd loop
1745
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 name :: names := names;
1746
1747 // If the record component doesn't have a binding, use the value
1748 // from the submodifier instead.
1749
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 97 times.
98 if ValuesUtil.isEmpty(v) then
1750 try
1751
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 (submods, SOME(submod)) := List.deleteMemberOnTrue(name, submods, isSubModNamed);
1752 1 v := subModValue(submod);
1753 else
1754 end try;
1755 end if;
1756
1757 vals := v :: vals;
1758 end for;
1759
1760 3 val.orderd := listReverse(vals);
1761 3 eqmod.modifierAsValue := SOME(val);
1762 3 outMod.binding := SOME(eqmod);
1763 // Remove all submodifier bindings, they have been merged into the
1764 // record binding.
1765 3 outMod.subModLst := stripSubModBindings(inModInner.subModLst);
1766 then
1767 outMod;
1768
1769 // The outer modifier consists of submodifiers, while the inner has a record binding.
1770 case (DAE.MOD(binding = NONE(), subModLst = submods as _ :: _),
1771 DAE.MOD(binding = SOME(eqmod as DAE.TYPED(modifierAsValue =
1772 SOME(val as Values.RECORD()))), subModLst = {}))
1773 algorithm
1774 ✗ names := val.comp;
1775 vals := {};
1776
1777 ✗ for v in val.orderd loop
1778 ✗ name :: names := names;
1779
1780 // For each component in the record, check if we have a submodifier
1781 // for it. In that case, use the value from the submodifier instead.
1782 try
1783 ✗ (submods, SOME(submod)) := List.deleteMemberOnTrue(name, submods, isSubModNamed);
1784 ✗ v := subModValue(submod);
1785 else
1786 end try;
1787
1788 vals := v :: vals;
1789 end for;
1790
1791 ✗ val.orderd := listReverse(vals);
1792 ✗ eqmod.modifierAsValue := SOME(val);
1793 ✗ outMod.binding := SOME(eqmod);
1794 // Remove all submodifier bindings, they have been merged into the
1795 // record binding.
1796 ✗ outMod.subModLst := stripSubModBindings(outMod.subModLst);
1797 then
1798 outMod;
1799
1800 case (DAE.MOD(), DAE.MOD())
1801 algorithm
1802 468223 outMod.subModLst := mergeSubs(outMod.subModLst, inModInner.subModLst, inCheckFinal);
1803 468220 outMod.binding := mergeEq(outMod.binding, inModInner.binding);
1804 then
1805 outMod;
1806
1807 end match;
1808 end doMerge;
1809
1810 protected function mergeSubs
1811 input list<DAE.SubMod> inSubMods1;
1812 input list<DAE.SubMod> inSubMods2;
1813 input Boolean inCheckFinal;
1814 output list<DAE.SubMod> outSubMods = {};
1815 protected
1816 list<DAE.SubMod> submods2;
1817 String name;
1818 DAE.Mod m1, m2;
1819 Option<DAE.SubMod> osm2;
1820 DAE.SubMod sm2;
1821 algorithm
1822
2/2
✓ Branch 0 taken 94371 times.
✓ Branch 1 taken 373852 times.
468223 if listEmpty(inSubMods1) then
1823 outSubMods := inSubMods2;
1824 elseif listEmpty(inSubMods2) then
1825 outSubMods := inSubMods1;
1826 else
1827 submods2 := inSubMods2;
1828
2/2
✓ Branch 1 taken 289677 times.
✓ Branch 2 taken 83927 times.
373604 for sm1 in inSubMods1 loop
1829 289677 (submods2, osm2) :=
1830 List.deleteMemberOnTrue(subModName(sm1), submods2, subModIsNamed);
1831
1832
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 289677 times.
✓ Branch 2 taken 142586 times.
✓ Branch 3 taken 147091 times.
289677 if isSome(osm2) then
1833 142586 SOME(sm2) := osm2;
1834 142586 DAE.NAMEMOD(ident = name, mod = m1) := sm1;
1835 142586 DAE.NAMEMOD(mod = m2) := sm2;
1836 142586 m1 := merge(m1, m2, name, inCheckFinal);
1837 142583 sm1 := DAE.NAMEMOD(name, m1);
1838 end if;
1839
1840 outSubMods := sm1 :: outSubMods;
1841 end for;
1842
1843 83927 outSubMods := List.append_reverse(outSubMods, submods2);
1844 end if;
1845 end mergeSubs;
1846
1847 protected function mergeEq
1848 "The outer modification, given in the first argument, takes precedence over
1849 the inner modifications."
1850 input Option<DAE.EqMod> inOuterEq;
1851 input Option<DAE.EqMod> inInnerEq;
1852 output Option<DAE.EqMod> outEqMod = if isSome(inOuterEq) then inOuterEq else inInnerEq;
1853 end mergeEq;
1854
1855 public function modEquation "This function simply extracts the equation part of a modification."
1856 input DAE.Mod inMod;
1857 output Option<DAE.EqMod> outEqMod;
1858 algorithm
1859 outEqMod := match inMod
1860 case DAE.NOMOD() then NONE();
1861 case DAE.REDECL() then NONE();
1862 1085104 case DAE.MOD() then inMod.binding;
1863 end match;
1864 end modEquation;
1865
1866 protected function modSubsetOrEqualOrNonOverlap "
1867 same as modEqual with the difference that we allow:
1868 outer(input arg1: mod1) - modifier to be a subset of
1869 inner(input arg2: mod2) - modifier,
1870 IF the subset is cotained in mod2 and those subset matches are equal
1871 or if outer(expr=NONE()) with inner(expr=(SOME))"
1872 input DAE.Mod mod1;
1873 input DAE.Mod mod2;
1874 output Boolean equal;
1875 algorithm
1876 equal := match(mod1,mod2)
1877 local
1878 SCode.Final f1,f2;
1879 SCode.Each each1,each2;
1880 list<DAE.SubMod> submods1,submods2;
1881 Option<DAE.EqMod> eqmod1,eqmod2;
1882
1883 // adrpo: handle non-overlap: final parameter Real eAxis_ia[3](each final unit="1") = {1,2,3};
1884 // mod1 = final each unit="1" mod2 = final = {1,2,3}
1885 // otherwise we get an error as: Error: Variable eAxis_ia: trying to override final variable ...
1886 case(DAE.MOD(f1,_,_,NONE(),_),DAE.MOD(f2,SCode.NOT_EACH(),{},SOME(_),_)) guard SCodeUtil.finalEqual(f1, f2)
1887 then
1888 true;
1889
1890 case(DAE.MOD(binding = eqmod1),DAE.MOD(_,SCode.NOT_EACH(),{},eqmod2,_)) guard eqModSubsetOrEqual(eqmod1,eqmod2)
1891 then
1892 true;
1893
1894 // handle subset equal
1895 case(DAE.MOD(f1,each1,submods1,eqmod1,_),DAE.MOD(f2,each2,submods2,eqmod2,_)) guard SCodeUtil.finalEqual(f1, f2) and SCodeUtil.eachEqual(each1,each2) and subModsEqual(submods1,submods2) and eqModSubsetOrEqual(eqmod1,eqmod2)
1896 then
1897 true;
1898
1899 // two exactly the same mod, return just one! (used when it is REDECL or a submod is REDECL)
1900 case(DAE.REDECL(f1, each1),DAE.REDECL(f2, each2)) guard SCodeUtil.finalEqual(f1, f2) and SCodeUtil.eachEqual(each1, each2) and SCodeUtil.elementEqual(mod1.element, mod2.element)
1901 then
1902 true;
1903
1904 case(DAE.NOMOD(),DAE.NOMOD()) then true;
1905
1906 else false;
1907
1908 end match;
1909 end modSubsetOrEqualOrNonOverlap;
1910
1911 protected function eqModSubsetOrEqual "
1912 Returns true if two EqMods are equal or outer(input arg1) is NONE"
1913 input Option<DAE.EqMod> eqMod1;
1914 input Option<DAE.EqMod> eqMod2;
1915 output Boolean equal;
1916 algorithm
1917 equal := matchcontinue(eqMod1,eqMod2)
1918 local
1919 Absyn.Exp aexp1,aexp2;
1920 // no mods
1921 case(NONE(),NONE()) then true;
1922
1923 // none vs. some (subset) mods
1924 case(NONE(),SOME(_)) then true;
1925
1926 // typed mods
1927 case(SOME(DAE.TYPED()),SOME(DAE.TYPED()))
1928 algorithm
1929 ✗ true := eqModEqual(eqMod1,eqMod2);
1930 then
1931 true;
1932
1933 // typed vs. untyped mods
1934 case(SOME(DAE.TYPED(modifierAsAbsynExp=aexp1)),SOME(DAE.UNTYPED(exp=aexp2)))
1935 algorithm
1936 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
1937 then
1938 true;
1939
1940 // untyped vs. typed
1941 case(SOME(DAE.UNTYPED(exp=aexp1)),SOME(DAE.TYPED(modifierAsAbsynExp=aexp2)))
1942 algorithm
1943 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
1944 then
1945 true;
1946
1947 // untyped mods
1948 case(SOME(DAE.UNTYPED(exp=aexp1)),SOME(DAE.UNTYPED(exp=aexp2)))
1949 algorithm
1950 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
1951 then
1952 true;
1953
1954 // anything else gives false
1955 else false;
1956 end matchcontinue;
1957 end eqModSubsetOrEqual;
1958
1959 protected function subModsSubsetOrEqual "
1960 Returns true if two submod lists are equal. Or all of the elements in subModLst1 have equalities in subModLst2.
1961 if subModLst2 then contain more elements is not a mather."
1962 input list<DAE.SubMod> subModLst1;
1963 input list<DAE.SubMod> subModLst2;
1964 output Boolean equal;
1965 algorithm
1966 equal := matchcontinue(subModLst1,subModLst2)
1967 local DAE.Ident id1,id2;
1968 DAE.Mod mod1,mod2;
1969 list<DAE.SubMod> rest1,rest2;
1970
1971 case ({},{}) then true;
1972
1973 case (DAE.NAMEMOD(id1,mod1)::rest1,DAE.NAMEMOD(id2,mod2)::rest2)
1974 algorithm
1975 ✗ true := stringEq(id1,id2);
1976 ✗ true := modEqual(mod1,mod2);
1977 ✗ true := subModsEqual(rest1,rest2);
1978 then
1979 true;
1980
1981 // otherwise false
1982 else false;
1983 end matchcontinue;
1984 end subModsSubsetOrEqual;
1985
1986 public function modEqual "
1987 Compares two DAE.Mod, returns true if equal"
1988 input DAE.Mod mod1;
1989 input DAE.Mod mod2;
1990 output Boolean equal;
1991 algorithm
1992 equal := match (mod1, mod2)
1993 case (DAE.MOD(), DAE.MOD())
1994 ✗ then SCodeUtil.finalEqual(mod1.finalPrefix, mod2.finalPrefix) and
1995 SCodeUtil.eachEqual(mod1.eachPrefix, mod2.eachPrefix) and
1996 List.isEqualOnTrue(mod1.subModLst, mod2.subModLst, subModEqual) and
1997 eqModEqual(mod1.binding, mod2.binding);
1998
1999 case (DAE.REDECL(), DAE.REDECL())
2000 ✗ then SCodeUtil.finalEqual(mod1.finalPrefix, mod2.finalPrefix) and
2001 SCodeUtil.eachEqual(mod1.eachPrefix, mod2.eachPrefix) and
2002 SCodeUtil.elementEqual(mod1.element, mod2.element);
2003
2004 case (DAE.NOMOD(), DAE.NOMOD()) then true;
2005 else false;
2006 end match;
2007 end modEqual;
2008
2009 protected function subModsEqual "Returns true if two submod lists are equal."
2010 input list<DAE.SubMod> inSubModLst1;
2011 input list<DAE.SubMod> inSubModLst2;
2012 output Boolean equal;
2013 algorithm
2014 equal := matchcontinue(inSubModLst1,inSubModLst2)
2015 local
2016 DAE.Ident id1,id2;
2017 DAE.Mod mod1,mod2;
2018 list<DAE.SubMod> subModLst1, subModLst2;
2019
2020
2021 case ({},{}) then true;
2022
2023 case (DAE.NAMEMOD(id1,mod1)::subModLst1,DAE.NAMEMOD(id2,mod2)::subModLst2)
2024 algorithm
2025 ✗ true := stringEq(id1,id2);
2026 ✗ true := modEqual(mod1,mod2);
2027 ✗ true := subModsEqual(subModLst1,subModLst2);
2028 then
2029 true;
2030
2031 // otherwise false
2032 else false;
2033
2034 end matchcontinue;
2035 end subModsEqual;
2036
2037 public function subModEqual "Returns true if two submod are equal."
2038 input DAE.SubMod subMod1;
2039 input DAE.SubMod subMod2;
2040 output Boolean equal;
2041 algorithm
2042 equal := match(subMod1,subMod2)
2043 local
2044 DAE.Ident id1,id2;
2045 DAE.Mod mod1,mod2;
2046
2047 case (DAE.NAMEMOD(id1,mod1),DAE.NAMEMOD(id2,mod2)) guard stringEq(id1,id2) and modEqual(mod1,mod2)
2048 then
2049 true;
2050
2051 // otherwise false
2052 else false;
2053 end match;
2054 end subModEqual;
2055
2056 protected function valEqual
2057 input Option<Values.Value> inV1;
2058 input Option<Values.Value> inV2;
2059 input Boolean equal;
2060 output Boolean bEq;
2061 algorithm
2062 bEq := match(inV1, inV2, equal)
2063 local Values.Value v1, v2;
2064 case (_, _, true) then true;
2065 case (NONE(), NONE(), _) then equal;
2066 case (SOME(v1), SOME(v2), false)
2067 algorithm
2068 ✗ bEq := ExpressionBasics.expEqual(
2069 ValuesUtil.valueExp(v1),
2070 ValuesUtil.valueExp(v2));
2071 then
2072 bEq;
2073 end match;
2074 end valEqual;
2075
2076 protected function eqModEqual "Returns true if two EqMods are equal"
2077 input Option<DAE.EqMod> eqMod1;
2078 input Option<DAE.EqMod> eqMod2;
2079 output Boolean equal;
2080 algorithm
2081 equal := matchcontinue(eqMod1,eqMod2)
2082 local
2083 Absyn.Exp aexp1,aexp2;
2084 DAE.Exp exp1,exp2;
2085 Option<Values.Value> v1, v2;
2086
2087 // no equ mods
2088 case(NONE(),NONE()) then true;
2089
2090 // typed equmods
2091 case(SOME(DAE.TYPED(modifierAsExp = exp1, modifierAsValue = v1)),
2092 SOME(DAE.TYPED(modifierAsExp = exp2, modifierAsValue = v2)))
2093 algorithm
2094 ✗ equal := ExpressionBasics.expEqual(exp1,exp2);
2095 // check the values as crefs might have been replaced!
2096 ✗ true := valEqual(v1, v2, equal);
2097 then
2098 true;
2099
2100 // typed vs. untyped equmods
2101 case(SOME(DAE.TYPED(modifierAsAbsynExp=aexp1)),SOME(DAE.UNTYPED(exp=aexp2)))
2102 algorithm
2103 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
2104 then
2105 true;
2106
2107 // untyped vs. typed equmods
2108 case(SOME(DAE.UNTYPED(exp=aexp1)),SOME(DAE.TYPED(modifierAsAbsynExp=aexp2)))
2109 algorithm
2110 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
2111 then
2112 true;
2113
2114 // untyped equmods
2115 case(SOME(DAE.UNTYPED(exp=aexp1)),SOME(DAE.UNTYPED(exp=aexp2)))
2116 algorithm
2117 ✗ true := AbsynUtil.expEqual(aexp1,aexp2);
2118 then
2119 true;
2120
2121 // anything else will give false
2122 else false;
2123
2124 end matchcontinue;
2125 end eqModEqual;
2126
2127 public function printModStr
2128 "This function prints a modification.
2129 It uses a few other function to do its stuff."
2130 input DAE.Mod inMod;
2131 output String outString;
2132 algorithm
2133 outString := matchcontinue inMod
2134 local
2135 String prefix,str,res,s1_1,s2;
2136 list<String> s1;
2137 SCode.Final finalPrefix;
2138 SCode.Each eachPrefix;
2139 list<DAE.SubMod> subs;
2140 Option<DAE.EqMod> eq;
2141
2142 case DAE.NOMOD() then "()";
2143
2144 case DAE.REDECL(finalPrefix = finalPrefix,eachPrefix = eachPrefix)
2145 algorithm
2146 ✗ prefix := SCodeDump.finalStr(finalPrefix) + SCodeDump.eachStr(eachPrefix);
2147 ✗ str := SCodeDump.unparseElementStr(inMod.element);
2148 ✗ res := stringAppendList({"(",prefix,str,")"});
2149 then
2150 res;
2151
2152 case DAE.MOD(finalPrefix = finalPrefix,eachPrefix = eachPrefix,subModLst =
2153 subs,binding = eq)
2154 algorithm
2155 ✗ prefix := SCodeDump.finalStr(finalPrefix) + SCodeDump.eachStr(eachPrefix);
2156 ✗ s1 := printSubs1Str(subs);
2157 ✗ s1_1 := stringDelimitList(s1, ", ");
2158 ✗ s1_1 := if not listEmpty(subs) then " {" + s1_1 + "} " else s1_1;
2159 ✗ s2 := printEqmodStr(eq);
2160 ✗ str := stringAppendList({prefix,s1_1,s2});
2161 then
2162 str;
2163
2164 ✗ else algorithm print(" failure in printModStr \n"); then fail();
2165
2166 end matchcontinue;
2167 end printModStr;
2168
2169 public function printMod "Print a modifier on the Print buffer."
2170 input DAE.Mod m;
2171 protected
2172 String str;
2173 algorithm
2174 ✗ str := printModStr(m);
2175 ✗ Print.printBuf(str);
2176 end printMod;
2177
2178 public function prettyPrintMod "
2179 Author BZ, 2009-07
2180 Prints a readable format of a modifier."
2181 input DAE.Mod m;
2182 input Integer depth;
2183 output String str;
2184 algorithm
2185 str := matchcontinue m
2186 local
2187 list<DAE.SubMod> subs;
2188 SCode.Final fp;
2189 DAE.EqMod eq;
2190
2191 case DAE.MOD(subModLst = subs, binding=NONE())
2192 5 then prettyPrintSubs(subs,depth);
2193
2194 case DAE.MOD(finalPrefix = fp, binding=SOME(eq))
2195
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
8 then (if SCodeUtil.finalBool(fp) then "final " else "") + " = " + TypesDump.unparseEqMod(eq);
2196
2197 case DAE.REDECL()
2198 14 then SCodeDump.unparseElementStr(m.element);
2199
2200 case DAE.NOMOD() then "";
2201
2202 else
2203 algorithm
2204 ✗ print(" failed prettyPrintMod\n");
2205 ✗ then
2206 fail();
2207
2208 end matchcontinue;
2209 end prettyPrintMod;
2210
2211 protected function prettyPrintSubs "
2212 Author BZ
2213 Helper function for prettyPrintMod"
2214 input list<DAE.SubMod> inSubs;
2215 input Integer depth;
2216 output String str;
2217 algorithm
2218 str := match inSubs
2219 local
2220 String s2,id;
2221 DAE.Mod m;
2222
2223 case {} then "";
2224 case (DAE.NAMEMOD(id,(DAE.REDECL())))::_
2225 algorithm
2226 ✗ s2 := " redeclare(" + id + "), class or component " + id;
2227 then
2228 s2;
2229 case (DAE.NAMEMOD(id,m))::_
2230 algorithm
2231 5 s2 := prettyPrintMod(m,depth+1);
2232 5 s2 := "(" + id + s2 + "), class or component " + id;
2233 then
2234 s2;
2235 end match;
2236 end prettyPrintSubs;
2237
2238 public function prettyPrintSubmod "
2239 Prints a readable format of a sub-modifier, used in error reporting for built-in classes"
2240 input DAE.SubMod inSub;
2241 output String str;
2242 algorithm
2243 str := match inSub
2244 local
2245 String s1,s2,id;
2246 DAE.Mod m;
2247
2248 case DAE.NAMEMOD(id, m as DAE.REDECL())
2249 algorithm
2250 ✗ s1 := SCodeDump.unparseElementStr(m.element);
2251 ✗ s2 := id + "(redeclare " +
2252 (if SCodeUtil.eachBool(m.eachPrefix) then "each " else "") +
2253 (if SCodeUtil.finalBool(m.finalPrefix) then "final " else "") + s1 + ")";
2254 then
2255 s2;
2256
2257 case DAE.NAMEMOD(id,m)
2258 algorithm
2259 ✗ s2 := prettyPrintMod(m,0);
2260 ✗ s2 := id + s2;
2261 then
2262 s2;
2263
2264 end match;
2265 end prettyPrintSubmod;
2266
2267 public function printSubs1Str "Helper function to printModStr"
2268 input list<DAE.SubMod> inTypesSubModLst;
2269 output list<String> outStringLst;
2270 algorithm
2271 outStringLst:=
2272 match inTypesSubModLst
2273 local
2274 String s1;
2275 list<String> res;
2276 DAE.SubMod x;
2277 list<DAE.SubMod> xs;
2278 case {} then {};
2279 case x :: xs
2280 algorithm
2281 ✗ s1 := printSubStr(x);
2282 ✗ res := printSubs1Str(xs);
2283 then
2284 (s1 :: res);
2285 end match;
2286 end printSubs1Str;
2287
2288 protected function printSubStr "Helper function to printSubs1Str"
2289 input DAE.SubMod inSubMod;
2290 output String outString;
2291 algorithm
2292 outString := match inSubMod
2293 local
2294 String mod_str,res,n;
2295 DAE.Mod mod;
2296 case DAE.NAMEMOD(ident = n,mod = mod)
2297 algorithm
2298 ✗ mod_str := printModStr(mod);
2299 ✗ res := stringAppend(n + " ", mod_str);
2300 then
2301 res;
2302 end match;
2303 end printSubStr;
2304
2305 protected function printEqmodStr
2306 "Helper function to printModStr"
2307 input Option<DAE.EqMod> inTypesEqModOption;
2308 output String outString;
2309 algorithm
2310 outString := matchcontinue inTypesEqModOption
2311 local
2312 String str,str2,e_val_str,res;
2313 DAE.Exp e;
2314 Values.Value e_val;
2315 DAE.Properties prop;
2316 Absyn.Exp ae;
2317
2318 case NONE() then "";
2319
2320 case SOME(DAE.TYPED(e,SOME(e_val),prop,_))
2321 algorithm
2322 ✗ str := ExpressionBasics.printExpStr(e);
2323 ✗ str2 := Types.printPropStr(prop);
2324 ✗ e_val_str := ValuesDump.valString(e_val);
2325 ✗ res := stringAppendList({" = (typed)",str," ",str2,", value: ",e_val_str});
2326 then
2327 res;
2328
2329 case SOME(DAE.TYPED(e,NONE(),prop,_))
2330 algorithm
2331 ✗ str := ExpressionBasics.printExpStr(e);
2332 ✗ str2 := Types.printPropStr(prop);
2333 ✗ res := stringAppendList({" = (typed)",str, ", type:\n", str2});
2334 then
2335 res;
2336
2337 case SOME(DAE.UNTYPED(exp=ae))
2338 algorithm
2339 ✗ str := Dump.printExpStr(ae);
2340 ✗ res := stringAppend(" =(untyped) ", str);
2341 then
2342 res;
2343
2344 else
2345 algorithm
2346 res := "---Mod.printEqmodStr FAILED---";
2347 then
2348 res;
2349 end matchcontinue;
2350 end printEqmodStr;
2351
2352 public function renameTopLevelNamedSubMod
2353 input DAE.Mod mod;
2354 input String oldIdent;
2355 input String newIdent;
2356 output DAE.Mod outMod = mod;
2357 algorithm
2358 outMod := match outMod
2359 case DAE.MOD()
2360 algorithm
2361
4/4
✓ Branch 0 taken 204601 times.
✓ Branch 1 taken 10063 times.
✓ Branch 2 taken 204601 times.
✓ Branch 3 taken 10063 times.
224727 outMod.subModLst := list(renameNamedSubMod(s, oldIdent, newIdent) for s in outMod.subModLst);
2362 then
2363 outMod;
2364
2365 else mod;
2366
2367 end match;
2368 end renameTopLevelNamedSubMod;
2369
2370 public function renameNamedSubMod
2371 input DAE.SubMod submod;
2372 input String oldIdent;
2373 input String newIdent;
2374 output DAE.SubMod outMod;
2375 algorithm
2376 outMod := match submod
2377 local
2378 DAE.Mod mod;
2379 String id;
2380 case DAE.NAMEMOD(id,mod) guard stringEq(id,oldIdent)
2381 ✗ then DAE.NAMEMOD(newIdent,mod);
2382 else submod;
2383 end match;
2384 end renameNamedSubMod;
2385
2386 public function emptyModOrEquality
2387 input DAE.Mod mod;
2388 output Boolean b;
2389 algorithm
2390 b := match mod
2391 case DAE.NOMOD() then true;
2392 case DAE.MOD(subModLst={}) then true;
2393 else false;
2394 end match;
2395 end emptyModOrEquality;
2396
2397 protected function intStringDot
2398 input Integer i;
2399 output String str;
2400 algorithm
2401 ✗ str := intString(i) + ".";
2402 end intStringDot;
2403
2404 protected function isPrefixOf
2405 input tuple<String, DAE.SubMod> indexSubMod;
2406 input String idx;
2407 output Boolean isPrefix;
2408 algorithm
2409 isPrefix := matchcontinue indexSubMod
2410 local
2411 String i;
2412 Integer len1, len2;
2413
2414 case (i, _)
2415 algorithm
2416 ✗ len1 := stringLength(i);
2417 ✗ len2 := stringLength(idx);
2418 // either one of them is a substring of the other
2419 ✗ true := (0 == System.strncmp(i, idx, intMin(len1, len2)));
2420 then true;
2421 else false;
2422 end matchcontinue;
2423 end isPrefixOf;
2424
2425 protected function getFullModsFromMod
2426 "@author: adrpo
2427 This function will create fully qualified crefs from
2428 modifications. See also getFullModsFromSubMods.
2429 Examples:
2430 x(start=1, stateSelect=s) => x.start, x.stateSelect
2431 (x.start=1, x.stateSelect=s) => x.start, x.stateSelect
2432 x([2] = 1, start = 2) => x[2], x.start"
2433 input DAE.ComponentRef inTopCref;
2434 input DAE.Mod inMod;
2435 output list<FullMod> outFullMods;
2436 algorithm
2437 outFullMods := match inMod
2438 // DAE.NOMOD empty case, no more dive in
2439 case DAE.NOMOD() then {};
2440
2441 // DAE.MOD
2442 case DAE.MOD()
2443 ✗ then getFullModsFromSubMods(inTopCref, inMod.subModLst);
2444
2445 // DAE.REDECL
2446 case DAE.REDECL()
2447 ✗ then {getFullModFromModRedeclare(inTopCref, inMod)};
2448
2449 end match;
2450 end getFullModsFromMod;
2451
2452 protected function getFullModFromModRedeclare
2453 "@author: adrpo
2454 This function will create fully qualified
2455 crefs from the redeclaration lists for redeclare mod.
2456 See also getFullModsFromMod, getFullModsFromSubMod
2457 Examples:
2458 x(redeclare package P = P, redeclare class C = C) => x.P, x.C"
2459 input DAE.ComponentRef inTopCref;
2460 input DAE.Mod inRedeclare;
2461 output FullMod outFullMod;
2462 protected
2463 SCode.Element el;
2464 DAE.Ident id;
2465 DAE.ComponentRef cref;
2466 algorithm
2467 ✗ DAE.REDECL(element = el) := inRedeclare;
2468 ✗ id := SCodeUtil.elementName(el);
2469 ✗ cref := ComponentReferenceBasics.makeCrefIdent(id, DAE.T_UNKNOWN_DEFAULT, {});
2470 ✗ cref := ComponentReference.joinCrefs(inTopCref, cref);
2471 ✗ outFullMod := MOD(cref, inRedeclare);
2472 end getFullModFromModRedeclare;
2473
2474 protected function getFullModsFromSubMods
2475 "@author: adrpo
2476 This function will create fully qualified crefs from
2477 sub modifications. See also getFullModsFromMod.
2478 Examples:
2479 x(start=1, stateSelect=s) => x.start, x.stateSelect
2480 (x.start=1, x.stateSelect=s) => x.start, x.stateSelect
2481 x([2] = 1, start = 2) => x[2], x.start"
2482 input DAE.ComponentRef inTopCref;
2483 input list<DAE.SubMod> inSubMods;
2484 output list<FullMod> outFullMods;
2485 algorithm
2486 outFullMods := match inSubMods
2487 local
2488 list<FullMod> fullMods1, fullMods2, fullMods;
2489 list<DAE.SubMod> rest;
2490 DAE.SubMod subMod;
2491 DAE.Ident id;
2492 DAE.Mod mod;
2493 DAE.ComponentRef cref;
2494
2495 // empty case
2496 case {} then {};
2497
2498 // named modifier, only add LEAFS to the list!
2499 case (subMod as DAE.NAMEMOD(id, mod))::rest
2500 algorithm
2501 ✗ cref := ComponentReference.joinCrefs(
2502 inTopCref,
2503 ComponentReferenceBasics.makeCrefIdent(
2504 id, DAE.T_UNKNOWN_DEFAULT, {}));
2505 ✗ fullMods1 := getFullModsFromMod(cref, mod);
2506 ✗ fullMods2 := getFullModsFromSubMods(inTopCref, rest);
2507 ✗ fullMods := listAppend(
2508 if listEmpty(fullMods1)
2509 then SUB_MOD(cref, subMod)::fullMods1 // add if LEAF
2510 else fullMods1,
2511 fullMods2);
2512 then
2513 fullMods;
2514
2515 end match;
2516 end getFullModsFromSubMods;
2517
2518 protected function fullModCrefsEqual
2519 "@author: adrpo
2520 This function checks if the crefs of the given full mods are equal"
2521 input FullMod inFullMod1;
2522 input FullMod inFullMod2;
2523 output Boolean isEqual;
2524 algorithm
2525 isEqual := match(inFullMod1, inFullMod2)
2526 local DAE.ComponentRef cr1, cr2;
2527 ✗ case (MOD(cr1, _), MOD(cr2, _)) then ComponentReferenceBasics.crefEqualNoStringCompare(cr1, cr2);
2528 ✗ case (SUB_MOD(cr1, _), SUB_MOD(cr2, _)) then ComponentReferenceBasics.crefEqualNoStringCompare(cr1, cr2);
2529 ✗ case (MOD(cr1, _), SUB_MOD(cr2, _)) then ComponentReferenceBasics.crefEqualNoStringCompare(cr1, cr2);
2530 ✗ case (SUB_MOD(cr1, _), MOD(cr2, _)) then ComponentReferenceBasics.crefEqualNoStringCompare(cr1, cr2);
2531 end match;
2532 end fullModCrefsEqual;
2533
2534 protected function prettyPrintFullMod
2535 "@author: adrpo
2536 This function checks if the crefs of the given full mods are equal"
2537 input FullMod inFullMod;
2538 input Integer inDepth;
2539 output String outStr;
2540 algorithm
2541 outStr := match inFullMod
2542 local
2543 DAE.Mod mod;
2544 DAE.SubMod subMod;
2545 DAE.ComponentRef cr;
2546 String str;
2547
2548 case MOD(cr, mod)
2549 algorithm
2550 ✗ str := ComponentReferenceBasics.printComponentRefStr(cr) + ": " + prettyPrintMod(mod, inDepth);
2551 then
2552 str;
2553
2554 case SUB_MOD(cr, subMod)
2555 algorithm
2556 ✗ str := ComponentReferenceBasics.printComponentRefStr(cr) + ": " + prettyPrintSubmod(subMod);
2557 then
2558 str;
2559
2560 end match;
2561 end prettyPrintFullMod;
2562
2563 public function getUnelabedSubMod
2564 input SCode.Mod inMod;
2565 input SCode.Ident inIdent;
2566 output SCode.Mod outSubMod;
2567 protected
2568 list<SCode.SubMod> submods;
2569 algorithm
2570
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3287 times.
3287 SCode.MOD(subModLst = submods) := inMod;
2571 3287 outSubMod := getUnelabedSubMod2(submods, inIdent);
2572 end getUnelabedSubMod;
2573
2574 protected function getUnelabedSubMod2
2575 input list<SCode.SubMod> inSubMods;
2576 input SCode.Ident inIdent;
2577 output SCode.Mod outMod;
2578 algorithm
2579 outMod := match inSubMods
2580 local
2581 SCode.Ident id;
2582 SCode.Mod m;
2583 list<SCode.SubMod> rest_mods;
2584
2585 case SCode.NAMEMOD(ident = id, mod = m) :: _ guard stringEqual(id, inIdent)
2586 then
2587 m;
2588
2589 case _ :: rest_mods
2590 3882 then getUnelabedSubMod2(rest_mods, inIdent);
2591
2592 end match;
2593 end getUnelabedSubMod2;
2594
2595 public function isUntypedMod
2596 "Returns true if a modifier contains any untyped parts, otherwise false."
2597 input DAE.Mod inMod;
2598 output Boolean outIsUntyped;
2599 algorithm
2600 outIsUntyped := match inMod
2601 case DAE.MOD(binding = SOME(DAE.UNTYPED())) then true;
2602 28017 case DAE.MOD() then List.any(inMod.subModLst, isUntypedSubMod);
2603 end match;
2604 end isUntypedMod;
2605
2606 protected function isUntypedSubMod
2607 "Returns true if a submodifier contains any untyped parts, otherwise false."
2608 input DAE.SubMod inSubMod;
2609 output Boolean outIsUntyped = isUntypedMod(inSubMod.mod);
2610 end isUntypedSubMod;
2611
2612 public function getUntypedCrefs
2613 input DAE.Mod inMod;
2614 output list<Absyn.ComponentRef> outCrefs;
2615 algorithm
2616 outCrefs := matchcontinue inMod
2617 local
2618 Absyn.Exp exp;
2619 list<Absyn.ComponentRef> crefs;
2620 list<DAE.SubMod> submods;
2621
2622 case DAE.MOD(binding = SOME(DAE.UNTYPED(exp = exp)))
2623 algorithm
2624 6825 crefs := AbsynUtil.getCrefFromExp(exp, true, true);
2625 then
2626 crefs;
2627
2628 case DAE.MOD(subModLst = submods)
2629 algorithm
2630 22122 crefs := List.fold(submods, getUntypedCrefFromSubMod, {});
2631 then
2632 crefs;
2633
2634 else {};
2635 end matchcontinue;
2636 end getUntypedCrefs;
2637
2638 protected function getUntypedCrefFromSubMod
2639 input DAE.SubMod inSubMod;
2640 input list<Absyn.ComponentRef> inCrefs;
2641 output list<Absyn.ComponentRef> outCrefs;
2642 algorithm
2643 outCrefs := match inSubMod
2644 local
2645 DAE.Mod mod;
2646 list<Absyn.ComponentRef> crefs;
2647
2648 case DAE.NAMEMOD(mod = mod)
2649 algorithm
2650 760 crefs := getUntypedCrefs(mod);
2651 760 then
2652 listAppend(crefs, inCrefs);
2653
2654 end match;
2655 end getUntypedCrefFromSubMod;
2656
2657 // moved from Types!
2658 public function stripSubmod
2659 "author: PA
2660 Removes the sub modifiers of a modifier."
2661 input DAE.Mod inMod;
2662 output DAE.Mod outMod = inMod;
2663 algorithm
2664 outMod := match outMod
2665 case DAE.MOD()
2666 algorithm
2667 2 outMod.subModLst := {};
2668 then
2669 outMod;
2670
2671 else outMod;
2672 end match;
2673 end stripSubmod;
2674
2675 public function removeFirstSubsRedecl "
2676 Author: BZ, 2009-08
2677 Removed REDECLARE() statements at first level of SubMods"
2678 input DAE.Mod inMod;
2679 output DAE.Mod outMod;
2680 algorithm
2681 outMod := matchcontinue inMod
2682 local
2683 SCode.Final f;
2684 SCode.Each each_;
2685 list<SubMod> subs;
2686 Option<EqMod> eq;
2687 DAE.Mod m;
2688 SourceInfo info;
2689
2690 case DAE.MOD(finalPrefix = f,eachPrefix = each_,subModLst = {},binding = eq,info=info)
2691 2153 then DAE.MOD(f,each_,{},eq,info);
2692 case DAE.MOD(subModLst = subs,binding = NONE())
2693 algorithm
2694
2/2
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 12 times.
46 {} := removeRedecl(subs);
2695 then
2696 DAE.NOMOD();
2697 case DAE.MOD(finalPrefix = f,eachPrefix = each_,subModLst = subs,binding = eq,info=info)
2698 algorithm
2699 1885 subs := removeRedecl(subs);
2700 1885 then
2701 DAE.MOD(f,each_,subs,eq,info);
2702 case m then m;
2703 end matchcontinue;
2704 end removeFirstSubsRedecl;
2705
2706 protected function removeRedecl "
2707 Author BZ
2708 helper function for removeFirstSubsRedecl"
2709 input list<SubMod> isubs;
2710 output list<SubMod> osubs;
2711 algorithm
2712 osubs := match isubs
2713 local
2714 SubMod sm;
2715 list<SubMod> subs;
2716
2717 case {} then {};
2718 13 case DAE.NAMEMOD(_,DAE.REDECL())::subs then removeRedecl(subs);
2719 case sm::subs
2720 algorithm
2721 2639 osubs := removeRedecl(subs);
2722 then
2723 sm::osubs;
2724 end match;
2725 end removeRedecl;
2726
2727 public function removeModList "
2728 Author BZ, 2009-07
2729 Delete a list of named modifiers"
2730 input DAE.Mod inMod;
2731 input list<String> remStrings;
2732 output DAE.Mod outMod;
2733 protected
2734 String s;
2735 algorithm
2736 outMod := match remStrings
2737 local
2738 case {} then inMod;
2739 case s::_
2740 ✗ then removeModList(removeMod(inMod,s),remStrings);
2741 end match;
2742 end removeModList;
2743
2744 public function removeMod "
2745 Author: BZ, 2009-05
2746 Remove a modifier(/s) on a specified component."
2747 input DAE.Mod inMod;
2748 input String componentModified;
2749 output DAE.Mod outMod;
2750 algorithm
2751 outMod := match inMod
2752 local
2753 SCode.Final f;
2754 SCode.Each e;
2755 list<SubMod> subs;
2756 Option<EqMod> oem;
2757 SourceInfo info;
2758
2759 case DAE.NOMOD() then DAE.NOMOD();
2760
2761 case DAE.REDECL()
2762
4/4
✓ Branch 1 taken 34 times.
✓ Branch 2 taken 87 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 27 times.
121 then if SCodeUtil.elementName(inMod.element) == componentModified then DAE.NOMOD() else inMod;
2763
2764 case DAE.MOD(f,e,subs,oem,info)
2765 algorithm
2766 //fprint(Flags.REDECL,"Removing redeclare mods: " + componentModified +" before" + Mod.printModStr(inmod) + "\n");
2767 84529 subs := removeModInSubs(subs,componentModified);
2768 84529 outMod := DAE.MOD(f,e,subs,oem,info);
2769 //fprint(Flags.REDECL,"Removing redeclare mods: " + componentModified +" after" + Mod.printModStr(outmod) + "\n");
2770 then
2771 outMod;
2772 end match;
2773 end removeMod;
2774
2775 protected function removeModInSubs "
2776 Author BZ, 2009-05
2777 Helper function for removeMod, removes modifiers in submods;
2778 "
2779 input list<SubMod> inSubs;
2780 input String componentName;
2781 output list<SubMod> outsubs;
2782 algorithm
2783 outsubs := match inSubs
2784 local
2785 DAE.Mod m1;
2786 list<SubMod> subs1,subs2,subs;
2787 String s1;
2788
2789 case {} then {};
2790 case (DAE.NAMEMOD(s1,m1))::subs
2791 algorithm
2792
4/4
✓ Branch 0 taken 134569 times.
✓ Branch 1 taken 305833 times.
✓ Branch 3 taken 66454 times.
✓ Branch 4 taken 68115 times.
440402 subs1 := if stringEq(s1,componentName) then {} else {DAE.NAMEMOD(s1,m1)};
2793 440402 subs2 := removeModInSubs(subs,componentName) "check for multiple mod on same comp";
2794 440402 outsubs := listAppend(subs1,subs2);
2795 then
2796 outsubs;
2797 end match;
2798 end removeModInSubs;
2799
2800 public function addEachIfNeeded
2801 "This function adds each to the mods
2802 if the dimensions are not empty."
2803 input DAE.Mod inMod;
2804 input DAE.Dimensions inDimensions;
2805 output DAE.Mod outMod;
2806 algorithm
2807 outMod := matchcontinue (inMod, inDimensions)
2808 local
2809 SCode.Final finalPrefix;
2810 SCode.Element el;
2811 DAE.Mod mod;
2812 SCode.Each eachPrefix;
2813 list<DAE.SubMod> subs;
2814 Option<DAE.EqMod> eq;
2815 SourceInfo info;
2816
2817 case (_, {}) then inMod;
2818 case (DAE.NOMOD(), _) then DAE.NOMOD();
2819
2820 case (DAE.REDECL(finalPrefix,_,el,mod), _)
2821 ✗ then
2822 DAE.REDECL(finalPrefix,SCode.EACH(),el,mod);
2823
2824 // do not each the subs of already each'ed mod
2825 case (DAE.MOD(finalPrefix,SCode.EACH(),subs,eq,info), _)
2826 ✗ then
2827 DAE.MOD(finalPrefix,SCode.EACH(),subs,eq,info);
2828
2829 case (DAE.MOD(finalPrefix,eachPrefix,subs,eq,info), _)
2830 algorithm
2831 28 subs := addEachToSubsIfNeeded(subs, inDimensions);
2832 28 then
2833 DAE.MOD(finalPrefix,eachPrefix,subs,eq,info);
2834
2835 else
2836 algorithm
2837 ✗ print("Mod.addEachIfNeeded failed on: " + printModStr(inMod) + "\n");
2838 ✗ then
2839 fail();
2840
2841 end matchcontinue;
2842 end addEachIfNeeded;
2843
2844 public function addEachOneLevel
2845 "This function adds each to the mods
2846 if the dimensions are not empty."
2847 input DAE.Mod inMod;
2848 output DAE.Mod outMod;
2849 algorithm
2850 outMod := match inMod
2851 local
2852 SCode.Final finalPrefix;
2853 SCode.Element el;
2854 DAE.Mod mod;
2855 list<DAE.SubMod> subs;
2856 Option<DAE.EqMod> eq;
2857 SourceInfo info;
2858
2859 case DAE.NOMOD() then DAE.NOMOD();
2860
2861 case DAE.REDECL(finalPrefix,_,el,mod)
2862 ✗ then
2863 DAE.REDECL(finalPrefix,SCode.EACH(),el,mod);
2864
2865 case DAE.MOD(finalPrefix,_,subs,eq,info)
2866 66 then
2867 DAE.MOD(finalPrefix,SCode.EACH(),subs,eq,info);
2868
2869 else
2870 algorithm
2871 ✗ print("Mod.addEachOneLevel failed on: " + printModStr(inMod) + "\n");
2872 ✗ then
2873 fail();
2874
2875 end match;
2876 end addEachOneLevel;
2877
2878 public function addEachToSubsIfNeeded
2879 input list<DAE.SubMod> inSubMods;
2880 input DAE.Dimensions inDimensions;
2881 output list<DAE.SubMod> outSubMods;
2882 algorithm
2883 outSubMods := match(inSubMods, inDimensions)
2884 local
2885 list<DAE.SubMod> rest;
2886 DAE.Mod m;
2887 String id;
2888
2889 case (_, {}) then inSubMods;
2890
2891 case ({}, _) then {};
2892
2893 case (DAE.NAMEMOD(id, m)::rest, _)
2894 algorithm
2895 66 m := addEachOneLevel(m);
2896 66 rest := addEachToSubsIfNeeded(rest, inDimensions);
2897 66 then
2898 DAE.NAMEMOD(id, m)::rest;
2899
2900 end match;
2901 end addEachToSubsIfNeeded;
2902
2903 public function isEmptyMod
2904 "@author: adrpo
2905 returns true if this is an empty modifier"
2906 input DAE.Mod inMod;
2907 output Boolean isEmpty;
2908 algorithm
2909 isEmpty := match inMod
2910 case DAE.NOMOD() then true;
2911 // That's a NOMOD() if I ever saw one...
2912 case DAE.MOD(subModLst = {}, binding = NONE()) then true;
2913 else false;
2914 end match;
2915 end isEmptyMod;
2916
2917 public function isNoMod
2918 input DAE.Mod inMod;
2919 output Boolean outIsNoMod;
2920 algorithm
2921 outIsNoMod := match inMod
2922 case DAE.NOMOD() then true;
2923 else false;
2924 end match;
2925 end isNoMod;
2926
2927 public function getModInfo
2928 input DAE.Mod inMod;
2929 output SourceInfo outInfo;
2930 algorithm
2931 outInfo := match inMod
2932 local
2933 SourceInfo info;
2934
2935 296676 case DAE.MOD() then inMod.info;
2936 18 case DAE.REDECL() then SCodeUtil.elementInfo(inMod.element);
2937 else Absyn.dummyInfo;
2938 end match;
2939 end getModInfo;
2940
2941 public function isRedeclareMod
2942 input DAE.Mod inMod;
2943 output Boolean yes;
2944 algorithm
2945 yes := match inMod
2946 case DAE.REDECL() then true;
2947 else false;
2948 end match;
2949 end isRedeclareMod;
2950
2951
2952 public function getClassModifier
2953 "return the modifier present in the environment for this class or DAE.NOMOD if ther is none"
2954 input FCore.Graph inEnv;
2955 input FCore.Name inName;
2956 output DAE.Mod outMod;
2957 protected
2958 FCore.Node n;
2959 DAE.Mod mod;
2960 algorithm
2961 outMod := matchcontinue inName
2962
2963 case _
2964 algorithm
2965 1695737 n := FNode.fromRef(FNode.child(FGraph.lastScopeRef(inEnv), inName));
2966
2/2
✓ Branch 3 taken 1687838 times.
✓ Branch 4 taken 7899 times.
1695737 if (not FNode.isInstance(FNode.fromRef(FGraph.lastScopeRef(inEnv)))) then
2967
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1687838 times.
1687838 FCore.N(data=FCore.CL(mod = mod)) := n;
2968 1687838 mod := Mod.removeMod(mod, inName);
2969 /*
2970 if not isEmptyMod(mod)
2971 then
2972 print("Env: " + FGraph.printGraphPathStr(inEnv) + " " + inName + "(" + printModStr(mod) + ")" + "\n");
2973 end if;
2974 */
2975 else
2976 mod := DAE.NOMOD();
2977 end if;
2978 then mod;
2979
2980 else DAE.NOMOD();
2981
2982 end matchcontinue;
2983 end getClassModifier;
2984
2985 protected function subModValue
2986 input DAE.SubMod inSubMod;
2987 output Values.Value outValue;
2988 algorithm
2989
4/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
1 DAE.NAMEMOD(mod = DAE.MOD(binding = SOME(DAE.TYPED(modifierAsValue = SOME(outValue)))))
2990 := inSubMod;
2991 end subModValue;
2992
2993 protected function subModName
2994 input DAE.SubMod inSubMod;
2995 output DAE.Ident outName;
2996 algorithm
2997 289685 DAE.NAMEMOD(ident = outName) := inSubMod;
2998 end subModName;
2999
3000 protected function subModIsNamed
3001 input String inName;
3002 input DAE.SubMod inSubMod;
3003 output Boolean outNameEq;
3004 algorithm
3005
4/4
✓ Branch 1 taken 149883 times.
✓ Branch 2 taken 526035 times.
✓ Branch 4 taken 7297 times.
✓ Branch 5 taken 142586 times.
1501719 outNameEq := inName == subModName(inSubMod);
3006 end subModIsNamed;
3007
3008 protected function subModInfo
3009 input DAE.SubMod inSubMod;
3010 output SourceInfo outInfo;
3011 protected
3012 DAE.Mod mod;
3013 algorithm
3014 ✗ DAE.NAMEMOD(mod = mod) := inSubMod;
3015 ✗ outInfo := getModInfo(mod);
3016 end subModInfo;
3017
3018 protected function setEqMod
3019 input Option<DAE.EqMod> inEqMod;
3020 input DAE.Mod inMod;
3021 output DAE.Mod outMod = inMod;
3022 algorithm
3023 outMod := match outMod
3024 case DAE.MOD()
3025 algorithm
3026 5 outMod.binding := inEqMod;
3027 then
3028 outMod;
3029
3030 else outMod;
3031 end match;
3032 end setEqMod;
3033
3034 protected function stripSubModBindings
3035 input list<DAE.SubMod> inSubMods;
3036 output list<DAE.SubMod> outSubMods = {};
3037 protected
3038 DAE.Ident id;
3039 DAE.Mod mod;
3040 algorithm
3041
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 3 times.
8 for submod in inSubMods loop
3042 5 DAE.NAMEMOD(id, mod) := submod;
3043 5 mod := setEqMod(NONE(), mod);
3044
3045
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1 time.
5 if not isEmptyMod(mod) then
3046 4 outSubMods := DAE.NAMEMOD(id, mod) :: outSubMods;
3047 end if;
3048 end for;
3049
3050 3 outSubMods := listReverse(outSubMods);
3051 end stripSubModBindings;
3052
3053 public function filterRedeclares
3054 input DAE.Mod inMod;
3055 output DAE.Mod outMod = inMod;
3056 algorithm
3057 outMod := match outMod
3058 case DAE.MOD()
3059 algorithm
3060 1046 outMod.subModLst := filterRedeclaresSubMods(outMod.subModLst);
3061
1/2
✓ Branch 0 taken 1046 times.
✗ Branch 1 not taken.
1046 outMod.binding := NONE();
3062
1/2
✓ Branch 0 taken 1046 times.
✗ Branch 1 not taken.
1046 then
3063 if listEmpty(outMod.subModLst) then DAE.NOMOD() else outMod;
3064
3065 else outMod;
3066 end match;
3067 end filterRedeclares;
3068
3069 protected function filterRedeclaresSubMods
3070 input list<DAE.SubMod> inSubMods;
3071 output list<DAE.SubMod> outSubMods = {};
3072 protected
3073 DAE.Ident id;
3074 DAE.Mod mod;
3075 algorithm
3076
2/2
✓ Branch 0 taken 293 times.
✓ Branch 1 taken 1046 times.
1339 for submod in inSubMods loop
3077 293 DAE.NAMEMOD(id, mod) := submod;
3078 293 mod := filterRedeclares(mod);
3079
3080
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 293 times.
293 if isRedeclareMod(mod) then
3081 ✗ outSubMods := DAE.NAMEMOD(id, mod) :: outSubMods;
3082 end if;
3083 end for;
3084
3085 1046 outSubMods := listReverse(outSubMods);
3086 end filterRedeclaresSubMods;
3087
3088 public function unparseModStr
3089 input DAE.Mod inMod;
3090 output String outString;
3091 algorithm
3092 outString := match inMod
3093 local
3094 String final_str, each_str, sub_str, binding_str, el_str;
3095
3096 case DAE.NOMOD() then "";
3097
3098 case DAE.MOD()
3099 algorithm
3100
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
8 final_str := if SCodeUtil.finalBool(inMod.finalPrefix) then "final " else "";
3101
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 each_str := if SCodeUtil.eachBool(inMod.eachPrefix) then "each " else "";
3102 8 sub_str := List.toStringCustom(inMod.subModLst, unparseSubModStr, "", "(", ", ", ")", false);
3103 8 binding_str := unparseBindingStr(inMod.binding);
3104 8 then
3105 final_str + each_str + sub_str + binding_str;
3106
3107 case DAE.REDECL()
3108 algorithm
3109 ✗ final_str := if SCodeUtil.finalBool(inMod.finalPrefix) then "final " else "";
3110 ✗ each_str := if SCodeUtil.eachBool(inMod.eachPrefix) then "each " else "";
3111 ✗ el_str := SCodeDump.unparseElementStr(inMod.element);
3112 ✗ then
3113 final_str + each_str + "redeclare " + el_str;
3114
3115 end match;
3116 end unparseModStr;
3117
3118 protected function unparseSubModStr
3119 input DAE.SubMod inSubMod;
3120 output String outString;
3121 algorithm
3122 outString := match inSubMod
3123 ✗ case DAE.NAMEMOD() then inSubMod.ident + " = " + unparseModStr(inSubMod.mod);
3124 end match;
3125 end unparseSubModStr;
3126
3127 protected function unparseBindingStr
3128 input Option<DAE.EqMod> inBinding;
3129 output String outString;
3130 algorithm
3131 outString := match inBinding
3132 local
3133 Absyn.Exp exp;
3134
3135 case NONE() then "";
3136 7 case SOME(DAE.TYPED(modifierAsAbsynExp = exp)) then " = " + Dump.printExpStr(exp);
3137 1 case SOME(DAE.UNTYPED(exp = exp)) then " = " + Dump.printExpStr(exp);
3138 end match;
3139 end unparseBindingStr;
3140
3141 annotation(__OpenModelica_Interface="frontend");
3142 end Mod;
3143