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 |