OMCompiler/Compiler/NFFrontEnd/NFBackendExtension.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 NFBackendExtension | ||
| 37 | " ========================================================================== | ||
| 38 | kabdelhak: The following structures are used only in the backend to avoid a | ||
| 39 | forward dependency of the frontend to the backend. All functions for these | ||
| 40 | structures are defined in NBVariable.mo | ||
| 41 | ========================================================================== " | ||
| 42 | |||
| 43 | protected | ||
| 44 | // OF imports | ||
| 45 | import Absyn; | ||
| 46 | import AbsynUtil; | ||
| 47 | import DAE; | ||
| 48 | import Dump; | ||
| 49 | import SCode; | ||
| 50 | import SCodeUtil; | ||
| 51 | |||
| 52 | //NF imports | ||
| 53 | import Attributes = NFAttributes; | ||
| 54 | import NFBinding.Binding; | ||
| 55 | import NFBinding.Source; | ||
| 56 | import Call = NFCall; | ||
| 57 | import Ceval = NFCeval; | ||
| 58 | import ComplexType = NFComplexType; | ||
| 59 | import NFComponent.Component; | ||
| 60 | import ComponentRef = NFComponentRef; | ||
| 61 | import Dimension = NFDimension; | ||
| 62 | import Expression = NFExpression; | ||
| 63 | import ExpressionIterator = NFExpressionIterator; | ||
| 64 | import NFFunction.Function; | ||
| 65 | import NFPrefixes.{Direction, Variability}; | ||
| 66 | import NFInstNode.InstNode; | ||
| 67 | import Type = NFType; | ||
| 68 | import Variable = NFVariable; | ||
| 69 | |||
| 70 | // Util imports | ||
| 71 | import Pointer; | ||
| 72 | import PointerWeak; | ||
| 73 | import UnorderedMap; | ||
| 74 | import MetaModelica.Dangerous.listReverseInPlace; | ||
| 75 | |||
| 76 | public | ||
| 77 | uniontype BackendInfo | ||
| 78 | record BACKEND_INFO | ||
| 79 | VariableKind varKind "Structural kind: state, algebraic..."; | ||
| 80 | VariableAttributes attributes "values on built-in attributes"; | ||
| 81 | Annotations annotations "values on annotations (vendor specific)"; | ||
| 82 | Option<PointerWeak<Variable>> var_pre "Pointer (var -> pre) or (pre -> var) if existent."; | ||
| 83 | Option<PointerWeak<Variable>> var_seed "Pointer (var -> seed) or (seed -> var) if existent."; | ||
| 84 | Option<PointerWeak<Variable>> var_pder_res "Pointer (var -> pder, result var in Jacobian) or (pder -> var) if existent."; | ||
| 85 | Option<PointerWeak<Variable>> var_pder_tmp "Pointer (var -> pder, tmp var in Jacobian) or (pder -> var) if existent."; | ||
| 86 | Option<PointerWeak<Variable>> var_start "Pointer (var -> start) or (start -> var) if existent."; | ||
| 87 | Option<PointerWeak<Variable>> parent "record parent if it is part of a record."; | ||
| 88 | end BACKEND_INFO; | ||
| 89 | |||
| 90 | function toString | ||
| 91 | input BackendInfo backendInfo; | ||
| 92 | output String str; | ||
| 93 | algorithm | ||
| 94 | ✗ | str := VariableAttributes.toString(backendInfo.attributes); | |
| 95 | ✗ | str := VariableKind.toString(backendInfo.varKind) + (if str == "" then "" else " " + str); | |
| 96 | end toString; | ||
| 97 | |||
| 98 | function map | ||
| 99 | input output BackendInfo binfo; | ||
| 100 | input expFunc func; | ||
| 101 | partial function expFunc | ||
| 102 | input output Expression exp; | ||
| 103 | end expFunc; | ||
| 104 | algorithm | ||
| 105 | 28789 | binfo.attributes := VariableAttributes.map(binfo.attributes, func); | |
| 106 | end map; | ||
| 107 | |||
| 108 | function getVarKind | ||
| 109 | input BackendInfo binfo; | ||
| 110 | output VariableKind varKind = binfo.varKind; | ||
| 111 | end getVarKind; | ||
| 112 | |||
| 113 | function setVarKind | ||
| 114 | input output BackendInfo binfo; | ||
| 115 | input VariableKind varKind; | ||
| 116 | algorithm | ||
| 117 | 16067 | binfo.varKind := varKind; | |
| 118 | end setVarKind; | ||
| 119 | |||
| 120 | function setStateSelect | ||
| 121 | input output BackendInfo info; | ||
| 122 | input StateSelect stateSelect_val; | ||
| 123 | input Boolean overwrite = false; | ||
| 124 | algorithm | ||
| 125 | 110 | info.attributes := VariableAttributes.setStateSelect(info.attributes, stateSelect_val, overwrite); | |
| 126 | end setStateSelect; | ||
| 127 | |||
| 128 | function setParent | ||
| 129 | input output BackendInfo binfo; | ||
| 130 | input Pointer<Variable> parent; | ||
| 131 | algorithm | ||
| 132 | 804 | binfo.parent := SOME(PointerWeak.downgrade(parent)); | |
| 133 | end setParent; | ||
| 134 | |||
| 135 | function weaken | ||
| 136 | "A partner edge owns nothing: the variable is in `VariablePointers`." | ||
| 137 | input Option<Pointer<Variable>> strong; | ||
| 138 | output Option<PointerWeak<Variable>> weak; | ||
| 139 | algorithm | ||
| 140 | weak := match strong | ||
| 141 | local Pointer<Variable> p; | ||
| 142 | 4683 | case SOME(p) then SOME(PointerWeak.downgrade(p)); | |
| 143 | else NONE(); | ||
| 144 | end match; | ||
| 145 | end weaken; | ||
| 146 | |||
| 147 | function strengthen | ||
| 148 | "NONE() if the partner is gone, which the callers already handle." | ||
| 149 | input Option<PointerWeak<Variable>> weak; | ||
| 150 | output Option<Pointer<Variable>> strong; | ||
| 151 | algorithm | ||
| 152 | strong := matchcontinue weak | ||
| 153 | local PointerWeak<Variable> w; | ||
| 154 | 4100 | case SOME(w) then SOME(PointerWeak.upgrade(w)); | |
| 155 | else NONE(); | ||
| 156 | end matchcontinue; | ||
| 157 | end strengthen; | ||
| 158 | |||
| 159 | partial function setPartner | ||
| 160 | input output BackendInfo binfo; | ||
| 161 | input Option<Pointer<Variable>> var_ptr; | ||
| 162 | end setPartner; | ||
| 163 | |||
| 164 | function setVarPre extends setPartner; | ||
| 165 | algorithm | ||
| 166 | 162 | binfo.var_pre := weaken(var_ptr); | |
| 167 | end setVarPre; | ||
| 168 | |||
| 169 | function setVarSeed extends setPartner; | ||
| 170 | algorithm | ||
| 171 | 1492 | binfo.var_seed := weaken(var_ptr); | |
| 172 | end setVarSeed; | ||
| 173 | |||
| 174 | function setVarPDer extends setPartner; | ||
| 175 | input Boolean isTmp; | ||
| 176 | algorithm | ||
| 177 |
2/2✓ Branch 0 taken 684 times.
✓ Branch 1 taken 1694 times.
|
2378 | if isTmp then |
| 178 | 684 | binfo.var_pder_tmp := weaken(var_ptr); | |
| 179 | else | ||
| 180 | 1694 | binfo.var_pder_res := weaken(var_ptr); | |
| 181 | end if; | ||
| 182 | end setVarPDer; | ||
| 183 | |||
| 184 | function setVarStart extends setPartner; | ||
| 185 | algorithm | ||
| 186 | 406 | binfo.var_start := weaken(var_ptr); | |
| 187 | end setVarStart; | ||
| 188 | |||
| 189 | function setAttributes | ||
| 190 | input output BackendInfo binfo; | ||
| 191 | input VariableAttributes attributes; | ||
| 192 | input Annotations annotations; | ||
| 193 | algorithm | ||
| 194 | 5554 | binfo.attributes := attributes; | |
| 195 | binfo.annotations := annotations; | ||
| 196 | end setAttributes; | ||
| 197 | |||
| 198 | function setHideResult | ||
| 199 | input output BackendInfo binfo; | ||
| 200 | input Boolean hideResult; | ||
| 201 | algorithm | ||
| 202 | binfo := match binfo | ||
| 203 | local | ||
| 204 | Annotations anno; | ||
| 205 | case BACKEND_INFO(annotations = anno as ANNOTATIONS()) algorithm | ||
| 206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 967 times.
|
967 | anno.hideResult := hideResult; |
| 207 | 967 | binfo.annotations := anno; | |
| 208 | then binfo; | ||
| 209 | else binfo; | ||
| 210 | end match; | ||
| 211 | end setHideResult; | ||
| 212 | |||
| 213 | function scalarize | ||
| 214 | input BackendInfo binfo; | ||
| 215 | input Integer length; | ||
| 216 | output list<BackendInfo> binfo_list; | ||
| 217 | algorithm | ||
| 218 | binfo_list := match binfo.varKind | ||
| 219 | local | ||
| 220 | list<VariableAttributes> scalar_attributes; | ||
| 221 | Boolean uniform; | ||
| 222 | 47468 | case VariableKind.FRONTEND_DUMMY() then List.fill(binfo, length); | |
| 223 | else algorithm | ||
| 224 | 1483 | (scalar_attributes, uniform) := VariableAttributes.scalarize(binfo.attributes, length); | |
| 225 |
2/2✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 475 times.
|
1483 | if uniform then |
| 226 | 1008 | binfo.attributes := listHead(scalar_attributes); | |
| 227 | end if; | ||
| 228 |
6/6✓ Branch 0 taken 1008 times.
✓ Branch 1 taken 475 times.
✓ Branch 3 taken 3651 times.
✓ Branch 4 taken 475 times.
✓ Branch 5 taken 3651 times.
✓ Branch 6 taken 475 times.
|
5134 | then if uniform then List.fill(binfo, length) else |
| 229 | list(BACKEND_INFO(binfo.varKind, attr, binfo.annotations, binfo.var_pre, binfo.var_seed, binfo.var_pder_res, binfo.var_pder_tmp, binfo.var_start, binfo.parent) for attr in scalar_attributes); | ||
| 230 | end match; | ||
| 231 | end scalarize; | ||
| 232 | end BackendInfo; | ||
| 233 | |||
| 234 | constant BackendInfo DUMMY_BACKEND_INFO = BackendInfo.BACKEND_INFO(VariableKind.FRONTEND_DUMMY(), EMPTY_VAR_ATTR_REAL, EMPTY_ANNOTATIONS, NONE(), NONE(), NONE(), NONE(), NONE(), NONE()); | ||
| 235 | |||
| 236 | uniontype VariableKind | ||
| 237 | record TIME end TIME; | ||
| 238 | record ALGEBRAIC end ALGEBRAIC; | ||
| 239 | record STATE | ||
| 240 | Integer index "how often this states was differentiated"; | ||
| 241 | Option<PointerWeak<Variable>> derivative "pointer to the derivative"; | ||
| 242 | Boolean natural "false if it was forced by StateSelect.always or StateSelect.prefer or generated by index reduction"; | ||
| 243 | end STATE; | ||
| 244 | record STATE_DER | ||
| 245 | PointerWeak<Variable> state "Original state"; | ||
| 246 | Option<Pointer<Expression>> alias "Optional alias state expression. Result of differentiating the state if existant!"; | ||
| 247 | end STATE_DER; | ||
| 248 | record DUMMY_DER | ||
| 249 | PointerWeak<Variable> dummy_state "corresponding dummy state"; | ||
| 250 | end DUMMY_DER; | ||
| 251 | record DUMMY_STATE | ||
| 252 | PointerWeak<Variable> dummy_der "corresponding dummy derivative"; | ||
| 253 | end DUMMY_STATE; // ToDo: maybe dynamic state for dynamic state selection in index reduction | ||
| 254 | record DISCRETE end DISCRETE; | ||
| 255 | record DISCRETE_STATE end DISCRETE_STATE; | ||
| 256 | record PREVIOUS end PREVIOUS; | ||
| 257 | record CLOCK end CLOCK; | ||
| 258 | record CLOCKED end CLOCKED; | ||
| 259 | record PARAMETER | ||
| 260 | Option<Integer> resize_value "if the parameter is resizable, this is the computed optimal size"; | ||
| 261 | end PARAMETER; | ||
| 262 | record CONSTANT end CONSTANT; | ||
| 263 | record ITERATOR end ITERATOR; | ||
| 264 | record RECORD | ||
| 265 | list<PointerWeak<Variable>> children; | ||
| 266 | Variability min_var; | ||
| 267 | Variability max_var; | ||
| 268 | end RECORD; | ||
| 269 | record START | ||
| 270 | PointerWeak<Variable> original "Pointer to the corresponding original variable."; | ||
| 271 | end START; | ||
| 272 | record EXTOBJ | ||
| 273 | Absyn.Path fullClassName; | ||
| 274 | end EXTOBJ; | ||
| 275 | record JAC_VAR end JAC_VAR; | ||
| 276 | record JAC_TMP_VAR end JAC_TMP_VAR; | ||
| 277 | record SEED_VAR end SEED_VAR; | ||
| 278 | record OPT_CONSTR end OPT_CONSTR; | ||
| 279 | record OPT_FCONSTR end OPT_FCONSTR; | ||
| 280 | record OPT_INPUT_WITH_DER end OPT_INPUT_WITH_DER; | ||
| 281 | record OPT_INPUT_DER end OPT_INPUT_DER; | ||
| 282 | record OPT_TGRID end OPT_TGRID; | ||
| 283 | record OPT_LOOP_INPUT | ||
| 284 | ComponentRef replaceCref; | ||
| 285 | end OPT_LOOP_INPUT; | ||
| 286 | // ToDo maybe deprecated: | ||
| 287 | record ALG_STATE "algebraic state used by inline solver" end ALG_STATE; | ||
| 288 | record ALG_STATE_OLD "algebraic state old value used by inline solver" end ALG_STATE_OLD; | ||
| 289 | record RESIDUAL_VAR end RESIDUAL_VAR; | ||
| 290 | record DAE_AUX_VAR "auxiliary variable used for DAEmode" end DAE_AUX_VAR; | ||
| 291 | record LOOP_ITERATION "used in SIMCODE, iteration variables in algebraic loops" end LOOP_ITERATION; | ||
| 292 | record LOOP_SOLVED "used in SIMCODE, inner variables of a torn algebraic loop" end LOOP_SOLVED; | ||
| 293 | record FRONTEND_DUMMY "Undefined variable type. Only to be used during frontend phase." end FRONTEND_DUMMY; | ||
| 294 | |||
| 295 | function toString | ||
| 296 | input VariableKind varKind; | ||
| 297 | output String str; | ||
| 298 | algorithm | ||
| 299 | str := match varKind | ||
| 300 | case TIME() then "[TIME]"; | ||
| 301 | case ALGEBRAIC() then "[ALGB]"; | ||
| 302 | case STATE() then "[STAT]"; | ||
| 303 | case STATE_DER() then "[DER-]"; | ||
| 304 | case DUMMY_DER() then "[DDER]"; | ||
| 305 | case DUMMY_STATE() then "[DSTA]"; | ||
| 306 | case DISCRETE() then "[DISC]"; | ||
| 307 | case DISCRETE_STATE() then "[DISS]"; | ||
| 308 | case PREVIOUS() then "[PRE-]"; | ||
| 309 | case CLOCK() then "[CLCK]"; | ||
| 310 | case CLOCKED() then "[CLKD]"; | ||
| 311 | case PARAMETER() then "[PRMT]"; | ||
| 312 | case CONSTANT() then "[CNST]"; | ||
| 313 | case ITERATOR() then "[ITER]"; | ||
| 314 | case RECORD() then "[RECD]"; | ||
| 315 | case START() then "[STRT]"; | ||
| 316 | case EXTOBJ() then "[EXTO]"; | ||
| 317 | case JAC_VAR() then "[JVAR]"; | ||
| 318 | case JAC_TMP_VAR() then "[JTMP]"; | ||
| 319 | case SEED_VAR() then "[SEED]"; | ||
| 320 | case OPT_CONSTR() then "[OPT][CONS]"; | ||
| 321 | case OPT_FCONSTR() then "[OPT][FCON]"; | ||
| 322 | case OPT_INPUT_WITH_DER() then "[OPT][INWD]"; | ||
| 323 | case OPT_INPUT_DER() then "[OPT][INPD]"; | ||
| 324 | case OPT_TGRID() then "[OPT][TGRD]"; | ||
| 325 | case OPT_LOOP_INPUT() then "[OPT][LOOP]"; | ||
| 326 | case ALG_STATE() then "[ASTA]"; | ||
| 327 | case RESIDUAL_VAR() then "[RES-]"; | ||
| 328 | case DAE_AUX_VAR() then "[AUX-]"; | ||
| 329 | case LOOP_ITERATION() then "[LOOP]"; | ||
| 330 | case LOOP_SOLVED() then "[INNR]"; | ||
| 331 | case FRONTEND_DUMMY() then "[DMMY]"; | ||
| 332 | else "[FAIL] " + getInstanceName() + " failed."; | ||
| 333 | end match; | ||
| 334 | end toString; | ||
| 335 | |||
| 336 | function isTimeDependent | ||
| 337 | input VariableKind varKind; | ||
| 338 | output Boolean b; | ||
| 339 | algorithm | ||
| 340 | // ToDo: check other types! | ||
| 341 | b := match varKind | ||
| 342 | case PARAMETER() then false; | ||
| 343 | case CONSTANT() then false; | ||
| 344 | case ITERATOR() then false; | ||
| 345 | case START() then false; | ||
| 346 | else true; | ||
| 347 | end match; | ||
| 348 | end isTimeDependent; | ||
| 349 | |||
| 350 | function fromType | ||
| 351 | "only creates record, parameter, discrete or algebraic kind" | ||
| 352 | input Type ty; | ||
| 353 | input Boolean makeParam; | ||
| 354 | output VariableKind varKind; | ||
| 355 | protected | ||
| 356 | Variability variability; | ||
| 357 | algorithm | ||
| 358 |
2/2✓ Branch 2 taken 48 times.
✓ Branch 3 taken 777 times.
|
825 | if Type.isRecord(Type.arrayElementType(ty)) then |
| 359 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 2 times.
|
48 | variability := if makeParam then NFPrefixes.Variability.PARAMETER else NFPrefixes.Variability.CONTINUOUS; |
| 360 | 48 | varKind := RECORD({}, variability, variability); // ToDo: children! | |
| 361 | elseif makeParam then | ||
| 362 | varKind := PARAMETER(NONE()); | ||
| 363 | elseif Type.isDiscrete(ty) then | ||
| 364 | varKind := DISCRETE(); | ||
| 365 | else | ||
| 366 | varKind := ALGEBRAIC(); | ||
| 367 | end if; | ||
| 368 | end fromType; | ||
| 369 | end VariableKind; | ||
| 370 | |||
| 371 | uniontype VariableAttributes | ||
| 372 | record VAR_ATTR_REAL | ||
| 373 | Option<Binding> quantity "quantity"; | ||
| 374 | Option<Binding> unit "SI Unit for actual computation value"; | ||
| 375 | Option<Binding> displayUnit "SI Unit only for displaying"; | ||
| 376 | Option<Binding> min "Lower boundry"; | ||
| 377 | Option<Binding> max "Upper boundry"; | ||
| 378 | Option<Binding> start "start value"; | ||
| 379 | Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 380 | Option<Binding> nominal "nominal"; | ||
| 381 | Option<StateSelect> stateSelect "Priority to be selected as a state during index reduction"; | ||
| 382 | Option<TearingSelect> tearingSelect "Priority to be selected as an iteration variable during tearing"; | ||
| 383 | Option<Uncertainty> uncertainty "Attributes from data reconcilliation"; | ||
| 384 | Option<Distribution> distribution "ToDo: ???"; | ||
| 385 | Option<Binding> binding "A binding expression for certain types. E.G. parameters"; | ||
| 386 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 387 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 388 | end VAR_ATTR_REAL; | ||
| 389 | |||
| 390 | record VAR_ATTR_INT | ||
| 391 | Option<Binding> quantity "quantity"; | ||
| 392 | Option<Binding> min "Lower boundry"; | ||
| 393 | Option<Binding> max "Upper boundry"; | ||
| 394 | Option<Binding> start "start value"; | ||
| 395 | Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 396 | Option<Uncertainty> uncertainty "Attributes from data reconcilliation"; | ||
| 397 | Option<Distribution> distribution "ToDo: ???"; | ||
| 398 | Option<Binding> binding "A binding expression for certain types. E.G. parameters"; | ||
| 399 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 400 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 401 | end VAR_ATTR_INT; | ||
| 402 | |||
| 403 | record VAR_ATTR_BOOL | ||
| 404 | Option<Binding> quantity "quantity"; | ||
| 405 | Option<Binding> start "start value"; | ||
| 406 | Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 407 | Option<Binding> binding "A binding expression for certain types. E.G. parameters"; | ||
| 408 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 409 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 410 | end VAR_ATTR_BOOL; | ||
| 411 | |||
| 412 | record VAR_ATTR_CLOCK | ||
| 413 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 414 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 415 | end VAR_ATTR_CLOCK; | ||
| 416 | |||
| 417 | record VAR_ATTR_STRING | ||
| 418 | "kabdelhak: why does string have quantity/start/fixed?" | ||
| 419 | Option<Binding> quantity "quantity"; | ||
| 420 | Option<Binding> start "start value"; | ||
| 421 | Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 422 | Option<Binding> binding "A binding expression for certain types. E.G. parameters"; | ||
| 423 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 424 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 425 | end VAR_ATTR_STRING; | ||
| 426 | |||
| 427 | record VAR_ATTR_ENUMERATION | ||
| 428 | Option<Binding> quantity "quantity"; | ||
| 429 | Option<Binding> min "Lower boundry"; | ||
| 430 | Option<Binding> max "Upper boundry"; | ||
| 431 | Option<Binding> start "start value"; | ||
| 432 | Option<Binding> fixed "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 433 | Option<Binding> binding "A binding expression for certain types. E.G. parameters"; | ||
| 434 | Option<Boolean> isProtected "Defined in protected scope"; | ||
| 435 | Option<Boolean> finalPrefix "Defined as final"; | ||
| 436 | end VAR_ATTR_ENUMERATION; | ||
| 437 | |||
| 438 | record VAR_ATTR_RECORD | ||
| 439 | UnorderedMap<String, Integer> indexMap; | ||
| 440 | array<VariableAttributes> childrenAttr; | ||
| 441 | end VAR_ATTR_RECORD; | ||
| 442 | |||
| 443 | type VarType = enumeration(ENUMERATION, CLOCK, STRING); | ||
| 444 | |||
| 445 | function toString | ||
| 446 | input VariableAttributes attr; | ||
| 447 | output String str = ""; | ||
| 448 | algorithm | ||
| 449 | str := match attr | ||
| 450 | case VAR_ATTR_REAL() | ||
| 451 | 1944 | then attributesToString({ | |
| 452 | ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)), | ||
| 453 | ("start", Util.applyOption(attr.start, Binding.getTypedExp)), | ||
| 454 | ("min", Util.applyOption(attr.min, Binding.getTypedExp)), | ||
| 455 | ("max", Util.applyOption(attr.max, Binding.getTypedExp)), | ||
| 456 | ("nominal", Util.applyOption(attr.nominal, Binding.getTypedExp)) | ||
| 457 | }, attr.stateSelect, attr.tearingSelect); | ||
| 458 | |||
| 459 | case VAR_ATTR_INT() | ||
| 460 | 192 | then attributesToString({ | |
| 461 | ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)), | ||
| 462 | ("start", Util.applyOption(attr.start, Binding.getTypedExp)), | ||
| 463 | ("min", Util.applyOption(attr.min, Binding.getTypedExp)), | ||
| 464 | ("max", Util.applyOption(attr.max, Binding.getTypedExp)) | ||
| 465 | }, NONE(), NONE()); | ||
| 466 | |||
| 467 | case VAR_ATTR_BOOL() | ||
| 468 | ✗ | then attributesToString({ | |
| 469 | ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)), | ||
| 470 | ("start", Util.applyOption(attr.start, Binding.getTypedExp)) | ||
| 471 | }, NONE(), NONE()); | ||
| 472 | |||
| 473 | case VAR_ATTR_CLOCK() | ||
| 474 | then ""; | ||
| 475 | |||
| 476 | case VAR_ATTR_STRING() | ||
| 477 | ✗ | then attributesToString({ | |
| 478 | ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)), | ||
| 479 | ("start", Util.applyOption(attr.start, Binding.getTypedExp)) | ||
| 480 | }, NONE(), NONE()); | ||
| 481 | |||
| 482 | case VAR_ATTR_ENUMERATION() | ||
| 483 | ✗ | then attributesToString({ | |
| 484 | ("fixed", Util.applyOption(attr.fixed, Binding.getTypedExp)), | ||
| 485 | ("start", Util.applyOption(attr.start, Binding.getTypedExp)), | ||
| 486 | ("min", Util.applyOption(attr.min, Binding.getTypedExp)), | ||
| 487 | ("max", Util.applyOption(attr.max, Binding.getTypedExp)) | ||
| 488 | }, NONE(), NONE()); | ||
| 489 | |||
| 490 | case VAR_ATTR_RECORD() | ||
| 491 | ✗ | then List.toString(UnorderedMap.toList(attr.indexMap), function recordString(childrenAttr = attr.childrenAttr), List.Style.FLAT); | |
| 492 | |||
| 493 | else getInstanceName() + " failed. Attribute string could not be created."; | ||
| 494 | end match; | ||
| 495 | // put the string in parentheses only if it is not empty | ||
| 496 |
3/4✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1053 times.
|
1068 | str := if "" == str then "" else "(" + str + ")"; |
| 497 | end toString; | ||
| 498 | |||
| 499 | function recordString | ||
| 500 | input tuple<String, Integer> attr_tpl; | ||
| 501 | input array<VariableAttributes> childrenAttr; | ||
| 502 | output String str; | ||
| 503 | protected | ||
| 504 | String name; | ||
| 505 | Integer index; | ||
| 506 | algorithm | ||
| 507 | ✗ | (name, index) := attr_tpl; | |
| 508 | ✗ | str := name + toString(childrenAttr[index]); | |
| 509 | end recordString; | ||
| 510 | |||
| 511 | function create | ||
| 512 | input list<tuple<String, Binding>> attrs; | ||
| 513 | input Type ty; | ||
| 514 | input Attributes compAttrs; | ||
| 515 | input list<Variable> children; | ||
| 516 | input SCode.Comment comment; | ||
| 517 | output VariableAttributes attributes; | ||
| 518 | protected | ||
| 519 | Boolean is_final; | ||
| 520 | ComplexType complexTy; | ||
| 521 | algorithm | ||
| 522 |
4/4✓ Branch 0 taken 13435 times.
✓ Branch 1 taken 975 times.
✓ Branch 2 taken 13373 times.
✓ Branch 3 taken 62 times.
|
14410 | is_final := compAttrs.isFinal or |
| 523 | compAttrs.variability == Variability.STRUCTURAL_PARAMETER; | ||
| 524 | |||
| 525 | attributes := match Type.arrayElementType(ty) | ||
| 526 | 7637 | case Type.REAL() then createReal(attrs, is_final, comment); | |
| 527 | 5830 | case Type.INTEGER() then createInt(attrs, is_final); | |
| 528 | 645 | case Type.BOOLEAN() then createBool(attrs, is_final); | |
| 529 | 30 | case Type.STRING() then createString(attrs, is_final); | |
| 530 | 70 | case Type.ENUMERATION() then createEnum(attrs, is_final); | |
| 531 | 39 | case Type.CLOCK() then createClock(is_final); | |
| 532 | case Type.COMPLEX(complexTy = complexTy as ComplexType.RECORD()) | ||
| 533 | 156 | then createRecord(attrs, complexTy.indexMap, children, is_final); | |
| 534 | |||
| 535 | 3 | else createReal(attrs, is_final, comment); | |
| 536 | end match; | ||
| 537 | end create; | ||
| 538 | |||
| 539 | function map | ||
| 540 | input output VariableAttributes attributes; | ||
| 541 | input expFunc func; | ||
| 542 | partial function expFunc | ||
| 543 | input output Expression exp; | ||
| 544 | end expFunc; | ||
| 545 | algorithm | ||
| 546 | attributes := match attributes | ||
| 547 | case VAR_ATTR_REAL() algorithm | ||
| 548 | 53266 | attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func)); | |
| 549 | 53266 | attributes.unit := Util.applyOption(attributes.unit, function Binding.mapExp(mapFn = func)); | |
| 550 | 53266 | attributes.displayUnit := Util.applyOption(attributes.displayUnit, function Binding.mapExp(mapFn = func)); | |
| 551 | 53266 | attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func)); | |
| 552 | 53266 | attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func)); | |
| 553 | 53266 | attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func)); | |
| 554 | 53266 | attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func)); | |
| 555 | 53266 | attributes.nominal := Util.applyOption(attributes.nominal, function Binding.mapExp(mapFn = func)); | |
| 556 | 53266 | attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func)); | |
| 557 | then attributes; | ||
| 558 | |||
| 559 | case VAR_ATTR_INT() algorithm | ||
| 560 | 2024 | attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func)); | |
| 561 | 2024 | attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func)); | |
| 562 | 2024 | attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func)); | |
| 563 | 2024 | attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func)); | |
| 564 | 2024 | attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func)); | |
| 565 | 2024 | attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func)); | |
| 566 | then attributes; | ||
| 567 | |||
| 568 | case VAR_ATTR_BOOL() algorithm | ||
| 569 | 2580 | attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func)); | |
| 570 | 2580 | attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func)); | |
| 571 | 2580 | attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func)); | |
| 572 | 2580 | attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func)); | |
| 573 | then attributes; | ||
| 574 | |||
| 575 | case VAR_ATTR_STRING() algorithm | ||
| 576 | 120 | attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func)); | |
| 577 | 120 | attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func)); | |
| 578 | 120 | attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func)); | |
| 579 | 120 | attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func)); | |
| 580 | then attributes; | ||
| 581 | |||
| 582 | case VAR_ATTR_ENUMERATION() algorithm | ||
| 583 | 272 | attributes.quantity := Util.applyOption(attributes.quantity, function Binding.mapExp(mapFn = func)); | |
| 584 | 272 | attributes.min := Util.applyOption(attributes.min, function Binding.mapExp(mapFn = func)); | |
| 585 | 272 | attributes.max := Util.applyOption(attributes.max, function Binding.mapExp(mapFn = func)); | |
| 586 | 272 | attributes.start := Util.applyOption(attributes.start, function Binding.mapExp(mapFn = func)); | |
| 587 | 272 | attributes.fixed := Util.applyOption(attributes.fixed, function Binding.mapExp(mapFn = func)); | |
| 588 | 272 | attributes.binding := Util.applyOption(attributes.binding, function Binding.mapExp(mapFn = func)); | |
| 589 | then attributes; | ||
| 590 | |||
| 591 | case VAR_ATTR_RECORD() algorithm | ||
| 592 |
4/4✓ Branch 0 taken 682 times.
✓ Branch 1 taken 312 times.
✓ Branch 3 taken 682 times.
✓ Branch 4 taken 312 times.
|
2300 | attributes.childrenAttr := listArray(list(map(attr, func) for attr in attributes.childrenAttr)); |
| 593 | then attributes; | ||
| 594 | |||
| 595 | else attributes; | ||
| 596 | end match; | ||
| 597 | end map; | ||
| 598 | |||
| 599 | function setFixed | ||
| 600 | input output VariableAttributes attributes; | ||
| 601 | input Type ty; | ||
| 602 | input Boolean b = true; | ||
| 603 | input Boolean overwrite = false; | ||
| 604 | protected | ||
| 605 | list<Integer> sizes; | ||
| 606 | Expression start, iter_range, fixedExp = Expression.BOOLEAN(b); | ||
| 607 | Option<Expression> step; | ||
| 608 | InstNode iter_name; | ||
| 609 | list<tuple<InstNode, Expression>> iterators = {}; | ||
| 610 | Binding fixedBinding; | ||
| 611 | algorithm | ||
| 612 | // make array constructor if it is an array | ||
| 613 |
2/2✓ Branch 1 taken 439 times.
✓ Branch 2 taken 3003 times.
|
3442 | if Type.isArray(ty) then |
| 614 |
4/4✓ Branch 1 taken 633 times.
✓ Branch 2 taken 439 times.
✓ Branch 3 taken 633 times.
✓ Branch 4 taken 439 times.
|
1072 | sizes := list(Dimension.size(dim) for dim in Type.arrayDims(ty)); |
| 615 | start := Expression.INTEGER(1); | ||
| 616 | step := NONE(); | ||
| 617 |
2/2✓ Branch 0 taken 633 times.
✓ Branch 1 taken 439 times.
|
1072 | for stop in sizes loop |
| 618 | 633 | iter_name := InstNode.newUniqueIterator(); | |
| 619 | 633 | iter_range := Expression.RANGE(Type.INTEGER(), start, step, Expression.INTEGER(stop)); | |
| 620 | 633 | iterators := (iter_name, iter_range) :: iterators; | |
| 621 | end for; | ||
| 622 | 439 | fixedExp := Expression.CALL(Call.TYPED_ARRAY_CONSTRUCTOR(ty, Expression.variability(fixedExp), NFPrefixes.Purity.PURE, fixedExp, listReverse(iterators))); | |
| 623 | end if; | ||
| 624 | 3442 | fixedBinding := Binding.makeFlat(fixedExp, Variability.CONSTANT, Source.GENERATED); | |
| 625 | |||
| 626 | attributes := match attributes | ||
| 627 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.fixed)) algorithm | ||
| 628 | 2657 | attributes.fixed := SOME(fixedBinding); | |
| 629 | then attributes; | ||
| 630 | |||
| 631 | case VAR_ATTR_INT() guard(overwrite or isNone(attributes.fixed)) algorithm | ||
| 632 | 175 | attributes.fixed := SOME(fixedBinding); | |
| 633 | then attributes; | ||
| 634 | |||
| 635 | case VAR_ATTR_BOOL() guard(overwrite or isNone(attributes.fixed)) algorithm | ||
| 636 | 486 | attributes.fixed := SOME(fixedBinding); | |
| 637 | then attributes; | ||
| 638 | |||
| 639 | case VAR_ATTR_STRING() guard(overwrite or isNone(attributes.fixed)) algorithm | ||
| 640 | 30 | attributes.fixed := SOME(fixedBinding); | |
| 641 | then attributes; | ||
| 642 | |||
| 643 | case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.fixed)) algorithm | ||
| 644 | 67 | attributes.fixed := SOME(fixedBinding); | |
| 645 | then attributes; | ||
| 646 | |||
| 647 | else attributes; | ||
| 648 | end match; | ||
| 649 | end setFixed; | ||
| 650 | |||
| 651 | function isFixed | ||
| 652 | input VariableAttributes attributes; | ||
| 653 | output Boolean fixed; | ||
| 654 | algorithm | ||
| 655 | fixed := match attributes | ||
| 656 | local | ||
| 657 | Binding b; | ||
| 658 | ✗ | case VAR_ATTR_REAL(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b)); | |
| 659 | ✗ | case VAR_ATTR_INT(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b)); | |
| 660 | ✗ | case VAR_ATTR_BOOL(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b)); | |
| 661 | ✗ | case VAR_ATTR_STRING(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b)); | |
| 662 | ✗ | case VAR_ATTR_ENUMERATION(fixed = SOME(b)) then Expression.isAllTrue(Binding.getTypedExp(b)); | |
| 663 | else false; | ||
| 664 | end match; | ||
| 665 | end isFixed; | ||
| 666 | |||
| 667 | function setStartAttribute | ||
| 668 | input output VariableAttributes attributes; | ||
| 669 | input Expression start; | ||
| 670 | input Boolean overwrite = false; | ||
| 671 | protected | ||
| 672 | Binding startBinding; | ||
| 673 | algorithm | ||
| 674 | 2981 | startBinding := Binding.makeFlat(start, Expression.variability(start), Source.GENERATED); | |
| 675 | attributes := match attributes | ||
| 676 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.start)) algorithm | ||
| 677 | 1937 | attributes.start := SOME(startBinding); | |
| 678 | then attributes; | ||
| 679 | |||
| 680 | case VAR_ATTR_INT() guard(overwrite or isNone(attributes.start)) algorithm | ||
| 681 | 176 | attributes.start := SOME(startBinding); | |
| 682 | then attributes; | ||
| 683 | |||
| 684 | case VAR_ATTR_BOOL() guard(overwrite or isNone(attributes.start)) algorithm | ||
| 685 | 497 | attributes.start := SOME(startBinding); | |
| 686 | then attributes; | ||
| 687 | |||
| 688 | case VAR_ATTR_STRING() guard(overwrite or isNone(attributes.start)) algorithm | ||
| 689 | 27 | attributes.start := SOME(startBinding); | |
| 690 | then attributes; | ||
| 691 | |||
| 692 | case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.start)) algorithm | ||
| 693 | 67 | attributes.start := SOME(startBinding); | |
| 694 | then attributes; | ||
| 695 | |||
| 696 | else attributes; | ||
| 697 | end match; | ||
| 698 | end setStartAttribute; | ||
| 699 | |||
| 700 | function getStartAttribute | ||
| 701 | input VariableAttributes attributes; | ||
| 702 | output Option<Expression> start; | ||
| 703 | algorithm | ||
| 704 | start := match attributes | ||
| 705 | 7050 | case VAR_ATTR_REAL() then Util.applyOption(attributes.start, Binding.getTypedExp); | |
| 706 | 254 | case VAR_ATTR_INT() then Util.applyOption(attributes.start, Binding.getTypedExp); | |
| 707 | 547 | case VAR_ATTR_BOOL() then Util.applyOption(attributes.start, Binding.getTypedExp); | |
| 708 | 30 | case VAR_ATTR_STRING() then Util.applyOption(attributes.start, Binding.getTypedExp); | |
| 709 | 68 | case VAR_ATTR_ENUMERATION() then Util.applyOption(attributes.start, Binding.getTypedExp); | |
| 710 | else NONE(); | ||
| 711 | end match; | ||
| 712 | end getStartAttribute; | ||
| 713 | |||
| 714 | function setMin | ||
| 715 | input output VariableAttributes attributes; | ||
| 716 | input Option<Expression> min_val; | ||
| 717 | input Boolean overwrite = false; | ||
| 718 | protected | ||
| 719 | Option<Binding> min_binding = Util.applyOption(min_val, expToGeneratedBinding); | ||
| 720 | algorithm | ||
| 721 | attributes := match attributes | ||
| 722 | |||
| 723 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.min)) algorithm | ||
| 724 | 78 | attributes.min := min_binding; | |
| 725 | then attributes; | ||
| 726 | |||
| 727 | case VAR_ATTR_INT() guard(overwrite or isNone(attributes.min)) algorithm | ||
| 728 | 10 | attributes.min := min_binding; | |
| 729 | then attributes; | ||
| 730 | |||
| 731 | case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.min)) algorithm | ||
| 732 | ✗ | attributes.min := min_binding; | |
| 733 | then attributes; | ||
| 734 | |||
| 735 | else attributes; | ||
| 736 | end match; | ||
| 737 | end setMin; | ||
| 738 | |||
| 739 | function setMax | ||
| 740 | input output VariableAttributes attributes; | ||
| 741 | input Option<Expression> max_val; | ||
| 742 | input Boolean overwrite = false; | ||
| 743 | protected | ||
| 744 | Option<Binding> max_binding = Util.applyOption(max_val, expToGeneratedBinding); | ||
| 745 | algorithm | ||
| 746 | attributes := match attributes | ||
| 747 | |||
| 748 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.max)) algorithm | ||
| 749 | 67 | attributes.max := max_binding; | |
| 750 | then attributes; | ||
| 751 | |||
| 752 | case VAR_ATTR_INT() guard(overwrite or isNone(attributes.max)) algorithm | ||
| 753 | 10 | attributes.max := max_binding; | |
| 754 | then attributes; | ||
| 755 | |||
| 756 | case VAR_ATTR_ENUMERATION() guard(overwrite or isNone(attributes.max)) algorithm | ||
| 757 | ✗ | attributes.max := max_binding; | |
| 758 | then attributes; | ||
| 759 | |||
| 760 | else attributes; | ||
| 761 | end match; | ||
| 762 | end setMax; | ||
| 763 | |||
| 764 | function merge | ||
| 765 | "Merges the attributes from src into dst. Used by inlining to carry the | ||
| 766 | attributes declared on a function input/output (src) onto the model | ||
| 767 | variable (dst) that is bound to it, so they are not lost when the call is | ||
| 768 | replaced by the function body (see #15947). The model variable wins for | ||
| 769 | any scalar attribute that is already set; for min/max the tightest bound | ||
| 770 | wins." | ||
| 771 | input output VariableAttributes dst; | ||
| 772 | input VariableAttributes src; | ||
| 773 | algorithm | ||
| 774 | dst := match (dst, src) | ||
| 775 | case (VAR_ATTR_REAL(), VAR_ATTR_REAL()) algorithm | ||
| 776 | 1674 | dst.quantity := mergeOpt(dst.quantity, src.quantity); | |
| 777 | 1674 | dst.unit := mergeOpt(dst.unit, src.unit); | |
| 778 | 1674 | dst.displayUnit := mergeOpt(dst.displayUnit, src.displayUnit); | |
| 779 | 1674 | dst.min := tightestBound(dst.min, src.min, true); | |
| 780 | 1674 | dst.max := tightestBound(dst.max, src.max, false); | |
| 781 | 1674 | dst.start := mergeOpt(dst.start, src.start); | |
| 782 | 1674 | dst.fixed := mergeOpt(dst.fixed, src.fixed); | |
| 783 | 1674 | dst.nominal := mergeOpt(dst.nominal, src.nominal); | |
| 784 | then dst; | ||
| 785 | |||
| 786 | case (VAR_ATTR_INT(), VAR_ATTR_INT()) algorithm | ||
| 787 | 8 | dst.quantity := mergeOpt(dst.quantity, src.quantity); | |
| 788 | 8 | dst.min := tightestBound(dst.min, src.min, true); | |
| 789 | 8 | dst.max := tightestBound(dst.max, src.max, false); | |
| 790 | 8 | dst.start := mergeOpt(dst.start, src.start); | |
| 791 | 8 | dst.fixed := mergeOpt(dst.fixed, src.fixed); | |
| 792 | then dst; | ||
| 793 | |||
| 794 | case (VAR_ATTR_BOOL(), VAR_ATTR_BOOL()) algorithm | ||
| 795 | ✗ | dst.quantity := mergeOpt(dst.quantity, src.quantity); | |
| 796 | ✗ | dst.start := mergeOpt(dst.start, src.start); | |
| 797 | ✗ | dst.fixed := mergeOpt(dst.fixed, src.fixed); | |
| 798 | then dst; | ||
| 799 | |||
| 800 | case (VAR_ATTR_STRING(), VAR_ATTR_STRING()) algorithm | ||
| 801 | ✗ | dst.quantity := mergeOpt(dst.quantity, src.quantity); | |
| 802 | ✗ | dst.start := mergeOpt(dst.start, src.start); | |
| 803 | ✗ | dst.fixed := mergeOpt(dst.fixed, src.fixed); | |
| 804 | then dst; | ||
| 805 | |||
| 806 | case (VAR_ATTR_ENUMERATION(), VAR_ATTR_ENUMERATION()) algorithm | ||
| 807 | ✗ | dst.quantity := mergeOpt(dst.quantity, src.quantity); | |
| 808 | ✗ | dst.min := mergeOpt(dst.min, src.min); | |
| 809 | ✗ | dst.max := mergeOpt(dst.max, src.max); | |
| 810 | ✗ | dst.start := mergeOpt(dst.start, src.start); | |
| 811 | ✗ | dst.fixed := mergeOpt(dst.fixed, src.fixed); | |
| 812 | then dst; | ||
| 813 | |||
| 814 | else dst; | ||
| 815 | end match; | ||
| 816 | end merge; | ||
| 817 | |||
| 818 | function mergeOpt | ||
| 819 | "Keeps dst if it is already set, otherwise takes src." | ||
| 820 | input output Option<Binding> dst; | ||
| 821 | input Option<Binding> src; | ||
| 822 | algorithm | ||
| 823 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 10068 times.
✓ Branch 2 taken 5463 times.
✓ Branch 3 taken 4605 times.
|
10068 | dst := if isSome(dst) then dst else src; |
| 824 | end mergeOpt; | ||
| 825 | |||
| 826 | function tightestBound | ||
| 827 | "Picks the tighter of two bounds when both are constant numbers, otherwise | ||
| 828 | keeps the already present (dst) bound. isMin = true for lower bounds | ||
| 829 | (the larger value is tighter), false for upper bounds (the smaller value | ||
| 830 | is tighter)." | ||
| 831 | input Option<Binding> dst; | ||
| 832 | input Option<Binding> src; | ||
| 833 | input Boolean isMin; | ||
| 834 | output Option<Binding> res; | ||
| 835 | protected | ||
| 836 | Binding db, sb; | ||
| 837 | Expression de, se; | ||
| 838 | Real dv, sv; | ||
| 839 | algorithm | ||
| 840 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 3364 times.
✓ Branch 2 taken 2042 times.
✓ Branch 3 taken 1322 times.
|
3364 | if isNone(dst) then |
| 841 | res := src; | ||
| 842 | elseif isNone(src) then | ||
| 843 | res := dst; | ||
| 844 | else | ||
| 845 | 1779 | SOME(db) := dst; | |
| 846 | 1779 | SOME(sb) := src; | |
| 847 | 1779 | de := Binding.getTypedExp(db); | |
| 848 | 1779 | se := Binding.getTypedExp(sb); | |
| 849 | // both bounds must be constant numbers to be able to compare them | ||
| 850 |
3/4✓ Branch 1 taken 1523 times.
✓ Branch 2 taken 256 times.
✓ Branch 4 taken 1523 times.
✗ Branch 5 not taken.
|
1779 | if Expression.isConstNumber(de) and Expression.isConstNumber(se) then |
| 851 | 1523 | dv := Expression.realValue(de); | |
| 852 | 1523 | sv := Expression.realValue(se); | |
| 853 |
2/2✓ Branch 0 taken 823 times.
✓ Branch 1 taken 700 times.
|
1523 | if isMin then |
| 854 |
2/2✓ Branch 0 taken 818 times.
✓ Branch 1 taken 5 times.
|
823 | res := if sv > dv then src else dst; |
| 855 | else | ||
| 856 |
1/2✓ Branch 0 taken 700 times.
✗ Branch 1 not taken.
|
700 | res := if sv < dv then src else dst; |
| 857 | end if; | ||
| 858 | else | ||
| 859 | res := dst; | ||
| 860 | end if; | ||
| 861 | end if; | ||
| 862 | end tightestBound; | ||
| 863 | |||
| 864 | function setStateSelect | ||
| 865 | input output VariableAttributes attributes; | ||
| 866 | input StateSelect stateSelect_val; | ||
| 867 | input Boolean overwrite = false; | ||
| 868 | algorithm | ||
| 869 | attributes := match attributes | ||
| 870 | |||
| 871 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.stateSelect)) algorithm | ||
| 872 | 125 | attributes.stateSelect := SOME(stateSelect_val); | |
| 873 | then attributes; | ||
| 874 | |||
| 875 | else attributes; | ||
| 876 | end match; | ||
| 877 | end setStateSelect; | ||
| 878 | |||
| 879 | function getStateSelect | ||
| 880 | input VariableAttributes attributes; | ||
| 881 | output StateSelect stateSelect; | ||
| 882 | algorithm | ||
| 883 | stateSelect := match attributes | ||
| 884 | case VAR_ATTR_REAL(stateSelect = SOME(stateSelect)) then stateSelect; | ||
| 885 | else StateSelect.DEFAULT; | ||
| 886 | end match; | ||
| 887 | end getStateSelect; | ||
| 888 | |||
| 889 | function setTearingSelect | ||
| 890 | input output VariableAttributes attributes; | ||
| 891 | input TearingSelect tearingSelect_val; | ||
| 892 | input Boolean overwrite = false; | ||
| 893 | algorithm | ||
| 894 | attributes := match attributes | ||
| 895 | |||
| 896 | case VAR_ATTR_REAL() guard(overwrite or isNone(attributes.tearingSelect)) algorithm | ||
| 897 | ✗ | attributes.tearingSelect := SOME(tearingSelect_val); | |
| 898 | then attributes; | ||
| 899 | |||
| 900 | else attributes; | ||
| 901 | end match; | ||
| 902 | end setTearingSelect; | ||
| 903 | |||
| 904 | function getTearingSelect | ||
| 905 | input VariableAttributes attributes; | ||
| 906 | output TearingSelect tearingSelect; | ||
| 907 | algorithm | ||
| 908 | tearingSelect := match attributes | ||
| 909 | case VAR_ATTR_REAL(tearingSelect = SOME(tearingSelect)) then tearingSelect; | ||
| 910 | else TearingSelect.DEFAULT; | ||
| 911 | end match; | ||
| 912 | end getTearingSelect; | ||
| 913 | |||
| 914 | function getMin | ||
| 915 | input VariableAttributes attr; | ||
| 916 | output Option<Expression> min; | ||
| 917 | algorithm | ||
| 918 | min := match attr | ||
| 919 | 1947 | case VAR_ATTR_REAL() then Util.applyOption(attr.min, Binding.getTypedExp); | |
| 920 | 20 | case VAR_ATTR_INT() then Util.applyOption(attr.min, Binding.getTypedExp); | |
| 921 | 1 | case VAR_ATTR_ENUMERATION() then Util.applyOption(attr.min, Binding.getTypedExp); | |
| 922 | else NONE(); | ||
| 923 | end match; | ||
| 924 | end getMin; | ||
| 925 | |||
| 926 | function getMax | ||
| 927 | input VariableAttributes attr; | ||
| 928 | output Option<Expression> max; | ||
| 929 | algorithm | ||
| 930 | max := match attr | ||
| 931 | 1947 | case VAR_ATTR_REAL() then Util.applyOption(attr.max, Binding.getTypedExp); | |
| 932 | 20 | case VAR_ATTR_INT() then Util.applyOption(attr.max, Binding.getTypedExp); | |
| 933 | 1 | case VAR_ATTR_ENUMERATION() then Util.applyOption(attr.max, Binding.getTypedExp); | |
| 934 | else NONE(); | ||
| 935 | end match; | ||
| 936 | end getMax; | ||
| 937 | |||
| 938 | function getNominal | ||
| 939 | input VariableAttributes attr; | ||
| 940 | output Option<Expression> nominal; | ||
| 941 | algorithm | ||
| 942 | nominal := match attr | ||
| 943 | 1951 | case VAR_ATTR_REAL() then Util.applyOption(attr.nominal, Binding.getTypedExp); | |
| 944 | else NONE(); | ||
| 945 | end match; | ||
| 946 | end getNominal; | ||
| 947 | |||
| 948 | function scalarizeReal | ||
| 949 | input ExpressionIterator quantity_iter "quantity"; | ||
| 950 | input ExpressionIterator unit_iter "SI Unit for actual computation value"; | ||
| 951 | input ExpressionIterator displayUnit_iter "SI Unit only for displaying"; | ||
| 952 | input ExpressionIterator min_iter "Lower boundry"; | ||
| 953 | input ExpressionIterator max_iter "Upper boundry"; | ||
| 954 | input ExpressionIterator start_iter "start value"; | ||
| 955 | input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 956 | input ExpressionIterator nominal_iter "nominal"; | ||
| 957 | input Option<StateSelect> stateSelect "Priority to be selected as a state during index reduction"; | ||
| 958 | input Option<TearingSelect> tearingSelect "Priority to be selected as an iteration variable during tearing"; | ||
| 959 | input Option<Uncertainty> uncertainty "Attributes from data reconcilliation"; | ||
| 960 | input Option<Distribution> distribution "ToDo: ???"; | ||
| 961 | input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters"; | ||
| 962 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 963 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 964 | input Integer length "length of result"; | ||
| 965 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 966 | output Boolean uniform; | ||
| 967 | protected | ||
| 968 | Option<Expression> quantity_e, unit_e, displayUnit_e, min_e, max_e, start_e, fixed_e, nominal_e, binding_e; | ||
| 969 | ExpressionIterator quantity_loc = quantity_iter, unit_loc = unit_iter, displayUnit_loc = displayUnit_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, nominal_loc = nominal_iter, binding_loc = binding_iter; | ||
| 970 | algorithm | ||
| 971 |
4/4✓ Branch 0 taken 1159 times.
✓ Branch 1 taken 245 times.
✓ Branch 3 taken 200 times.
✓ Branch 4 taken 959 times.
|
1404 | uniform := length > 1 and List.all({quantity_iter, unit_iter, displayUnit_iter, min_iter, max_iter, start_iter, fixed_iter, nominal_iter, binding_iter}, ExpressionIterator.isUniform); |
| 972 |
2/2✓ Branch 0 taken 444 times.
✓ Branch 1 taken 1 time.
|
5951 | for i in 1:(if uniform then 1 else length) loop |
| 973 | 4547 | (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc); | |
| 974 | 4547 | (unit_loc, unit_e) := ExpressionIterator.nextOpt(unit_loc); | |
| 975 | 4547 | (displayUnit_loc, displayUnit_e) := ExpressionIterator.nextOpt(displayUnit_loc); | |
| 976 | 4547 | (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc); | |
| 977 | 4547 | (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc); | |
| 978 | 4547 | (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc); | |
| 979 | 4547 | (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc); | |
| 980 | 4547 | (nominal_loc, nominal_e) := ExpressionIterator.nextOpt(nominal_loc); | |
| 981 | 4547 | (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc); | |
| 982 | 4547 | scalar_attributes := VAR_ATTR_REAL( | |
| 983 | Util.applyOption(quantity_e, expToGeneratedBinding), | ||
| 984 | Util.applyOption(unit_e, expToGeneratedBinding), | ||
| 985 | Util.applyOption(displayUnit_e, expToGeneratedBinding), | ||
| 986 | Util.applyOption(min_e, expToGeneratedBinding), | ||
| 987 | Util.applyOption(max_e, expToGeneratedBinding), | ||
| 988 | Util.applyOption(start_e, expToGeneratedBinding), | ||
| 989 | Util.applyOption(fixed_e, expToGeneratedBinding), | ||
| 990 | Util.applyOption(nominal_e, expToGeneratedBinding), | ||
| 991 | stateSelect, tearingSelect, uncertainty, distribution, | ||
| 992 | Util.applyOption(binding_e, expToGeneratedBinding), | ||
| 993 | isProtected, finalPrefix) :: scalar_attributes; | ||
| 994 | end for; | ||
| 995 |
2/2✓ Branch 0 taken 959 times.
✓ Branch 1 taken 445 times.
|
1404 | scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes); |
| 996 | end scalarizeReal; | ||
| 997 | |||
| 998 | function scalarizeInt | ||
| 999 | input ExpressionIterator quantity_iter "quantity"; | ||
| 1000 | input ExpressionIterator min_iter "Lower boundry"; | ||
| 1001 | input ExpressionIterator max_iter "Upper boundry"; | ||
| 1002 | input ExpressionIterator start_iter "start value"; | ||
| 1003 | input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 1004 | input Option<Uncertainty> uncertainty "Attributes from data reconcilliation"; | ||
| 1005 | input Option<Distribution> distribution "ToDo: ???"; | ||
| 1006 | input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters"; | ||
| 1007 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 1008 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 1009 | input Integer length "length of result"; | ||
| 1010 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 1011 | output Boolean uniform; | ||
| 1012 | protected | ||
| 1013 | Option<Expression> quantity_e, min_e, max_e, start_e, fixed_e, binding_e; | ||
| 1014 | ExpressionIterator quantity_loc = quantity_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter; | ||
| 1015 | algorithm | ||
| 1016 |
4/4✓ Branch 0 taken 53 times.
✓ Branch 1 taken 9 times.
✓ Branch 3 taken 17 times.
✓ Branch 4 taken 36 times.
|
62 | uniform := length > 1 and List.all({quantity_iter, min_iter, max_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform); |
| 1017 |
1/2✓ Branch 0 taken 26 times.
✗ Branch 1 not taken.
|
157 | for i in 1:(if uniform then 1 else length) loop |
| 1018 | 95 | (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc); | |
| 1019 | 95 | (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc); | |
| 1020 | 95 | (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc); | |
| 1021 | 95 | (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc); | |
| 1022 | 95 | (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc); | |
| 1023 | 95 | (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc); | |
| 1024 | 95 | scalar_attributes := VAR_ATTR_INT( | |
| 1025 | Util.applyOption(quantity_e, expToGeneratedBinding), | ||
| 1026 | Util.applyOption(min_e, expToGeneratedBinding), | ||
| 1027 | Util.applyOption(max_e, expToGeneratedBinding), | ||
| 1028 | Util.applyOption(start_e, expToGeneratedBinding), | ||
| 1029 | Util.applyOption(fixed_e, expToGeneratedBinding), | ||
| 1030 | uncertainty, distribution, | ||
| 1031 | Util.applyOption(binding_e, expToGeneratedBinding), | ||
| 1032 | isProtected, finalPrefix) :: scalar_attributes; | ||
| 1033 | end for; | ||
| 1034 |
2/2✓ Branch 0 taken 36 times.
✓ Branch 1 taken 26 times.
|
62 | scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes); |
| 1035 | end scalarizeInt; | ||
| 1036 | |||
| 1037 | function scalarizeBool | ||
| 1038 | input ExpressionIterator quantity_iter "quantity"; | ||
| 1039 | input ExpressionIterator start_iter "start value"; | ||
| 1040 | input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 1041 | input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters"; | ||
| 1042 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 1043 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 1044 | input Integer length "length of result"; | ||
| 1045 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 1046 | output Boolean uniform; | ||
| 1047 | protected | ||
| 1048 | Option<Expression> quantity_e, start_e, fixed_e, binding_e; | ||
| 1049 | ExpressionIterator quantity_loc = quantity_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter; | ||
| 1050 | algorithm | ||
| 1051 |
3/4✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
|
17 | uniform := length > 1 and List.all({quantity_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform); |
| 1052 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
34 | for i in 1:(if uniform then 1 else length) loop |
| 1053 | 17 | (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc); | |
| 1054 | 17 | (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc); | |
| 1055 | 17 | (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc); | |
| 1056 | 17 | (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc); | |
| 1057 | 17 | scalar_attributes := VAR_ATTR_BOOL( | |
| 1058 | Util.applyOption(quantity_e, expToGeneratedBinding), | ||
| 1059 | Util.applyOption(start_e, expToGeneratedBinding), | ||
| 1060 | Util.applyOption(fixed_e, expToGeneratedBinding), | ||
| 1061 | Util.applyOption(binding_e, expToGeneratedBinding), | ||
| 1062 | isProtected, finalPrefix) :: scalar_attributes; | ||
| 1063 | end for; | ||
| 1064 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 4 times.
|
17 | scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes); |
| 1065 | end scalarizeBool; | ||
| 1066 | |||
| 1067 | function scalarizeClock | ||
| 1068 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 1069 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 1070 | input Integer length "length of result"; | ||
| 1071 | output list<VariableAttributes> scalar_attributes = List.fill(VAR_ATTR_CLOCK(isProtected, finalPrefix), length); | ||
| 1072 | output Boolean uniform = true; | ||
| 1073 | end scalarizeClock; | ||
| 1074 | |||
| 1075 | function scalarizeString | ||
| 1076 | input ExpressionIterator quantity_iter "quantity"; | ||
| 1077 | input ExpressionIterator start_iter "start value"; | ||
| 1078 | input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 1079 | input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters"; | ||
| 1080 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 1081 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 1082 | input Integer length "length of result"; | ||
| 1083 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 1084 | output Boolean uniform; | ||
| 1085 | protected | ||
| 1086 | Option<Expression> quantity_e, start_e, fixed_e, binding_e; | ||
| 1087 | ExpressionIterator quantity_loc = quantity_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter; | ||
| 1088 | algorithm | ||
| 1089 | ✗ | uniform := length > 1 and List.all({quantity_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform); | |
| 1090 | ✗ | for i in 1:(if uniform then 1 else length) loop | |
| 1091 | ✗ | (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc); | |
| 1092 | ✗ | (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc); | |
| 1093 | ✗ | (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc); | |
| 1094 | ✗ | (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc); | |
| 1095 | ✗ | scalar_attributes := VAR_ATTR_STRING( | |
| 1096 | Util.applyOption(quantity_e, expToGeneratedBinding), | ||
| 1097 | Util.applyOption(start_e, expToGeneratedBinding), | ||
| 1098 | Util.applyOption(fixed_e, expToGeneratedBinding), | ||
| 1099 | Util.applyOption(binding_e, expToGeneratedBinding), | ||
| 1100 | isProtected, finalPrefix) :: scalar_attributes; | ||
| 1101 | end for; | ||
| 1102 | ✗ | scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes); | |
| 1103 | end scalarizeString; | ||
| 1104 | |||
| 1105 | function scalarizeEnumeration | ||
| 1106 | input ExpressionIterator quantity_iter "quantity"; | ||
| 1107 | input ExpressionIterator min_iter "Lower boundry"; | ||
| 1108 | input ExpressionIterator max_iter "Upper boundry"; | ||
| 1109 | input ExpressionIterator start_iter "start value"; | ||
| 1110 | input ExpressionIterator fixed_iter "fixed - true: default for parameter/constant, false - default for other variables"; | ||
| 1111 | input ExpressionIterator binding_iter "A binding expression for certain types. E.G. parameters"; | ||
| 1112 | input Option<Boolean> isProtected "Defined in protected scope"; | ||
| 1113 | input Option<Boolean> finalPrefix "Defined as final"; | ||
| 1114 | input Integer length "length of result"; | ||
| 1115 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 1116 | output Boolean uniform; | ||
| 1117 | protected | ||
| 1118 | Option<Expression> quantity_e, min_e, max_e, start_e, fixed_e, binding_e; | ||
| 1119 | ExpressionIterator quantity_loc = quantity_iter, min_loc = min_iter, max_loc = max_iter, start_loc = start_iter, fixed_loc = fixed_iter, binding_loc = binding_iter; | ||
| 1120 | algorithm | ||
| 1121 | ✗ | uniform := length > 1 and List.all({quantity_iter, min_iter, max_iter, start_iter, fixed_iter, binding_iter}, ExpressionIterator.isUniform); | |
| 1122 | ✗ | for i in 1:(if uniform then 1 else length) loop | |
| 1123 | ✗ | (quantity_loc, quantity_e) := ExpressionIterator.nextOpt(quantity_loc); | |
| 1124 | ✗ | (min_loc, min_e) := ExpressionIterator.nextOpt(min_loc); | |
| 1125 | ✗ | (max_loc, max_e) := ExpressionIterator.nextOpt(max_loc); | |
| 1126 | ✗ | (start_loc, start_e) := ExpressionIterator.nextOpt(start_loc); | |
| 1127 | ✗ | (fixed_loc, fixed_e) := ExpressionIterator.nextOpt(fixed_loc); | |
| 1128 | ✗ | (binding_loc, binding_e) := ExpressionIterator.nextOpt(binding_loc); | |
| 1129 | ✗ | scalar_attributes := VAR_ATTR_ENUMERATION( | |
| 1130 | Util.applyOption(quantity_e, expToGeneratedBinding), | ||
| 1131 | Util.applyOption(min_e, expToGeneratedBinding), | ||
| 1132 | Util.applyOption(max_e, expToGeneratedBinding), | ||
| 1133 | Util.applyOption(start_e, expToGeneratedBinding), | ||
| 1134 | Util.applyOption(fixed_e, expToGeneratedBinding), | ||
| 1135 | Util.applyOption(binding_e, expToGeneratedBinding), | ||
| 1136 | isProtected, finalPrefix) :: scalar_attributes; | ||
| 1137 | end for; | ||
| 1138 | ✗ | scalar_attributes := if uniform then List.fill(listHead(scalar_attributes), length) else listReverseInPlace(scalar_attributes); | |
| 1139 | end scalarizeEnumeration; | ||
| 1140 | |||
| 1141 | function scalarize | ||
| 1142 | input VariableAttributes attributes; | ||
| 1143 | input Integer length; | ||
| 1144 | output list<VariableAttributes> scalar_attributes = {}; | ||
| 1145 | output Boolean uniform "every element got the same attribute record"; | ||
| 1146 | algorithm | ||
| 1147 | (scalar_attributes, uniform) := match attributes | ||
| 1148 | 1404 | case VAR_ATTR_REAL() then scalarizeReal( | |
| 1149 | quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)), | ||
| 1150 | unit_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.unit, Binding.getTypedExp)), | ||
| 1151 | displayUnit_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.displayUnit, Binding.getTypedExp)), | ||
| 1152 | min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)), | ||
| 1153 | max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)), | ||
| 1154 | start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)), | ||
| 1155 | fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)), | ||
| 1156 | nominal_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.nominal, Binding.getTypedExp)), | ||
| 1157 | stateSelect = attributes.stateSelect, | ||
| 1158 | tearingSelect = attributes.tearingSelect, | ||
| 1159 | uncertainty = attributes.uncertainty, | ||
| 1160 | distribution = attributes.distribution, | ||
| 1161 | binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)), | ||
| 1162 | isProtected = attributes.isProtected, | ||
| 1163 | finalPrefix = attributes.finalPrefix, | ||
| 1164 | length = length | ||
| 1165 | ); | ||
| 1166 | |||
| 1167 | 62 | case VAR_ATTR_INT() then scalarizeInt( | |
| 1168 | quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)), | ||
| 1169 | min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)), | ||
| 1170 | max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)), | ||
| 1171 | start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)), | ||
| 1172 | fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)), | ||
| 1173 | uncertainty = attributes.uncertainty, | ||
| 1174 | distribution = attributes.distribution, | ||
| 1175 | binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)), | ||
| 1176 | isProtected = attributes.isProtected, | ||
| 1177 | finalPrefix = attributes.finalPrefix, | ||
| 1178 | length = length | ||
| 1179 | ); | ||
| 1180 | |||
| 1181 | 17 | case VAR_ATTR_BOOL() then scalarizeBool( | |
| 1182 | quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)), | ||
| 1183 | start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)), | ||
| 1184 | fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)), | ||
| 1185 | binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)), | ||
| 1186 | isProtected = attributes.isProtected, | ||
| 1187 | finalPrefix = attributes.finalPrefix, | ||
| 1188 | length = length | ||
| 1189 | ); | ||
| 1190 | |||
| 1191 | ✗ | case VAR_ATTR_CLOCK() then scalarizeClock( | |
| 1192 | isProtected = attributes.isProtected, | ||
| 1193 | finalPrefix = attributes.finalPrefix, | ||
| 1194 | length = length | ||
| 1195 | ); | ||
| 1196 | |||
| 1197 | ✗ | case VAR_ATTR_STRING() then scalarizeString( | |
| 1198 | quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)), | ||
| 1199 | start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)), | ||
| 1200 | fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)), | ||
| 1201 | binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)), | ||
| 1202 | isProtected = attributes.isProtected, | ||
| 1203 | finalPrefix = attributes.finalPrefix, | ||
| 1204 | length = length | ||
| 1205 | ); | ||
| 1206 | |||
| 1207 | ✗ | case VAR_ATTR_ENUMERATION() then scalarizeEnumeration( | |
| 1208 | quantity_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.quantity, Binding.getTypedExp)), | ||
| 1209 | min_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.min, Binding.getTypedExp)), | ||
| 1210 | max_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.max, Binding.getTypedExp)), | ||
| 1211 | start_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.start, Binding.getTypedExp)), | ||
| 1212 | fixed_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.fixed, Binding.getTypedExp)), | ||
| 1213 | binding_iter = ExpressionIterator.fromExpOpt(Util.applyOption(attributes.binding, Binding.getTypedExp)), | ||
| 1214 | isProtected = attributes.isProtected, | ||
| 1215 | finalPrefix = attributes.finalPrefix, | ||
| 1216 | length = length | ||
| 1217 | ); | ||
| 1218 | |||
| 1219 | // kabdelhak: ToDo: need to discuss this case | ||
| 1220 | ✗ | case VAR_ATTR_RECORD() then ({attributes}, false); | |
| 1221 | |||
| 1222 | else algorithm | ||
| 1223 | ✗ | Error.terminate(getInstanceName() + "failed. Not yet handled: " + toString(attributes), sourceInfo()); | |
| 1224 | ✗ | then fail(); | |
| 1225 | end match; | ||
| 1226 | end scalarize; | ||
| 1227 | |||
| 1228 | function elemType | ||
| 1229 | input VariableAttributes attr; | ||
| 1230 | output Type ty; | ||
| 1231 | algorithm | ||
| 1232 | ty := match attr | ||
| 1233 | case VAR_ATTR_REAL() then Type.REAL(); | ||
| 1234 | case VAR_ATTR_INT() then Type.INTEGER(); | ||
| 1235 | case VAR_ATTR_BOOL() then Type.BOOLEAN(); | ||
| 1236 | case VAR_ATTR_CLOCK() then Type.CLOCK(); | ||
| 1237 | case VAR_ATTR_STRING() then Type.STRING(); | ||
| 1238 | // should probably add enumeration but currently the needed info is not stored here | ||
| 1239 | else algorithm | ||
| 1240 | ✗ | Error.terminate(getInstanceName() + " cannot create type from attributes: " + toString(attr), sourceInfo()); | |
| 1241 | ✗ | then fail(); | |
| 1242 | end match; | ||
| 1243 | end elemType; | ||
| 1244 | |||
| 1245 | //protected | ||
| 1246 | function attributesToString | ||
| 1247 | input list<tuple<String, Option<Expression>>> tpl_list; | ||
| 1248 | input Option<StateSelect> stateSelect; | ||
| 1249 | input Option<TearingSelect> tearingSelect; | ||
| 1250 | output String str = ""; | ||
| 1251 | protected | ||
| 1252 | list<String> buffer = {}; | ||
| 1253 | String name; | ||
| 1254 | algorithm | ||
| 1255 |
2/2✓ Branch 0 taken 5244 times.
✓ Branch 1 taken 1068 times.
|
6312 | for tpl in tpl_list loop |
| 1256 | 5244 | buffer := attributeToString(tpl, buffer); | |
| 1257 | end for; | ||
| 1258 | |||
| 1259 | 1068 | buffer := stateSelectStringBuffer(stateSelect, buffer); | |
| 1260 | 1068 | buffer := tearingSelectStringBuffer(tearingSelect, buffer); | |
| 1261 | |||
| 1262 | 1068 | buffer := listReverse(buffer); | |
| 1263 | |||
| 1264 |
2/2✓ Branch 0 taken 1053 times.
✓ Branch 1 taken 15 times.
|
1068 | if not listEmpty(buffer) then |
| 1265 | 15 | name :: buffer := buffer; | |
| 1266 | 15 | str := str + name; | |
| 1267 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 15 times.
|
18 | for name in buffer loop |
| 1268 | 3 | str := str + ", " + name; | |
| 1269 | end for; | ||
| 1270 | end if; | ||
| 1271 | end attributesToString; | ||
| 1272 | |||
| 1273 | function attributeToString | ||
| 1274 | "Creates an optional string for an optional attribute." | ||
| 1275 | input tuple<String, Option<Expression>> tpl; | ||
| 1276 | input output list<String> buffer; | ||
| 1277 | protected | ||
| 1278 | String name; | ||
| 1279 | Option<Expression> optAttr; | ||
| 1280 | Expression attr; | ||
| 1281 | algorithm | ||
| 1282 | 5244 | (name, optAttr) := tpl; | |
| 1283 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5244 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 5239 times.
|
5244 | if isSome(optAttr) then |
| 1284 | 5 | SOME(attr) := optAttr; | |
| 1285 | 5 | buffer := name + " = " + Expression.toString(attr) :: buffer; | |
| 1286 | end if; | ||
| 1287 | end attributeToString; | ||
| 1288 | |||
| 1289 | function stateSelectString | ||
| 1290 | input StateSelect stateSelect; | ||
| 1291 | output String str; | ||
| 1292 | algorithm | ||
| 1293 | str := match stateSelect | ||
| 1294 | case StateSelect.NEVER then "StateSelect = never"; | ||
| 1295 | case StateSelect.AVOID then "StateSelect = avoid"; | ||
| 1296 | case StateSelect.DEFAULT then "StateSelect = default"; | ||
| 1297 | case StateSelect.PREFER then "StateSelect = prefer"; | ||
| 1298 | case StateSelect.ALWAYS then "StateSelect = always"; | ||
| 1299 | end match; | ||
| 1300 | end stateSelectString; | ||
| 1301 | |||
| 1302 | function tearingSelectString | ||
| 1303 | input TearingSelect tearingSelect; | ||
| 1304 | output String str; | ||
| 1305 | algorithm | ||
| 1306 | str := match tearingSelect | ||
| 1307 | case TearingSelect.NEVER then "TearingSelect = never"; | ||
| 1308 | case TearingSelect.AVOID then "TearingSelect = avoid"; | ||
| 1309 | case TearingSelect.DEFAULT then "TearingSelect = default"; | ||
| 1310 | case TearingSelect.PREFER then "TearingSelect = prefer"; | ||
| 1311 | case TearingSelect.ALWAYS then "TearingSelect = always"; | ||
| 1312 | end match; | ||
| 1313 | end tearingSelectString; | ||
| 1314 | |||
| 1315 | function stateSelectStringBuffer | ||
| 1316 | input Option<StateSelect> optStateSelect; | ||
| 1317 | input output list<String> buffer; | ||
| 1318 | protected | ||
| 1319 | StateSelect stateSelect; | ||
| 1320 | algorithm | ||
| 1321 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 1055 times.
|
1068 | if isSome(optStateSelect) then |
| 1322 | 13 | SOME(stateSelect) := optStateSelect; | |
| 1323 | 13 | buffer := stateSelectString(stateSelect) :: buffer; | |
| 1324 | end if; | ||
| 1325 | end stateSelectStringBuffer; | ||
| 1326 | |||
| 1327 | function tearingSelectStringBuffer | ||
| 1328 | input Option<TearingSelect> optTearingSelect; | ||
| 1329 | input output list<String> buffer; | ||
| 1330 | protected | ||
| 1331 | TearingSelect tearingSelect; | ||
| 1332 | algorithm | ||
| 1333 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 1068 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1068 times.
|
1068 | if isSome(optTearingSelect) then |
| 1334 | ✗ | SOME(tearingSelect) := optTearingSelect; | |
| 1335 | ✗ | buffer := tearingSelectString(tearingSelect) :: buffer; | |
| 1336 | end if; | ||
| 1337 | end tearingSelectStringBuffer; | ||
| 1338 | |||
| 1339 | protected | ||
| 1340 | function createReal | ||
| 1341 | input list<tuple<String, Binding>> attrs; | ||
| 1342 | input Boolean isFinal; | ||
| 1343 | input SCode.Comment comment; | ||
| 1344 | output VariableAttributes attributes; | ||
| 1345 | protected | ||
| 1346 | String name; | ||
| 1347 | Binding b; | ||
| 1348 | Option<Binding> quantity = NONE(), unit = NONE(), displayUnit = NONE(); | ||
| 1349 | Option<Binding> min = NONE(), max = NONE(), start = NONE(), fixed = NONE(), nominal = NONE(); | ||
| 1350 | Option<StateSelect> state_select = NONE(); | ||
| 1351 | Option<TearingSelect> tearing_select = NONE(); | ||
| 1352 | algorithm | ||
| 1353 |
2/2✓ Branch 0 taken 21842 times.
✓ Branch 1 taken 7640 times.
|
29482 | for attr in attrs loop |
| 1354 | 21842 | (name, b) := attr; | |
| 1355 | () := match name | ||
| 1356 | 1893 | case "displayUnit" algorithm displayUnit := createAttribute(b); then (); | |
| 1357 | 124 | case "fixed" algorithm fixed := createAttribute(b); then (); | |
| 1358 | 1370 | case "max" algorithm max := createAttribute(b); then (); | |
| 1359 | 2440 | case "min" algorithm min := createAttribute(b); then (); | |
| 1360 | 2146 | case "nominal" algorithm nominal := createAttribute(b); then (); | |
| 1361 | 5630 | case "quantity" algorithm quantity := createAttribute(b); then (); | |
| 1362 | 2392 | case "start" algorithm start := createAttribute(b); then (); | |
| 1363 | 72 | case "stateSelect" algorithm state_select := createStateSelect(b); then (); | |
| 1364 | // TODO: VAR_ATTR_REAL has no field for unbounded (which should be named unbound). | ||
| 1365 | case "unbounded" then (); | ||
| 1366 | 5775 | case "unit" algorithm unit := createAttribute(b); then (); | |
| 1367 | |||
| 1368 | // The attributes should already be type checked, so we shouldn't get any | ||
| 1369 | // unknown attributes here. | ||
| 1370 | else | ||
| 1371 | algorithm | ||
| 1372 | ✗ | Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo()); | |
| 1373 | ✗ | then | |
| 1374 | fail(); | ||
| 1375 | end match; | ||
| 1376 | end for; | ||
| 1377 | 7640 | tearing_select := createTearingSelect(comment); | |
| 1378 | |||
| 1379 |
2/2✓ Branch 0 taken 7274 times.
✓ Branch 1 taken 366 times.
|
15280 | attributes := VariableAttributes.VAR_ATTR_REAL( |
| 1380 | quantity, unit, displayUnit, min, max, start, fixed, nominal, | ||
| 1381 | state_select, tearing_select, NONE(), NONE(), NONE(), NONE(), SOME(isFinal)); | ||
| 1382 | end createReal; | ||
| 1383 | |||
| 1384 | function createInt | ||
| 1385 | input list<tuple<String, Binding>> attrs; | ||
| 1386 | input Boolean isFinal; | ||
| 1387 | output VariableAttributes attributes; | ||
| 1388 | protected | ||
| 1389 | String name; | ||
| 1390 | Binding b; | ||
| 1391 | Option<Binding> quantity = NONE(), min = NONE(), max = NONE(); | ||
| 1392 | Option<Binding> start = NONE(), fixed = NONE(); | ||
| 1393 | algorithm | ||
| 1394 |
4/4✓ Branch 0 taken 81 times.
✓ Branch 1 taken 5749 times.
✓ Branch 2 taken 87 times.
✓ Branch 3 taken 5662 times.
|
5830 | if listEmpty(attrs) and not isFinal then |
| 1395 | attributes := EMPTY_VAR_ATTR_INT; | ||
| 1396 | else | ||
| 1397 |
2/2✓ Branch 0 taken 143 times.
✓ Branch 1 taken 168 times.
|
311 | for attr in attrs loop |
| 1398 | 143 | (name, b) := attr; | |
| 1399 | |||
| 1400 | () := match name | ||
| 1401 | ✗ | case "quantity" algorithm quantity := createAttribute(b); then (); | |
| 1402 | 66 | case "min" algorithm min := createAttribute(b); then (); | |
| 1403 | 55 | case "max" algorithm max := createAttribute(b); then (); | |
| 1404 | 14 | case "start" algorithm start := createAttribute(b); then (); | |
| 1405 | 8 | case "fixed" algorithm fixed := createAttribute(b); then (); | |
| 1406 | |||
| 1407 | // The attributes should already be type checked, so we shouldn't get any | ||
| 1408 | // unknown attributes here. | ||
| 1409 | else | ||
| 1410 | algorithm | ||
| 1411 | ✗ | Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo()); | |
| 1412 | ✗ | then | |
| 1413 | fail(); | ||
| 1414 | end match; | ||
| 1415 | end for; | ||
| 1416 | |||
| 1417 |
2/2✓ Branch 0 taken 57 times.
✓ Branch 1 taken 111 times.
|
336 | attributes := VariableAttributes.VAR_ATTR_INT( |
| 1418 | quantity, min, max, start, fixed, | ||
| 1419 | NONE(), NONE(), NONE(), NONE(), SOME(isFinal)); | ||
| 1420 | end if; | ||
| 1421 | end createInt; | ||
| 1422 | |||
| 1423 | function createBool | ||
| 1424 | input list<tuple<String, Binding>> attrs; | ||
| 1425 | input Boolean isFinal; | ||
| 1426 | output VariableAttributes attributes; | ||
| 1427 | protected | ||
| 1428 | String name; | ||
| 1429 | Binding b; | ||
| 1430 | Option<Binding> quantity = NONE(), start = NONE(), fixed = NONE(); | ||
| 1431 | algorithm | ||
| 1432 |
4/4✓ Branch 0 taken 17 times.
✓ Branch 1 taken 628 times.
✓ Branch 2 taken 469 times.
✓ Branch 3 taken 159 times.
|
645 | if listEmpty(attrs) and not isFinal then |
| 1433 | attributes := EMPTY_VAR_ATTR_BOOL; | ||
| 1434 | else | ||
| 1435 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 486 times.
|
509 | for attr in attrs loop |
| 1436 | 23 | (name, b) := attr; | |
| 1437 | |||
| 1438 | () := match name | ||
| 1439 | ✗ | case "quantity" algorithm quantity := createAttribute(b); then (); | |
| 1440 | 17 | case "start" algorithm start := createAttribute(b); then (); | |
| 1441 | 6 | case "fixed" algorithm fixed := createAttribute(b); then (); | |
| 1442 | |||
| 1443 | // The attributes should already be type checked, so we shouldn't get any | ||
| 1444 | // unknown attributes here. | ||
| 1445 | else | ||
| 1446 | algorithm | ||
| 1447 | ✗ | Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo()); | |
| 1448 | ✗ | then | |
| 1449 | fail(); | ||
| 1450 | end match; | ||
| 1451 | end for; | ||
| 1452 | |||
| 1453 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 469 times.
|
972 | attributes := VariableAttributes.VAR_ATTR_BOOL( |
| 1454 | quantity, start, fixed, NONE(), NONE(), SOME(isFinal)); | ||
| 1455 | end if; | ||
| 1456 | end createBool; | ||
| 1457 | |||
| 1458 | function createString | ||
| 1459 | input list<tuple<String, Binding>> attrs; | ||
| 1460 | input Boolean isFinal; | ||
| 1461 | output VariableAttributes attributes; | ||
| 1462 | protected | ||
| 1463 | String name; | ||
| 1464 | Binding b; | ||
| 1465 | Option<Binding> quantity = NONE(), start = NONE(), fixed = NONE(); | ||
| 1466 | algorithm | ||
| 1467 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 5 times.
✓ Branch 3 taken 25 times.
|
30 | if listEmpty(attrs) and not isFinal then |
| 1468 | attributes := EMPTY_VAR_ATTR_STRING; | ||
| 1469 | else | ||
| 1470 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | for attr in attrs loop |
| 1471 | ✗ | (name, b) := attr; | |
| 1472 | |||
| 1473 | () := match name | ||
| 1474 | ✗ | case "quantity" algorithm quantity := createAttribute(b); then (); | |
| 1475 | ✗ | case "start" algorithm start := createAttribute(b); then (); | |
| 1476 | ✗ | case "fixed" algorithm fixed := createAttribute(b); then (); | |
| 1477 | |||
| 1478 | // The attributes should already be type checked, so we shouldn't get any | ||
| 1479 | // unknown attributes here. | ||
| 1480 | else | ||
| 1481 | algorithm | ||
| 1482 | ✗ | Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo()); | |
| 1483 | ✗ | then | |
| 1484 | fail(); | ||
| 1485 | end match; | ||
| 1486 | end for; | ||
| 1487 | |||
| 1488 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
10 | attributes := VariableAttributes.VAR_ATTR_STRING( |
| 1489 | quantity, start, fixed, NONE(), NONE(), SOME(isFinal)); | ||
| 1490 | end if; | ||
| 1491 | end createString; | ||
| 1492 | |||
| 1493 | function createEnum | ||
| 1494 | input list<tuple<String, Binding>> attrs; | ||
| 1495 | input Boolean isFinal; | ||
| 1496 | output VariableAttributes attributes; | ||
| 1497 | protected | ||
| 1498 | String name; | ||
| 1499 | Binding b; | ||
| 1500 | Option<Binding> quantity = NONE(), min = NONE(), max = NONE(); | ||
| 1501 | Option<Binding> start = NONE(), fixed = NONE(); | ||
| 1502 | algorithm | ||
| 1503 |
4/4✓ Branch 0 taken 1 time.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 67 times.
✓ Branch 3 taken 2 times.
|
70 | if listEmpty(attrs) and not isFinal then |
| 1504 | attributes := EMPTY_VAR_ATTR_REAL; | ||
| 1505 | else | ||
| 1506 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 68 times.
|
70 | for attr in attrs loop |
| 1507 | 2 | (name, b) := attr; | |
| 1508 | |||
| 1509 | () := match name | ||
| 1510 | 1 | case "fixed" algorithm fixed := createAttribute(b); then (); | |
| 1511 | ✗ | case "max" algorithm max := createAttribute(b); then (); | |
| 1512 | ✗ | case "min" algorithm min := createAttribute(b); then (); | |
| 1513 | ✗ | case "quantity" algorithm quantity := createAttribute(b); then (); | |
| 1514 | 1 | case "start" algorithm start := createAttribute(b); then (); | |
| 1515 | |||
| 1516 | // The attributes should already be type checked, so we shouldn't get any | ||
| 1517 | // unknown attributes here. | ||
| 1518 | else | ||
| 1519 | algorithm | ||
| 1520 | ✗ | Error.terminate(getInstanceName() + " got unknown type attribute " + name, sourceInfo()); | |
| 1521 | ✗ | then | |
| 1522 | fail(); | ||
| 1523 | end match; | ||
| 1524 | end for; | ||
| 1525 | |||
| 1526 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 67 times.
|
136 | attributes := VariableAttributes.VAR_ATTR_ENUMERATION( |
| 1527 | quantity, min, max, start, fixed, NONE(), NONE(), SOME(isFinal)); | ||
| 1528 | end if; | ||
| 1529 | end createEnum; | ||
| 1530 | |||
| 1531 | function createClock | ||
| 1532 | input Boolean isFinal; | ||
| 1533 | output VariableAttributes attributes = VAR_ATTR_CLOCK(NONE(), SOME(isFinal)); | ||
| 1534 | end createClock; | ||
| 1535 | |||
| 1536 | function createRecord | ||
| 1537 | input list<tuple<String, Binding>> attrs; | ||
| 1538 | input UnorderedMap<String, Integer> indexMap; | ||
| 1539 | input list<Variable> children; | ||
| 1540 | input Boolean isFinal; | ||
| 1541 | output VariableAttributes attributes; | ||
| 1542 | protected | ||
| 1543 | array<VariableAttributes> childrenAttr = arrayCreate(listLength(children), EMPTY_VAR_ATTR_REAL); | ||
| 1544 | Integer index; | ||
| 1545 | algorithm | ||
| 1546 |
2/2✓ Branch 1 taken 341 times.
✓ Branch 2 taken 156 times.
|
497 | for var in children loop |
| 1547 | () := match UnorderedMap.get(ComponentRef.firstName(var.name), indexMap) | ||
| 1548 | case SOME(index) algorithm | ||
| 1549 | 341 | childrenAttr[index] := create(var.typeAttributes, var.ty, var.attributes, var.children, var.comment); | |
| 1550 | then (); | ||
| 1551 | else (); | ||
| 1552 | end match; | ||
| 1553 | end for; | ||
| 1554 | 156 | attributes := VAR_ATTR_RECORD(indexMap, childrenAttr); | |
| 1555 | end createRecord; | ||
| 1556 | |||
| 1557 | function createAttribute | ||
| 1558 | input Binding binding; | ||
| 1559 | output Option<Binding> attribute = SOME(binding); | ||
| 1560 | end createAttribute; | ||
| 1561 | |||
| 1562 | function createStateSelect | ||
| 1563 | input Binding binding; | ||
| 1564 | output Option<StateSelect> stateSelect; | ||
| 1565 | protected | ||
| 1566 | Expression exp = Binding.getTypedExp(binding); | ||
| 1567 | String name; | ||
| 1568 | algorithm | ||
| 1569 | 72 | name := getStateSelectName(exp); | |
| 1570 | 72 | stateSelect := SOME(lookupStateSelectMember(name)); | |
| 1571 | end createStateSelect; | ||
| 1572 | |||
| 1573 | function getStateSelectName | ||
| 1574 | input Expression exp; | ||
| 1575 | output String name; | ||
| 1576 | protected | ||
| 1577 | Expression arg; | ||
| 1578 | InstNode node; | ||
| 1579 | Call call; | ||
| 1580 | list<Expression> rest; | ||
| 1581 | algorithm | ||
| 1582 | name := match exp | ||
| 1583 | 72 | case Expression.ENUM_LITERAL() then exp.name; | |
| 1584 | ✗ | case Expression.CREF(cref = ComponentRef.CREF()) then ComponentRef.nodeName(exp.cref); | |
| 1585 | 43 | case Expression.CALL(call = call as Call.TYPED_ARRAY_CONSTRUCTOR()) then getStateSelectName(call.exp); | |
| 1586 | case Expression.CALL(call = call as Call.TYPED_CALL(arguments = arg::_)) | ||
| 1587 | guard(AbsynUtil.pathString(Function.nameConsiderBuiltin(call.fn)) == "fill") | ||
| 1588 | ✗ | then getStateSelectName(arg); | |
| 1589 | case Expression.ARRAY() algorithm | ||
| 1590 | ✗ | arg :: rest := arrayList(exp.elements); | |
| 1591 | ✗ | if not (listEmpty(rest) or List.all(rest, function Expression.isEqual(exp2=arg))) then | |
| 1592 | ✗ | Error.terminate(getInstanceName() + | |
| 1593 | " cannot handle array StateSelect with different values yet:" + Expression.toString(exp), sourceInfo()); | ||
| 1594 | ✗ | fail(); | |
| 1595 | end if; | ||
| 1596 | ✗ | then getStateSelectName(arg); | |
| 1597 | else algorithm | ||
| 1598 | ✗ | Error.terminate(getInstanceName() + | |
| 1599 | " got invalid StateSelect expression " + Expression.toString(exp), sourceInfo()); | ||
| 1600 | ✗ | then fail(); | |
| 1601 | end match; | ||
| 1602 | end getStateSelectName; | ||
| 1603 | |||
| 1604 | function lookupStateSelectMember | ||
| 1605 | input String name; | ||
| 1606 | output StateSelect stateSelect; | ||
| 1607 | algorithm | ||
| 1608 | stateSelect := match name | ||
| 1609 | case "never" then StateSelect.NEVER; | ||
| 1610 | case "avoid" then StateSelect.AVOID; | ||
| 1611 | case "default" then StateSelect.DEFAULT; | ||
| 1612 | case "prefer" then StateSelect.PREFER; | ||
| 1613 | case "always" then StateSelect.ALWAYS; | ||
| 1614 | else | ||
| 1615 | algorithm | ||
| 1616 | ✗ | Error.terminate(getInstanceName() + " got unknown StateSelect literal " + name, sourceInfo()); | |
| 1617 | ✗ | then | |
| 1618 | fail(); | ||
| 1619 | end match; | ||
| 1620 | end lookupStateSelectMember; | ||
| 1621 | |||
| 1622 | function createTearingSelect | ||
| 1623 | "__OpenModelica_tearingSelect is an annotation and has to be extracted from the comment." | ||
| 1624 | input SCode.Comment cmt; | ||
| 1625 | output Option<TearingSelect> tearingSelect = NONE(); | ||
| 1626 | protected | ||
| 1627 | Option<SCode.Annotation> opt_anno; | ||
| 1628 | SCode.Annotation anno; | ||
| 1629 | SCode.Mod mod; | ||
| 1630 | Option<Absyn.Exp> opt_val; | ||
| 1631 | Absyn.Exp val; | ||
| 1632 | String name; | ||
| 1633 | SourceInfo info; | ||
| 1634 | algorithm | ||
| 1635 | 7640 | opt_anno := SCodeUtil.commentAnnotation(cmt); | |
| 1636 | |||
| 1637 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 7640 times.
✓ Branch 2 taken 5244 times.
✓ Branch 3 taken 2396 times.
|
7640 | if isNone(opt_anno) then |
| 1638 | // No annotation. | ||
| 1639 | 5244 | return; | |
| 1640 | end if; | ||
| 1641 | |||
| 1642 | 2396 | SOME(anno) := opt_anno; | |
| 1643 | 2396 | mod := SCodeUtil.lookupAnnotation(anno, "__OpenModelica_tearingSelect"); | |
| 1644 | |||
| 1645 |
1/2✓ Branch 1 taken 2396 times.
✗ Branch 2 not taken.
|
2396 | if SCodeUtil.isEmptyMod(mod) then |
| 1646 | 2396 | mod := SCodeUtil.lookupAnnotation(anno, "tearingSelect"); | |
| 1647 | |||
| 1648 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2396 times.
|
2396 | if not SCodeUtil.isEmptyMod(mod) then |
| 1649 | ✗ | Error.addSourceMessage(Error.DEPRECATED_EXPRESSION, | |
| 1650 | {"tearingSelect", "__OpenModelica_tearingSelect"}, SCodeUtil.getModifierInfo(mod)); | ||
| 1651 | end if; | ||
| 1652 | end if; | ||
| 1653 | |||
| 1654 | 2396 | opt_val := SCodeUtil.getModifierBinding(mod); | |
| 1655 | |||
| 1656 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2396 times.
✓ Branch 2 taken 2396 times.
✗ Branch 3 not taken.
|
2396 | if isNone(opt_val) then |
| 1657 | // Annotation exists but has no value. | ||
| 1658 | 2396 | return; | |
| 1659 | end if; | ||
| 1660 | |||
| 1661 | ✗ | SOME(val) := opt_val; | |
| 1662 | ✗ | info := SCodeUtil.getModifierInfo(mod); | |
| 1663 | ✗ | name := getTearingSelectName(val, info); | |
| 1664 | ✗ | tearingSelect := lookupTearingSelectMember(name); | |
| 1665 | |||
| 1666 | ✗ | if isNone(tearingSelect) then | |
| 1667 | ✗ | Error.addSourceMessage(Error.UNKNOWN_ANNOTATION_VALUE, {Dump.printExpStr(val), "__OpenModelica_tearingSelect"}, info); | |
| 1668 | end if; | ||
| 1669 | end createTearingSelect; | ||
| 1670 | |||
| 1671 | function getTearingSelectName | ||
| 1672 | input Absyn.Exp exp; | ||
| 1673 | input SourceInfo info; | ||
| 1674 | output String name; | ||
| 1675 | algorithm | ||
| 1676 | name := match exp | ||
| 1677 | // TearingSelect.name | ||
| 1678 | case Absyn.Exp.CREF(componentRef = | ||
| 1679 | Absyn.ComponentRef.CREF_QUAL(name = "TearingSelect", subscripts = {}, componentRef = | ||
| 1680 | Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {}))) | ||
| 1681 | then name; | ||
| 1682 | |||
| 1683 | // Single name without the TearingSelect prefix is deprecated and no longer accepted. | ||
| 1684 | case Absyn.Exp.CREF(componentRef = Absyn.ComponentRef.CREF_IDENT(name = name, subscripts = {})) | ||
| 1685 | algorithm | ||
| 1686 | ✗ | Error.addSourceMessage(Error.DEPRECATED_EXPRESSION, {name, "TearingSelect." + name}, info); | |
| 1687 | then | ||
| 1688 | ""; | ||
| 1689 | |||
| 1690 | else ""; | ||
| 1691 | end match; | ||
| 1692 | end getTearingSelectName; | ||
| 1693 | |||
| 1694 | function lookupTearingSelectMember | ||
| 1695 | input String name; | ||
| 1696 | output Option<TearingSelect> tearingSelect; | ||
| 1697 | algorithm | ||
| 1698 | tearingSelect := match name | ||
| 1699 | case "never" then SOME(TearingSelect.NEVER); | ||
| 1700 | case "avoid" then SOME(TearingSelect.AVOID); | ||
| 1701 | case "default" then SOME(TearingSelect.DEFAULT); | ||
| 1702 | case "prefer" then SOME(TearingSelect.PREFER); | ||
| 1703 | case "always" then SOME(TearingSelect.ALWAYS); | ||
| 1704 | else NONE(); | ||
| 1705 | end match; | ||
| 1706 | end lookupTearingSelectMember; | ||
| 1707 | |||
| 1708 | function expToGeneratedBinding | ||
| 1709 | input Expression exp; | ||
| 1710 | output Binding binding = Binding.makeFlat(exp, Variability.CONSTANT, Source.GENERATED); | ||
| 1711 | end expToGeneratedBinding; | ||
| 1712 | end VariableAttributes; | ||
| 1713 | |||
| 1714 | constant VariableAttributes EMPTY_VAR_ATTR_REAL = VAR_ATTR_REAL(NONE(),NONE(),NONE(), NONE(), NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE()); | ||
| 1715 | constant VariableAttributes EMPTY_VAR_ATTR_INT = VAR_ATTR_INT(NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE()); | ||
| 1716 | constant VariableAttributes EMPTY_VAR_ATTR_BOOL = VAR_ATTR_BOOL(NONE(),NONE(),NONE(),NONE(),NONE(),NONE()); | ||
| 1717 | constant VariableAttributes EMPTY_VAR_ATTR_CLOCK = VAR_ATTR_CLOCK(NONE(),NONE()); | ||
| 1718 | constant VariableAttributes EMPTY_VAR_ATTR_STRING = VAR_ATTR_STRING(NONE(),NONE(),NONE(),NONE(),NONE(),NONE()); | ||
| 1719 | constant VariableAttributes EMPTY_VAR_ATTR_ENUMERATION = VAR_ATTR_ENUMERATION(NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE(),NONE()); | ||
| 1720 | |||
| 1721 | type StateSelect = enumeration(NEVER, AVOID, DEFAULT, PREFER, ALWAYS); | ||
| 1722 | type TearingSelect = enumeration(NEVER, AVOID, DEFAULT, PREFER, ALWAYS); | ||
| 1723 | type Uncertainty = enumeration(GIVEN, SOUGHT, REFINE, PROPAGATE); | ||
| 1724 | |||
| 1725 | uniontype Distribution | ||
| 1726 | record DISTRIBUTION | ||
| 1727 | Expression name; | ||
| 1728 | Expression params; | ||
| 1729 | Expression paramNames; | ||
| 1730 | end DISTRIBUTION; | ||
| 1731 | end Distribution; | ||
| 1732 | |||
| 1733 | uniontype Annotations | ||
| 1734 | record ANNOTATIONS | ||
| 1735 | "all annotations that are vendor specific | ||
| 1736 | note: doesn't include __OpenModelica_tearingSelect, this is considered a first class attribute" | ||
| 1737 | Boolean hideResult; | ||
| 1738 | Boolean resizable; | ||
| 1739 | Boolean optimizable; | ||
| 1740 | Option<OptimizerExpression> optimizerExpression; | ||
| 1741 | end ANNOTATIONS; | ||
| 1742 | |||
| 1743 | function create | ||
| 1744 | input SCode.Comment comment; | ||
| 1745 | input Attributes attributes; | ||
| 1746 | output Annotations annotations = EMPTY_ANNOTATIONS; | ||
| 1747 | protected | ||
| 1748 | SCode.Mod mod; | ||
| 1749 | Boolean b; | ||
| 1750 | algorithm | ||
| 1751 | // set if it was set globally | ||
| 1752 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 12368 times.
|
12387 | if attributes.isResizable then |
| 1753 | 19 | annotations.resizable := true; | |
| 1754 | end if; | ||
| 1755 | |||
| 1756 | () := match comment | ||
| 1757 | case SCode.COMMENT(annotation_=SOME(SCode.ANNOTATION(modification=mod as SCode.MOD()))) algorithm | ||
| 1758 |
2/2✓ Branch 0 taken 3538 times.
✓ Branch 1 taken 2796 times.
|
6334 | for submod in mod.subModLst loop |
| 1759 | () := match submod | ||
| 1760 | case SCode.NAMEMOD(ident = "HideResult", mod = SCode.MOD(binding = SOME(Absyn.BOOL(true)))) algorithm | ||
| 1761 | 262 | annotations.hideResult := true; | |
| 1762 | then (); | ||
| 1763 | case SCode.NAMEMOD(ident = "__OpenModelica_resizable", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1764 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | annotations.resizable := b; |
| 1765 | then (); | ||
| 1766 | case SCode.NAMEMOD(ident = "optimizable", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1767 | ✗ | annotations.optimizable := b; | |
| 1768 | then (); | ||
| 1769 | |||
| 1770 | // TODO: check for conflicting annotations? | ||
| 1771 | case SCode.NAMEMOD(ident = "isMayer", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1772 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.MAYER); | |
| 1773 | then (); | ||
| 1774 | case SCode.NAMEMOD(ident = "isLagrange", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1775 | 1 | annotations.optimizerExpression := SOME(OptimizerExpression.LAGRANGE); | |
| 1776 | then (); | ||
| 1777 | case SCode.NAMEMOD(ident = "isConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1778 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.PATH_CONSTRAINT); | |
| 1779 | then (); | ||
| 1780 | case SCode.NAMEMOD(ident = "isInitialConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1781 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.INITIAL_CONSTRAINT); | |
| 1782 | then (); | ||
| 1783 | case SCode.NAMEMOD(ident = "isFinalConstraint", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1784 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.FINAL_CONSTRAINT); | |
| 1785 | then (); | ||
| 1786 | case SCode.NAMEMOD(ident = "isInitialTime", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1787 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.INITIAL_TIME); | |
| 1788 | then (); | ||
| 1789 | case SCode.NAMEMOD(ident = "isFinalTime", mod = SCode.MOD(binding = SOME(Absyn.BOOL(b)))) algorithm | ||
| 1790 | ✗ | annotations.optimizerExpression := SOME(OptimizerExpression.FINAL_TIME); | |
| 1791 | then (); | ||
| 1792 | else (); | ||
| 1793 | end match; | ||
| 1794 | end for; | ||
| 1795 | then (); | ||
| 1796 | else (); | ||
| 1797 | end match; | ||
| 1798 | end create; | ||
| 1799 | end Annotations; | ||
| 1800 | |||
| 1801 | // TODO: how to use Initial or Final state? - better state-pair Real x_0 = x (initialState = true); -> binding only for initial time / optimizer? | ||
| 1802 | type OptimizerExpression = enumeration(MAYER, LAGRANGE, PATH_CONSTRAINT, INITIAL_CONSTRAINT, FINAL_CONSTRAINT, INITIAL_TIME, FINAL_TIME); | ||
| 1803 | |||
| 1804 | constant Annotations EMPTY_ANNOTATIONS = ANNOTATIONS(false, false, false, NONE()); | ||
| 1805 | |||
| 1806 | annotation(__OpenModelica_Interface="nf_frontend"); | ||
| 1807 | end NFBackendExtension; | ||
| 1808 |