OMCompiler/Compiler/FrontEnd/Algorithm.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 Algorithm | ||
| 37 | " | ||
| 38 | file: Algorithm.mo | ||
| 39 | package: Algorithm | ||
| 40 | description: Algorithm datatypes | ||
| 41 | |||
| 42 | |||
| 43 | This file contains data types and functions for managing | ||
| 44 | algorithm sections. The algorithms in the AST are analyzed by the `Inst\' | ||
| 45 | module (Inst.mo) which uses this module to represent the algorithms. No | ||
| 46 | processing of any kind, except for building the datastructure is | ||
| 47 | done in this module. | ||
| 48 | |||
| 49 | It is used primarily by Inst.mo which both provides its input data | ||
| 50 | and uses its \"output\" data. | ||
| 51 | |||
| 52 | " | ||
| 53 | |||
| 54 | public import Absyn; | ||
| 55 | public import DAE; | ||
| 56 | public import SCode; | ||
| 57 | |||
| 58 | protected import ComponentReference; | ||
| 59 | protected import ComponentReferenceBasics; | ||
| 60 | protected import DAEUtil; | ||
| 61 | protected import Debug; | ||
| 62 | protected import ElementSource; | ||
| 63 | protected import Error; | ||
| 64 | protected import Expression; | ||
| 65 | protected import Flags; | ||
| 66 | protected import List; | ||
| 67 | import SCodeUtil; | ||
| 68 | protected import SCodeDump; | ||
| 69 | protected import Types; | ||
| 70 | protected import TypesDump; | ||
| 71 | protected import Util; | ||
| 72 | protected import ExpressionBasics; | ||
| 73 | |||
| 74 | public function algorithmEmpty "Returns true if algorithm is empty, i.e. no statements" | ||
| 75 | input DAE.Algorithm alg; | ||
| 76 | output Boolean empty; | ||
| 77 | algorithm | ||
| 78 | empty := match alg | ||
| 79 | case DAE.ALGORITHM_STMTS({}) then true; | ||
| 80 | else false; | ||
| 81 | end match; | ||
| 82 | end algorithmEmpty; | ||
| 83 | |||
| 84 | public function isReinitStatement "returns true if statement is a reinit" | ||
| 85 | input DAE.Statement stmt; | ||
| 86 | output Boolean res; | ||
| 87 | algorithm | ||
| 88 | res := match stmt | ||
| 89 | case DAE.STMT_REINIT() then true; | ||
| 90 | else false; | ||
| 91 | end match; | ||
| 92 | end isReinitStatement; | ||
| 93 | |||
| 94 | public function isNotAssertStatement "returns true if statement is NOT an assert" | ||
| 95 | input DAE.Statement stmt; | ||
| 96 | output Boolean res; | ||
| 97 | algorithm | ||
| 98 | res := match stmt | ||
| 99 | case DAE.STMT_ASSERT() then false; | ||
| 100 | else true; | ||
| 101 | end match; | ||
| 102 | end isNotAssertStatement; | ||
| 103 | |||
| 104 | public function makeAssignmentNoTypeCheck | ||
| 105 | "Used to optimize assignments to NORETCALL if applicable" | ||
| 106 | input DAE.Type ty; | ||
| 107 | input DAE.Exp lhs; | ||
| 108 | input DAE.Exp rhs; | ||
| 109 | input DAE.ElementSource source; | ||
| 110 | output DAE.Statement outStatement; | ||
| 111 | algorithm | ||
| 112 | outStatement := match lhs | ||
| 113 | case DAE.CREF(componentRef=DAE.WILD()) | ||
| 114 | 6 | then DAE.STMT_NORETCALL(rhs, source); | |
| 115 | case DAE.PATTERN(pattern=DAE.PAT_WILD()) | ||
| 116 | 2 | then DAE.STMT_NORETCALL(rhs, source); | |
| 117 | 9826 | else DAE.STMT_ASSIGN(ty, lhs, rhs, source); | |
| 118 | end match; | ||
| 119 | end makeAssignmentNoTypeCheck; | ||
| 120 | |||
| 121 | public function makeArrayAssignmentNoTypeCheck | ||
| 122 | "Used to optimize assignments to NORETCALL if applicable" | ||
| 123 | input DAE.Type ty; | ||
| 124 | input DAE.Exp lhs; | ||
| 125 | input DAE.Exp rhs; | ||
| 126 | input DAE.ElementSource source; | ||
| 127 | output DAE.Statement outStatement; | ||
| 128 | algorithm | ||
| 129 | outStatement := match lhs | ||
| 130 | case DAE.CREF(DAE.WILD()) | ||
| 131 | ✗ | then DAE.STMT_NORETCALL(rhs, source); | |
| 132 | ✗ | else DAE.STMT_ASSIGN_ARR(ty, lhs, rhs, source); | |
| 133 | end match; | ||
| 134 | end makeArrayAssignmentNoTypeCheck; | ||
| 135 | |||
| 136 | public function makeTupleAssignmentNoTypeCheck | ||
| 137 | "Used to optimize assignments to NORETCALL if applicable" | ||
| 138 | input DAE.Type ty; | ||
| 139 | input list<DAE.Exp> lhs; | ||
| 140 | input DAE.Exp rhs; | ||
| 141 | input DAE.ElementSource source; | ||
| 142 | output DAE.Statement outStatement; | ||
| 143 | protected | ||
| 144 | Boolean b1,b2; | ||
| 145 | algorithm | ||
| 146 | 1613 | b1 := List.all(lhs, Expression.isWild); | |
| 147 | 1613 | b2 := List.all(List.restOrEmpty(lhs), Expression.isWild); | |
| 148 | 1613 | outStatement := makeTupleAssignmentNoTypeCheck2(b1,b2,ty,lhs,rhs,source); | |
| 149 | end makeTupleAssignmentNoTypeCheck; | ||
| 150 | |||
| 151 | protected function makeTupleAssignmentNoTypeCheck2 | ||
| 152 | input Boolean allWild; | ||
| 153 | input Boolean singleAssign; | ||
| 154 | input DAE.Type ty; | ||
| 155 | input list<DAE.Exp> lhs; | ||
| 156 | input DAE.Exp rhs; | ||
| 157 | input DAE.ElementSource source; | ||
| 158 | output DAE.Statement outStatement; | ||
| 159 | algorithm | ||
| 160 | outStatement := match (allWild, singleAssign, ty, lhs) | ||
| 161 | local | ||
| 162 | DAE.Type ty1; | ||
| 163 | DAE.Exp lhs1; | ||
| 164 | 49 | case (true, _, _, _) then DAE.STMT_NORETCALL(rhs, source); | |
| 165 | case (_, true, DAE.T_TUPLE(types=(ty1 as DAE.T_ARRAY())::_), lhs1::_) | ||
| 166 | 2 | then DAE.STMT_ASSIGN_ARR(ty1, lhs1, DAE.TSUB(rhs, 1, ty1), source); | |
| 167 | case (_, true, DAE.T_TUPLE(types=ty1::_), lhs1::_) | ||
| 168 | 114 | then DAE.STMT_ASSIGN(ty1, lhs1, DAE.TSUB(rhs,1,ty1), source); | |
| 169 | 1448 | else DAE.STMT_TUPLE_ASSIGN(ty,lhs,rhs,source); | |
| 170 | end match; | ||
| 171 | end makeTupleAssignmentNoTypeCheck2; | ||
| 172 | |||
| 173 | public function makeAssignment | ||
| 174 | "This function creates an `DAE.STMT_ASSIGN\' construct, and checks that the | ||
| 175 | assignment is semantically valid, which means that the component | ||
| 176 | being assigned is not constant, and that the types match. | ||
| 177 | LS: Added call to getPropType and isPropAnyConst instead of | ||
| 178 | having PROP in the rules. Otherwise rules must be repeated because of | ||
| 179 | combinations with PROP_TUPLE" | ||
| 180 | input DAE.Exp inExp1; | ||
| 181 | input DAE.Properties inProperties2; | ||
| 182 | input DAE.Exp inExp3; | ||
| 183 | input DAE.Properties inProperties4; | ||
| 184 | input DAE.Attributes inAttributes; | ||
| 185 | input SCode.Initial initial_; | ||
| 186 | input DAE.ElementSource source; | ||
| 187 | output DAE.Statement outStatement; | ||
| 188 | algorithm | ||
| 189 | outStatement := matchcontinue (inExp1, inProperties2, inExp3, inProperties4, inAttributes, initial_) | ||
| 190 | local | ||
| 191 | String lhs_str, rhs_str, lt_str, rt_str; | ||
| 192 | DAE.Exp lhs, rhs; | ||
| 193 | DAE.Properties lprop, rprop, lhprop, rhprop; | ||
| 194 | DAE.ComponentRef cr; | ||
| 195 | DAE.Type lt, rt; | ||
| 196 | SourceInfo info; | ||
| 197 | |||
| 198 | case ((DAE.CREF(componentRef=DAE.WILD())), _, rhs, _, _, _) | ||
| 199 | 2 | then DAE.STMT_NORETCALL(rhs, source); | |
| 200 | |||
| 201 | // assign to parameter in algorithm okay if record | ||
| 202 | case ((lhs as DAE.CREF(componentRef=cr)), lhprop, rhs, rhprop, _, SCode.NON_INITIAL()) | ||
| 203 | algorithm | ||
| 204 |
1/2✓ Branch 1 taken 35007 times.
✗ Branch 2 not taken.
|
35007 | DAE.C_PARAM() := Types.propAnyConst(lhprop); |
| 205 | ✗ | true := ComponentReference.isRecord(cr); | |
| 206 | ✗ | outStatement := makeAssignment2(lhs, lhprop, rhs, rhprop, source); | |
| 207 | then outStatement; | ||
| 208 | |||
| 209 | // assign to parameter in algorithm produce error | ||
| 210 | case (lhs, lprop, rhs, _, _, SCode.NON_INITIAL()) | ||
| 211 | algorithm | ||
| 212 |
1/2✓ Branch 1 taken 35014 times.
✗ Branch 2 not taken.
|
35014 | DAE.C_PARAM() := Types.propAnyConst(lprop); |
| 213 | ✗ | lhs_str := ExpressionBasics.printExpStr(lhs); | |
| 214 | ✗ | rhs_str := ExpressionBasics.printExpStr(rhs); | |
| 215 | ✗ | Error.addSourceMessage(Error.ASSIGN_PARAM_ERROR, {lhs_str, rhs_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 216 | ✗ | then | |
| 217 | fail(); | ||
| 218 | |||
| 219 | // assignment to a constant, report error | ||
| 220 | case (lhs, _, _, _, DAE.ATTR(variability = SCode.CONST()), _) | ||
| 221 | algorithm | ||
| 222 | ✗ | lhs_str := ExpressionBasics.printExpStr(lhs); | |
| 223 | ✗ | Error.addSourceMessage(Error.ASSIGN_READONLY_ERROR, {"constant", lhs_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 224 | ✗ | then | |
| 225 | fail(); | ||
| 226 | |||
| 227 | // assignment to parameter ok in initial algorithm | ||
| 228 | case (lhs, lhprop, rhs, rhprop, _, SCode.INITIAL()) | ||
| 229 | algorithm | ||
| 230 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 94 times.
|
99 | DAE.C_PARAM() := Types.propAnyConst(lhprop); |
| 231 | 94 | outStatement := makeAssignment2(lhs, lhprop, rhs, rhprop, source); | |
| 232 | then outStatement; | ||
| 233 | |||
| 234 | case (lhs, lhprop, rhs, rhprop, DAE.ATTR(), _) | ||
| 235 | algorithm | ||
| 236 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 35019 times.
|
35019 | DAE.C_VAR() := Types.propAnyConst(lhprop); |
| 237 | 35019 | outStatement := makeAssignment2(lhs, lhprop, rhs, rhprop, source); | |
| 238 | then outStatement; | ||
| 239 | |||
| 240 | /* report an error */ | ||
| 241 | case (lhs, lprop, rhs, rprop, _, _) | ||
| 242 | algorithm | ||
| 243 | ✗ | lt := Types.getPropType(lprop); | |
| 244 | ✗ | rt := Types.getPropType(rprop); | |
| 245 | ✗ | false := Types.equivtypes(lt, rt); | |
| 246 | ✗ | lhs_str := ExpressionBasics.printExpStr(lhs); | |
| 247 | ✗ | rhs_str := ExpressionBasics.printExpStr(rhs); | |
| 248 | ✗ | lt_str := TypesDump.unparseTypeNoAttr(lt); | |
| 249 | ✗ | rt_str := TypesDump.unparseTypeNoAttr(rt); | |
| 250 | ✗ | info := ElementSource.getElementSourceFileInfo(source); | |
| 251 | ✗ | Types.typeErrorSanityCheck(lt_str, rt_str, info); | |
| 252 | ✗ | Error.addSourceMessage(Error.ASSIGN_TYPE_MISMATCH_ERROR, | |
| 253 | {lhs_str, rhs_str, lt_str, rt_str}, info); | ||
| 254 | ✗ | then | |
| 255 | fail(); | ||
| 256 | |||
| 257 | /* failing */ | ||
| 258 | case (lhs, _, rhs, _, _, _) | ||
| 259 | algorithm | ||
| 260 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 261 | ✗ | Debug.traceln("- Algorithm.makeAssignment failed"); | |
| 262 | ✗ | Debug.trace(" "); | |
| 263 | ✗ | Debug.trace(ExpressionBasics.printExpStr(lhs)); | |
| 264 | ✗ | Debug.trace(" := "); | |
| 265 | ✗ | Debug.traceln(ExpressionBasics.printExpStr(rhs)); | |
| 266 | ✗ | then | |
| 267 | fail(); | ||
| 268 | end matchcontinue; | ||
| 269 | end makeAssignment; | ||
| 270 | |||
| 271 | protected function makeAssignment2 | ||
| 272 | "Help function to makeAssignment" | ||
| 273 | input DAE.Exp lhs; | ||
| 274 | input DAE.Properties lhprop; | ||
| 275 | input DAE.Exp rhs; | ||
| 276 | input DAE.Properties rhprop; | ||
| 277 | input DAE.ElementSource source; | ||
| 278 | output DAE.Statement outStatement; | ||
| 279 | algorithm | ||
| 280 | outStatement := match lhs | ||
| 281 | local | ||
| 282 | DAE.Exp rhs_1, e3, e1; | ||
| 283 | DAE.Type t, ty; | ||
| 284 | |||
| 285 | case DAE.CREF() guard not Types.isPropArray(lhprop) | ||
| 286 | algorithm | ||
| 287 | 34359 | rhs_1 := Types.matchProp(rhs, rhprop, lhprop, true); | |
| 288 | 34359 | t := getPropExpType(lhprop); | |
| 289 | () := match rhs_1 | ||
| 290 | case DAE.CALL(attr=DAE.CALL_ATTR(builtin=true), path=Absyn.IDENT("listAppend"), expLst=(e1 as DAE.CREF())::_) | ||
| 291 | guard ExpressionBasics.expEqual(lhs, e1) | ||
| 292 | algorithm | ||
| 293 |
6/8✓ Branch 1 taken 3 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 3 times.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✓ Branch 10 taken 3 times.
|
6 | if Flags.isSet(Flags.LIST_REVERSE_WRONG_ORDER) and not max(SCodeUtil.commentHasBooleanNamedAnnotation(comment, "__OpenModelica_DisableListAppendWarning") for comment in ElementSource.getComments(source)) then |
| 294 | ✗ | Error.addSourceMessage(Error.LIST_REVERSE_WRONG_ORDER, {ExpressionBasics.printExpStr(e1)}, ElementSource.getElementSourceFileInfo(source)); | |
| 295 | ✗ | fail(); | |
| 296 | end if; | ||
| 297 | then (); | ||
| 298 | else (); | ||
| 299 | end match; | ||
| 300 | 34359 | then | |
| 301 | DAE.STMT_ASSIGN(t, lhs, rhs_1, source); | ||
| 302 | /* TODO: Use this when we have fixed states in BackendDAE .lower(...) | ||
| 303 | case (e1 as DAE.CALL(Absyn.IDENT("der"), {DAE.CREF(_, _)}, _, _, _), lhprop, rhs, rhprop) | ||
| 304 | algorithm | ||
| 305 | (rhs_1, _) = Types.matchProp(rhs, rhprop, lhprop); | ||
| 306 | false = Types.isPropArray(lhprop); | ||
| 307 | t = getPropExpType(lhprop); | ||
| 308 | then | ||
| 309 | DAE.STMT_ASSIGN(t, e1, rhs_1); | ||
| 310 | */ | ||
| 311 | case DAE.CREF() // guard Types.isPropArray(lhprop) | ||
| 312 | algorithm | ||
| 313 | 747 | (rhs_1, _) := Types.matchProp(rhs, rhprop, lhprop, false /* Don't duplicate errors */); | |
| 314 | 747 | ty := Types.getPropType(lhprop); | |
| 315 | 747 | t := Types.simplifyType(ty); | |
| 316 | 747 | then | |
| 317 | DAE.STMT_ASSIGN_ARR(t, lhs, rhs_1, source); | ||
| 318 | |||
| 319 | case e3 as DAE.ASUB(_, _) | ||
| 320 | algorithm | ||
| 321 | 7 | (rhs_1, _) := Types.matchProp(rhs, rhprop, lhprop, true); | |
| 322 | //false = Types.isPropArray(lhprop); | ||
| 323 | 7 | t := getPropExpType(lhprop); | |
| 324 | 7 | then | |
| 325 | DAE.STMT_ASSIGN(t, e3, rhs_1, source); | ||
| 326 | end match; | ||
| 327 | end makeAssignment2; | ||
| 328 | |||
| 329 | public function makeSimpleAssignment | ||
| 330 | input tuple<DAE.Exp, DAE.Exp> inTpl; | ||
| 331 | input DAE.ElementSource source; | ||
| 332 | output DAE.Statement outStmt; | ||
| 333 | protected | ||
| 334 | DAE.Exp e1, e2; | ||
| 335 | DAE.Type tp; | ||
| 336 | algorithm | ||
| 337 | ✗ | (e1 as DAE.CREF(ty=tp), e2) := inTpl; | |
| 338 | ✗ | outStmt := DAE.STMT_ASSIGN(tp, e1, e2, source); | |
| 339 | end makeSimpleAssignment; | ||
| 340 | |||
| 341 | public function makeAssignmentsList | ||
| 342 | input list<DAE.Exp> lhsExps; | ||
| 343 | input list<DAE.Properties> lhsProps; | ||
| 344 | input list<DAE.Exp> rhsExps; | ||
| 345 | input list<DAE.Properties> rhsProps; | ||
| 346 | input DAE.Attributes attributes; | ||
| 347 | input SCode.Initial initial_; | ||
| 348 | input DAE.ElementSource source; | ||
| 349 | output list<DAE.Statement> assignments; | ||
| 350 | algorithm | ||
| 351 | assignments := match(lhsExps, lhsProps, rhsExps, rhsProps) | ||
| 352 | local | ||
| 353 | DAE.Exp lhs, rhs; | ||
| 354 | list<DAE.Exp> rest_lhs, rest_rhs; | ||
| 355 | DAE.Properties lhs_prop, rhs_prop; | ||
| 356 | list<DAE.Properties> rest_lhs_prop, rest_rhs_prop; | ||
| 357 | DAE.Statement ass; | ||
| 358 | list<DAE.Statement> rest_ass; | ||
| 359 | case ({}, {}, _, _) then {}; /* rhs does not need to be empty */ | ||
| 360 | case (DAE.CREF(componentRef=DAE.WILD()) :: rest_lhs, _ :: rest_lhs_prop, _ :: rest_rhs, _ :: rest_rhs_prop) | ||
| 361 | ✗ | then makeAssignmentsList(rest_lhs, rest_lhs_prop, rest_rhs, rest_rhs_prop, attributes, initial_, source); | |
| 362 | case (lhs :: rest_lhs, lhs_prop :: rest_lhs_prop, rhs :: rest_rhs, rhs_prop :: rest_rhs_prop) | ||
| 363 | algorithm | ||
| 364 | 2 | ass := makeAssignment(lhs, lhs_prop, rhs, rhs_prop, attributes, initial_, source); | |
| 365 | 2 | rest_ass := makeAssignmentsList(rest_lhs, rest_lhs_prop, rest_rhs, rest_rhs_prop, attributes, initial_, source); | |
| 366 | then | ||
| 367 | ass :: rest_ass; | ||
| 368 | end match; | ||
| 369 | end makeAssignmentsList; | ||
| 370 | |||
| 371 | public function checkLHSWritable | ||
| 372 | "@author: adrpo | ||
| 373 | check if the parameters on rhs have fixed = false | ||
| 374 | and fail otherwise" | ||
| 375 | input list<DAE.Exp> lhs; | ||
| 376 | input list<DAE.Properties> props; | ||
| 377 | input DAE.Exp rhs; | ||
| 378 | input DAE.ElementSource source; | ||
| 379 | protected | ||
| 380 | DAE.Type ty; | ||
| 381 | Integer i = 1; | ||
| 382 | String c, l, r; | ||
| 383 | algorithm | ||
| 384 |
2/2✓ Branch 0 taken 2026 times.
✓ Branch 1 taken 960 times.
|
2986 | for p in props loop |
| 385 | () := match p | ||
| 386 | // variables is fine | ||
| 387 | case DAE.PROP(constFlag = DAE.C_VAR()) then (); | ||
| 388 | // constant | ||
| 389 | case DAE.PROP(_, DAE.C_CONST()) | ||
| 390 | algorithm | ||
| 391 | ✗ | l := stringAppendList({"(", stringDelimitList(List.map(lhs, ExpressionBasics.printExpStr), ", "), ")"}); | |
| 392 | ✗ | r := ExpressionBasics.printExpStr(rhs); | |
| 393 | ✗ | Error.addSourceMessage(Error.ASSIGN_CONSTANT_ERROR, {l, r}, ElementSource.getElementSourceFileInfo(source)); | |
| 394 | ✗ | fail(); | |
| 395 | then | ||
| 396 | (); | ||
| 397 | // parameters | ||
| 398 | case DAE.PROP(ty, DAE.C_PARAM()) | ||
| 399 | algorithm | ||
| 400 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | if Types.getFixedVarAttributeParameterOrConstant(ty) then |
| 401 | 2 | l := stringAppendList({"(", stringDelimitList(List.map(lhs, ExpressionBasics.printExpStr), ", "), ")"}); | |
| 402 | 1 | r := ExpressionBasics.printExpStr(rhs); | |
| 403 | 1 | c := ExpressionBasics.printExpStr(listGet(lhs, i)); | |
| 404 | 1 | Error.addSourceMessage(Error.ASSIGN_PARAM_FIXED_ERROR, {c, l, r}, ElementSource.getElementSourceFileInfo(source)); | |
| 405 | 1 | fail(); | |
| 406 | end if; | ||
| 407 | then | ||
| 408 | (); | ||
| 409 | // tuples? TODO! FIXME! can we get tuple here? maybe only for MetaModelica | ||
| 410 | case DAE.PROP_TUPLE(_, _) then (); | ||
| 411 | end match; | ||
| 412 | 2025 | i := i + 1; | |
| 413 | end for; | ||
| 414 | end checkLHSWritable; | ||
| 415 | |||
| 416 | public function makeTupleAssignment "This function creates an `DAE.STMT_TUPLE_ASSIGN\' construct, and checks that the | ||
| 417 | assignment is semantically valid, which means that the component | ||
| 418 | being assigned is not constant, and that the types match." | ||
| 419 | input list<DAE.Exp> inExpExpLst; | ||
| 420 | input list<DAE.Properties> inTypesPropertiesLst; | ||
| 421 | input DAE.Exp inExp; | ||
| 422 | input DAE.Properties inProperties; | ||
| 423 | input SCode.Initial initial_; | ||
| 424 | input DAE.ElementSource source; | ||
| 425 | output DAE.Statement outStatement; | ||
| 426 | algorithm | ||
| 427 | outStatement := matchcontinue (inExpExpLst, inTypesPropertiesLst, inExp, inProperties, initial_) | ||
| 428 | local | ||
| 429 | list<DAE.Const> bvals; | ||
| 430 | list<String> sl; | ||
| 431 | String s, lhs_str, rhs_str, str1, str2, strInitial; | ||
| 432 | list<DAE.Exp> lhs, expl; | ||
| 433 | list<DAE.Properties> lprop, lhprops; | ||
| 434 | DAE.Exp rhs; | ||
| 435 | DAE.Properties rprop; | ||
| 436 | list<DAE.Type> lhrtypes, tpl; | ||
| 437 | DAE.Type ty; | ||
| 438 | |||
| 439 | case (lhs, lprop, rhs, _, _) | ||
| 440 | algorithm | ||
| 441 | 963 | bvals := List.map(lprop, Types.propAnyConst); | |
| 442 |
1/2✓ Branch 1 taken 914 times.
✗ Branch 2 not taken.
|
963 | DAE.C_CONST() := List.reduce(bvals, Types.constOr); |
| 443 | ✗ | sl := List.map(lhs, ExpressionBasics.printExpStr); | |
| 444 | ✗ | s := stringDelimitList(sl, ", "); | |
| 445 | ✗ | lhs_str := stringAppendList({"(", s, ")"}); | |
| 446 | ✗ | rhs_str := ExpressionBasics.printExpStr(rhs); | |
| 447 | ✗ | Error.addSourceMessage(Error.ASSIGN_CONSTANT_ERROR, {lhs_str, rhs_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 448 | ✗ | then | |
| 449 | fail(); | ||
| 450 | case (lhs, lprop, rhs, _, SCode.NON_INITIAL()) | ||
| 451 | algorithm | ||
| 452 | 962 | bvals := List.map(lprop, Types.propAnyConst); | |
| 453 |
1/2✓ Branch 1 taken 913 times.
✗ Branch 2 not taken.
|
962 | DAE.C_PARAM() := List.reduce(bvals, Types.constOr); |
| 454 | ✗ | sl := List.map(lhs, ExpressionBasics.printExpStr); | |
| 455 | ✗ | s := stringDelimitList(sl, ", "); | |
| 456 | ✗ | lhs_str := stringAppendList({"(", s, ")"}); | |
| 457 | ✗ | rhs_str := ExpressionBasics.printExpStr(rhs); | |
| 458 | ✗ | Error.addSourceMessage(Error.ASSIGN_PARAM_ERROR, {lhs_str, rhs_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 459 | ✗ | then | |
| 460 | fail(); | ||
| 461 | // a normal prop in rhs that contains a T_TUPLE! | ||
| 462 | case (expl, lhprops, rhs, DAE.PROP(type_ = ty as DAE.T_TUPLE(types = tpl)), _) | ||
| 463 | algorithm | ||
| 464 | 139 | checkLHSWritable(expl, lhprops, rhs, source); | |
| 465 | 139 | lhrtypes := List.map(lhprops, Types.getPropType); | |
| 466 | 139 | Types.matchTypeTupleCall(rhs, tpl, lhrtypes); | |
| 467 | /* Don\'t use new rhs\', since type conversions of | ||
| 468 | several output args are not clearly defined. */ | ||
| 469 | 139 | then makeTupleAssignmentNoTypeCheck(ty, expl, rhs, source); | |
| 470 | // a tuple in rhs | ||
| 471 | case (expl, lhprops, rhs, DAE.PROP_TUPLE(type_ = ty as DAE.T_TUPLE(types = tpl), tupleConst = DAE.TUPLE_CONST()), _) | ||
| 472 | algorithm | ||
| 473 | 822 | checkLHSWritable(expl, lhprops, rhs, source); | |
| 474 | 821 | lhrtypes := List.map(lhprops, Types.getPropType); | |
| 475 | 821 | Types.matchTypeTupleCall(rhs, tpl, lhrtypes); | |
| 476 | /* Don\'t use new rhs\', since type conversions of several output args are not clearly defined. */ | ||
| 477 | 820 | then makeTupleAssignmentNoTypeCheck(ty, expl, rhs, source); | |
| 478 | case (lhs, lprop, rhs, rprop, _) | ||
| 479 | algorithm | ||
| 480 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
4 | true := Flags.isSet(Flags.FAILTRACE); |
| 481 | ✗ | sl := List.map(lhs, ExpressionBasics.printExpStr); | |
| 482 | ✗ | s := stringDelimitList(sl, ", "); | |
| 483 | ✗ | lhs_str := stringAppendList({"(", s, ")"}); | |
| 484 | ✗ | rhs_str := ExpressionBasics.printExpStr(rhs); | |
| 485 | ✗ | str1 := stringDelimitList(List.map(lprop, Types.printPropStr), ", "); | |
| 486 | ✗ | str2 := Types.printPropStr(rprop); | |
| 487 | ✗ | strInitial := SCodeDump.printInitialStr(initial_); | |
| 488 | ✗ | Debug.traceln("- Algorithm.makeTupleAssignment failed on: \n\t" + | |
| 489 | lhs_str + " = " + rhs_str + | ||
| 490 | "\n\tprops lhs: (" + str1 + ") = props rhs: " + str2 + | ||
| 491 | "\n\tin " + strInitial + " section"); | ||
| 492 | ✗ | then | |
| 493 | fail(); | ||
| 494 | end matchcontinue; | ||
| 495 | end makeTupleAssignment; | ||
| 496 | |||
| 497 | protected function getPropExpType "Returns the expression type for a given Properties by calling | ||
| 498 | getTypeExpType. Used by makeAssignment." | ||
| 499 | input DAE.Properties p; | ||
| 500 | output DAE.Type t; | ||
| 501 | protected | ||
| 502 | DAE.Type ty; | ||
| 503 | algorithm | ||
| 504 | 34366 | ty := Types.getPropType(p); | |
| 505 | 34366 | t := Types.simplifyType(ty); | |
| 506 | end getPropExpType; | ||
| 507 | |||
| 508 | public function makeIf "This function creates an `DAE.STMT_IF\' construct, checking that the types | ||
| 509 | of the parts are correct. Else part is generated using the makeElse | ||
| 510 | function." | ||
| 511 | input DAE.Exp inExp; | ||
| 512 | input DAE.Properties inProperties; | ||
| 513 | input list<DAE.Statement> inTrueBranch; | ||
| 514 | input list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> inElseIfBranches; | ||
| 515 | input list<DAE.Statement> inElseBranch; | ||
| 516 | input DAE.ElementSource source; | ||
| 517 | output list<DAE.Statement> outStatements; | ||
| 518 | algorithm | ||
| 519 | outStatements := | ||
| 520 | matchcontinue (inExp, inProperties, inTrueBranch, inElseIfBranches, inElseBranch) | ||
| 521 | local | ||
| 522 | DAE.Else else_; | ||
| 523 | DAE.Exp e; | ||
| 524 | list<DAE.Statement> tb, fb; | ||
| 525 | list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> eib; | ||
| 526 | String e_str, t_str; | ||
| 527 | DAE.Type t; | ||
| 528 | DAE.Properties prop; | ||
| 529 | case (DAE.BCONST(true), _, tb, _, _) | ||
| 530 | then tb; | ||
| 531 | case (DAE.BCONST(false), _, _, {}, fb) | ||
| 532 | then fb; | ||
| 533 | case (DAE.BCONST(false), _, _, (e, prop, tb)::eib, fb) | ||
| 534 | 6 | then makeIf(e, prop, tb, eib, fb, source); | |
| 535 | case (e, DAE.PROP(type_ = t), tb, eib, fb) | ||
| 536 | algorithm | ||
| 537 | 1720 | (e, _) := Types.matchType(e, t, DAE.T_BOOL_DEFAULT, true); | |
| 538 | 1720 | else_ := makeElse(eib, fb, source); | |
| 539 | 1720 | then | |
| 540 | {DAE.STMT_IF(e, tb, else_, source)}; | ||
| 541 | case (e, DAE.PROP(type_ = t), _, _, _) | ||
| 542 | algorithm | ||
| 543 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 544 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 545 | ✗ | Error.addSourceMessage(Error.IF_CONDITION_TYPE_ERROR, {e_str, t_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 546 | ✗ | then | |
| 547 | fail(); | ||
| 548 | end matchcontinue; | ||
| 549 | end makeIf; | ||
| 550 | |||
| 551 | public function makeIfFromBranches " | ||
| 552 | Create an if-statement from branches, optimizing as needed." | ||
| 553 | input list<tuple<DAE.Exp, list<DAE.Statement>>> branches; | ||
| 554 | input DAE.ElementSource source; | ||
| 555 | output list<DAE.Statement> outStatements; | ||
| 556 | algorithm | ||
| 557 | outStatements := match branches | ||
| 558 | local | ||
| 559 | DAE.Else else_; | ||
| 560 | DAE.Exp e; | ||
| 561 | list<DAE.Statement> br; | ||
| 562 | list<tuple<DAE.Exp, list<DAE.Statement>>> rest; | ||
| 563 | case {} then {}; | ||
| 564 | case (e, br)::rest | ||
| 565 | algorithm | ||
| 566 | ✗ | else_ := makeElseFromBranches(rest); | |
| 567 | ✗ | then {DAE.STMT_IF(e, br, else_, source)}; | |
| 568 | end match; | ||
| 569 | end makeIfFromBranches; | ||
| 570 | |||
| 571 | protected function makeElseFromBranches "Creates the ELSE part of the DAE.STMT_IF." | ||
| 572 | input list<tuple<DAE.Exp, list<DAE.Statement>>> inTpl; | ||
| 573 | output DAE.Else outElse; | ||
| 574 | algorithm | ||
| 575 | outElse := match inTpl | ||
| 576 | local | ||
| 577 | list<DAE.Statement> b; | ||
| 578 | DAE.Else else_; | ||
| 579 | DAE.Exp e; | ||
| 580 | list<tuple<DAE.Exp, list<DAE.Statement>>> xs; | ||
| 581 | case {} then DAE.NOELSE(); | ||
| 582 | ✗ | case {(DAE.BCONST(true), b)} then DAE.ELSE(b); | |
| 583 | case (e, b)::xs | ||
| 584 | algorithm | ||
| 585 | ✗ | else_ := makeElseFromBranches(xs); | |
| 586 | ✗ | then DAE.ELSEIF(e, b, else_); | |
| 587 | end match; | ||
| 588 | end makeElseFromBranches; | ||
| 589 | |||
| 590 | public function optimizeIf | ||
| 591 | "Every time we re-create/walk an if-statement, we optimize a bit :)" | ||
| 592 | input DAE.Exp icond; | ||
| 593 | input list<DAE.Statement> istmts; | ||
| 594 | input DAE.Else iels; | ||
| 595 | input DAE.ElementSource isource; | ||
| 596 | output list<DAE.Statement> ostmts "can be empty or selected branch"; | ||
| 597 | output Boolean changed; | ||
| 598 | algorithm | ||
| 599 | (ostmts,changed) := match (icond, istmts, iels, isource) | ||
| 600 | local | ||
| 601 | list<DAE.Statement> stmts; | ||
| 602 | DAE.Else els; | ||
| 603 | DAE.ElementSource source; | ||
| 604 | DAE.Exp cond; | ||
| 605 | |||
| 606 | case (DAE.BCONST(true), stmts, _, _) then (stmts,true); | ||
| 607 | case (DAE.BCONST(false), _, DAE.NOELSE(), _) then ({},true); | ||
| 608 | case (DAE.BCONST(false), _, DAE.ELSE(stmts), _) then (stmts,true); | ||
| 609 | ✗ | case (DAE.BCONST(false), _, DAE.ELSEIF(cond, stmts, els), source) algorithm (ostmts,_) := optimizeIf(cond, stmts, els, source); then (ostmts,true); | |
| 610 | 47585 | else (DAE.STMT_IF(icond, istmts, iels, isource)::{},false); | |
| 611 | end match; | ||
| 612 | end optimizeIf; | ||
| 613 | |||
| 614 | public function optimizeElseIf | ||
| 615 | "Every time we re-create/walk an if-statement, we optimize a bit :)" | ||
| 616 | input DAE.Exp cond; | ||
| 617 | input list<DAE.Statement> stmts; | ||
| 618 | input DAE.Else els; | ||
| 619 | output DAE.Else oelse; | ||
| 620 | algorithm | ||
| 621 | oelse := match cond | ||
| 622 | ✗ | case DAE.BCONST(true) then DAE.ELSE(stmts); | |
| 623 | case DAE.BCONST(false) then els; | ||
| 624 | 14437 | else DAE.ELSEIF(cond, stmts, els); | |
| 625 | end match; | ||
| 626 | end optimizeElseIf; | ||
| 627 | |||
| 628 | protected function makeElse "This function creates the ELSE part of the DAE.STMT_IF and checks if is correct." | ||
| 629 | input list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> inTuple; | ||
| 630 | input list<DAE.Statement> inStatementLst; | ||
| 631 | input DAE.ElementSource inSource; | ||
| 632 | output DAE.Else outElse; | ||
| 633 | algorithm | ||
| 634 | outElse := matchcontinue(inTuple, inStatementLst) | ||
| 635 | local | ||
| 636 | list<DAE.Statement> fb, b; | ||
| 637 | DAE.Else else_; | ||
| 638 | DAE.Exp e; | ||
| 639 | list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> xs; | ||
| 640 | String e_str, t_str; | ||
| 641 | DAE.Type t; | ||
| 642 | SourceInfo info; | ||
| 643 | |||
| 644 | case ({}, {}) then DAE.NOELSE(); /* This removes empty else branches */ | ||
| 645 | 1121 | case ({}, fb) then DAE.ELSE(fb); | |
| 646 | ✗ | case (((DAE.BCONST(true), DAE.PROP(), b) :: _), _) then DAE.ELSE(b); | |
| 647 | 2 | case (((DAE.BCONST(false), DAE.PROP(), _) :: xs), fb) then makeElse(xs, fb, inSource); | |
| 648 | case (((e, DAE.PROP(type_ = t), b) :: xs), fb) | ||
| 649 | algorithm | ||
| 650 | 499 | (e, _) := Types.matchType(e, t, DAE.T_BOOL_DEFAULT, true); | |
| 651 | 499 | else_ := makeElse(xs, fb, inSource); | |
| 652 | 499 | then | |
| 653 | DAE.ELSEIF(e, b, else_); | ||
| 654 | case (((e, DAE.PROP(type_ = t), _) :: _), _) | ||
| 655 | algorithm | ||
| 656 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 657 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 658 | ✗ | info := ElementSource.getElementSourceFileInfo(inSource); | |
| 659 | ✗ | Error.addSourceMessage(Error.IF_CONDITION_TYPE_ERROR, {e_str, t_str}, info); | |
| 660 | ✗ | then | |
| 661 | fail(); | ||
| 662 | end matchcontinue; | ||
| 663 | end makeElse; | ||
| 664 | |||
| 665 | public function makeFor "This function creates a DAE.STMT_FOR construct, checking | ||
| 666 | that the types of the parts are correct." | ||
| 667 | input String inIdent; | ||
| 668 | input DAE.Exp inExp; | ||
| 669 | input DAE.Properties inProperties; | ||
| 670 | input list<DAE.Statement> inStatementLst; | ||
| 671 | input DAE.ElementSource source; | ||
| 672 | output DAE.Statement outStatement; | ||
| 673 | algorithm | ||
| 674 | outStatement := matchcontinue (inIdent, inExp, inProperties, inStatementLst) | ||
| 675 | local | ||
| 676 | Boolean isArray; | ||
| 677 | String i, e_str, t_str; | ||
| 678 | DAE.Exp e; | ||
| 679 | DAE.Type t; | ||
| 680 | list<DAE.Statement> stmts; | ||
| 681 | DAE.Dimensions dims; | ||
| 682 | |||
| 683 | case (i, e, DAE.PROP(type_ = DAE.T_ARRAY(ty = t, dims = dims)), stmts) | ||
| 684 | algorithm | ||
| 685 | 235 | isArray := Types.isNonscalarArray(t, dims); | |
| 686 |
1/2✓ Branch 0 taken 235 times.
✗ Branch 1 not taken.
|
470 | then DAE.STMT_FOR(t, isArray, i, e, stmts, source, {}); |
| 687 | |||
| 688 | case (i, e, DAE.PROP(type_ = DAE.T_METALIST(ty = t)), stmts) | ||
| 689 | algorithm | ||
| 690 | 251 | t := Types.simplifyType(t); | |
| 691 | 251 | then DAE.STMT_FOR(t, false, i, e, stmts, source, {}); | |
| 692 | |||
| 693 | case (i, e, DAE.PROP(type_ = DAE.T_METAARRAY(ty = t)), stmts) | ||
| 694 | algorithm | ||
| 695 | 3 | t := Types.simplifyType(t); | |
| 696 | 3 | then DAE.STMT_FOR(t, false, i, e, stmts, source, {}); | |
| 697 | |||
| 698 | case (_, e, DAE.PROP(type_ = t), _) | ||
| 699 | algorithm | ||
| 700 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 701 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 702 | ✗ | Error.addSourceMessage(Error.FOR_EXPRESSION_TYPE_ERROR, {e_str, t_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 703 | ✗ | then | |
| 704 | fail(); | ||
| 705 | end matchcontinue; | ||
| 706 | end makeFor; | ||
| 707 | |||
| 708 | public function makeParFor "This function creates a DAE.STMT_PARFOR construct, checking | ||
| 709 | that the types of the parts are correct." | ||
| 710 | input String inIdent; | ||
| 711 | input DAE.Exp inExp; | ||
| 712 | input DAE.Properties inProperties; | ||
| 713 | input list<DAE.Statement> inStatementLst; | ||
| 714 | input list<tuple<DAE.ComponentRef, SourceInfo>> inLoopPrlVars; | ||
| 715 | input DAE.ElementSource source; | ||
| 716 | output DAE.Statement outStatement; | ||
| 717 | algorithm | ||
| 718 | outStatement := match (inIdent, inExp, inProperties, inStatementLst) | ||
| 719 | local | ||
| 720 | Boolean isArray; | ||
| 721 | String i, e_str, t_str; | ||
| 722 | DAE.Exp e; | ||
| 723 | DAE.Type t; | ||
| 724 | list<DAE.Statement> stmts; | ||
| 725 | DAE.Dimensions dims; | ||
| 726 | |||
| 727 | case (i, e, DAE.PROP(type_ = DAE.T_ARRAY(ty = t, dims = dims)), stmts) | ||
| 728 | algorithm | ||
| 729 | ✗ | isArray := Types.isNonscalarArray(t, dims); | |
| 730 | ✗ | then | |
| 731 | DAE.STMT_PARFOR(t, isArray, i, e, stmts, inLoopPrlVars, source); | ||
| 732 | |||
| 733 | case (_, e, DAE.PROP(type_ = t), _) | ||
| 734 | algorithm | ||
| 735 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 736 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 737 | ✗ | Error.addSourceMessage(Error.FOR_EXPRESSION_TYPE_ERROR, {e_str, t_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 738 | ✗ | then | |
| 739 | fail(); | ||
| 740 | end match; | ||
| 741 | end makeParFor; | ||
| 742 | |||
| 743 | public function makeWhile "This function creates a DAE.STMT_WHILE construct, checking that the types | ||
| 744 | of the parts are correct." | ||
| 745 | input DAE.Exp inExp; | ||
| 746 | input DAE.Properties inProperties; | ||
| 747 | input list<DAE.Statement> inStatementLst; | ||
| 748 | input DAE.ElementSource source; | ||
| 749 | output DAE.Statement outStatement; | ||
| 750 | algorithm | ||
| 751 | outStatement:= | ||
| 752 | match (inExp, inProperties, inStatementLst) | ||
| 753 | local | ||
| 754 | DAE.Exp e; | ||
| 755 | list<DAE.Statement> stmts; | ||
| 756 | String e_str, t_str; | ||
| 757 | DAE.Type t; | ||
| 758 | 121 | case (e, DAE.PROP(type_ = DAE.T_BOOL()), stmts) then DAE.STMT_WHILE(e, stmts, source); | |
| 759 | case (e, DAE.PROP(type_ = t), _) | ||
| 760 | algorithm | ||
| 761 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 762 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 763 | ✗ | Error.addSourceMessage(Error.WHILE_CONDITION_TYPE_ERROR, {e_str, t_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 764 | ✗ | then | |
| 765 | fail(); | ||
| 766 | end match; | ||
| 767 | end makeWhile; | ||
| 768 | |||
| 769 | public function makeWhenA "This function creates a DAE.STMT_WHEN algorithm construct, | ||
| 770 | checking that the types of the parts are correct." | ||
| 771 | input DAE.Exp inExp; | ||
| 772 | input DAE.Properties inProperties; | ||
| 773 | input list<DAE.Statement> inStatementLst; | ||
| 774 | input Option<DAE.Statement> elseWhenStmt; | ||
| 775 | input DAE.ElementSource source; | ||
| 776 | output DAE.Statement outStatement; | ||
| 777 | algorithm | ||
| 778 | outStatement:= | ||
| 779 | match (inExp, inProperties, inStatementLst, elseWhenStmt) | ||
| 780 | local | ||
| 781 | DAE.Exp e; | ||
| 782 | list<DAE.Statement> stmts; | ||
| 783 | Option<DAE.Statement> elsew; | ||
| 784 | String e_str, t_str; | ||
| 785 | DAE.Type t; | ||
| 786 | 96 | case (e, DAE.PROP(type_ = DAE.T_BOOL()), stmts, elsew) then DAE.STMT_WHEN(e, {}, false, stmts, elsew, source); | |
| 787 | 45 | case (e, DAE.PROP(type_ = DAE.T_ARRAY(ty = DAE.T_BOOL())), stmts, elsew) then DAE.STMT_WHEN(e, {}, false, stmts, elsew, source); | |
| 788 | case (e, DAE.PROP(type_ = t), _, _) | ||
| 789 | algorithm | ||
| 790 | ✗ | e_str := ExpressionBasics.printExpStr(e); | |
| 791 | ✗ | t_str := TypesDump.unparseTypeNoAttr(t); | |
| 792 | ✗ | Error.addSourceMessage(Error.WHEN_CONDITION_TYPE_ERROR, {e_str, t_str}, ElementSource.getElementSourceFileInfo(source)); | |
| 793 | ✗ | then | |
| 794 | fail(); | ||
| 795 | end match; | ||
| 796 | end makeWhenA; | ||
| 797 | |||
| 798 | public function makeReinit " creates a reinit statement in an algorithm | ||
| 799 | statement, only valid in when algorithm sections." | ||
| 800 | input DAE.Exp inExp1; | ||
| 801 | input DAE.Exp inExp2; | ||
| 802 | input DAE.Properties inProperties3; | ||
| 803 | input DAE.Properties inProperties4; | ||
| 804 | input DAE.ElementSource source; | ||
| 805 | output list<DAE.Statement> outStatement; | ||
| 806 | algorithm | ||
| 807 | outStatement := matchcontinue (inExp1, inExp2, inProperties3, inProperties4) | ||
| 808 | local | ||
| 809 | DAE.Exp var, val, var_1, val_1; | ||
| 810 | DAE.Type tp1, tp2; | ||
| 811 | |||
| 812 | case (var as DAE.CREF(), val, DAE.PROP(tp1, _), DAE.PROP(tp2, _)) | ||
| 813 | algorithm | ||
| 814 | 21 | val_1 := Types.matchType(val, tp2, DAE.T_REAL_DEFAULT, true); | |
| 815 | 21 | var_1 := Types.matchType(var, tp1, DAE.T_REAL_DEFAULT, true); | |
| 816 | 21 | then | |
| 817 | {DAE.STMT_REINIT(var_1, val_1, source)}; | ||
| 818 | |||
| 819 | else | ||
| 820 | algorithm | ||
| 821 | ✗ | Error.addSourceMessage(Error.INTERNAL_ERROR, {"reinit called with wrong args"}, ElementSource.getElementSourceFileInfo(source)); | |
| 822 | ✗ | then | |
| 823 | fail(); | ||
| 824 | |||
| 825 | // TODO: Add checks for reinit here. 1. First argument must be variable. 2. Expressions must be real. | ||
| 826 | end matchcontinue; | ||
| 827 | end makeReinit; | ||
| 828 | |||
| 829 | public function makeAssert "Creates an assert statement from two expressions. | ||
| 830 | " | ||
| 831 | input DAE.Exp cond "condition"; | ||
| 832 | input DAE.Exp msg "message"; | ||
| 833 | input DAE.Exp level; | ||
| 834 | input DAE.Properties inProperties3; | ||
| 835 | input DAE.Properties inProperties4; | ||
| 836 | input DAE.Properties inProperties5; | ||
| 837 | input DAE.ElementSource source; | ||
| 838 | output list<DAE.Statement> outStatement; | ||
| 839 | algorithm | ||
| 840 | outStatement := match (cond, inProperties3, inProperties4, inProperties5) | ||
| 841 | local | ||
| 842 | SourceInfo info; | ||
| 843 | DAE.Type t1, t2, t3; | ||
| 844 | String strTy, strExp; | ||
| 845 | case (DAE.BCONST(true), DAE.PROP(type_ = DAE.T_BOOL()), DAE.PROP(type_ = DAE.T_STRING()), DAE.PROP(type_ = DAE.T_ENUMERATION(path=Absyn.FULLYQUALIFIED(Absyn.IDENT("AssertionLevel"))))) | ||
| 846 | then {}; | ||
| 847 | case (_, DAE.PROP(type_ = DAE.T_BOOL()), DAE.PROP(type_ = DAE.T_STRING()), DAE.PROP(type_ = DAE.T_ENUMERATION(path=Absyn.FULLYQUALIFIED(Absyn.IDENT("AssertionLevel"))))) | ||
| 848 | 547 | then {DAE.STMT_ASSERT(cond, msg, level, source)}; | |
| 849 | case (_, DAE.PROP(type_ = t1), DAE.PROP(type_ = t2), DAE.PROP(type_ = t3)) | ||
| 850 | algorithm | ||
| 851 | ✗ | info := ElementSource.getElementSourceFileInfo(source); | |
| 852 | ✗ | strExp := ExpressionBasics.printExpStr(cond); | |
| 853 | ✗ | strTy := TypesDump.unparseType(t1); | |
| 854 | ✗ | Error.assertionOrAddSourceMessage(Types.isBooleanOrSubTypeBoolean(t1), Error.EXP_TYPE_MISMATCH, {strExp, "Boolean", strTy}, info); | |
| 855 | ✗ | strExp := ExpressionBasics.printExpStr(msg); | |
| 856 | ✗ | strTy := TypesDump.unparseType(t2); | |
| 857 | ✗ | Error.assertionOrAddSourceMessage(Types.isString(t2), Error.EXP_TYPE_MISMATCH, {strExp, "String", strTy}, info); | |
| 858 | ✗ | failure(DAE.T_ENUMERATION(path=Absyn.IDENT("AssertionLevel")) := t3); | |
| 859 | ✗ | strExp := ExpressionBasics.printExpStr(level); | |
| 860 | ✗ | strTy := TypesDump.unparseType(t3); | |
| 861 | ✗ | Error.assertionOrAddSourceMessage(Types.isString(t3), Error.EXP_TYPE_MISMATCH, {strExp, "AssertionLevel", strTy}, info); | |
| 862 | ✗ | then fail(); | |
| 863 | end match; | ||
| 864 | end makeAssert; | ||
| 865 | |||
| 866 | public function makeTerminate " | ||
| 867 | Creates a terminate statement from message expression. | ||
| 868 | " | ||
| 869 | input DAE.Exp msg "message"; | ||
| 870 | input DAE.Properties props; | ||
| 871 | input DAE.ElementSource source; | ||
| 872 | output list<DAE.Statement> outStatement; | ||
| 873 | algorithm | ||
| 874 | outStatement := match props | ||
| 875 | ✗ | case DAE.PROP(type_ = DAE.T_STRING()) then {DAE.STMT_TERMINATE(msg, source)}; | |
| 876 | end match; | ||
| 877 | end makeTerminate; | ||
| 878 | |||
| 879 | public function getCrefFromAlg "Returns all crefs from an algorithm" | ||
| 880 | input DAE.Algorithm alg; | ||
| 881 | output list<DAE.ComponentRef> crs; | ||
| 882 | algorithm | ||
| 883 | ✗ | crs := List.unionOnTrueList(List.map(getAllExps(alg), Expression.extractCrefsFromExp), ComponentReferenceBasics.crefEqual); | |
| 884 | end getCrefFromAlg; | ||
| 885 | |||
| 886 | |||
| 887 | public function getAllExps " | ||
| 888 | This function goes through the Algorithm structure and finds all the | ||
| 889 | expressions and returns them in a list | ||
| 890 | " | ||
| 891 | input DAE.Algorithm inAlgorithm; | ||
| 892 | output list<DAE.Exp> outExpExpLst; | ||
| 893 | algorithm | ||
| 894 | outExpExpLst:= | ||
| 895 | match inAlgorithm | ||
| 896 | local | ||
| 897 | list<DAE.Exp> exps; | ||
| 898 | list<DAE.Statement> stmts; | ||
| 899 | case DAE.ALGORITHM_STMTS(statementLst = stmts) | ||
| 900 | algorithm | ||
| 901 | 42 | exps := getAllExpsStmts(stmts); | |
| 902 | then | ||
| 903 | exps; | ||
| 904 | end match; | ||
| 905 | end getAllExps; | ||
| 906 | |||
| 907 | public function getAllExpsStmts " | ||
| 908 | This function takes a list of statements and returns all expressions and subexpressions | ||
| 909 | in all statements. | ||
| 910 | " | ||
| 911 | input list<DAE.Statement> stmts; | ||
| 912 | output list<DAE.Exp> exps; | ||
| 913 | algorithm | ||
| 914 | 42 | (_, (_,exps)) := DAEUtil.traverseDAEEquationsStmts(stmts, Expression.traverseSubexpressionsHelper, (Expression.expressionCollector, {})); | |
| 915 | end getAllExpsStmts; | ||
| 916 | |||
| 917 | public function getStatementSource | ||
| 918 | input DAE.Statement stmt; | ||
| 919 | output DAE.ElementSource source; | ||
| 920 | algorithm | ||
| 921 | source := match stmt | ||
| 922 | case DAE.STMT_ASSIGN(source=source) then source; | ||
| 923 | case DAE.STMT_TUPLE_ASSIGN(source=source) then source; | ||
| 924 | case DAE.STMT_ASSIGN_ARR(source=source) then source; | ||
| 925 | case DAE.STMT_IF(source=source) then source; | ||
| 926 | case DAE.STMT_FOR(source=source) then source; | ||
| 927 | case DAE.STMT_PARFOR(source=source) then source; | ||
| 928 | case DAE.STMT_WHILE(source=source) then source; | ||
| 929 | case DAE.STMT_WHEN(source=source) then source; | ||
| 930 | case DAE.STMT_ASSERT(source=source) then source; | ||
| 931 | case DAE.STMT_TERMINATE(source=source) then source; | ||
| 932 | case DAE.STMT_REINIT(source=source) then source; | ||
| 933 | case DAE.STMT_NORETCALL(source=source) then source; | ||
| 934 | case DAE.STMT_RETURN(source=source) then source; | ||
| 935 | case DAE.STMT_BREAK(source=source) then source; | ||
| 936 | case DAE.STMT_CONTINUE(source=source) then source; | ||
| 937 | case DAE.STMT_FAILURE(source=source) then source; | ||
| 938 | else | ||
| 939 | algorithm | ||
| 940 | ✗ | Error.addMessage(Error.INTERNAL_ERROR, {"Algorithm.getStatementSource"}); | |
| 941 | ✗ | then fail(); | |
| 942 | end match; | ||
| 943 | end getStatementSource; | ||
| 944 | |||
| 945 | public function isNotDummyStatement | ||
| 946 | input DAE.Statement stmt; | ||
| 947 | output Boolean b; | ||
| 948 | algorithm | ||
| 949 | b := match stmt | ||
| 950 | local | ||
| 951 | DAE.Exp exp; | ||
| 952 | case DAE.STMT_NORETCALL(exp=exp) | ||
| 953 | algorithm | ||
| 954 | 942 | (_,b) := Expression.traverseExpBottomUp(exp,Expression.hasNoSideEffects,true); | |
| 955 | 942 | then not b; // has side effects => this is an expression that could do something | |
| 956 | else true; | ||
| 957 | end match; | ||
| 958 | end isNotDummyStatement; | ||
| 959 | |||
| 960 | annotation(__OpenModelica_Interface="frontend_base"); | ||
| 961 | end Algorithm; | ||
| 962 |