OMCompiler/Compiler/FrontEnd/CheckModel.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 CheckModel " | ||
| 37 | file: CheckModel.mo | ||
| 38 | package: CheckModel | ||
| 39 | description: Check the Model. | ||
| 40 | |||
| 41 | " | ||
| 42 | |||
| 43 | public import Absyn; | ||
| 44 | public import DAE; | ||
| 45 | |||
| 46 | protected import BaseHashSet; | ||
| 47 | protected import ClassInf; | ||
| 48 | protected import ComponentReference; | ||
| 49 | protected import ComponentReferenceBasics; | ||
| 50 | protected import DAEDump; | ||
| 51 | protected import DAEUtil; | ||
| 52 | protected import Debug; | ||
| 53 | protected import ExecStat; | ||
| 54 | protected import Expression; | ||
| 55 | protected import Flags; | ||
| 56 | protected import HashSet; | ||
| 57 | protected import List; | ||
| 58 | protected import PrefixUtil; | ||
| 59 | protected import Util; | ||
| 60 | protected import Error; | ||
| 61 | |||
| 62 | public function checkModel "This function perform a model check. Count Variables and equations and | ||
| 63 | detect the simple equations." | ||
| 64 | input DAE.DAElist inDAELst; | ||
| 65 | output Integer varSize; | ||
| 66 | output Integer eqnSize; | ||
| 67 | output Integer simpleEqnSize; | ||
| 68 | protected | ||
| 69 | list<DAE.Element> eqns, lst; | ||
| 70 | HashSet.HashSet hs; | ||
| 71 | Boolean debug_dump = Flags.isSet(Flags.DUMP_CHECK_MODEL); | ||
| 72 | CountVarEqnFoldArg arg; | ||
| 73 | algorithm | ||
| 74 | 82 | ExecStat.execStat("CheckModel - start counting"); | |
| 75 | 82 | DAE.DAE(lst) := inDAELst; | |
| 76 | 82 | hs := HashSet.emptyHashSet(); | |
| 77 | 82 | (varSize, eqnSize, eqns, hs) := countVarEqnSizeList(lst, (0, 0, {}, hs), debug_dump); | |
| 78 | 82 | simpleEqnSize := countSimpleEqnSize(eqns, 0, hs); | |
| 79 | 82 | ExecStat.execStat("CheckModel - end counting"); | |
| 80 | end checkModel; | ||
| 81 | |||
| 82 | protected type CountVarEqnFoldArg = | ||
| 83 | tuple<Integer/*varSize*/, Integer/*eqnSize*/, list<DAE.Element>/*eqns*/, HashSet.HashSet/*vars*/>; | ||
| 84 | |||
| 85 | protected function countVarEqnSizeList | ||
| 86 | input list<DAE.Element> elements; | ||
| 87 | input output CountVarEqnFoldArg arg; | ||
| 88 | input Boolean debugDump; | ||
| 89 | algorithm | ||
| 90 |
2/2✓ Branch 0 taken 180208 times.
✓ Branch 1 taken 174 times.
|
180382 | for e in elements loop |
| 91 | 180208 | arg := countVarEqnSize(e, arg, debugDump); | |
| 92 | end for; | ||
| 93 | end countVarEqnSizeList; | ||
| 94 | |||
| 95 | protected function countVarEqnSize | ||
| 96 | input DAE.Element element; | ||
| 97 | input CountVarEqnFoldArg inArg; | ||
| 98 | input Boolean debugDump; | ||
| 99 | output CountVarEqnFoldArg outArg; | ||
| 100 | algorithm | ||
| 101 | outArg := match element | ||
| 102 | local | ||
| 103 | DAE.Exp e; | ||
| 104 | DAE.ComponentRef cr; | ||
| 105 | DAE.ElementSource source; | ||
| 106 | Integer varSize, eqnSize, size; | ||
| 107 | list<DAE.Element> eqns, daeElts; | ||
| 108 | HashSet.HashSet hs; | ||
| 109 | DAE.Algorithm alg; | ||
| 110 | list<DAE.ComponentRef> crlst; | ||
| 111 | DAE.Type tp; | ||
| 112 | DAE.Element elem; | ||
| 113 | |||
| 114 | // external Objects | ||
| 115 | case DAE.EXTOBJECTCLASS() | ||
| 116 | then inArg; | ||
| 117 | |||
| 118 | // external Variables | ||
| 119 | case DAE.VAR(ty = DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ())) | ||
| 120 | then inArg; | ||
| 121 | |||
| 122 | // parameter variables | ||
| 123 | case DAE.VAR(kind = DAE.PARAM()) | ||
| 124 | then inArg; | ||
| 125 | |||
| 126 | // constant variables | ||
| 127 | case DAE.VAR(kind = DAE.CONST()) | ||
| 128 | then inArg; | ||
| 129 | |||
| 130 | // continuous/discrete variables | ||
| 131 | case DAE.VAR(componentRef=cr) | ||
| 132 | algorithm | ||
| 133 | 98227 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 134 | 98227 | size := Expression.sizeOf(element.ty); | |
| 135 | 98227 | varSize := varSize + size; | |
| 136 | 98227 | dumpVar(cr, size, debugDump); | |
| 137 | |||
| 138 |
3/4✓ Branch 1 taken 1 time.
✓ Branch 2 taken 98226 times.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
|
98227 | if DAEUtil.isInput(element) and DAEUtil.isPublicVar(element) then |
| 139 | 1 | eqnSize := eqnSize + size; | |
| 140 | 1 | dumpEqn(element, size, debugDump); | |
| 141 | else | ||
| 142 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 98226 times.
✓ Branch 2 taken 7221 times.
✓ Branch 3 taken 91005 times.
|
98226 | if isSome(element.binding) then |
| 143 | 7221 | eqnSize := eqnSize + size; | |
| 144 | 7221 | elem := DAE.EQUATION(Expression.crefExp(element.componentRef), Util.getOption(element.binding), element.source); | |
| 145 | 7221 | dumpEqn(elem, size, debugDump); | |
| 146 | eqns := elem :: eqns; | ||
| 147 | end if; | ||
| 148 | |||
| 149 | 98226 | hs := BaseHashSet.add(cr, hs); | |
| 150 | end if; | ||
| 151 | 98227 | then | |
| 152 | (varSize, eqnSize, eqns, hs); | ||
| 153 | |||
| 154 | // equations | ||
| 155 | case DAE.EQUATION(exp=e) | ||
| 156 | algorithm | ||
| 157 | 17542 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 158 | 17542 | size := Expression.sizeOf(Expression.typeof(e)); | |
| 159 | 17542 | dumpEqn(element, size, debugDump); | |
| 160 | 17542 | then (varSize, eqnSize+size, element::eqns, hs); | |
| 161 | |||
| 162 | // initial equations | ||
| 163 | case DAE.INITIALEQUATION() | ||
| 164 | then inArg; | ||
| 165 | |||
| 166 | // effort variable equality equations | ||
| 167 | case DAE.EQUEQUATION(cr1 = cr) | ||
| 168 | algorithm | ||
| 169 | 22729 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 170 | 22729 | tp := ComponentReference.crefTypeConsiderSubs(cr); | |
| 171 | 22729 | size := Expression.sizeOf(tp); | |
| 172 | 22729 | dumpEqn(element, size, debugDump); | |
| 173 | 22729 | then (varSize, eqnSize+size, element::eqns, hs); | |
| 174 | |||
| 175 | // a solved equation | ||
| 176 | case DAE.DEFINE(componentRef = cr) | ||
| 177 | algorithm | ||
| 178 | ✗ | (varSize, eqnSize, eqns, hs) := inArg; | |
| 179 | ✗ | tp := ComponentReference.crefTypeConsiderSubs(cr); | |
| 180 | ✗ | size := Expression.sizeOf(tp); | |
| 181 | ✗ | dumpEqn(element, size, debugDump); | |
| 182 | ✗ | then (varSize, eqnSize+size, element::eqns, hs); | |
| 183 | |||
| 184 | // complex equations | ||
| 185 | case DAE.COMPLEX_EQUATION(lhs = e) | ||
| 186 | algorithm | ||
| 187 | 664 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 188 | 664 | size := Expression.sizeOf(Expression.typeof(e)); | |
| 189 | 664 | dumpEqn(element, size, debugDump); | |
| 190 | 664 | then (varSize, eqnSize+size, element::eqns, hs); | |
| 191 | |||
| 192 | // complex initial equations | ||
| 193 | case DAE.INITIAL_COMPLEX_EQUATION() | ||
| 194 | then inArg; | ||
| 195 | |||
| 196 | // array equations | ||
| 197 | case DAE.ARRAY_EQUATION() | ||
| 198 | algorithm | ||
| 199 | 11424 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 200 | 11424 | size := Expression.sizeOf(Expression.typeof(element.exp)); | |
| 201 | 11424 | dumpEqn(element, size, debugDump); | |
| 202 | 11424 | then (varSize, eqnSize+size, element::eqns, hs); | |
| 203 | |||
| 204 | // initial array equations | ||
| 205 | case DAE.INITIAL_ARRAY_EQUATION() | ||
| 206 | then inArg; | ||
| 207 | |||
| 208 | // when equations | ||
| 209 | case DAE.WHEN_EQUATION(equations = daeElts) | ||
| 210 | algorithm | ||
| 211 | 3 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 212 | 3 | (_, size, _, _) := countVarEqnSizeList(daeElts, (0, 0, {}, hs), false); | |
| 213 | 3 | dumpEqn(element, size, debugDump); | |
| 214 | 3 | then (varSize, eqnSize+size, eqns, hs); | |
| 215 | |||
| 216 | case DAE.INITIAL_FOR_EQUATION() | ||
| 217 | algorithm | ||
| 218 | ✗ | (varSize, eqnSize, eqns, hs) := inArg; | |
| 219 | ✗ | (_, size, _, _) := countVarEqnSizeList(element.equations, (0, 0, {}, hs), false); | |
| 220 | ✗ | size := size * Expression.sizeOf(Expression.typeof(element.range)); | |
| 221 | ✗ | dumpEqn(element, size, debugDump); | |
| 222 | ✗ | then | |
| 223 | (varSize, eqnSize+size, eqns, hs); | ||
| 224 | |||
| 225 | case DAE.FOR_EQUATION() | ||
| 226 | algorithm | ||
| 227 | ✗ | (varSize, eqnSize, eqns, hs) := inArg; | |
| 228 | ✗ | (_, size, _, _) := countVarEqnSizeList(element.equations, (0, 0, {}, hs), false); | |
| 229 | ✗ | size := size * Expression.sizeOf(Expression.typeof(element.range)); | |
| 230 | ✗ | dumpEqn(element, size, debugDump); | |
| 231 | ✗ | then | |
| 232 | (varSize, eqnSize+size, eqns, hs); | ||
| 233 | |||
| 234 | // if equation with condition false and no else | ||
| 235 | case DAE.IF_EQUATION(condition1 = {DAE.BCONST(false)}, equations3 = {}) | ||
| 236 | then inArg; | ||
| 237 | |||
| 238 | // if equation | ||
| 239 | case DAE.IF_EQUATION(equations2 = daeElts::_) | ||
| 240 | algorithm | ||
| 241 | 7 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 242 | 7 | (_, size, _, _) := countVarEqnSizeList(daeElts, (0, 0, {}, hs), false); | |
| 243 | 7 | dumpEqn(element, size, debugDump); | |
| 244 | 7 | then (varSize, eqnSize+size, eqns, hs); | |
| 245 | |||
| 246 | // initial if equation with condition false and no else | ||
| 247 | case DAE.INITIAL_IF_EQUATION(condition1 = {DAE.BCONST(false)}, equations3 = {}) | ||
| 248 | then inArg; | ||
| 249 | |||
| 250 | // initial if equation | ||
| 251 | case DAE.INITIAL_IF_EQUATION() | ||
| 252 | then inArg; | ||
| 253 | |||
| 254 | // algorithm | ||
| 255 | case DAE.ALGORITHM(algorithm_ = alg, source = source) | ||
| 256 | algorithm | ||
| 257 | 6 | (varSize, eqnSize, eqns, hs) := inArg; | |
| 258 | 6 | crlst := checkAndGetAlgorithmOutputs(alg, source, DAE.EXPAND()); | |
| 259 | 6 | size := listLength(crlst); | |
| 260 | 6 | dumpEqn(element, size, debugDump); | |
| 261 | 6 | then | |
| 262 | (varSize, eqnSize+size, eqns, hs); | ||
| 263 | |||
| 264 | // initial algorithm | ||
| 265 | case DAE.INITIALALGORITHM() | ||
| 266 | then inArg; | ||
| 267 | |||
| 268 | // flat class / COMP | ||
| 269 | case DAE.COMP(dAElist = daeElts) | ||
| 270 | 82 | then countVarEqnSizeList(daeElts, inArg, debugDump); | |
| 271 | |||
| 272 | // reinit | ||
| 273 | case DAE.REINIT() | ||
| 274 | then inArg; | ||
| 275 | |||
| 276 | // assert in equation | ||
| 277 | case DAE.ASSERT() | ||
| 278 | then inArg; | ||
| 279 | |||
| 280 | // assert in equation | ||
| 281 | case DAE.INITIAL_ASSERT() | ||
| 282 | then inArg; | ||
| 283 | |||
| 284 | // terminate in equation section is converted to ALGORITHM | ||
| 285 | case DAE.TERMINATE() | ||
| 286 | then inArg; | ||
| 287 | |||
| 288 | case DAE.INITIAL_TERMINATE() | ||
| 289 | then inArg; | ||
| 290 | |||
| 291 | case DAE.NORETCALL() | ||
| 292 | then inArg; | ||
| 293 | |||
| 294 | case DAE.INITIAL_NORETCALL() | ||
| 295 | then inArg; | ||
| 296 | |||
| 297 | // constraint (Optimica) Just pass the constraints for now. Should anything more be done here? | ||
| 298 | case DAE.CONSTRAINT() | ||
| 299 | then inArg; | ||
| 300 | |||
| 301 | // flat state machine section | ||
| 302 | case DAE.FLAT_SM(dAElist = daeElts) | ||
| 303 | ✗ | then countVarEqnSizeList(daeElts, inArg, debugDump); | |
| 304 | |||
| 305 | // a state/mode component in a state machine | ||
| 306 | case DAE.SM_COMP(dAElist = daeElts) | ||
| 307 | ✗ | then countVarEqnSizeList(daeElts, inArg, debugDump); | |
| 308 | |||
| 309 | else | ||
| 310 | algorithm | ||
| 311 | // show only on failtrace! | ||
| 312 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 313 | ✗ | Debug.traceln("- CheckModel.countVarEqnSize failed on: " + DAEDump.dumpElementsStr({element})); | |
| 314 | ✗ | then | |
| 315 | fail(); | ||
| 316 | end match; | ||
| 317 | end countVarEqnSize; | ||
| 318 | |||
| 319 | protected function dumpVar | ||
| 320 | input DAE.ComponentRef cref; | ||
| 321 | input Integer size; | ||
| 322 | input Boolean dump; | ||
| 323 | algorithm | ||
| 324 |
1/2✓ Branch 0 taken 98227 times.
✗ Branch 1 not taken.
|
98227 | if dump then |
| 325 | ✗ | print("[var: " + String(size) + "] " + ComponentReferenceBasics.printComponentRefStr(cref) + "\n"); | |
| 326 | end if; | ||
| 327 | end dumpVar; | ||
| 328 | |||
| 329 | protected function dumpEqn | ||
| 330 | input DAE.Element eqn; | ||
| 331 | input Integer size; | ||
| 332 | input Boolean dump; | ||
| 333 | algorithm | ||
| 334 |
1/2✓ Branch 0 taken 59597 times.
✗ Branch 1 not taken.
|
59597 | if dump then |
| 335 | ✗ | print("[eqn: " + String(size) + "] " + DAEDump.dumpEquationStr(eqn)); | |
| 336 | end if; | ||
| 337 | end dumpEqn; | ||
| 338 | |||
| 339 | public function checkAndGetAlgorithmOutputs | ||
| 340 | "mahge: | ||
| 341 | counts the ouputs of algorithms depending on where the | ||
| 342 | section came from. If the algorithm section came from a scalar | ||
| 343 | component the it is counted acorrding to the inCrefExpansionRule. | ||
| 344 | However in some cases where algorithms come from a member of an array | ||
| 345 | of components expanding arrays and counting them as full in every | ||
| 346 | algorithm secion will cause duplicate countings. | ||
| 347 | See spec 3.3 Modelica spec 3.3 rev 11.1.2 and ticket 2452 | ||
| 348 | " | ||
| 349 | input DAE.Algorithm inAlgorithm; | ||
| 350 | input DAE.ElementSource inSource; | ||
| 351 | input DAE.Expand inCrefExpansionRule; | ||
| 352 | output list<DAE.ComponentRef> outCrefLst; | ||
| 353 | algorithm | ||
| 354 | outCrefLst := matchcontinue inSource | ||
| 355 | local | ||
| 356 | |||
| 357 | case DAE.SOURCE(instance = DAE.NOCOMPPRE()) | ||
| 358 | 1662 | then algorithmOutputs(inAlgorithm, inCrefExpansionRule); | |
| 359 | |||
| 360 | // the algorithm came from a component that is member of an array or not | ||
| 361 | case DAE.SOURCE() | ||
| 362 |
2/2✓ Branch 1 taken 106 times.
✓ Branch 2 taken 512 times.
|
618 | then |
| 363 | if PrefixUtil.hasSubs(inSource.instance) | ||
| 364 | then algorithmOutputs(inAlgorithm, DAE.NOT_EXPAND()) | ||
| 365 | else algorithmOutputs(inAlgorithm, inCrefExpansionRule); | ||
| 366 | |||
| 367 | else | ||
| 368 | algorithm | ||
| 369 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {"checkAndGetAlgorithmOutputs failed."}); | |
| 370 | ✗ | then fail(); | |
| 371 | end matchcontinue; | ||
| 372 | end checkAndGetAlgorithmOutputs; | ||
| 373 | |||
| 374 | public function isCrefListAlgorithmOutput | ||
| 375 | "This function verfies if all crefs in crefList are outputs | ||
| 376 | of the passed algorithm" | ||
| 377 | input list<DAE.ComponentRef> crefList; | ||
| 378 | input DAE.Algorithm inAlgorithm; | ||
| 379 | input DAE.ElementSource inSource; | ||
| 380 | input DAE.Expand inCrefExpansionRule; | ||
| 381 | output Boolean outResult = false; | ||
| 382 | protected | ||
| 383 | HashSet.HashSet ht = HashSet.emptyHashSet(); | ||
| 384 | list<DAE.ComponentRef> algOutCrefs; | ||
| 385 | algorithm | ||
| 386 | 505 | algOutCrefs := CheckModel.checkAndGetAlgorithmOutputs(inAlgorithm, inSource, inCrefExpansionRule); | |
| 387 | 505 | ht := List.fold(algOutCrefs, BaseHashSet.add, ht); | |
| 388 |
2/2✓ Branch 0 taken 2200 times.
✓ Branch 1 taken 502 times.
|
2702 | for cr in crefList loop |
| 389 |
2/2✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2197 times.
|
2200 | if not BaseHashSet.has(cr, ht) then |
| 390 | 3 | return; | |
| 391 | end if; | ||
| 392 | end for; | ||
| 393 | outResult := true; | ||
| 394 | end isCrefListAlgorithmOutput; | ||
| 395 | |||
| 396 | protected function algorithmOutputs "This function finds the the outputs of an algorithm. | ||
| 397 | An input is all values that are reffered on the right hand side of any | ||
| 398 | statement in the algorithm and an output is a variables belonging to the | ||
| 399 | variables that are assigned a value in the algorithm. If a variable is an | ||
| 400 | input and an output it will be treated as an output." | ||
| 401 | input DAE.Algorithm inAlgorithm; | ||
| 402 | input DAE.Expand inCrefExpansion "expand array to full dimension?"; | ||
| 403 | output list<DAE.ComponentRef> outCrefLst; | ||
| 404 | protected | ||
| 405 | list<DAE.Statement> stmts; | ||
| 406 | algorithm | ||
| 407 | 2280 | DAE.ALGORITHM_STMTS(statementLst=stmts) := inAlgorithm; | |
| 408 | 2280 | outCrefLst := algorithmStatementListOutputs(stmts, inCrefExpansion); | |
| 409 | end algorithmOutputs; | ||
| 410 | |||
| 411 | public function algorithmStatementListOutputs "This function finds the the outputs of an algorithm. | ||
| 412 | An input is all values that are reffered on the right hand side of any | ||
| 413 | statement in the algorithm and an output is a variables belonging to the | ||
| 414 | variables that are assigned a value in the algorithm. If a variable is an | ||
| 415 | input and an output it will be treated as an output." | ||
| 416 | input list<DAE.Statement> inStmts; | ||
| 417 | input DAE.Expand inCrefExpansion "expand array to full dimension?"; | ||
| 418 | output list<DAE.ComponentRef> outCrefLst; | ||
| 419 | protected | ||
| 420 | HashSet.HashSet hs; | ||
| 421 | algorithm | ||
| 422 | 11300 | hs := HashSet.emptyHashSet(); | |
| 423 | 11300 | hs := List.fold1(inStmts, statementOutputs, inCrefExpansion, hs); | |
| 424 | 11300 | outCrefLst := BaseHashSet.hashSetList(hs); | |
| 425 | end algorithmStatementListOutputs; | ||
| 426 | |||
| 427 | protected function statementOutputs "Helper relation to algorithmOutputs" | ||
| 428 | input DAE.Statement inStatement; | ||
| 429 | input DAE.Expand inCrefExpansion "expand array to full dimension?"; | ||
| 430 | input HashSet.HashSet iht; | ||
| 431 | output HashSet.HashSet oht; | ||
| 432 | algorithm | ||
| 433 | oht := matchcontinue inStatement | ||
| 434 | local | ||
| 435 | HashSet.HashSet ht; | ||
| 436 | DAE.ComponentRef cr; | ||
| 437 | list<DAE.ComponentRef> crlst; | ||
| 438 | DAE.Exp e, exp1; | ||
| 439 | DAE.Statement stmt; | ||
| 440 | list<DAE.Statement> stmts; | ||
| 441 | DAE.Else elsebranch; | ||
| 442 | list<DAE.Exp> expl; | ||
| 443 | DAE.Type tp; | ||
| 444 | DAE.Ident iteratorName; | ||
| 445 | String str; | ||
| 446 | list<DAE.Subscript> subs; | ||
| 447 | |||
| 448 | // a := expr; | ||
| 449 | case DAE.STMT_ASSIGN(exp1 = exp1) | ||
| 450 | algorithm | ||
| 451 | 38651 | (_, (_, ht)) := Expression.traverseExpTopDown(exp1, statementOutputsCrefFinder, (inCrefExpansion, iht)); | |
| 452 | then ht; | ||
| 453 | |||
| 454 | // (a, b, ...) := expr; | ||
| 455 | case DAE.STMT_TUPLE_ASSIGN(expExpLst = expl) | ||
| 456 | algorithm | ||
| 457 | 356 | (_, (_, ht)) := Expression.traverseExpListTopDown(expl, statementOutputsCrefFinder, (inCrefExpansion, iht)); | |
| 458 | then ht; | ||
| 459 | |||
| 460 | // a := expr; // where a is array | ||
| 461 | case DAE.STMT_ASSIGN_ARR(lhs=exp1) | ||
| 462 | algorithm | ||
| 463 | // (_, (_, ht)) = Expression.traverseExpTopDown(exp1, statementOutputsCrefFinder, (inCrefExpansion, iht)); | ||
| 464 | 1622 | cr := Expression.expCref(exp1); | |
| 465 | 1622 | subs := ComponentReference.crefLastSubs(cr); | |
| 466 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 1602 times.
|
1622 | if not listEmpty(subs) // not an empty subs list |
| 467 | then | ||
| 468 | 20 | subs := List.fill(DAE.WHOLEDIM(), listLength(subs)); | |
| 469 | 20 | cr := ComponentReference.crefSetLastSubs(cr, subs); | |
| 470 | end if; | ||
| 471 | 1622 | crlst := ComponentReference.expandCref(cr, true); | |
| 472 | 1622 | ht := List.fold(crlst, BaseHashSet.add, iht); | |
| 473 | then ht; | ||
| 474 | |||
| 475 | case DAE.STMT_IF(statementLst = stmts, else_ = elsebranch) | ||
| 476 | algorithm | ||
| 477 | 6606 | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 478 | 6606 | ht := statementElseOutputs(elsebranch, inCrefExpansion, ht); | |
| 479 | then ht; | ||
| 480 | |||
| 481 | case DAE.STMT_FOR(type_=tp, iter = iteratorName, range = e, statementLst = stmts) | ||
| 482 | algorithm | ||
| 483 | // replace the iterator variable with the range expression | ||
| 484 | 3545 | cr := ComponentReferenceBasics.makeCrefIdent(iteratorName, tp, {}); | |
| 485 | 3545 | (stmts, _) := DAEUtil.traverseDAEEquationsStmts(stmts, Expression.traverseSubexpressionsHelper, (Expression.replaceCref, (cr, e))); | |
| 486 | 3545 | ht := List.fold1(stmts, statementOutputs, DAE.EXPAND(), iht); | |
| 487 | then ht; | ||
| 488 | |||
| 489 | case DAE.STMT_PARFOR(type_=tp, iter = iteratorName, range = e, statementLst = stmts) | ||
| 490 | algorithm | ||
| 491 | // replace the iterator variable with the range expression | ||
| 492 | ✗ | cr := ComponentReferenceBasics.makeCrefIdent(iteratorName, tp, {}); | |
| 493 | ✗ | (stmts, _) := DAEUtil.traverseDAEEquationsStmts(stmts, Expression.traverseSubexpressionsHelper, (Expression.replaceCref, (cr, e))); | |
| 494 | ✗ | ht := List.fold1(stmts, statementOutputs, DAE.EXPAND(), iht); | |
| 495 | then ht; | ||
| 496 | |||
| 497 | case DAE.STMT_WHILE(statementLst = stmts) | ||
| 498 | algorithm | ||
| 499 | ✗ | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 500 | then ht; | ||
| 501 | |||
| 502 | case DAE.STMT_WHEN(statementLst = stmts, elseWhen = NONE()) | ||
| 503 | algorithm | ||
| 504 | 2350 | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 505 | then ht; | ||
| 506 | |||
| 507 | case DAE.STMT_WHEN(statementLst = stmts, elseWhen = SOME(stmt)) | ||
| 508 | algorithm | ||
| 509 | 1014 | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 510 | 1014 | ht := statementOutputs(stmt, inCrefExpansion, ht); | |
| 511 | then ht; | ||
| 512 | |||
| 513 | case DAE.STMT_ASSERT() then iht; | ||
| 514 | case DAE.STMT_TERMINATE() then iht; | ||
| 515 | |||
| 516 | // reinit is not a output | ||
| 517 | case DAE.STMT_REINIT() then iht; | ||
| 518 | case DAE.STMT_NORETCALL() then iht; | ||
| 519 | case DAE.STMT_RETURN(_) then iht; | ||
| 520 | case DAE.STMT_BREAK(_) then iht; | ||
| 521 | case DAE.STMT_CONTINUE(_) then iht; | ||
| 522 | case DAE.STMT_ARRAY_INIT() then iht; | ||
| 523 | // MetaModelica extension. KS | ||
| 524 | case DAE.STMT_FAILURE(body = stmts) | ||
| 525 | algorithm | ||
| 526 | ✗ | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 527 | then ht; | ||
| 528 | |||
| 529 | else | ||
| 530 | algorithm | ||
| 531 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 532 | ✗ | str := DAEDump.ppStatementStr(inStatement); | |
| 533 | ✗ | Debug.traceln("- CheckModel.statementOutputs failed for " + str); | |
| 534 | ✗ | then | |
| 535 | fail(); | ||
| 536 | |||
| 537 | end matchcontinue; | ||
| 538 | end statementOutputs; | ||
| 539 | |||
| 540 | protected function statementElseOutputs "Helper function to statementOutputs" | ||
| 541 | input DAE.Else inElseBranch; | ||
| 542 | input DAE.Expand inCrefExpansion "expand array to full dimension?"; | ||
| 543 | input HashSet.HashSet iht; | ||
| 544 | output HashSet.HashSet oht; | ||
| 545 | algorithm | ||
| 546 | oht := match inElseBranch | ||
| 547 | local | ||
| 548 | list<DAE.Statement> stmts; | ||
| 549 | DAE.Else elseBranch; | ||
| 550 | HashSet.HashSet ht; | ||
| 551 | |||
| 552 | case DAE.NOELSE() then iht; | ||
| 553 | |||
| 554 | case DAE.ELSEIF(statementLst=stmts, else_=elseBranch) | ||
| 555 | algorithm | ||
| 556 | 2055 | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 557 | 2055 | ht := statementElseOutputs(elseBranch, inCrefExpansion, ht); | |
| 558 | then ht; | ||
| 559 | |||
| 560 | case DAE.ELSE(statementLst=stmts) | ||
| 561 | algorithm | ||
| 562 | 1056 | ht := List.fold1(stmts, statementOutputs, inCrefExpansion, iht); | |
| 563 | then ht; | ||
| 564 | end match; | ||
| 565 | end statementElseOutputs; | ||
| 566 | |||
| 567 | protected function statementOutputsCrefFinder "author: Frenkel TUD 2012-06" | ||
| 568 | input DAE.Exp inExp; | ||
| 569 | input tuple<DAE.Expand, HashSet.HashSet> inTpl; | ||
| 570 | output DAE.Exp outExp; | ||
| 571 | output Boolean cont; | ||
| 572 | output tuple<DAE.Expand, HashSet.HashSet> outTpl; | ||
| 573 | algorithm | ||
| 574 | (outExp,cont,outTpl) := matchcontinue (inExp,inTpl) | ||
| 575 | local | ||
| 576 | DAE.Exp e, exp, e1, e2; | ||
| 577 | HashSet.HashSet ht; | ||
| 578 | DAE.ComponentRef cr, first_cref; | ||
| 579 | list<DAE.ComponentRef> crlst; | ||
| 580 | DAE.Expand expand; | ||
| 581 | |||
| 582 | // Skip wild | ||
| 583 | case (e as DAE.CREF(componentRef=DAE.WILD()), _) | ||
| 584 | then (e, false, inTpl); | ||
| 585 | |||
| 586 | // Skip time | ||
| 587 | case (e as DAE.CREF(componentRef=DAE.CREF_IDENT(ident="time", subscriptLst={})), _) | ||
| 588 | then (e, false, inTpl); | ||
| 589 | |||
| 590 | // Skip external Objects | ||
| 591 | case (e as DAE.CREF(ty=DAE.T_COMPLEX(complexClassType = ClassInf.EXTERNAL_OBJ())), _) | ||
| 592 | then (e, false, inTpl); | ||
| 593 | |||
| 594 | // records are not arays, expand them always | ||
| 595 | case (e as DAE.CREF(componentRef=cr, ty=DAE.T_COMPLEX(complexClassType = ClassInf.RECORD())), (expand,ht)) | ||
| 596 | algorithm | ||
| 597 | 96 | cr := ComponentReference.crefStripSubs(cr); | |
| 598 | 96 | crlst := ComponentReference.expandCref(cr, true); | |
| 599 | 96 | ht := List.fold(crlst, BaseHashSet.add, ht); | |
| 600 | 96 | then (e, false, (expand,ht)); | |
| 601 | |||
| 602 | // NOT_EXPAND strategy (needed for equations translated to algorithms) | ||
| 603 | case (e as DAE.CREF(componentRef=cr), (expand as DAE.NOT_EXPAND(),ht)) | ||
| 604 | algorithm | ||
| 605 | 1489 | ht := List.fold({cr}, BaseHashSet.add, ht); | |
| 606 | 1489 | then (e, false, (expand,ht)); | |
| 607 | |||
| 608 | // EXPAND | ||
| 609 | /* mahge: | ||
| 610 | Modelica spec 3.3 rev 11.1.2 | ||
| 611 | "If at least one element of an array appears on the left hand side of the assignment operator, then the | ||
| 612 | complete array is initialized in this algorithm section" | ||
| 613 | So we strip the all subs except for model subs and send the whole array to expansion. i.e. we consider the whole array as modified. | ||
| 614 | */ | ||
| 615 | case (e as DAE.CREF(componentRef=cr), (expand,ht)) | ||
| 616 | algorithm | ||
| 617 | 37795 | cr := ComponentReference.crefStripSubsExceptModelSubs(cr); | |
| 618 | // check if first element already is in the set and only expand if not (saves a lot of expand work) | ||
| 619 | // ticket #7832 | ||
| 620 | 37795 | first_cref := ComponentReference.crefArrayGetFirstCref(cr); | |
| 621 |
2/2✓ Branch 1 taken 19460 times.
✓ Branch 2 taken 18335 times.
|
37795 | if not BaseHashSet.has(first_cref, ht) then |
| 622 | 19460 | crlst := ComponentReference.expandCref(cr, true); | |
| 623 | 19460 | ht := List.fold(crlst, BaseHashSet.add, ht); | |
| 624 | end if; | ||
| 625 | 37795 | then (e, false, (expand,ht)); | |
| 626 | |||
| 627 | case (e as DAE.ASUB(exp=exp), _) | ||
| 628 | algorithm | ||
| 629 | ✗ | (_, outTpl) := Expression.traverseExpTopDown(exp, statementOutputsCrefFinder, inTpl); | |
| 630 | ✗ | then (e, false, outTpl); | |
| 631 | |||
| 632 | case (e as DAE.TSUB(exp=exp), _) | ||
| 633 | algorithm | ||
| 634 | ✗ | (_, outTpl) := Expression.traverseExpTopDown(exp, statementOutputsCrefFinder, inTpl); | |
| 635 | ✗ | then (e, false, outTpl); | |
| 636 | |||
| 637 | case (e as DAE.RELATION(), _) | ||
| 638 | then (e, false, inTpl); | ||
| 639 | |||
| 640 | case (e as DAE.RANGE(), _) | ||
| 641 | then (e, false, inTpl); | ||
| 642 | |||
| 643 | case (e as DAE.IFEXP(expThen=e1, expElse=e2), _) | ||
| 644 | algorithm | ||
| 645 | ✗ | (_, outTpl) := Expression.traverseExpTopDown(e1, statementOutputsCrefFinder, inTpl); | |
| 646 | ✗ | (_, outTpl) := Expression.traverseExpTopDown(e2, statementOutputsCrefFinder, outTpl); | |
| 647 | ✗ | then (e, false, outTpl); | |
| 648 | |||
| 649 | case (e, _) then (e, true, inTpl); | ||
| 650 | |||
| 651 | end matchcontinue; | ||
| 652 | end statementOutputsCrefFinder; | ||
| 653 | |||
| 654 | protected function countSimpleEqnSize | ||
| 655 | input list<DAE.Element> inEqns; | ||
| 656 | input Integer isimpleEqnSize; | ||
| 657 | input HashSet.HashSet ihs; | ||
| 658 | output Integer osimpleEqnSize; | ||
| 659 | algorithm | ||
| 660 | 82 | osimpleEqnSize := List.applyAndFold1(inEqns, intAdd, countSimpleEqnSizeWork, ihs, 0); | |
| 661 | end countSimpleEqnSize; | ||
| 662 | |||
| 663 | protected function countSimpleEqnSizeWork | ||
| 664 | input DAE.Element inEqns; | ||
| 665 | input HashSet.HashSet ihs; | ||
| 666 | output Integer osimpleEqnSize; | ||
| 667 | algorithm | ||
| 668 | osimpleEqnSize := matchcontinue inEqns | ||
| 669 | local | ||
| 670 | DAE.Exp e1, e2; | ||
| 671 | DAE.ComponentRef cr; | ||
| 672 | DAE.Type tp; | ||
| 673 | |||
| 674 | // equations | ||
| 675 | case DAE.EQUATION(exp=e1, scalar=e2) | ||
| 676 | 24746 | then simpleEquation(e1, e2, ihs); | |
| 677 | |||
| 678 | // effort variable equality equations | ||
| 679 | case DAE.EQUEQUATION(cr1 = cr) | ||
| 680 | algorithm | ||
| 681 | 22727 | tp := ComponentReference.crefTypeConsiderSubs(cr); | |
| 682 | 22727 | then Expression.sizeOf(tp); | |
| 683 | |||
| 684 | // a solved equation | ||
| 685 | case DAE.DEFINE(componentRef = cr, exp=e2) | ||
| 686 | algorithm | ||
| 687 | ✗ | e1 := Expression.crefExp(cr); | |
| 688 | ✗ | then simpleEquation(e1, e2, ihs); | |
| 689 | |||
| 690 | // complex equations | ||
| 691 | case DAE.COMPLEX_EQUATION(lhs = e1, rhs = e2) | ||
| 692 | 664 | then simpleEquation(e1, e2, ihs); | |
| 693 | |||
| 694 | // array equations | ||
| 695 | case DAE.ARRAY_EQUATION(exp = e1, array = e2) | ||
| 696 | 11424 | then simpleEquation(e1, e2, ihs); | |
| 697 | |||
| 698 | else 0; | ||
| 699 | end matchcontinue; | ||
| 700 | end countSimpleEqnSizeWork; | ||
| 701 | |||
| 702 | protected function simpleEquation | ||
| 703 | input DAE.Exp e1; | ||
| 704 | input DAE.Exp e2; | ||
| 705 | input HashSet.HashSet ihs; | ||
| 706 | output Integer osimpleEqnSize; | ||
| 707 | algorithm | ||
| 708 | osimpleEqnSize := matchcontinue(e1, e2) | ||
| 709 | local | ||
| 710 | list<DAE.Exp> ea1, ea2; | ||
| 711 | // a = b; | ||
| 712 | case (DAE.CREF(), DAE.CREF()) | ||
| 713 | 7628 | then | |
| 714 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 715 | // a = -b; | ||
| 716 | case (DAE.CREF(), DAE.UNARY(DAE.UMINUS(_), DAE.CREF())) | ||
| 717 | 220 | then | |
| 718 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 719 | case (DAE.CREF(), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF())) | ||
| 720 | ✗ | then | |
| 721 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 722 | // -a = b; | ||
| 723 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.CREF()) | ||
| 724 | ✗ | then | |
| 725 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 726 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.CREF()) | ||
| 727 | ✗ | then | |
| 728 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 729 | // a + b = 0 | ||
| 730 | case (DAE.BINARY(DAE.CREF(), DAE.ADD(), DAE.CREF()), _) | ||
| 731 | algorithm | ||
| 732 |
2/2✓ Branch 1 taken 102 times.
✓ Branch 2 taken 2491 times.
|
2593 | true := Expression.isZero(e2); |
| 733 | 2491 | then | |
| 734 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 735 | case (DAE.BINARY(DAE.CREF(), DAE.ADD_ARR(), DAE.CREF()), _) | ||
| 736 | algorithm | ||
| 737 | ✗ | true := Expression.isZero(e2); | |
| 738 | ✗ | then | |
| 739 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 740 | // a - b = 0 | ||
| 741 | case (DAE.BINARY(DAE.CREF(), DAE.SUB(), DAE.CREF()), _) | ||
| 742 | algorithm | ||
| 743 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1930 times.
|
1931 | true := Expression.isZero(e2); |
| 744 | 1930 | then | |
| 745 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 746 | case (DAE.BINARY(DAE.CREF(), DAE.SUB_ARR(), DAE.CREF()), _) | ||
| 747 | algorithm | ||
| 748 | ✗ | true := Expression.isZero(e2); | |
| 749 | ✗ | then | |
| 750 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 751 | // -a + b = 0 | ||
| 752 | case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.ADD(), DAE.CREF()), _) | ||
| 753 | algorithm | ||
| 754 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 99 times.
|
99 | true := Expression.isZero(e2); |
| 755 | 99 | then | |
| 756 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 757 | case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.ADD_ARR(), DAE.CREF()), _) | ||
| 758 | algorithm | ||
| 759 | ✗ | true := Expression.isZero(e2); | |
| 760 | ✗ | then | |
| 761 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 762 | // -a - b = 0 | ||
| 763 | case (DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.SUB(), DAE.CREF()), _) | ||
| 764 | algorithm | ||
| 765 | ✗ | true := Expression.isZero(e2); | |
| 766 | ✗ | then | |
| 767 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 768 | case (DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.SUB_ARR(), DAE.CREF()), _) | ||
| 769 | algorithm | ||
| 770 | ✗ | true := Expression.isZero(e2); | |
| 771 | ✗ | then | |
| 772 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 773 | // 0 = a + b | ||
| 774 | case (_, DAE.BINARY(DAE.CREF(), DAE.ADD(), DAE.CREF())) | ||
| 775 | algorithm | ||
| 776 |
2/2✓ Branch 1 taken 33 times.
✓ Branch 2 taken 907 times.
|
940 | true := Expression.isZero(e1); |
| 777 | 907 | then | |
| 778 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 779 | case (_, DAE.BINARY(DAE.CREF(), DAE.ADD_ARR(), DAE.CREF())) | ||
| 780 | algorithm | ||
| 781 | ✗ | true := Expression.isZero(e1); | |
| 782 | ✗ | then | |
| 783 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 784 | // 0 = a - b | ||
| 785 | case (_, DAE.BINARY(DAE.CREF(), DAE.SUB(), DAE.CREF())) | ||
| 786 | algorithm | ||
| 787 |
1/2✓ Branch 1 taken 360 times.
✗ Branch 2 not taken.
|
360 | true := Expression.isZero(e1); |
| 788 | ✗ | then | |
| 789 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 790 | case (_, DAE.BINARY(DAE.CREF(), DAE.SUB_ARR(), DAE.CREF())) | ||
| 791 | algorithm | ||
| 792 | ✗ | true := Expression.isZero(e1); | |
| 793 | ✗ | then | |
| 794 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 795 | // 0 = -a + b | ||
| 796 | case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.ADD(), DAE.CREF())) | ||
| 797 | algorithm | ||
| 798 | ✗ | true := Expression.isZero(e1); | |
| 799 | ✗ | then | |
| 800 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 801 | case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.ADD_ARR(), DAE.CREF())) | ||
| 802 | algorithm | ||
| 803 | ✗ | true := Expression.isZero(e1); | |
| 804 | ✗ | then | |
| 805 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 806 | // 0 = -a - b | ||
| 807 | case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.SUB(), DAE.CREF())) | ||
| 808 | algorithm | ||
| 809 | ✗ | true := Expression.isZero(e1); | |
| 810 | ✗ | then | |
| 811 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 812 | case (_, DAE.BINARY(DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.SUB_ARR(), DAE.CREF())) | ||
| 813 | algorithm | ||
| 814 | ✗ | true := Expression.isZero(e1); | |
| 815 | ✗ | then | |
| 816 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 817 | // a = der(b); | ||
| 818 | case (DAE.CREF(), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})) | ||
| 819 | 2524 | then | |
| 820 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 821 | // der(a) = b; | ||
| 822 | case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.CREF()) | ||
| 823 | 6 | then | |
| 824 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 825 | // a = -der(b); | ||
| 826 | case (DAE.CREF(), DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))) | ||
| 827 | ✗ | then | |
| 828 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 829 | case (DAE.CREF(), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))) | ||
| 830 | ✗ | then | |
| 831 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 832 | // -der(a) = b; | ||
| 833 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.CREF()) | ||
| 834 | ✗ | then | |
| 835 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 836 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.CREF()) | ||
| 837 | ✗ | then | |
| 838 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 839 | // -a = der(b); | ||
| 840 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})) | ||
| 841 | ✗ | then | |
| 842 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 843 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})) | ||
| 844 | ✗ | then | |
| 845 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 846 | // der(a) = -b; | ||
| 847 | case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.UNARY(DAE.UMINUS(_), DAE.CREF())) | ||
| 848 | 1 | then | |
| 849 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 850 | case (DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF())) | ||
| 851 | ✗ | then | |
| 852 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 853 | // -a = -der(b); | ||
| 854 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))) | ||
| 855 | ✗ | then | |
| 856 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 857 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()}))) | ||
| 858 | ✗ | then | |
| 859 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 860 | // -der(a) = -b; | ||
| 861 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.UNARY(DAE.UMINUS(_), DAE.CREF())) | ||
| 862 | ✗ | then | |
| 863 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 864 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CALL(path = Absyn.IDENT(name = "der"), expLst = {DAE.CREF()})), DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF())) | ||
| 865 | ✗ | then | |
| 866 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 867 | |||
| 868 | // a = const; | ||
| 869 | case (DAE.CREF(), _) | ||
| 870 | algorithm | ||
| 871 |
2/2✓ Branch 1 taken 6880 times.
✓ Branch 2 taken 11184 times.
|
18064 | true := Expression.isConst(e2); |
| 872 | 11184 | then | |
| 873 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 874 | // const = a; | ||
| 875 | case (_, DAE.CREF()) | ||
| 876 | algorithm | ||
| 877 |
2/2✓ Branch 1 taken 136 times.
✓ Branch 2 taken 43 times.
|
179 | true := Expression.isConst(e1); |
| 878 | 43 | then | |
| 879 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 880 | |||
| 881 | // -a = const; | ||
| 882 | case (DAE.UNARY(DAE.UMINUS(_), DAE.CREF()), _) | ||
| 883 | algorithm | ||
| 884 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
3 | true := Expression.isConst(e2); |
| 885 | ✗ | then | |
| 886 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 887 | case (DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF()), _) | ||
| 888 | algorithm | ||
| 889 | ✗ | true := Expression.isConst(e2); | |
| 890 | ✗ | then | |
| 891 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 892 | // const = -a; | ||
| 893 | case (_, DAE.UNARY(DAE.UMINUS(_), DAE.CREF())) | ||
| 894 | algorithm | ||
| 895 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | true := Expression.isConst(e1); |
| 896 | ✗ | then | |
| 897 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 898 | case (_, DAE.UNARY(DAE.UMINUS_ARR(_), DAE.CREF())) | ||
| 899 | algorithm | ||
| 900 | ✗ | true := Expression.isConst(e1); | |
| 901 | ✗ | then | |
| 902 | Expression.sizeOf(Expression.typeof(e2)); | ||
| 903 | |||
| 904 | case(_, _) | ||
| 905 | algorithm | ||
| 906 |
3/4✓ Branch 1 taken 9678 times.
✓ Branch 2 taken 123 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9678 times.
|
9801 | true := Expression.isArray(e1) or Expression.isMatrix(e1); |
| 907 |
2/4✓ Branch 1 taken 123 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 123 times.
✗ Branch 5 not taken.
|
123 | true := Expression.isArray(e2) or Expression.isMatrix(e2); |
| 908 | ✗ | ea1 := Expression.flattenArrayExpToList(e1); | |
| 909 | ✗ | ea2 := Expression.flattenArrayExpToList(e2); | |
| 910 | ✗ | then | |
| 911 | simpleEquations(ea1, ea2, 0, ihs); | ||
| 912 | |||
| 913 | case(_, _) | ||
| 914 | algorithm | ||
| 915 |
4/4✓ Branch 3 taken 1 time.
✓ Branch 4 taken 9493 times.
✓ Branch 5 taken 9367 times.
✓ Branch 6 taken 126 times.
|
9801 | (_, (_, _::{})) := Expression.traverseExpBottomUp(Expression.expSub(e1, e2), traversingComponentRefFinder, (ihs, {})); |
| 916 | 126 | then | |
| 917 | Expression.sizeOf(Expression.typeof(e1)); | ||
| 918 | |||
| 919 | else | ||
| 920 | then | ||
| 921 | 0; | ||
| 922 | end matchcontinue; | ||
| 923 | end simpleEquation; | ||
| 924 | |||
| 925 | protected function traversingComponentRefFinder | ||
| 926 | input DAE.Exp inExp; | ||
| 927 | input tuple<HashSet.HashSet, list<DAE.ComponentRef>> inTpl; | ||
| 928 | output DAE.Exp outExp; | ||
| 929 | output tuple<HashSet.HashSet, list<DAE.ComponentRef>> outTpl; | ||
| 930 | algorithm | ||
| 931 | (outExp,outTpl) := matchcontinue (inExp,inTpl) | ||
| 932 | local | ||
| 933 | HashSet.HashSet hs; | ||
| 934 | list<DAE.ComponentRef> crefs, crlst; | ||
| 935 | DAE.ComponentRef cr; | ||
| 936 | DAE.Exp e; | ||
| 937 | |||
| 938 | case (DAE.CREF(componentRef = DAE.WILD()), _) | ||
| 939 | then (inExp,inTpl); | ||
| 940 | |||
| 941 | case (e as DAE.CREF(componentRef=cr), (hs, crefs)) | ||
| 942 | algorithm | ||
| 943 | 49741 | crlst := ComponentReference.expandCref(cr, true); | |
| 944 | 49741 | crefs := getcr(crlst, hs, crefs); | |
| 945 | 49741 | then (e, (hs, crefs)); | |
| 946 | |||
| 947 | else (inExp,inTpl); | ||
| 948 | |||
| 949 | end matchcontinue; | ||
| 950 | end traversingComponentRefFinder; | ||
| 951 | |||
| 952 | protected function getcr | ||
| 953 | input list<DAE.ComponentRef> crefs; | ||
| 954 | input HashSet.HashSet hs; | ||
| 955 | input list<DAE.ComponentRef> iAcc; | ||
| 956 | output list<DAE.ComponentRef> oAcc; | ||
| 957 | algorithm | ||
| 958 | oAcc := match crefs | ||
| 959 | local | ||
| 960 | DAE.ComponentRef cr; | ||
| 961 | list<DAE.ComponentRef> rest, crlst; | ||
| 962 | case {} then iAcc; | ||
| 963 | case cr::rest guard BaseHashSet.has(cr, hs) | ||
| 964 | algorithm | ||
| 965 | 75078 | crlst := List.unionEltOnTrue(cr, iAcc, ComponentReferenceBasics.crefEqual); | |
| 966 | 75078 | then | |
| 967 | getcr(rest, hs, crlst); | ||
| 968 | case _::rest | ||
| 969 | 12041 | then | |
| 970 | getcr(rest, hs, iAcc); | ||
| 971 | end match; | ||
| 972 | end getcr; | ||
| 973 | |||
| 974 | protected function simpleEquations | ||
| 975 | input list<DAE.Exp> e1lst; | ||
| 976 | input list<DAE.Exp> e2lst; | ||
| 977 | input Integer isimpleEqnSize; | ||
| 978 | input HashSet.HashSet ihs; | ||
| 979 | output Integer osimpleEqnSize; | ||
| 980 | algorithm | ||
| 981 | osimpleEqnSize := match(e1lst, e2lst) | ||
| 982 | local | ||
| 983 | DAE.Exp e1, e2; | ||
| 984 | list<DAE.Exp> r1, r2; | ||
| 985 | Integer size; | ||
| 986 | case ({}, {}) then isimpleEqnSize; | ||
| 987 | case (e1::r1, e2::r2) | ||
| 988 | algorithm | ||
| 989 | ✗ | size := simpleEquation(e1, e2, ihs); | |
| 990 | ✗ | then | |
| 991 | simpleEquations(r1, r2, size+isimpleEqnSize, ihs); | ||
| 992 | end match; | ||
| 993 | end simpleEquations; | ||
| 994 | |||
| 995 | annotation(__OpenModelica_Interface="frontend"); | ||
| 996 | end CheckModel; | ||
| 997 |