Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 42.0% 81 / 0 / 193
Functions: -% 0 / 1 / 1
Branches: 37.5% 18 / 0 / 48

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