Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 66.2% 816 / 0 / 1233
Functions: -% 0 / 1 / 1
Branches: 47.0% 301 / 0 / 640

OMCompiler/Compiler/FrontEnd/InstSection.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 InstSection
37 " file: InstSection.mo
38 package: InstSection
39 description: Model instantiation
40
41
42 This module is responsible for instantiation of Modelica equation
43 and algorithm sections (including connect equations)."
44
45 public import Absyn;
46 public import AbsynUtil;
47 public import ClassInf;
48 public import DAE.Connect;
49 public import ConnectionGraph;
50 public import DAE;
51 public import FCore;
52 public import FGraph;
53 public import InnerOuter;
54 public import SCode;
55
56 protected import Algorithm;
57 protected import Ceval;
58 protected import ComponentReference;
59 protected import ComponentReferenceBasics;
60 protected import Config;
61 protected import ConnectUtil;
62 protected import DAEUtil;
63 protected import Debug;
64 protected import Dump;
65 protected import ElementSource;
66 protected import Error;
67 protected import Expression;
68 protected import ExpressionSimplify;
69 protected import ExpressionSimplifyTypes;
70 protected import Flags;
71 protected import Inst;
72 protected import InstDAE;
73 protected import InstFunction;
74 protected import InstUtil;
75 protected import List;
76 protected import Lookup;
77 protected import Patternm;
78 protected import PrefixUtil;
79 import SCodeUtil;
80 protected import Static;
81 protected import Types;
82 protected import Util;
83 protected import Values;
84 protected import ValuesUtil;
85 protected import ValuesDump;
86 protected import System;
87 protected import ErrorExt;
88 protected import SCodeDump;
89 protected import DAEDump;
90 protected import ExpressionBasics;
91 protected import ClassInfUtil;
92
93 protected type Ident = DAE.Ident "an identifier";
94 protected type InstanceHierarchy = InnerOuter.InstHierarchy "an instance hierarchy";
95 protected constant Boolean alwaysUnroll = true;
96
97 public function instEquation
98 "author: LS, ELN
99
100 Instantiates an equation by calling
101 instEquationCommon with Inital set
102 to NON_INITIAL."
103 input FCore.Cache inCache;
104 input FCore.Graph inEnv;
105 input InnerOuter.InstHierarchy inIH;
106 input DAE.Prefix inPrefix;
107 input Connect.Sets inSets;
108 input ClassInf.State inState;
109 input SCode.Equation inEquation;
110 input Boolean inImpl;
111 input Boolean unrollForLoops "Unused, to comply with Inst.instList interface.";
112 input ConnectionGraph.ConnectionGraph inGraph;
113 output FCore.Cache outCache;
114 output FCore.Graph outEnv;
115 output InnerOuter.InstHierarchy outIH;
116 output DAE.DAElist outDae;
117 output Connect.Sets outSets;
118 output ClassInf.State outState;
119 output ConnectionGraph.ConnectionGraph outGraph;
120 algorithm
121 26265 (outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
122 instEquationCommon(inCache, inEnv, inIH, inPrefix, inSets, inState, inEquation,
123 SCode.NON_INITIAL(), inImpl, inGraph);
124 end instEquation;
125
126 public function instInitialEquation
127 "author: LS, ELN
128 Instantiates initial equation by calling inst_equation_common with Inital
129 set to INITIAL."
130 input FCore.Cache inCache;
131 input FCore.Graph inEnv;
132 input InnerOuter.InstHierarchy inIH;
133 input DAE.Prefix inPrefix;
134 input Connect.Sets inSets;
135 input ClassInf.State inState;
136 input SCode.Equation inEquation;
137 input Boolean inImpl;
138 input Boolean unrollForLoops "Unused, to comply with Inst.instList interface.";
139 input ConnectionGraph.ConnectionGraph inGraph;
140 output FCore.Cache outCache;
141 output FCore.Graph outEnv;
142 output InnerOuter.InstHierarchy outIH;
143 output DAE.DAElist outDae;
144 output Connect.Sets outSets;
145 output ClassInf.State outState;
146 output ConnectionGraph.ConnectionGraph outGraph;
147 algorithm
148 713 (outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
149 instEquationCommon(inCache, inEnv, inIH, inPrefix, inSets, inState, inEquation,
150 SCode.INITIAL(), inImpl, inGraph);
151 end instInitialEquation;
152
153 protected function instEquationCommon
154 "The DAE output of the translation contains equations which
155 in most cases directly corresponds to equations in the source.
156 Some of them are also generated from `connect\' clauses.
157
158 This function takes an equation from the source and generates DAE
159 equations and connection sets."
160 input FCore.Cache inCache;
161 input FCore.Graph inEnv;
162 input InnerOuter.InstHierarchy inIH;
163 input DAE.Prefix inPrefix;
164 input Connect.Sets inSets;
165 input ClassInf.State inState;
166 input SCode.Equation inEquation;
167 input SCode.Initial inInitial;
168 input Boolean inImpl;
169 input ConnectionGraph.ConnectionGraph inGraph;
170 output FCore.Cache outCache;
171 output FCore.Graph outEnv;
172 output InnerOuter.InstHierarchy outIH;
173 output DAE.DAElist outDae;
174 output Connect.Sets outSets;
175 output ClassInf.State outState;
176 output ConnectionGraph.ConnectionGraph outGraph;
177 protected
178 Integer errorCount = Error.getNumErrorMessages();
179 String s;
180 ClassInf.State state;
181 algorithm
182 try
183 26978 state := ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION());
184 26977 (outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
185 instEquationCommonWork(inCache, inEnv, inIH, inPrefix, inSets, state,
186 inEquation, inInitial, inImpl, inGraph, DAE.FLATTEN(inEquation,NONE()));
187 26955 outDae := DAEUtil.traverseDAE(outDae, AvlTreePathFunction.Tree.EMPTY(),
188 Expression.traverseSubexpressionsHelper,
189 (ExpressionSimplify.simplifyWork, ExpressionSimplifyTypes.optionSimplifyOnly));
190 else
191 // The instantiation failed; produce an appropriate error message and fail.
192 try
193 // If the class state cannot accept an equation, that is the cause.
194
2/2
✓ Branch 0 taken 23 times.
✓ Branch 1 taken 1 time.
24 failure(ClassInfUtil.trans(inState,ClassInf.FOUND_EQUATION()));
195 1 s := ClassInfUtil.printStateStr(inState);
196 1 Error.addSourceMessage(Error.EQUATION_TRANSITION_FAILURE, {s}, SCodeUtil.getEquationInfo(inEquation));
197 else
198 // We only want to print a generic error message if no other error message was printed.
199 // Providing two error messages for the same error is confusing (but better than none).
200
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 22 times.
22 if errorCount == Error.getNumErrorMessages() then
201 ✗ s := "\n" + SCodeDump.equationStr(inEquation);
202 ✗ Error.addSourceMessage(Error.EQUATION_GENERIC_FAILURE, {s}, SCodeUtil.getEquationInfo(inEquation));
203 end if;
204 end try;
205 23 fail();
206 end try;
207 end instEquationCommon;
208
209 protected function instEquationCommonWork
210 "The DAE output of the translation contains equations which in most cases
211 directly corresponds to equations in the source. Some of them are also
212 generated from connect clauses.
213
214 This function takes an equation from the source and generates DAE equations
215 and connection sets."
216 input FCore.Cache inCache;
217 input FCore.Graph inEnv;
218 input InnerOuter.InstHierarchy inIH;
219 input DAE.Prefix inPrefix;
220 input Connect.Sets inSets;
221 input ClassInf.State inState;
222 input SCode.Equation inEquation;
223 input SCode.Initial inInitial;
224 input Boolean inImpl;
225 input ConnectionGraph.ConnectionGraph inGraph;
226 input DAE.SymbolicOperation inFlattenOp;
227 output FCore.Cache outCache = inCache;
228 output FCore.Graph outEnv = inEnv;
229 output InnerOuter.InstHierarchy outIH = inIH;
230 output DAE.DAElist outDae;
231 output Connect.Sets outSets = inSets;
232 output ClassInf.State outState;
233 output ConnectionGraph.ConnectionGraph outGraph = inGraph;
234 algorithm
235 (outDae, outState) := matchcontinue inEquation
236 local
237 Absyn.ComponentRef lhs_acr, rhs_acr, acr;
238 SourceInfo info;
239 Absyn.Exp lhs_aexp, rhs_aexp, range_aexp;
240 SCode.Comment comment;
241 DAE.Exp lhs_exp, rhs_exp, exp, cond_exp, msg_exp, level_exp, cr_exp;
242 DAE.Properties lhs_prop, rhs_prop, prop, cr_prop;
243 DAE.ElementSource source;
244 list<DAE.Exp> expl;
245 list<DAE.Properties> props;
246 DAE.Const c;
247 Values.Value val;
248 list<SCode.Equation> eql, else_branch;
249 list<list<SCode.Equation>> branches, rest_branches;
250 list<list<DAE.Element>> ell;
251 list<DAE.Element> el, el2;
252 Option<DAE.Element> else_when;
253 list<tuple<Absyn.ComponentRef, Integer>> iter_crefs;
254 DAE.Type ty;
255 FCore.Graph env;
256 Values.Value val;
257 DAE.ComponentRef cr;
258
259 // Connect equations.
260 case SCode.EQ_CONNECT(crefLeft = lhs_acr, crefRight = rhs_acr, info = info)
261 algorithm
262
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4312 times.
4312 if SCodeUtil.isInitial(inInitial) then
263 ✗ Error.addSourceMessage(Error.CONNECT_IN_INITIAL_EQUATION, {}, info);
264 ✗ fail();
265 end if;
266
267 4312 (outCache, outEnv, outIH, outSets, outDae, outGraph) :=
268 instConnect(outCache, outEnv, outIH, outSets, inPrefix, lhs_acr,
269 rhs_acr, inImpl, inGraph, info);
270 4310 outState := instEquationCommonCiTrans(inState, inInitial);
271 4310 then
272 (outDae, outState);
273
274 // Equality equations.
275 case SCode.EQ_EQUALS(expLeft = lhs_aexp, expRight = rhs_aexp, info = info,
276 comment = comment)
277 algorithm
278 // Check that the equation is valid if the lhs is a tuple.
279 18847 checkTupleCallEquationMessage(lhs_aexp, rhs_aexp, info);
280
281 18844 (outCache, lhs_exp, lhs_prop) := Static.elabExpLHS(inCache, inEnv, lhs_aexp, inImpl, true, inPrefix, info);
282 18842 (outCache, rhs_exp, rhs_prop) :=
283 Static.elabExp(inCache, inEnv, rhs_aexp, inImpl, true, inPrefix, info);
284
285 18836 (outCache, lhs_exp, lhs_prop) :=
286 Ceval.cevalIfConstant(outCache, inEnv, lhs_exp, lhs_prop, inImpl, info);
287 18836 (outCache, rhs_exp, rhs_prop) :=
288 Ceval.cevalIfConstant(outCache, inEnv, rhs_exp, rhs_prop, inImpl, info);
289
290 18836 (outCache, lhs_exp, rhs_exp, lhs_prop) :=
291 condenseArrayEquation(outCache, inEnv, lhs_aexp, rhs_aexp, lhs_exp,
292 rhs_exp, lhs_prop, rhs_prop, inImpl, inPrefix, info);
293
294 18836 (outCache, lhs_exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, lhs_exp, inPrefix);
295 18836 (outCache, rhs_exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, rhs_exp, inPrefix);
296
297 // Set the source of this element.
298 18836 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
299 18836 source := ElementSource.addCommentToSource(source, SOME(comment));
300
301 // Check that the lhs and rhs get along.
302 18836 outDae := instEqEquation(lhs_exp, lhs_prop, rhs_exp, rhs_prop, source, inInitial, inImpl);
303 18833 outState := instEquationCommonCiTrans(inState, inInitial);
304 18833 then
305 (outDae, outState);
306
307 case SCode.EQ_IF(thenBranch = branches, elseBranch = else_branch, info = info)
308 algorithm
309 // Elaborate all of the conditions.
310 1672 (outCache, expl, props) := Static.elabExpList(outCache, outEnv,
311 inEquation.condition, inImpl, true, inPrefix, info);
312
313 // Check that all conditions are Boolean.
314 1672 prop := Types.propsAnd(props);
315 1672 checkIfConditionTypes(prop, inEquation.condition, props, info);
316
317 // Try to select one of the branches.
318 try
319 1672 rest_branches := branches;
320 1672 eql := else_branch;
321
322 // Go through each condition and select the first branch whose
323 // condition is a parameter expression evaluating to true. If a
324 // non-parameter expression is encountered this will fail and fall
325 // back to instantiating the whole if equation below. If all
326 // conditions evaluate to false the else branch will be selected.
327
2/2
✓ Branch 0 taken 1810 times.
✓ Branch 1 taken 700 times.
2510 for cond in expl loop
328
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1810 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1810 times.
1810 DAE.PROP(constFlag = c) :: props := props;
329
2/2
✓ Branch 1 taken 311 times.
✓ Branch 2 taken 1499 times.
1810 true := Types.isParameterOrConstant(c);
330
331 1499 (outCache, val) := Ceval.ceval(outCache, outEnv, cond, inImpl, Absyn.NO_MSG(), 0);
332
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1406 times.
1406 true := checkIfConditionBinding(val, info);
333
334
2/2
✓ Branch 1 taken 568 times.
✓ Branch 2 taken 838 times.
1406 if ValuesUtil.valueBool(val) then
335 568 eql := listHead(rest_branches);
336 break;
337 end if;
338
339 838 rest_branches := listRest(rest_branches);
340 end for;
341
342 // Add evaluated parameter condition to the structural parameter list to mark it final later
343 1268 outCache := InstUtil.popStructuralParameters(outCache,inPrefix);
344
345 // A branch was selected, instantiate it.
346
2/2
✓ Branch 1 taken 963 times.
✓ Branch 2 taken 305 times.
2231 (outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
347 Inst.instList(outCache, inEnv, inIH, inPrefix, inSets, inState,
348 if SCodeUtil.isInitial(inInitial) then instInitialEquation else instEquation,
349 eql, inImpl, alwaysUnroll, inGraph);
350 else
351 404 (outCache, expl) := PrefixUtil.prefixExpList(outCache, inEnv, inIH, expl, inPrefix);
352
353 // Set the source of this element.
354 404 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
355
356 // Instantiate all branches.
357
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 397 times.
404 if SCodeUtil.isInitial(inInitial) then
358 7 (outCache, outEnv, outIH, outState, ell) :=
359 instInitialIfEqBranches(outCache, inEnv, inIH, inPrefix, inState, branches, inImpl);
360 7 (outCache, outEnv, outIH, outState, el) :=
361 instInitialIfEqBranch(outCache, outEnv, outIH, inPrefix, outState, else_branch, inImpl);
362
363 14 outDae := DAE.DAE({DAE.INITIAL_IF_EQUATION(expl, ell, el, source)});
364 else
365 397 (outCache, outEnv, outIH, outState, ell) :=
366 instIfEqBranches(outCache, inEnv, inIH, inPrefix, inState, branches, inImpl);
367 397 (outCache, outEnv, outIH, outState, el) :=
368 instIfEqBranch(outCache, outEnv, outIH, inPrefix, outState, else_branch, inImpl);
369
370 794 outDae := DAE.DAE({DAE.IF_EQUATION(expl, ell, el, source)});
371 end if;
372 end try;
373 1672 then
374 (outDae, outState);
375
376 case SCode.EQ_WHEN(info = info)
377 algorithm
378
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 if SCodeUtil.isInitial(inInitial) then
379 ✗ Error.addSourceMessageAndFail(Error.INITIAL_WHEN, {}, info);
380 end if;
381
382 141 (outCache, outEnv, outIH, cond_exp, el, outGraph) :=
383 instWhenEqBranch(inCache, inEnv, inIH, inPrefix, inSets, inState,
384 (inEquation.condition, inEquation.eEquationLst), inImpl,
385 alwaysUnroll, inGraph, info);
386
387 // Set the source of this element.
388 138 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
389
390 else_when := NONE();
391
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 138 times.
277 for branch in listReverse(inEquation.elseBranches) loop
392 1 (outCache, outEnv, outIH, exp, el2, outGraph) :=
393 instWhenEqBranch(outCache, outEnv, outIH, inPrefix, inSets, inState,
394 branch, inImpl, alwaysUnroll, outGraph, info);
395 1 else_when := SOME(DAE.WHEN_EQUATION(exp, el2, else_when, source));
396 end for;
397
398 138 outState := instEquationCommonCiTrans(inState, inInitial);
399 276 outDae := DAE.DAE({DAE.WHEN_EQUATION(cond_exp, el, else_when, source)});
400 138 then
401 (outDae, outState);
402
403 case SCode.EQ_FOR(info = info)
404 algorithm
405 // Check if we have an explicit range, and use it if that's the case.
406 // Otherwise, try to deduce the implicit range based on how the iterator is used.
407
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 282 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 282 times.
282 if isSome(inEquation.range) then
408 1 SOME(range_aexp) := inEquation.range;
409
410 // Elaborate the range.
411
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 282 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 282 times.
282 (outCache, exp, DAE.PROP(type_ = DAE.T_ARRAY(ty = ty), constFlag = c)) :=
412 Static.elabExp(outCache, inEnv, range_aexp, inImpl, true, inPrefix, info);
413 else
414 ✗ iter_crefs := SCodeUtil.findIteratorIndexedCrefsInEquations(
415 inEquation.eEquationLst, inEquation.index);
416 ✗ (exp, DAE.PROP(type_ = DAE.T_ARRAY(ty = ty), constFlag = c), outCache) :=
417 Static.deduceIterationRange(inEquation.index, iter_crefs, inEnv, outCache, info);
418
419 // Ceval below should not fail on our generated range, but just in case...
420 range_aexp := Absyn.STRING("Internal error: generated implicit range could not be evaluated.");
421 end if;
422
423 // Add the iterator to the environment.
424 282 env := addForLoopScope(inEnv, inEquation.index, ty, SCode.VAR(), SOME(c));
425
426 // Try to constant evaluate the range.
427 try
428 282 (outCache, val) := Ceval.ceval(outCache, inEnv, exp, inImpl, Absyn.NO_MSG(), 0);
429 else
430 // Evaluation failed, which is normally an error since the range
431 // should be a parameter expression. If we're doing checkModel we
432 // allow it though, and use {1} as range to check that the loop can be
433 // instantiated.
434
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Flags.getConfigBool(Flags.CHECK_MODEL) then
435 ✗ val := Values.ARRAY({Values.INTEGER(1)}, {1});
436 else
437 2 Error.addSourceMessageAndFail(Error.NON_PARAMETER_ITERATOR_RANGE,
438 {Dump.printExpStr(range_aexp)}, info);
439 end if;
440 end try;
441
442 281 (outCache, outDae, outSets, outGraph) := unroll(outCache, env, inIH,
443 inPrefix, inSets, inState, inEquation.index, ty, val,
444 inEquation.eEquationLst, inInitial, inImpl, inGraph);
445 281 outState := instEquationCommonCiTrans(inState, inInitial);
446 281 then
447 (outDae, outState);
448
449 case SCode.EQ_ASSERT(info = info)
450 algorithm
451 1182 (outCache, cond_exp) := instOperatorArg(outCache, inEnv, inIH, inPrefix,
452 inEquation.condition, inImpl, DAE.T_BOOL_DEFAULT, "assert", "condition", 1, info);
453 1182 (outCache, msg_exp) := instOperatorArg(outCache, inEnv, inIH, inPrefix,
454 inEquation.message, inImpl, DAE.T_STRING_DEFAULT, "assert", "message", 2, info);
455 1182 (outCache, level_exp) := instOperatorArg(outCache, inEnv, inIH, inPrefix,
456 inEquation.level, inImpl, DAE.T_ASSERTIONLEVEL, "assert", "level", 3, info);
457
458 1182 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
459
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1170 times.
1182 if SCodeUtil.isInitial(inInitial) then
460 24 outDae := DAE.DAE({DAE.INITIAL_ASSERT(cond_exp, msg_exp, level_exp, source)});
461 else
462 2340 outDae := DAE.DAE({DAE.ASSERT(cond_exp, msg_exp, level_exp, source)});
463 end if;
464 1182 then
465 (outDae, inState);
466
467 case SCode.EQ_TERMINATE(info = info)
468 algorithm
469 6 (outCache, msg_exp) := instOperatorArg(outCache, inEnv, inIH, inPrefix,
470 inEquation.message, inImpl, DAE.T_STRING_DEFAULT, "terminate", "message", 1, info);
471
472 6 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
473
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 5 times.
6 if SCodeUtil.isInitial(inInitial) then
474 2 outDae := DAE.DAE({DAE.INITIAL_TERMINATE(msg_exp, source)});
475 else
476 10 outDae := DAE.DAE({DAE.TERMINATE(msg_exp, source)});
477 end if;
478 6 then
479 (outDae, inState);
480
481 case SCode.EQ_REINIT(cref = Absyn.CREF(componentRef = acr), info = info)
482 algorithm
483 // Elaborate the cref.
484
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 15 times.
16 (outCache, cr_exp as DAE.CREF(cr, ty), cr_prop, _) :=
485 Static.elabCrefNoEval(outCache, inEnv, acr, inImpl, false, inPrefix, info);
486
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 14 times.
15 true := checkReinitType(ty, cr_prop, cr, info);
487
488 // Elaborate the reinit expression.
489 14 (outCache, exp, prop) :=
490 Static.elabExp(outCache, inEnv, inEquation.expReinit, inImpl, true, inPrefix, info);
491 14 (outCache, exp, prop) :=
492 Ceval.cevalIfConstant(outCache, inEnv, exp, prop, inImpl, info);
493
494 // Check that the cref and the expression have matching types.
495 14 exp := Types.matchProp(exp, prop, cr_prop, true);
496
497 14 (outCache, cr_exp, exp, cr_prop) := condenseArrayEquation(outCache,
498 inEnv, inEquation.cref, inEquation.expReinit, cr_exp,
499 exp, cr_prop, prop, inImpl, inPrefix, info);
500 14 (outCache, cr_exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, cr_exp, inPrefix);
501 14 (outCache, exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, exp, inPrefix);
502
503 14 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
504
505 14 DAE.DAE(el) := instEqEquation(cr_exp, cr_prop, exp, prop, source, inInitial, inImpl);
506
4/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 14 times.
30 el := list(makeDAEArrayEqToReinitForm(e) for e in el);
507 14 outDae := DAE.DAE(el);
508 then
509 (outDae, inState);
510
511 case SCode.EQ_NORETCALL(info = info)
512 algorithm
513
2/2
✓ Branch 1 taken 478 times.
✓ Branch 2 taken 42 times.
520 if isConnectionsOperator(inEquation.exp) then
514 // Handle Connections.* operators.
515 478 (outCache, outEnv, outIH, outDae, outSets, outState, outGraph) :=
516 handleConnectionsOperators(inCache, inEnv, inIH, inPrefix, inSets,
517 inState, inEquation, inInitial, inImpl, inGraph, inFlattenOp);
518 else
519 // Handle normal no return calls.
520 42 (outCache, exp) := Static.elabExp(inCache, inEnv, inEquation.exp,
521 inImpl, false, inPrefix, info);
522 // This is probably an external function call that the user wants to
523 // evaluate at runtime, so don't ceval it.
524 41 (outCache, exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, exp, inPrefix);
525
526 41 source := makeEqSource(info, inEnv, inPrefix, inFlattenOp);
527 41 outDae := instEquationNoRetCallVectorization(exp, inInitial, source);
528 41 outState := inState;
529 end if;
530 519 then
531 (outDae, outState);
532
533 else
534 algorithm
535
1/2
✓ Branch 1 taken 22 times.
✗ Branch 2 not taken.
22 true := Flags.isSet(Flags.FAILTRACE);
536 ✗ Debug.trace("- InstSection.instEquationCommonWork failed for eqn: ");
537 ✗ Debug.traceln(SCodeDump.equationStr(inEquation) + " in scope: " +
538 FGraph.getGraphNameStr(inEnv));
539 ✗ then
540 fail();
541
542 end matchcontinue;
543 end instEquationCommonWork;
544
545 protected function makeEqSource
546 input Absyn.Info inInfo;
547 input FCore.Graph inEnv;
548 input DAE.Prefix inPrefix;
549 input DAE.SymbolicOperation inFlattenOp;
550 output DAE.ElementSource outSource;
551 algorithm
552 20621 outSource := ElementSource.createElementSource(inInfo, FGraph.getScopePath(inEnv), inPrefix);
553 20621 outSource := ElementSource.addSymbolicTransformation(outSource, inFlattenOp);
554 end makeEqSource;
555
556 protected function checkIfConditionTypes
557 "Checks that all conditions in an if-equation are Boolean."
558 input DAE.Properties inAccumProp;
559 input list<Absyn.Exp> inConditions;
560 input list<DAE.Properties> inProperties;
561 input SourceInfo inInfo;
562 algorithm
563 () := match inAccumProp
564 local
565 list<DAE.Properties> props;
566 DAE.Type ty;
567 String exp_str, ty_str;
568
569 // Boolean type, ok.
570 case DAE.PROP(type_ = DAE.T_BOOL()) then ();
571
572 // Any other type, find the offending condition and print an error.
573 else
574 algorithm
575 props := inProperties;
576
577 ✗ for cond in inConditions loop
578 ✗ DAE.PROP(type_ = ty) :: props := props;
579
580 ✗ if not Types.isScalarBoolean(ty) then
581 ✗ exp_str := Dump.printExpStr(cond);
582 ✗ ty_str := TypesDump.unparseTypeNoAttr(ty);
583 ✗ Error.addSourceMessageAndFail(Error.IF_CONDITION_TYPE_ERROR,
584 {exp_str, ty_str}, inInfo);
585 end if;
586 end for;
587
588 ✗ Error.addInternalError("InstSection.checkIfConditionTypes failed to find non-Boolean condition.", inInfo);
589 ✗ then
590 fail();
591
592 end match;
593 end checkIfConditionTypes;
594
595 protected function checkIfConditionBinding
596 "Checks that the condition of an if-branch has a binding."
597 input Values.Value inValues;
598 input SourceInfo inInfo;
599 output Boolean outHasBindings;
600 protected
601 Option<Values.Value> empty_val;
602 String name;
603 algorithm
604 1406 empty_val := ValuesUtil.containsEmpty(inValues);
605
606
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1406 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1406 times.
1406 if isSome(empty_val) then
607 ✗ SOME(Values.EMPTY(name = name)) := empty_val;
608 ✗ Error.addSourceMessage(Error.CONDITIONAL_EXP_WITHOUT_VALUE, {name}, inInfo);
609 outHasBindings := false;
610 else
611 outHasBindings := true;
612 end if;
613 end checkIfConditionBinding;
614
615 protected function instOperatorArg
616 "Helper function to instEquationCommonWork. Elaborates and type checks an
617 argument for some builtin operators, like assert and terminate."
618 input FCore.Cache inCache;
619 input FCore.Graph inEnv;
620 input InnerOuter.InstHierarchy inIH;
621 input DAE.Prefix inPrefix;
622 input Absyn.Exp inArg;
623 input Boolean inImpl;
624 input DAE.Type inExpectedType;
625 input String inOperatorName;
626 input String inArgName;
627 input Integer inArgIndex;
628 input SourceInfo inInfo;
629 output FCore.Cache outCache;
630 output DAE.Exp outArg;
631 protected
632 DAE.Properties props;
633 DAE.Type ty;
634 algorithm
635 3552 (outCache, outArg, props) :=
636 Static.elabExp(inCache, inEnv, inArg, inImpl, true, inPrefix, inInfo);
637 3552 ty := Types.getPropType(props);
638
639
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3552 times.
3552 if not Types.subtype(ty, inExpectedType) then
640 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
641 {intString(inArgIndex), inOperatorName, inArgName,
642 Dump.printExpStr(inArg), TypesDump.unparseTypeNoAttr(ty),
643 TypesDump.unparseType(inExpectedType)}, inInfo);
644 end if;
645
646 3552 (outCache, outArg) :=
647 Ceval.cevalIfConstant(outCache, inEnv, outArg, props, inImpl, inInfo);
648 3552 (outCache, outArg) :=
649 PrefixUtil.prefixExp(outCache, inEnv, inIH, outArg, inPrefix);
650 end instOperatorArg;
651
652 protected function isConnectionsOperator
653 input Absyn.Exp inExp;
654 output Boolean yes;
655 algorithm
656 yes := match inExp
657 local
658 Absyn.Ident id;
659
660 case Absyn.CALL(function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT(id, {})))
661 478 then listMember(id, {"root", "potentialRoot", "branch", "uniqueRoot"});
662
663 else false;
664 end match;
665 end isConnectionsOperator;
666
667 protected function handleConnectionsOperators
668 "This function handles Connections.* no return operators"
669 input FCore.Cache inCache;
670 input FCore.Graph inEnv;
671 input InnerOuter.InstHierarchy inIH;
672 input DAE.Prefix inPrefix;
673 input Connect.Sets inSets;
674 input ClassInf.State inState;
675 input SCode.Equation inEquation;
676 input SCode.Initial inInitial;
677 input Boolean inImpl;
678 input ConnectionGraph.ConnectionGraph inGraph;
679 input DAE.SymbolicOperation flattenOp;
680 output FCore.Cache outCache;
681 output FCore.Graph outEnv;
682 output InnerOuter.InstHierarchy outIH;
683 output DAE.DAElist outDae;
684 output Connect.Sets outSets;
685 output ClassInf.State outState;
686 output ConnectionGraph.ConnectionGraph outGraph;
687 algorithm
688 (outCache,outEnv,outIH,outDae,outSets,outState,outGraph):=
689 matchcontinue (inCache, inEnv, inIH, inPrefix, inSets, inState, inEquation, inGraph)
690 local
691 Connect.Sets csets;
692 ClassInf.State ci_state;
693 FCore.Graph env;
694 DAE.Prefix pre;
695 Absyn.ComponentRef cr,cr1,cr2;
696 Boolean b1, b2;
697 String s;
698 Absyn.Exp msg;
699 DAE.Exp e_1,e_2,msg_1;
700 SCode.Equation eqn;
701 FCore.Cache cache;
702 ConnectionGraph.ConnectionGraph graph;
703 InstanceHierarchy ih;
704 SourceInfo info;
705 Integer ipriority;
706 DAE.ComponentRef cr_,cr1_,cr2_;
707 DAE.Exp exp;
708 Absyn.FunctionArgs functionArgs;
709
710 // Connections.root(cr) - zero sized cref
711 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
712 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("root", {})),
713 functionArgs = Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {}))), graph)
714 algorithm
715
3/8
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
20 (cache,SOME((DAE.ARRAY(array = {}),_,_))) := Static.elabCref(cache,env, cr, false /* ??? */,false,pre,info);
716 ✗ s := SCodeDump.equationStr(inEquation);
717 ✗ Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO, {s}, info);
718 then
719 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
720
721 // Connections.root(cr)
722 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
723 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("root", {})),
724 functionArgs = Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {}))), graph)
725 algorithm
726
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 20 times.
20 (cache,SOME((DAE.CREF(cr_,_),_,_))) := Static.elabCref(cache,env, cr, false /* ??? */,false,pre,info);
727 20 (cache,cr_) := PrefixUtil.prefixCref(cache,env,ih,pre, cr_);
728 20 graph := ConnectionGraph.addDefiniteRoot(graph, cr_);
729 then
730 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
731
732 // Connections.potentialRoot(cr, priority = p) - zero sized cref
733 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
734 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("potentialRoot", {})),
735 functionArgs = functionArgs)), graph)
736 algorithm
737 150 (cr,_) := potentialRootArguments(functionArgs, info, pre, inEquation);
738
3/8
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✓ Branch 5 taken 150 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
150 (cache,SOME((DAE.ARRAY(array = {}),_,_))) := Static.elabCref(cache,env, cr, false /* ??? */,false,pre,info);
739 ✗ s := SCodeDump.equationStr(inEquation);
740 ✗ Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO, {s}, info);
741 then
742 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
743
744 // Connections.potentialRoot(cr, priority = p)
745 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
746 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("potentialRoot", {})),
747 functionArgs = functionArgs)), graph)
748 algorithm
749 150 (cr, ipriority) := potentialRootArguments(functionArgs, info, pre, inEquation);
750
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 150 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 150 times.
150 (cache,SOME((DAE.CREF(cr_,_),_,_))) := Static.elabCref(cache, env, cr, false /* ??? */,false, pre, info);
751 150 (cache,cr_) := PrefixUtil.prefixCref(cache,env,ih,pre, cr_);
752 150 graph := ConnectionGraph.addPotentialRoot(graph, cr_, intReal(ipriority));
753 then
754 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
755
756 // Connections.uniqueRoot(cr, message) - zero sized cref
757 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
758 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("uniqueRoot", {})),
759 functionArgs = functionArgs)), graph)
760 algorithm
761 ✗ (cr,_) := uniqueRootArguments(functionArgs, info, pre, inEquation);
762 ✗ (cache,SOME((DAE.ARRAY(array = {}),_,_))) := Static.elabCref(cache,env, cr, false /* ??? */,false,pre,info);
763 ✗ s := SCodeDump.equationStr(inEquation);
764 ✗ Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO, {s}, info);
765 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRoot"}, info);
766 then
767 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
768
769 // Connections.uniqueRoot(cr, message)
770 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
771 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("uniqueRoot", {})),
772 functionArgs = functionArgs)), graph)
773 algorithm
774 ✗ (cr, msg) := uniqueRootArguments(functionArgs, info, pre, inEquation);
775 ✗ (cache,exp,_) := Static.elabExp(cache, env, Absyn.CREF(cr), false, true, pre, info);
776 ✗ (cache,msg_1,_) := Static.elabExp(cache, env, msg, false, false, pre, info);
777 ✗ (cache,exp) := PrefixUtil.prefixExp(cache,env,ih,exp,pre);
778 ✗ (cache,msg_1) := PrefixUtil.prefixExp(cache,env,ih,msg_1,pre);
779 ✗ graph := ConnectionGraph.addUniqueRoots(graph, exp, msg_1);
780 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRoot"}, info);
781 then
782 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
783
784 // Connections.branch(cr1,cr2)
785 case (cache, env, ih, pre, csets, ci_state, SCode.EQ_NORETCALL(info=info,exp=Absyn.CALL(
786 function_ = Absyn.CREF_QUAL("Connections", {}, Absyn.CREF_IDENT("branch", {})),
787 functionArgs = Absyn.FUNCTIONARGS({Absyn.CREF(cr1), Absyn.CREF(cr2)}, {}))), graph)
788 algorithm
789
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 308 times.
308 (cache,SOME((e_1,_,_))) := Static.elabCref(cache,env, cr1, false /* ??? */,false,pre,info);
790
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 308 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 308 times.
308 (cache,SOME((e_2,_,_))) := Static.elabCref(cache,env, cr2, false /* ??? */,false,pre,info);
791 // handle zero sized crefs
792 308 b1 := Types.isZeroLengthArray(Expression.typeof(e_1));
793 308 b2 := Types.isZeroLengthArray(Expression.typeof(e_2));
794
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 if boolOr(b1, b2)
795 then // handle zero sized crefs
796 ✗ s := SCodeDump.equationStr(inEquation);
797 ✗ Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO, {s}, info);
798 else // not zero sized
799
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 DAE.CREF(cr1_,_) := e_1;
800
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 308 times.
308 DAE.CREF(cr2_,_) := e_2;
801 308 (cache,cr1_) := PrefixUtil.prefixCref(cache,env,ih,pre, cr1_);
802 308 (cache,cr2_) := PrefixUtil.prefixCref(cache,env,ih,pre, cr2_);
803 308 graph := ConnectionGraph.addBranch(graph, cr1_, cr2_);
804 end if;
805 then
806 (cache,env,ih,DAE.emptyDae,csets,ci_state,graph);
807
808 // failure
809 case (_, env, _, _, _, _, eqn, _)
810 algorithm
811 ✗ true := Flags.isSet(Flags.FAILTRACE);
812 ✗ s := SCodeDump.equationStr(eqn);
813 ✗ Debug.trace("- handleConnectionsOperators failed for eqn: ");
814 ✗ Debug.traceln(s + " in scope:" + FGraph.getGraphNameStr(env));
815 ✗ then
816 fail();
817 end matchcontinue;
818 end handleConnectionsOperators;
819
820 protected function potentialRootArguments
821 input Absyn.FunctionArgs inFunctionArgs;
822 input SourceInfo info;
823 input DAE.Prefix inPrefix;
824 input SCode.Equation inEquation;
825 output Absyn.ComponentRef outCref;
826 output Integer outPriority;
827 algorithm
828 (outCref, outPriority) := match inFunctionArgs
829 local
830 Absyn.ComponentRef cr;
831 Integer p;
832 String s1, s2;
833
834 case Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {}) then (cr, 0);
835 case Absyn.FUNCTIONARGS({Absyn.CREF(cr), Absyn.INTEGER(p)}, {}) then (cr, p);
836 case Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {Absyn.NAMEDARG("priority", Absyn.INTEGER(p))}) then (cr, p);
837 else
838 algorithm
839 ✗ s1 := SCodeDump.equationStr(inEquation);
840 ✗ s2 := PrefixUtil.printPrefixStr3(inPrefix);
841 ✗ Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {s1, s2}, info);
842 ✗ then
843 fail();
844 end match;
845 end potentialRootArguments;
846
847 protected function uniqueRootArguments
848 input Absyn.FunctionArgs inFunctionArgs;
849 input SourceInfo info;
850 input DAE.Prefix inPrefix;
851 input SCode.Equation inEquation;
852 output Absyn.ComponentRef outCref;
853 output Absyn.Exp outMessage;
854 algorithm
855 (outCref, outMessage) := match inFunctionArgs
856 local
857 Absyn.ComponentRef cr;
858 Absyn.Exp msg;
859 String s1, s2;
860
861 case Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {}) then (cr, Absyn.STRING(""));
862 case Absyn.FUNCTIONARGS({Absyn.CREF(cr), msg}, {}) then (cr, msg);
863 case Absyn.FUNCTIONARGS({Absyn.CREF(cr)}, {Absyn.NAMEDARG("message", msg)}) then (cr, msg);
864 else
865 algorithm
866 ✗ s1 := SCodeDump.equationStr(inEquation);
867 ✗ s2 := PrefixUtil.printPrefixStr3(inPrefix);
868 ✗ Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {s1, s2}, info);
869 ✗ then
870 fail();
871 end match;
872 end uniqueRootArguments;
873
874 protected function checkReinitType
875 "Checks that the base type of the given type is Real, otherwise it prints an
876 error message that the first argument to reinit must be a subtype of Real."
877 input DAE.Type inType;
878 input DAE.Properties inProperties;
879 input DAE.ComponentRef inCref;
880 input SourceInfo inInfo;
881 output Boolean outSucceeded;
882 algorithm
883 outSucceeded := matchcontinue inProperties
884 local
885 DAE.Type ty;
886 String cref_str, ty_str, cnst_str;
887 DAE.Const cnst;
888
889 case _
890 algorithm
891 15 ty := Types.arrayElementType(inType);
892
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 false := Types.isReal(ty);
893 ✗ cref_str := ComponentReferenceBasics.printComponentRefStr(inCref);
894 ✗ ty_str := TypesDump.unparseType(ty);
895 ✗ Error.addSourceMessage(Error.REINIT_MUST_BE_REAL,
896 {cref_str, ty_str}, inInfo);
897 then
898 false;
899
900 case DAE.PROP(constFlag = cnst)
901 algorithm
902
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 1 time.
15 false := Types.isVar(cnst);
903 1 cnst_str := TypesDump.unparseConst(cnst);
904 1 cref_str := ComponentReferenceBasics.printComponentRefStr(inCref);
905 1 Error.addSourceMessage(Error.REINIT_MUST_BE_VAR,
906 {cref_str, cnst_str}, inInfo);
907 then
908 false;
909
910 else true;
911
912 end matchcontinue;
913 end checkReinitType;
914
915 protected function checkTupleCallEquationMessage
916 "Checks that if a tuple is used on the left side of an equation, then it
917 must consist only of component references and the right side must be a
918 function call."
919 input Absyn.Exp left;
920 input Absyn.Exp right;
921 input SourceInfo info;
922 algorithm
923 () := match (AbsynUtil.stripCommentExpressions(left), AbsynUtil.stripCommentExpressions(right))
924 local
925 list<Absyn.Exp> crefs;
926 String left_str, right_str;
927
928 case (Absyn.TUPLE({_}), _) then ();
929
930 case (Absyn.TUPLE(crefs), Absyn.CALL())
931 algorithm
932
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 40 times.
43 if not List.all(crefs, AbsynUtil.isCref) then
933 3 left_str := Dump.printExpStr(left);
934 3 right_str := Dump.printExpStr(right);
935 6 Error.addSourceMessageAndFail(Error.TUPLE_ASSIGN_CREFS_ONLY,
936 {left_str + " = " + right_str + ";"}, info);
937 end if;
938 then
939 ();
940
941 case (Absyn.TUPLE(), _)
942 algorithm
943 ✗ left_str := Dump.printExpStr(left);
944 ✗ right_str := Dump.printExpStr(right);
945 ✗ Error.addSourceMessage(Error.TUPLE_ASSIGN_FUNCALL_ONLY,
946 {left_str + " = " + right_str + ";"}, info);
947 ✗ then
948 fail();
949
950 else ();
951 end match;
952 end checkTupleCallEquationMessage;
953
954 protected function instEquationNoRetCallVectorization
955 "Creates DAE for NORETCALLs and also performs vectorization if needed."
956 input DAE.Exp exp;
957 input SCode.Initial initial_;
958 input DAE.ElementSource source "the origin of the element";
959 output DAE.DAElist dae;
960 algorithm
961 dae := match initial_
962 82 case SCode.NON_INITIAL() then DAE.DAE({DAE.NORETCALL(exp, source)});
963 ✗ case SCode.INITIAL() then DAE.DAE({DAE.INITIAL_NORETCALL(exp, source)});
964 end match;
965 end instEquationNoRetCallVectorization;
966
967 protected function makeDAEArrayEqToReinitForm
968 "Function for transforming DAE equations into DAE.REINIT form,
969 used by instEquationCommon."
970 input DAE.Element inEq;
971 output DAE.Element outEqn;
972 algorithm
973 outEqn := match inEq
974 local
975 DAE.ComponentRef cr1, cr2;
976 DAE.Exp e2, e;
977 DAE.Type t;
978 DAE.ElementSource source "the origin of the element";
979
980 case DAE.EQUATION(DAE.CREF(componentRef=cr1), e, source)
981 16 then DAE.REINIT(cr1, e, source);
982
983 case DAE.DEFINE(cr1, e, source)
984 ✗ then DAE.REINIT(cr1, e, source);
985
986 case DAE.EQUEQUATION(cr1, cr2, source)
987 algorithm
988 ✗ t := ComponentReference.crefLastType(cr2);
989 ✗ e2 := Expression.makeCrefExp(cr2, t);
990 ✗ then
991 DAE.REINIT(cr1, e2, source);
992
993 case DAE.ARRAY_EQUATION(exp = DAE.CREF(componentRef = cr1), array = e, source = source)
994 ✗ then DAE.REINIT(cr1, e, source);
995
996 else
997 algorithm
998 ✗ true := Flags.isSet(Flags.FAILTRACE);
999 ✗ Debug.traceln("Failure in: makeDAEArrayEqToReinitForm");
1000 ✗ then
1001 fail();
1002
1003 end match;
1004 end makeDAEArrayEqToReinitForm;
1005
1006 protected function condenseArrayEquation "This function transforms makes the two sides of an array equation
1007 into its condensed form. By default, most array variables are vectorized,
1008 i.e. v becomes {v[1],v[2],..,v[n]}. But for array equations containing function calls this is not wanted.
1009 This function detect this case and elaborates expressions without vectorization."
1010 input FCore.Cache inCache;
1011 input FCore.Graph inEnv;
1012 input Absyn.Exp ie1;
1013 input Absyn.Exp ie2;
1014 input DAE.Exp elabedE1;
1015 input DAE.Exp elabedE2;
1016 input DAE.Properties iprop "To determine if array equation";
1017 input DAE.Properties iprop2 "To determine if array equation";
1018 input Boolean impl;
1019 input DAE.Prefix inPrefix;
1020 input SourceInfo info;
1021 output FCore.Cache outCache;
1022 output DAE.Exp outE1;
1023 output DAE.Exp outE2;
1024 output DAE.Properties oprop "If we have an expandable tuple";
1025 algorithm
1026 (outCache,outE1,outE2,oprop) := matchcontinue(inCache, inEnv, ie1, ie2, iprop, iprop2, inPrefix)
1027 local
1028 FCore.Cache cache;
1029 FCore.Graph env;
1030 Boolean b3,b4;
1031 DAE.Exp elabedE1_2, elabedE2_2;
1032 DAE.Properties prop1,prop,prop2;
1033 DAE.Prefix pre;
1034 Absyn.Exp e1,e2;
1035
1036 case(cache, env, e1, e2, prop, prop2, pre) algorithm
1037
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 18849 times.
18850 true := Flags.getConfigBool(Flags.CONDENSE_ARRAYS);
1038 18849 b3 := Types.isPropTupleArray(prop);
1039 18849 b4 := Types.isPropTupleArray(prop2);
1040
2/2
✓ Branch 0 taken 12913 times.
✓ Branch 1 taken 5936 times.
18849 true := boolOr(b3,b4);
1041
2/2
✓ Branch 1 taken 4389 times.
✓ Branch 2 taken 1547 times.
5936 true := Expression.containFunctioncall(elabedE2);
1042 1547 (e1,prop) := expandTupleEquationWithWild(e1,prop2,prop);
1043 1547 (cache,elabedE1_2,prop1) := Static.elabExpLHS(cache,env, e1, impl,false,pre,info);
1044 1547 (cache, elabedE1_2, prop1) := Ceval.cevalIfConstant(cache, env, elabedE1_2, prop1, impl, info);
1045 1547 (cache,elabedE2_2,prop2) := Static.elabExp(cache,env, e2, impl,false,pre,info);
1046 1547 (cache, elabedE2_2, prop2) := Ceval.cevalIfConstant(cache, env, elabedE2_2, prop2, impl, info);
1047 1547 then
1048 (cache,elabedE1_2,elabedE2_2,prop);
1049 case(cache, _, _, _, prop, _, _)
1050 then (cache,elabedE1,elabedE2,prop);
1051 end matchcontinue;
1052 end condenseArrayEquation;
1053
1054 protected function expandTupleEquationWithWild
1055 "Author BZ 2008-06
1056 The function expands the inExp, Absyn.EXP, to contain as many elements as the, DAE.Properties, propCall does.
1057 The expand adds the elements at the end and they are containing Absyn.WILD() exps with type Types.ANYTYPE. "
1058 input Absyn.Exp inExp;
1059 input DAE.Properties propCall;
1060 input DAE.Properties propTuple;
1061 output Absyn.Exp outExp;
1062 output DAE.Properties oprop;
1063 algorithm
1064 (outExp,oprop) := match(inExp,propCall,propTuple)
1065 local
1066 list<Absyn.Exp> aexpl,aexpl2;
1067 list<DAE.Type> typeList;
1068 Integer fillValue "The amount of elements to add";
1069 DAE.Type propType;
1070 list<DAE.Type> lst,lst2;
1071 list<DAE.TupleConst> tupleConst,tupleConst2;
1072 DAE.Const tconst;
1073 Option<list<String>> names;
1074
1075 case (Absyn.TUPLE(aexpl),
1076 DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types=typeList,names=names)),
1077 DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types=lst),
1078 tupleConst = DAE.TUPLE_CONST(tupleConst)))
1079 algorithm
1080 29 fillValue := (listLength(typeList)-listLength(aexpl));
1081 29 lst2 := List.fill(DAE.T_ANYTYPE_DEFAULT,fillValue) "types";
1082 29 aexpl2 := List.fill(Absyn.CREF(Absyn.WILD()),fillValue) "epxressions";
1083 29 tupleConst2 := List.fill(DAE.SINGLE_CONST(DAE.C_VAR()),fillValue) "TupleConst's";
1084 29 aexpl2 := listAppend(aexpl,aexpl2);
1085 29 lst2 := listAppend(lst,lst2);
1086 29 tupleConst2 := listAppend(tupleConst,tupleConst2);
1087 29 then
1088 (Absyn.TUPLE(aexpl2),DAE.PROP_TUPLE(DAE.T_TUPLE(lst2,names),DAE.TUPLE_CONST(tupleConst2)));
1089
1090 case(_, DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(typeList,names)), DAE.PROP(propType,tconst))
1091 algorithm
1092 5 fillValue := (listLength(typeList)-1);
1093 5 aexpl2 := List.fill(Absyn.CREF(Absyn.WILD()),fillValue) "epxressions";
1094 5 lst2 := List.fill(DAE.T_ANYTYPE_DEFAULT,fillValue) "types";
1095 5 tupleConst2 := List.fill(DAE.SINGLE_CONST(DAE.C_VAR()),fillValue) "TupleConst's";
1096 aexpl := inExp::aexpl2;
1097 lst := propType::lst2;
1098 5 tupleConst := DAE.SINGLE_CONST(tconst)::tupleConst2;
1099 5 then
1100 (Absyn.TUPLE(aexpl),DAE.PROP_TUPLE(DAE.T_TUPLE(lst,names),DAE.TUPLE_CONST(tupleConst)));
1101
1102 case (_, _, _) guard(not Types.isPropTuple(propCall))
1103 then (inExp,propTuple);
1104
1105 else
1106 algorithm
1107 ✗ true := Flags.isSet(Flags.FAILTRACE);
1108 ✗ Debug.traceln("- expandTupleEquationWithWild failed");
1109 ✗ then
1110 fail();
1111
1112 end match;
1113 end expandTupleEquationWithWild;
1114
1115 protected function instEquationCommonCiTrans
1116 "updats The ClassInf state machine when an equation is instantiated."
1117 input ClassInf.State inState;
1118 input SCode.Initial inInitial;
1119 output ClassInf.State outState;
1120 algorithm
1121 outState := match inInitial
1122 case SCode.NON_INITIAL()
1123 23174 then ClassInfUtil.trans(inState, ClassInf.FOUND_EQUATION());
1124
1125 else inState;
1126 end match;
1127 end instEquationCommonCiTrans;
1128
1129 protected function unroll
1130 "Unrolling a loop is a way of removing the non-linear structure of the FOR
1131 clause by explicitly repeating the body of the loop once for each iteration."
1132 input FCore.Cache inCache;
1133 input FCore.Graph inEnv;
1134 input InnerOuter.InstHierarchy inIH;
1135 input DAE.Prefix inPrefix;
1136 input Connect.Sets inSets;
1137 input ClassInf.State inState;
1138 input Ident inIdent;
1139 input DAE.Type inIteratorType;
1140 input Values.Value inValue;
1141 input list<SCode.Equation> inEquations;
1142 input SCode.Initial inInitial;
1143 input Boolean inImplicit;
1144 input ConnectionGraph.ConnectionGraph inGraph;
1145 output FCore.Cache outCache = inCache;
1146 output DAE.DAElist outDae;
1147 output Connect.Sets outSets = inSets;
1148 output ConnectionGraph.ConnectionGraph outGraph = inGraph;
1149 protected
1150 list<Values.Value> values;
1151 FCore.Graph env;
1152 ClassInf.State ci_state = inState;
1153 list<DAE.DAElist> daes = {};
1154 DAE.DAElist dae;
1155 algorithm
1156 try
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 281 times.
281 Values.ARRAY(valueLst = values) := inValue;
1158
1159
2/2
✓ Branch 0 taken 2305 times.
✓ Branch 1 taken 281 times.
2586 for val in values loop
1160 2305 env := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(), FCore.forScopeName, NONE());
1161 // The iterator is not constant but the range is constant.
1162 2305 env := FGraph.addForIterator(env, inIdent, inIteratorType,
1163 DAE.VALBOUND(val, DAE.BINDING_FROM_DEFAULT_VALUE()), SCode.CONST(), SOME(DAE.C_CONST()));
1164
1165
2/2
✓ Branch 1 taken 2215 times.
✓ Branch 2 taken 90 times.
4520 (outCache, _, _, dae, outSets, ci_state, outGraph) :=
1166 Inst.instList(outCache, env, inIH, inPrefix, outSets, ci_state,
1167 if SCodeUtil.isInitial(inInitial) then instInitialEquation else instEquation,
1168 inEquations, inImplicit, alwaysUnroll, outGraph);
1169
1170 2305 daes := dae :: daes;
1171 end for;
1172
1173 281 outDae := List.fold(daes, DAEUtil.joinDaes, DAE.emptyDae);
1174 else
1175 ✗ true := Flags.isSet(Flags.FAILTRACE);
1176 ✗ Debug.traceln("- InstSection.unroll failed: " + ValuesDump.valString(inValue));
1177 ✗ fail();
1178 end try;
1179 end unroll;
1180
1181 protected function addForLoopScope
1182 "Adds a scope to the environment used in for loops.
1183 adrpo NOTE:
1184 The variability of the iterator SHOULD
1185 be determined by the range constantness!"
1186 input FCore.Graph env;
1187 input Ident iterName;
1188 input DAE.Type iterType;
1189 input SCode.Variability iterVariability;
1190 input Option<DAE.Const> constOfForIteratorRange;
1191 output FCore.Graph newEnv;
1192 algorithm
1193 772 newEnv := FGraph.openScope(env, SCode.NOT_ENCAPSULATED(), FCore.forScopeName, NONE());
1194 772 newEnv := FGraph.addForIterator(newEnv, iterName, iterType, DAE.UNBOUND(), iterVariability, constOfForIteratorRange);
1195 end addForLoopScope;
1196
1197 protected function addParForLoopScope
1198 "Adds a scope to the environment used in for loops.
1199 adrpo NOTE:
1200 The variability of the iterator SHOULD
1201 be determined by the range constantness!"
1202 input FCore.Graph env;
1203 input Ident iterName;
1204 input DAE.Type iterType;
1205 input SCode.Variability iterVariability;
1206 input Option<DAE.Const> constOfForIteratorRange;
1207 output FCore.Graph newEnv;
1208 algorithm
1209 ✗ newEnv := FGraph.openScope(env, SCode.NOT_ENCAPSULATED(), FCore.parForScopeName, NONE());
1210 ✗ newEnv := FGraph.addForIterator(newEnv, iterName, iterType, DAE.UNBOUND(), iterVariability, constOfForIteratorRange);
1211 end addParForLoopScope;
1212
1213 public function instEqEquation "author: LS, ELN
1214 Equations follow the same typing rules as equality expressions.
1215 This function adds the equation to the DAE."
1216 input DAE.Exp inExp1;
1217 input DAE.Properties inProperties2;
1218 input DAE.Exp inExp3;
1219 input DAE.Properties inProperties4;
1220 input DAE.ElementSource source "the origin of the element";
1221 input SCode.Initial inInitial5;
1222 input Boolean inImplicit;
1223 input SourceInfo extraInfo=Absyn.dummyInfo "We have 2 sources?";
1224 output DAE.DAElist outDae;
1225 algorithm
1226 outDae := matchcontinue (inExp1, inProperties2, inExp3, inProperties4, inInitial5)
1227 local
1228 DAE.Exp e1_1,e1,e2,e2_1;
1229 DAE.Type t_1,t1,t2,t;
1230 DAE.DAElist dae;
1231 DAE.Properties p1,p2;
1232 SCode.Initial initial_;
1233 String e1_str,t1_str,e2_str,t2_str,s1,s2;
1234 DAE.Const c;
1235 DAE.TupleConst tp;
1236 SourceInfo info;
1237
1238 /* TODO: Weird hack to make backend happy */
1239 case (e1 as DAE.CREF(), (p1 as DAE.PROP(type_ = DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(_)))), e2, (p2 as DAE.PROP(constFlag = c)), initial_) /* If it fails then this rule is matched. */
1240 algorithm
1241
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2715 times.
2715 (e2_1, DAE.PROP(t_1, _)) := Types.matchProp(e2, p2, p1, true);
1242 2715 (e1,_) := ExpressionSimplify.simplify(e1);
1243 2715 (e2_1,_) := ExpressionSimplify.simplify(e2_1);
1244 2715 dae := instEqEquation2(e1, e2_1, t_1, c, source, initial_);
1245 then
1246 dae;
1247
1248 case (e1, (p1 as DAE.PROP()), e2, (p2 as DAE.PROP(constFlag = c)), initial_) /* If e2 is not of e1's type, check if e1 has e2's type instead */
1249 algorithm
1250
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 46073 times.
54489 (e1_1, DAE.PROP(t_1, _)) := Types.matchProp(e1, p1, p2, false);
1251 46073 (e1_1,_) := ExpressionSimplify.simplify(e1_1);
1252 46073 (e2,_) := ExpressionSimplify.simplify(e2);
1253 46073 dae := instEqEquation2(e1_1, e2, t_1, c, source, initial_);
1254 then
1255 dae;
1256
1257 /* TODO: Make testsuite run properly even if this is the first case... Unknown dimensions are not matched fine here and should possibly be disallowed. */
1258 case (e1, (p1 as DAE.PROP()), e2, (p2 as DAE.PROP(constFlag = c)), initial_) /* If it fails then this rule is matched. */
1259 algorithm
1260
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8414 times.
8416 (e2_1, DAE.PROP(t_1, _)) := Types.matchProp(e2, p2, p1, true);
1261 8414 (e1,_) := ExpressionSimplify.simplify(e1);
1262 8414 (e2_1,_) := ExpressionSimplify.simplify(e2_1);
1263 8414 dae := instEqEquation2(e1, e2_1, t_1, c, source, initial_);
1264 then dae;
1265
1266 case (e1, (p1 as DAE.PROP_TUPLE()), e2, (p2 as DAE.PROP_TUPLE(tupleConst = tp)), initial_) /* PR. */
1267 algorithm
1268
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
45 (e1_1, DAE.PROP_TUPLE(t_1, _)) := Types.matchProp(e1, p1, p2, false);
1269 45 (e1_1,_) := ExpressionSimplify.simplify(e1_1);
1270 45 (e2,_) := ExpressionSimplify.simplify(e2);
1271 45 c := Types.propTupleAllConst(tp);
1272 45 dae := instEqEquation2(e1_1, e2, t_1, c, source, initial_);
1273 then
1274 dae;
1275
1276 case (e1, (p1 as DAE.PROP_TUPLE()), e2, (p2 as DAE.PROP_TUPLE(tupleConst = tp)), initial_) /* PR.
1277 An assignment to a variable of T_ENUMERATION type is an explicit
1278 assignment to the value componnent of the enumeration, i.e. having
1279 a type T_ENUM
1280 */
1281 algorithm
1282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (e2_1, DAE.PROP_TUPLE(t_1, _)) := Types.matchProp(e2, p2, p1, true);
1283 1 (e1,_) := ExpressionSimplify.simplify(e1);
1284 1 (e2_1,_) := ExpressionSimplify.simplify(e2_1);
1285 1 c := Types.propTupleAllConst(tp);
1286 1 dae := instEqEquation2(e1, e2_1, t_1, c, source, initial_);
1287 then
1288 dae;
1289
1290 case ((e1 as DAE.CREF()), DAE.PROP(type_ = DAE.T_ENUMERATION()), e2, DAE.PROP(type_ = t as DAE.T_ENUMERATION(), constFlag = c), initial_)
1291 algorithm
1292 ✗ (e1,_) := ExpressionSimplify.simplify(e1);
1293 ✗ (e2,_) := ExpressionSimplify.simplify(e2);
1294 ✗ dae := instEqEquation2(e1, e2, t, c, source, initial_);
1295 then
1296 dae;
1297
1298 // Assignment to a single component with a function returning multiple
1299 // values.
1300 case (e1, p1 as DAE.PROP(), e2, DAE.PROP_TUPLE(), initial_)
1301 algorithm
1302 1 p2 := Types.propTupleFirstProp(inProperties4);
1303
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 DAE.PROP(constFlag = c) := p2;
1304
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (e1, DAE.PROP(type_ = t_1)) := Types.matchProp(e1, p1, p2, false);
1305 1 (e1,_) := ExpressionSimplify.simplify(e1);
1306 1 e2 := DAE.TSUB(e2, 1, t_1);
1307 1 (e2,_) := ExpressionSimplify.simplify(e2);
1308 1 dae := instEqEquation2(e1, e2, t_1, c, source, initial_);
1309 then
1310 dae;
1311
1312 case (e1, DAE.PROP(type_ = t1), e2, DAE.PROP(type_ = t2), _)
1313 algorithm
1314 2 e1_str := ExpressionBasics.printExpStr(e1);
1315 2 t1_str := TypesDump.unparseTypeNoAttr(t1);
1316 2 e2_str := ExpressionBasics.printExpStr(e2);
1317 2 t2_str := TypesDump.unparseTypeNoAttr(t2);
1318 2 s1 := stringAppendList({e1_str,"=",e2_str});
1319 2 s2 := stringAppendList({t1_str,"=",t2_str});
1320 2 info := ElementSource.getElementSourceFileInfo(source);
1321 2 Types.typeErrorSanityCheck(t1_str, t2_str, info);
1322
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
4 Error.addMultiSourceMessage(Error.EQUATION_TYPE_MISMATCH_ERROR, {s1,s2}, if extraInfo.fileName=="" then {info} else {extraInfo,info});
1323 2 then fail();
1324 end matchcontinue;
1325 end instEqEquation;
1326
1327 protected function instEqEquation2
1328 "author: LS, ELN
1329 This is the second stage of instEqEquation, when the types are checked."
1330 input DAE.Exp inExp1;
1331 input DAE.Exp inExp2;
1332 input DAE.Type inType3;
1333 input DAE.Const inConst;
1334 input DAE.ElementSource source "the origin of the element";
1335 input SCode.Initial inInitial4;
1336 output DAE.DAElist outDae;
1337 algorithm
1338 outDae := matchcontinue (inExp1, inExp2, inType3, inInitial4)
1339 local
1340 DAE.DAElist dae;
1341 DAE.Exp e1,e2;
1342 SCode.Initial initial_;
1343 DAE.ComponentRef cr;
1344 list<DAE.Var> vs;
1345 DAE.Type tt;
1346 list<DAE.Exp> exps1,exps2;
1347 list<DAE.Type> tys;
1348
1349 case (e1, e2, DAE.T_INTEGER(), initial_)
1350 algorithm
1351 3337 dae := makeDaeEquation(e1, e2, source, initial_);
1352 then
1353 dae;
1354 case (e1, e2, DAE.T_REAL(), initial_)
1355 algorithm
1356 67891 dae := makeDaeEquation(e1, e2, source, initial_);
1357 then
1358 dae;
1359 case (e1, e2, DAE.T_STRING(), initial_)
1360 algorithm
1361 1817 dae := makeDaeEquation(e1, e2, source, initial_);
1362 then
1363 dae;
1364 case (e1, e2, DAE.T_BOOL(), initial_)
1365 algorithm
1366 3872 dae := makeDaeEquation(e1, e2, source, initial_);
1367 then
1368 dae;
1369 //BTH
1370 case (e1, e2, DAE.T_CLOCK(), initial_)
1371 algorithm
1372 3 dae := makeDaeEquation(e1, e2, source, initial_);
1373 then
1374 dae;
1375
1376 case (DAE.CREF(componentRef = cr), e2, DAE.T_ENUMERATION(), initial_)
1377 algorithm
1378 581 dae := makeDaeDefine(cr, e2, source, initial_);
1379 then
1380 dae;
1381
1382 case (e1, DAE.CREF(componentRef = cr), DAE.T_ENUMERATION(), initial_)
1383 1 then makeDaeDefine(cr, e1, source, initial_);
1384
1385 case (e1, e2, DAE.T_ENUMERATION(), initial_)
1386 1 then makeDaeEquation(e1, e2, source, initial_);
1387
1388 // array equations
1389 case (e1, e2, tt as DAE.T_ARRAY(), initial_)
1390 algorithm
1391 12917 dae := instArrayEquation(e1, e2, tt, inConst, source, initial_);
1392 then dae;
1393
1394 // tuples
1395 case (DAE.TUPLE(exps1), e2, DAE.T_TUPLE(types = _::_), initial_)
1396 algorithm
1397 46 exps1 := List.map(exps1,Expression.emptyToWild);
1398 46 checkNoDuplicateAssignments(exps1, ElementSource.getElementSourceFileInfo(source));
1399 44 e1 := DAE.TUPLE(exps1);
1400 44 dae := makeDaeEquation(e1, e2, source, initial_);
1401 then dae;
1402
1403 case (e1, e2, DAE.T_TUPLE(), initial_) guard not Expression.isTuple(e1)
1404 algorithm
1405 ✗ dae := makeDaeEquation(e1, e2, source, initial_);
1406 then dae;
1407
1408 // MetaModelica types
1409 case (e1, e2, DAE.T_METALIST(), initial_)
1410 algorithm
1411 ✗ true := Config.acceptMetaModelicaGrammar();
1412 ✗ dae := makeDaeEquation(e1, e2, source, initial_);
1413 then
1414 dae;
1415 case (e1, e2, DAE.T_METATUPLE(), initial_)
1416 algorithm
1417 ✗ true := Config.acceptMetaModelicaGrammar();
1418 ✗ dae := makeDaeEquation(e1, e2, source, initial_);
1419 then
1420 dae;
1421 case (e1, e2, DAE.T_METAOPTION(), initial_)
1422 algorithm
1423 ✗ true := Config.acceptMetaModelicaGrammar();
1424 ✗ dae := makeDaeEquation(e1, e2, source, initial_);
1425 then
1426 dae;
1427 case (e1, e2, DAE.T_METAUNIONTYPE(), initial_)
1428 algorithm
1429 ✗ true := Config.acceptMetaModelicaGrammar();
1430 ✗ dae := makeDaeEquation(e1, e2, source, initial_);
1431 then
1432 dae;
1433 // --------------
1434
1435 // Complex types extending basic type
1436 case (e1, e2, DAE.T_SUBTYPE_BASIC(complexType = tt), initial_)
1437 algorithm
1438 1999 dae := instEqEquation2(e1, e2, tt, inConst, source, initial_);
1439 then
1440 dae;
1441
1442 // split a complex equation to its elements
1443 case (e1, e2, DAE.T_COMPLEX(varLst = vs), initial_)
1444 algorithm
1445 2756 exps1 := Expression.splitRecord(e1,inType3);
1446 2739 exps2 := Expression.splitRecord(e2,inType3);
1447 1496 tys := List.map(vs, Types.getVarType);
1448 1496 dae := instEqEquation2List(exps1, exps2, tys, inConst, source, initial_, {});
1449 then dae;
1450
1451 /* all other COMPLEX equations */
1452 case (e1, e2, tt as DAE.T_COMPLEX(), initial_)
1453 algorithm
1454 1260 dae := instComplexEquation(e1,e2,tt,source,initial_);
1455 then dae;
1456
1457 else
1458 algorithm
1459
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
1460 ✗ Debug.trace("- InstSection.instEqEquation2 failed\n");
1461 ✗ then
1462 fail();
1463 end matchcontinue;
1464 end instEqEquation2;
1465
1466 protected function instEqEquation2List
1467 input list<DAE.Exp> inExps1;
1468 input list<DAE.Exp> inExps2;
1469 input list<DAE.Type> inTypes3;
1470 input DAE.Const const;
1471 input DAE.ElementSource source "the origin of the element";
1472 input SCode.Initial initial_;
1473 input list<DAE.DAElist> acc;
1474 output DAE.DAElist outDae;
1475 algorithm
1476 outDae := match (inExps1, inExps2, inTypes3)
1477 local
1478 list<DAE.Exp> rest1,rest2;
1479 list<DAE.Type> rest3;
1480 DAE.Type ty;
1481 DAE.Exp exp1,exp2;
1482 DAE.DAElist res;
1483 1496 case ({}, {}, {}) then DAEUtil.joinDaeLst(listReverse(acc));
1484 case (exp1::rest1, exp2::rest2, ty::rest3)
1485 algorithm
1486 3206 res := instEqEquation2(exp1,exp2,ty,const,source,initial_);
1487 3206 then instEqEquation2List(rest1,rest2,rest3,const,source,initial_,res::acc);
1488 end match;
1489 end instEqEquation2List;
1490
1491 public function makeDaeEquation
1492 "author: LS, ELN
1493 Constructs an equation in the DAE, they can be
1494 either an initial equation or an ordinary equation."
1495 input DAE.Exp inExp1;
1496 input DAE.Exp inExp2;
1497 input DAE.ElementSource inSource "the origin of the element";
1498 input SCode.Initial inInitial3;
1499 output DAE.DAElist outDae;
1500 algorithm
1501 outDae := match (inExp1,inExp2,inSource,inInitial3)
1502 local
1503 DAE.Exp e1,e2;
1504 DAE.ElementSource source;
1505 DAE.Element elt;
1506 case (e1,e2,source,SCode.NON_INITIAL())
1507 algorithm
1508 76600 elt := DAE.EQUATION(e1,e2,source);
1509 76600 source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1510 153200 then DAE.DAE({DAE.EQUATION(e1,e2,source)});
1511 case (e1,e2,source,SCode.INITIAL())
1512 algorithm
1513 382 elt := DAE.INITIALEQUATION(e1,e2,source);
1514 382 source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1515 764 then DAE.DAE({DAE.INITIALEQUATION(e1,e2,source)});
1516 end match;
1517 end makeDaeEquation;
1518
1519 protected function makeDaeDefine
1520 "author: LS, ELN "
1521 input DAE.ComponentRef inComponentRef;
1522 input DAE.Exp inExp;
1523 input DAE.ElementSource source "the origin of the element";
1524 input SCode.Initial inInitial;
1525 output DAE.DAElist outDae;
1526 algorithm
1527 outDae := match (inComponentRef, inExp, inInitial)
1528 local DAE.ComponentRef cr; DAE.Exp e2;
1529 case (cr, e2, SCode.NON_INITIAL())
1530 1164 then DAE.DAE({DAE.DEFINE(cr,e2,source)});
1531 case (cr, e2, SCode.INITIAL())
1532 ✗ then DAE.DAE({DAE.INITIALDEFINE(cr,e2,source)});
1533 end match;
1534 end makeDaeDefine;
1535
1536 protected function instArrayEquation
1537 "Instantiates an array equation, i.e. an equation where both sides are arrays."
1538 input DAE.Exp lhs;
1539 input DAE.Exp rhs;
1540 input DAE.Type tp;
1541 input DAE.Const inConst;
1542 input DAE.ElementSource inSource;
1543 input SCode.Initial initial_;
1544 output DAE.DAElist dae;
1545 algorithm
1546 dae := matchcontinue(tp, inSource, initial_)
1547 local
1548 Boolean b, b1, b2;
1549 DAE.Dimensions ds;
1550 DAE.Dimension dim, lhs_dim, rhs_dim;
1551 list<DAE.Exp> lhs_idxs, rhs_idxs;
1552 DAE.Type t;
1553 String lhs_str, rhs_str, eq_str;
1554 DAE.Element elt;
1555 DAE.ElementSource source;
1556
1557 /* Initial array equations with function calls => initial array equations */
1558 case (_, source, SCode.INITIAL())
1559 algorithm
1560 83 b1 := Expression.containVectorFunctioncall(lhs);
1561 83 b2 := Expression.containVectorFunctioncall(rhs);
1562
2/2
✓ Branch 0 taken 68 times.
✓ Branch 1 taken 15 times.
83 true := boolOr(b1, b2);
1563 15 ds := TypesDump.getDimensions(tp);
1564 15 elt := DAE.INITIAL_ARRAY_EQUATION(ds, lhs, rhs, source);
1565 15 source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1566 30 then
1567 DAE.DAE({DAE.INITIAL_ARRAY_EQUATION(ds, lhs, rhs, source)});
1568
1569 /* Arrays with function calls => array equations */
1570 case (_, source, SCode.NON_INITIAL())
1571 algorithm
1572 12834 b1 := Expression.containVectorFunctioncall(lhs);
1573 12834 b2 := Expression.containVectorFunctioncall(rhs);
1574
2/2
✓ Branch 0 taken 11411 times.
✓ Branch 1 taken 1423 times.
12834 true := boolOr(b1, b2);
1575 1423 ds := TypesDump.getDimensions(tp);
1576 1423 elt := DAE.ARRAY_EQUATION(ds, lhs, rhs, source);
1577 1423 source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1578 2846 then
1579 DAE.DAE({DAE.ARRAY_EQUATION(ds, lhs, rhs, source)});
1580
1581 // Array equation of any size, non-expanding case
1582 case (DAE.T_ARRAY(ty = t, dims = {_}), _, _)
1583 algorithm
1584
1/2
✓ Branch 1 taken 11479 times.
✗ Branch 2 not taken.
11479 false := Config.splitArrays();
1585 // Expand along the first dimensions of the expressions, and generate an
1586 // equation for each pair of elements.
1587 ✗ DAE.T_ARRAY(dims = lhs_dim :: _) := Expression.typeof(lhs);
1588 ✗ DAE.T_ARRAY(dims = rhs_dim :: _) := Expression.typeof(rhs);
1589 ✗ lhs_idxs := expandArrayDimension(lhs_dim, lhs);
1590 ✗ rhs_idxs := expandArrayDimension(rhs_dim, rhs);
1591 ✗ dae := instArrayElEq(lhs, rhs, t, inConst, lhs_idxs, rhs_idxs, inSource, initial_);
1592 then
1593 dae;
1594
1595 // Array dimension of known size, expanding case.
1596 case (DAE.T_ARRAY(ty = t, dims = {dim}), _, _)
1597 algorithm
1598
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11479 times.
11479 true := Config.splitArrays();
1599
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11479 times.
11479 true := Expression.dimensionKnown(dim);
1600 // Expand along the first dimensions of the expressions, and generate an
1601 // equation for each pair of elements.
1602
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 11479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11479 times.
11479 DAE.T_ARRAY(dims = lhs_dim :: _) := Expression.typeof(lhs);
1603
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 11479 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 11479 times.
11479 DAE.T_ARRAY(dims = rhs_dim :: _) := Expression.typeof(rhs);
1604 11479 lhs_idxs := expandArrayDimension(lhs_dim, lhs);
1605 11479 rhs_idxs := expandArrayDimension(rhs_dim, rhs);
1606 11479 dae := instArrayElEq(lhs, rhs, t, inConst, lhs_idxs, rhs_idxs, inSource, initial_);
1607 then
1608 dae;
1609
1610 case (DAE.T_ARRAY(dims = {dim}), source, _)
1611 algorithm
1612 ✗ true := Config.splitArrays();
1613 ✗ true := Expression.dimensionKnown(dim);
1614 ✗ true := Expression.isRange(lhs) or Expression.isRange(rhs) or Expression.isReduction(lhs) or Expression.isReduction(rhs);
1615 ✗ ds := TypesDump.getDimensions(tp);
1616 ✗ b := SCodeUtil.isInitial(initial_);
1617 ✗ elt := if b then DAE.INITIAL_ARRAY_EQUATION(ds, lhs, rhs, source) else DAE.ARRAY_EQUATION(ds, lhs, rhs, source);
1618 ✗ source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1619 ✗ elt := if b then DAE.INITIAL_ARRAY_EQUATION(ds, lhs, rhs, source) else DAE.ARRAY_EQUATION(ds, lhs, rhs, source);
1620 ✗ then
1621 DAE.DAE({elt});
1622
1623 // Array dimension of unknown size, expanding case.
1624 case (DAE.T_ARRAY(ty = t, dims = {dim}), _, _)
1625 algorithm
1626 ✗ true := Config.splitArrays();
1627 ✗ false := Expression.dimensionKnown(dim);
1628 // It's ok with array equation of unknown size if checkModel is used.
1629 ✗ true := Flags.getConfigBool(Flags.CHECK_MODEL);
1630 // Expand along the first dimensions of the expressions, and generate an
1631 // equation for each pair of elements.
1632 ✗ DAE.T_ARRAY(dims = lhs_dim :: _) := Expression.typeof(lhs);
1633 ✗ DAE.T_ARRAY(dims = rhs_dim :: _) := Expression.typeof(rhs);
1634 ✗ lhs_idxs := expandArrayDimension(lhs_dim, lhs);
1635 ✗ rhs_idxs := expandArrayDimension(rhs_dim, rhs);
1636 ✗ dae := instArrayElEq(lhs, rhs, t, inConst, lhs_idxs, rhs_idxs, inSource, initial_);
1637 then
1638 dae;
1639
1640 // Array equation of unknown size, e.g. Real x[:], y[:]; equation x = y; (expanding case)
1641 case (DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}), source, SCode.INITIAL())
1642 algorithm
1643 ✗ true := Config.splitArrays();
1644 // It's ok with array equation of unknown size if checkModel is used.
1645 ✗ true := Flags.getConfigBool(Flags.CHECK_MODEL);
1646 // generate an initial array equation of dim 1
1647 // Now the dimension can be made DAE.DIM_UNKNOWN(), I just don't want to break anything for now -- alleb
1648 ✗ elt := DAE.INITIAL_ARRAY_EQUATION({DAE.DIM_INTEGER(1)}, lhs, rhs, source);
1649 ✗ source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1650 ✗ then
1651 DAE.DAE({DAE.INITIAL_ARRAY_EQUATION({DAE.DIM_INTEGER(1)}, lhs, rhs, source)});
1652
1653 // Array equation of unknown size, e.g. Real x[:], y[:]; equation x = y; (expanding case)
1654 case (DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}), source, SCode.NON_INITIAL())
1655 algorithm
1656 ✗ true := Config.splitArrays();
1657 // It's ok with array equation of unknown size if checkModel is used.
1658 ✗ true := Flags.getConfigBool(Flags.CHECK_MODEL);
1659 // generate an array equation of dim 1
1660 // Now the dimension can be made DAE.DIM_UNKNOWN(), I just don't want to break anything for now -- alleb
1661 ✗ elt := DAE.ARRAY_EQUATION({DAE.DIM_INTEGER(1)}, lhs, rhs, source);
1662 ✗ source := ElementSource.addSymbolicTransformationFlattenedEqs(source, elt);
1663 ✗ then
1664 DAE.DAE({DAE.ARRAY_EQUATION({DAE.DIM_INTEGER(1)}, lhs, rhs, source)});
1665
1666 // Array equation of unknown size, e.g. Real x[:], y[:]; equation x = y; (expanding case)
1667 case (DAE.T_ARRAY(dims = {DAE.DIM_UNKNOWN()}), _, _)
1668 algorithm
1669 ✗ true := Config.splitArrays();
1670 // It's ok with array equation of unknown size if checkModel is used.
1671 ✗ false := Flags.getConfigBool(Flags.CHECK_MODEL);
1672 ✗ lhs_str := ExpressionBasics.printExpStr(lhs);
1673 ✗ rhs_str := ExpressionBasics.printExpStr(rhs);
1674 ✗ eq_str := stringAppendList({lhs_str, "=", rhs_str});
1675 ✗ Error.addSourceMessage(Error.INST_ARRAY_EQ_UNKNOWN_SIZE, {eq_str}, ElementSource.getElementSourceFileInfo(inSource));
1676 ✗ then
1677 fail();
1678
1679 else
1680 algorithm
1681 ✗ true := Flags.isSet(Flags.FAILTRACE);
1682 ✗ Debug.trace("- InstSection.instArrayEquation failed\n");
1683 ✗ then
1684 fail();
1685 end matchcontinue;
1686 end instArrayEquation;
1687
1688 protected function instArrayElEq
1689 "This function loops recursively through all indices in the two arrays and
1690 generates an equation for each pair of elements."
1691 input DAE.Exp inLhsExp;
1692 input DAE.Exp inRhsExp;
1693 input DAE.Type inType;
1694 input DAE.Const inConst;
1695 input list<DAE.Exp> inLhsIndices;
1696 input list<DAE.Exp> inRhsIndices;
1697 input DAE.ElementSource inSource;
1698 input SCode.Initial inInitial;
1699 output DAE.DAElist outDAE = DAE.emptyDae;
1700 protected
1701 DAE.Exp rhs_idx;
1702 list<DAE.Exp> rhs_idxs = listReverse(inRhsIndices);
1703 DAE.DAElist dae;
1704 algorithm
1705
2/2
✓ Branch 1 taken 32767 times.
✓ Branch 2 taken 11479 times.
44246 for lhs_idx in listReverse(inLhsIndices) loop
1706
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 32767 times.
32767 rhs_idx :: rhs_idxs := rhs_idxs;
1707
1708 32767 dae := instEqEquation2(lhs_idx, rhs_idx, inType, inConst, inSource, inInitial);
1709 32767 outDAE := DAEUtil.joinDaes(dae, outDAE);
1710 end for;
1711 end instArrayElEq;
1712
1713 protected function unrollForLoop
1714 "Unrolls a for-loop that contains when-statements."
1715 input FCore.Cache inCache;
1716 input FCore.Graph inEnv;
1717 input InnerOuter.InstHierarchy inIH;
1718 input DAE.Prefix inPrefix;
1719 input ClassInf.State inState;
1720 input String inIterator;
1721 input DAE.Exp inRange;
1722 input DAE.Properties inRangeProps;
1723 input list<SCode.Statement> inBody;
1724 input SCode.Statement inStatement;
1725 input SourceInfo inInfo;
1726 input DAE.ElementSource inSource;
1727 input SCode.Initial inInitial;
1728 input Boolean inImpl;
1729 input Boolean inUnrollLoops;
1730 output FCore.Cache outCache;
1731 output list<DAE.Statement> outStatements;
1732 protected
1733 DAE.Type ty;
1734 DAE.Const c;
1735 FCore.Graph env;
1736 Values.Value val;
1737 algorithm
1738 try
1739
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 DAE.T_ARRAY(ty = ty) := Types.getPropType(inRangeProps);
1740 1 c := Types.getPropConst(inRangeProps);
1741
1742 // We can unroll ONLY if we have a parameter range expression.
1743
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := Types.isParameterOrConstant(c);
1744 1 env := addForLoopScope(inEnv, inIterator, ty, SCode.VAR(), SOME(c));
1745 1 (outCache, val) :=
1746 Ceval.ceval(inCache, env, inRange, inImpl, Absyn.MSG(inInfo), 0);
1747 1 (outCache, outStatements) := loopOverRange(inCache, env, inIH, inPrefix,
1748 inState, inIterator, val, inBody, inSource, inInitial, inImpl, inUnrollLoops);
1749 else
1750 ✗ Error.addSourceMessageAndFail(Error.UNROLL_LOOP_CONTAINING_WHEN,
1751 {SCodeDump.statementStr(inStatement)}, inInfo);
1752 end try;
1753 end unrollForLoop;
1754
1755 protected function instForStatement
1756 input FCore.Cache inCache;
1757 input FCore.Graph inEnv;
1758 input InnerOuter.InstHierarchy inIH;
1759 input DAE.Prefix inPrefix;
1760 input ClassInf.State inState;
1761 input SCode.Statement inForStatement;
1762 input DAE.ElementSource inSource;
1763 input SCode.Initial inInitial;
1764 input Boolean inImpl;
1765 input Boolean inUnrollLoops;
1766 output FCore.Cache outCache;
1767 output list<DAE.Statement> outStatements "For statements can produce multiple statements due to unrolling.";
1768 protected
1769 String iterator;
1770 Option<Absyn.Exp> oarange;
1771 Absyn.Exp arange;
1772 DAE.Exp range;
1773 DAE.Properties prop;
1774 list<SCode.Statement> body;
1775 SourceInfo info;
1776 list<AbsynUtil.IteratorIndexedCref> iter_crefs;
1777 algorithm
1778
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
491 SCode.ALG_FOR(index = iterator, range = oarange, forBody = body, info = info) := inForStatement;
1779
1780
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 491 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 487 times.
491 if isSome(oarange) then
1781 487 SOME(arange) := oarange;
1782 487 (outCache, range, prop) :=
1783 Static.elabExp(inCache, inEnv, arange, inImpl, true, inPrefix, info);
1784 else
1785 4 iter_crefs := SCodeUtil.findIteratorIndexedCrefsInStatements(body, iterator);
1786 4 (range, prop, outCache) :=
1787 Static.deduceIterationRange(iterator, iter_crefs, inEnv, inCache, info);
1788 end if;
1789
1790 // Only unroll for-loops containing when-statements.
1791
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 490 times.
491 if containsWhenStatements(body) then
1792 1 (outCache, outStatements) := unrollForLoop(inCache, inEnv, inIH, inPrefix,
1793 inState, iterator, range, prop, body, inForStatement, info, inSource,
1794 inInitial, inImpl, inUnrollLoops);
1795 else
1796 490 (outCache, outStatements) := instForStatement_dispatch(inCache, inEnv, inIH,
1797 inPrefix, inState, iterator, range, prop, body, info, inSource, inInitial, inImpl, inUnrollLoops);
1798 end if;
1799 end instForStatement;
1800
1801 protected function instForStatement_dispatch
1802 input FCore.Cache inCache;
1803 input FCore.Graph inEnv;
1804 input InnerOuter.InstHierarchy inIH;
1805 input DAE.Prefix inPrefix;
1806 input ClassInf.State inState;
1807 input String inIterator;
1808 input DAE.Exp inRange;
1809 input DAE.Properties inRangeProps;
1810 input list<SCode.Statement> inBody;
1811 input SourceInfo inInfo;
1812 input DAE.ElementSource inSource;
1813 input SCode.Initial inInitial;
1814 input Boolean inImpl;
1815 input Boolean inUnrollLoops;
1816 output FCore.Cache outCache = inCache;
1817 output list<DAE.Statement> outStatements;
1818 protected
1819 DAE.Type ty;
1820 DAE.Const c;
1821 FCore.Graph env;
1822 DAE.ElementSource source;
1823 DAE.Exp range;
1824 algorithm
1825 490 c := Types.getPropConst(inRangeProps);
1826
1827 // Remove the for-loop if the range is empty.
1828
2/2
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 345 times.
490 if Types.isParameterOrConstant(c) then
1829 try
1830
3/4
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 140 times.
✓ Branch 4 taken 140 times.
✗ Branch 5 not taken.
145 (outCache, Values.ARRAY(valueLst = {})) :=
1831 Ceval.ceval(outCache, inEnv, inRange, inImpl, Absyn.MSG(inInfo), 0);
1832 ✗ outStatements := {};
1833 ✗ return;
1834 else
1835 end try;
1836 end if;
1837
1838 490 ty := Types.getPropType(inRangeProps);
1839 490 ty := getIteratorType(ty, inIterator, inInfo);
1840
1841 489 (outCache, range) :=
1842 Ceval.cevalRangeIfConstant(outCache, inEnv, inRange, inRangeProps, inImpl, inInfo);
1843 489 (outCache, range) := PrefixUtil.prefixExp(outCache, inEnv, inIH, range, inPrefix);
1844 489 env := addForLoopScope(inEnv, inIterator, ty, SCode.VAR(), SOME(c));
1845 489 (outCache, outStatements) := instStatements(outCache, env, inIH, inPrefix,
1846 inState, inBody, inSource, inInitial, inImpl, inUnrollLoops);
1847
1848 489 source := ElementSource.addElementSourceFileInfo(inSource, inInfo);
1849 978 outStatements :=
1850 {Algorithm.makeFor(inIterator, range, inRangeProps, outStatements, source)};
1851 end instForStatement_dispatch;
1852
1853 protected function instComplexEquation "instantiate a comlex equation, i.e. c = Complex(1.0,-1.0) when Complex is a record"
1854 input DAE.Exp lhs;
1855 input DAE.Exp rhs;
1856 input DAE.Type tp;
1857 input DAE.ElementSource source "the origin of the element";
1858 input SCode.Initial initial_;
1859 output DAE.DAElist dae;
1860 algorithm
1861 dae := matchcontinue initial_
1862 local
1863 String s;
1864 SourceInfo info;
1865
1866 // Records
1867 case _
1868 algorithm
1869
2/2
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 1243 times.
1260 true := Types.isRecord(tp);
1870 1243 dae := makeComplexDaeEquation(lhs,rhs,source,initial_);
1871 then dae;
1872
1873 // External objects are treated as ordinary equations
1874 case _
1875 algorithm
1876
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 true := Types.isExternalObject(tp);
1877 17 dae := makeDaeEquation(lhs,rhs,source,initial_);
1878 // adrpo: TODO! FIXME! shouldn't we return the dae here??!!
1879 // PA: do not know, but at least return the functions.
1880 then
1881 dae;
1882
1883 // adrpo 2009-05-15: also T_COMPLEX that is NOT record but TYPE should be allowed
1884 // as is used in Modelica.Mechanics.MultiBody (Orientation type)
1885 case _ algorithm
1886 // adrpo: TODO! check if T_COMPLEX(ClassInf.TYPE)!
1887 ✗ dae := makeComplexDaeEquation(lhs,rhs,source,initial_);
1888 then dae;
1889
1890 // complex equation that is not of restriction record is not allowed
1891 else
1892 algorithm
1893 ✗ false := Types.isRecord(tp);
1894 ✗ s := ExpressionBasics.printExpStr(lhs) + " = " + ExpressionBasics.printExpStr(rhs);
1895 ✗ info := ElementSource.getElementSourceFileInfo(source);
1896 ✗ Error.addSourceMessage(Error.ILLEGAL_EQUATION_TYPE, {s}, info);
1897 ✗ then fail();
1898 end matchcontinue;
1899 end instComplexEquation;
1900
1901 protected function makeComplexDaeEquation "Creates a DAE.COMPLEX_EQUATION for equations involving records"
1902 input DAE.Exp lhs;
1903 input DAE.Exp rhs;
1904 input DAE.ElementSource source "the origin of the element";
1905 input SCode.Initial initial_;
1906 output DAE.DAElist dae;
1907 algorithm
1908 dae := match initial_
1909 local
1910 case SCode.NON_INITIAL()
1911 2486 then DAE.DAE({DAE.COMPLEX_EQUATION(lhs,rhs,source)});
1912
1913 case SCode.INITIAL()
1914 ✗ then DAE.DAE({DAE.INITIAL_COMPLEX_EQUATION(lhs,rhs,source)});
1915 end match;
1916 end makeComplexDaeEquation;
1917
1918 public function instAlgorithm
1919 "Algorithms are converted to the representation defined in
1920 the module Algorithm, and the added to the DAE result.
1921 This function converts an algorithm section."
1922 input FCore.Cache inCache;
1923 input FCore.Graph inEnv;
1924 input InnerOuter.InstHierarchy inIH;
1925 input DAE.Prefix inPrefix;
1926 input Connect.Sets inSets;
1927 input ClassInf.State inState;
1928 input SCode.AlgorithmSection inAlgorithm;
1929 input Boolean inImpl;
1930 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
1931 input ConnectionGraph.ConnectionGraph inGraph;
1932 output FCore.Cache outCache;
1933 output FCore.Graph outEnv;
1934 output InnerOuter.InstHierarchy outIH;
1935 output DAE.DAElist outDae;
1936 output Connect.Sets outSets;
1937 output ClassInf.State outState;
1938 output ConnectionGraph.ConnectionGraph outGraph;
1939 algorithm
1940 (outCache,outEnv,outIH,outDae,outSets,outState,outGraph) :=
1941 matchcontinue (inCache, inEnv, inIH, inPrefix, inSets, inState, inAlgorithm, inImpl, inGraph)
1942 local
1943 FCore.Graph env;
1944 list<DAE.Statement> statements_1;
1945 Connect.Sets csets;
1946 ClassInf.State ci_state;
1947 list<SCode.Statement> statements;
1948 SCode.Statement stmt;
1949 Boolean impl;
1950 FCore.Cache cache;
1951 DAE.Prefix pre;
1952 ConnectionGraph.ConnectionGraph graph;
1953 InstanceHierarchy ih;
1954 DAE.ElementSource source "the origin of the element";
1955 DAE.DAElist dae;
1956 String s;
1957 SourceInfo info;
1958
1959 case (cache, env, ih, pre, csets, ci_state, SCode.ALGORITHM(statements = statements), impl, graph) /* impl */
1960 algorithm
1961 // set the source of this element
1962 6237 ci_state := ClassInfUtil.trans(ci_state,ClassInf.FOUND_ALGORITHM());
1963 6237 source := ElementSource.createElementSource(Absyn.dummyInfo, FGraph.getScopePath(env), pre);
1964
1965 6237 (cache,statements_1) := instStatements(cache, env, ih, pre, ci_state, statements, source, SCode.NON_INITIAL(), impl, unrollForLoops);
1966 6177 (statements_1,_) := DAEUtil.traverseDAEEquationsStmts(statements_1,Expression.traverseSubexpressionsHelper,(ExpressionSimplify.simplifyWork,ExpressionSimplifyTypes.optionSimplifyOnly));
1967
1968 12354 dae := DAE.DAE({DAE.ALGORITHM(DAE.ALGORITHM_STMTS(statements_1),source)});
1969 then
1970 (cache,env,ih,dae,csets,ci_state,graph);
1971
1972 case (_, _, _, _, _, ci_state, SCode.ALGORITHM(statements = stmt::_), _, _)
1973 algorithm
1974
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 failure(ClassInfUtil.trans(ci_state,ClassInf.FOUND_ALGORITHM()));
1975 ✗ s := ClassInfUtil.printStateStr(ci_state);
1976 ✗ info := SCodeUtil.getStatementInfo(stmt);
1977 ✗ Error.addSourceMessage(Error.ALGORITHM_TRANSITION_FAILURE, {s}, info);
1978 ✗ then fail();
1979
1980 else
1981 algorithm
1982
1/2
✓ Branch 1 taken 60 times.
✗ Branch 2 not taken.
60 true := Flags.isSet(Flags.FAILTRACE);
1983 ✗ Debug.traceln("- InstSection.instAlgorithm failed");
1984 ✗ then
1985 fail();
1986 end matchcontinue;
1987 end instAlgorithm;
1988
1989 public function instInitialAlgorithm
1990 "Algorithms are converted to the representation defined
1991 in the module Algorithm, and the added to the DAE result.
1992 This function converts an algorithm section."
1993 input FCore.Cache inCache;
1994 input FCore.Graph inEnv;
1995 input InnerOuter.InstHierarchy inIH;
1996 input DAE.Prefix inPrefix;
1997 input Connect.Sets inSets;
1998 input ClassInf.State inState;
1999 input SCode.AlgorithmSection inAlgorithm;
2000 input Boolean inImpl;
2001 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
2002 input ConnectionGraph.ConnectionGraph inGraph;
2003 output FCore.Cache outCache;
2004 output FCore.Graph outEnv;
2005 output InnerOuter.InstHierarchy outIH;
2006 output DAE.DAElist outDae;
2007 output Connect.Sets outSets;
2008 output ClassInf.State outState;
2009 output ConnectionGraph.ConnectionGraph outGraph;
2010 algorithm
2011 (outCache,outEnv,outIH,outDae,outSets,outState,outGraph):=
2012 matchcontinue (inCache, inEnv, inIH, inPrefix, inSets, inState, inAlgorithm, inImpl, inGraph)
2013 local
2014 FCore.Graph env;
2015 list<DAE.Statement> statements_1;
2016 Connect.Sets csets;
2017 ClassInf.State ci_state;
2018 list<SCode.Statement> statements;
2019 Boolean impl;
2020 FCore.Cache cache;
2021 DAE.Prefix pre;
2022 ConnectionGraph.ConnectionGraph graph;
2023 InstanceHierarchy ih;
2024 DAE.ElementSource source "the origin of the element";
2025 DAE.DAElist dae;
2026
2027 case (cache, env, ih, pre, csets, ci_state, SCode.ALGORITHM(statements = statements), impl, graph)
2028 algorithm
2029 // set the source of this element
2030 21 source := ElementSource.createElementSource(Absyn.dummyInfo, FGraph.getScopePath(env), pre);
2031
2032 21 (cache,statements_1) := instStatements(cache, env, ih, pre, ci_state, statements, source, SCode.INITIAL(), impl, unrollForLoops);
2033 20 (statements_1,_) := DAEUtil.traverseDAEEquationsStmts(statements_1,Expression.traverseSubexpressionsHelper,(ExpressionSimplify.simplifyWork,ExpressionSimplifyTypes.optionSimplifyOnly));
2034
2035 40 dae := DAE.DAE({DAE.INITIALALGORITHM(DAE.ALGORITHM_STMTS(statements_1),source)});
2036 then
2037 (cache,env,ih,dae,csets,ci_state,graph);
2038
2039 else
2040 algorithm
2041
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 true := Flags.isSet(Flags.FAILTRACE);
2042 ✗ Debug.trace("- InstSection.instInitialAlgorithm failed\n");
2043 ✗ then
2044 fail();
2045 end matchcontinue;
2046 end instInitialAlgorithm;
2047
2048 public function instConstraint
2049 "Constraints are elaborated and converted to DAE"
2050 input FCore.Cache inCache;
2051 input FCore.Graph inEnv;
2052 input DAE.Prefix inPrefix;
2053 input ClassInf.State inState;
2054 input SCode.ConstraintSection inConstraints;
2055 input Boolean inImpl;
2056 output FCore.Cache outCache;
2057 output FCore.Graph outEnv;
2058 output DAE.DAElist outDae;
2059 output ClassInf.State outState;
2060 algorithm
2061 (outCache,outEnv,outDae,outState) :=
2062 matchcontinue (inCache,inEnv,inPrefix,inState,inConstraints,inImpl)
2063 local
2064 FCore.Graph env;
2065 list<DAE.Exp> constraints_1;
2066 ClassInf.State ci_state;
2067 list<Absyn.Exp> constraints;
2068 Boolean impl;
2069 FCore.Cache cache;
2070 DAE.Prefix pre;
2071 DAE.ElementSource source "the origin of the element";
2072 DAE.DAElist dae;
2073
2074 case (cache,env,pre,ci_state,SCode.CONSTRAINTS(constraints = constraints),impl)
2075 algorithm
2076 // set the source of this element
2077 3 ci_state := ClassInfUtil.trans(ci_state,ClassInf.FOUND_ALGORITHM());
2078 3 source := ElementSource.createElementSource(Absyn.dummyInfo, FGraph.getScopePath(env), pre);
2079
2080 3 (cache,constraints_1,_) := Static.elabExpList(cache, env, constraints, impl, true /*vect*/, pre, Absyn.dummyInfo);
2081 // (constraints_1,_) = DAEUtil.traverseDAEquationsStmts(constraints_1,Expression.traverseSubexpressionsHelper,(ExpressionSimplify.simplifyWork,false));
2082
2083 6 dae := DAE.DAE({DAE.CONSTRAINT(DAE.CONSTRAINT_EXPS(constraints_1),source)});
2084 then
2085 (cache,env,dae,ci_state);
2086 /*
2087 case (_,_,_,_,_,_,ci_state,SCode.ALGORITHM(constraints = exp::_),_,_,_)
2088 algorithm
2089 failure(_ = ClassInfUtil.trans(ci_state,ClassInf.FOUND_ALGORITHM()));
2090 s = ClassInfUtil.printStateStr(ci_state);
2091 Error.addMessage(Error.ALGORITHM_TRANSITION_FAILURE,{s});
2092 then fail();
2093 */
2094 else
2095 algorithm
2096 ✗ true := Flags.isSet(Flags.FAILTRACE);
2097 ✗ Debug.trace("- InstSection.instConstraints failed\n");
2098 ✗ then
2099 fail();
2100 end matchcontinue;
2101 end instConstraint;
2102
2103 public function instStatements
2104 "This function instantiates a list of algorithm statements."
2105 input FCore.Cache inCache;
2106 input FCore.Graph inEnv;
2107 input InnerOuter.InstHierarchy inIH;
2108 input DAE.Prefix inPrefix;
2109 input ClassInf.State inState;
2110 input list<SCode.Statement> inStatements;
2111 input DAE.ElementSource inSource;
2112 input SCode.Initial inInitial;
2113 input Boolean inImpl;
2114 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
2115 output FCore.Cache outCache = inCache;
2116 output list<DAE.Statement> outStatements;
2117 protected
2118 list<DAE.Statement> stmts;
2119 list<list<DAE.Statement>> stmtsl = {};
2120 algorithm
2121
2/2
✓ Branch 0 taken 38541 times.
✓ Branch 1 taken 16129 times.
54670 for stmt in inStatements loop
2122 38541 (outCache, stmts) := instStatement(inCache, inEnv, inIH, inPrefix, inState,
2123 stmt, inSource, inInitial, inImpl, unrollForLoops);
2124 38472 stmtsl := stmts :: stmtsl;
2125 end for;
2126
2127 16129 outStatements := List.flattenReverse(stmtsl);
2128 end instStatements;
2129
2130 protected function instExp
2131 "Helper function to instStatement. Elaborates, evalutes if constant, and
2132 prefixes an expression."
2133 input FCore.Cache inCache;
2134 input FCore.Graph inEnv;
2135 input InnerOuter.InstHierarchy inIH;
2136 input DAE.Prefix inPrefix;
2137 input Absyn.Exp inExp;
2138 input Boolean inImpl;
2139 input SourceInfo inInfo;
2140 output FCore.Cache outCache;
2141 output DAE.Exp outExp;
2142 output DAE.Properties outProperties;
2143 algorithm
2144 4367 (outCache, outExp, outProperties) := Static.elabExp(inCache, inEnv, inExp,
2145 inImpl, true, inPrefix, inInfo);
2146 4366 (outCache, outExp, outProperties) := Ceval.cevalIfConstant(outCache, inEnv,
2147 outExp, outProperties, inImpl, inInfo);
2148 4366 (outCache, outExp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, outExp, inPrefix);
2149 end instExp;
2150
2151 protected function instStatement
2152 "Instantiates an algorithm statement."
2153 input FCore.Cache inCache;
2154 input FCore.Graph inEnv;
2155 input InnerOuter.InstHierarchy inIH;
2156 input DAE.Prefix inPrefix;
2157 input ClassInf.State inState;
2158 input SCode.Statement inStatement;
2159 input DAE.ElementSource inSource;
2160 input SCode.Initial inInitial;
2161 input Boolean inImpl;
2162 input Boolean inUnrollLoops;
2163 output FCore.Cache outCache = inCache;
2164 output list<DAE.Statement> outStatements "More statements due to loop unrolling.";
2165 protected
2166 Integer num_errors = Error.getNumErrorMessages();
2167 algorithm
2168 try
2169 outStatements := match inStatement
2170 local
2171 DAE.Exp cond_exp, msg_exp, level_exp, exp, cr_exp;
2172 DAE.Properties cond_prop, msg_prop, level_prop, prop, cr_prop;
2173 list<DAE.Statement> if_branch, else_branch, branch;
2174 list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> else_if_branches;
2175 Absyn.Exp aexp;
2176 list<SCode.Statement> sstmts;
2177 DAE.ElementSource source;
2178 SourceInfo info;
2179 Option<DAE.Statement> when_stmt_opt;
2180 DAE.Statement when_stmt;
2181 list<DAE.MatchCase> cases;
2182
2183 case SCode.ALG_ASSIGN()
2184 algorithm
2185 34597 (outCache, outStatements) := instAssignment(outCache, inEnv, inIH, inPrefix,
2186 inStatement, inSource, inInitial, inImpl, inUnrollLoops, num_errors);
2187 34539 then
2188 outStatements;
2189
2190 case SCode.ALG_IF(info = info)
2191 algorithm
2192 // Instantiate the first branch.
2193 1741 (outCache, cond_exp, cond_prop) := instExp(outCache, inEnv, inIH,
2194 inPrefix, inStatement.boolExpr, inImpl, info);
2195 1741 (outCache, if_branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2196 inState, inStatement.trueBranch, inSource, inInitial, inImpl, inUnrollLoops);
2197
2198 // Instantiate the elseif branches.
2199 else_if_branches := {};
2200
2/2
✓ Branch 0 taken 509 times.
✓ Branch 1 taken 1741 times.
2250 for else_if in inStatement.elseIfBranch loop
2201 509 (aexp, sstmts) := else_if;
2202 509 (outCache, exp, prop) := instExp(outCache, inEnv, inIH, inPrefix,
2203 aexp, inImpl, info);
2204 509 (outCache, branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2205 inState, sstmts, inSource, inInitial, inImpl, inUnrollLoops);
2206 509 else_if_branches := (exp, prop, branch) :: else_if_branches;
2207 end for;
2208 1741 else_if_branches := listReverse(else_if_branches);
2209
2210 // Instantiate the else branch.
2211 1741 (outCache, else_branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2212 inState, inStatement.elseBranch, inSource, inInitial, inImpl, inUnrollLoops);
2213
2214 // Construct the if-statement.
2215 1741 source := ElementSource.addElementSourceFileInfo(inSource, info);
2216 1741 then
2217 Algorithm.makeIf(cond_exp, cond_prop, if_branch, else_if_branches, else_branch, source);
2218
2219 case SCode.ALG_FOR()
2220 algorithm
2221 491 (outCache, outStatements) := instForStatement(outCache, inEnv, inIH,
2222 inPrefix, inState, inStatement, inSource, inInitial, inImpl, inUnrollLoops);
2223 490 then
2224 outStatements;
2225
2226 case SCode.ALG_PARFOR()
2227 algorithm
2228 ✗ (outCache, outStatements) := instParForStatement(outCache, inEnv, inIH,
2229 inPrefix, inState, inStatement, inSource, inInitial, inImpl, inUnrollLoops);
2230 ✗ then
2231 outStatements;
2232
2233 case SCode.ALG_WHILE(info = info)
2234 algorithm
2235 121 (outCache, cond_exp, cond_prop) := instExp(outCache, inEnv, inIH,
2236 inPrefix, inStatement.boolExpr, inImpl, info);
2237 121 (outCache, branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2238 inState, inStatement.whileBody, inSource, inInitial, inImpl, inUnrollLoops);
2239
2240 121 source := ElementSource.addElementSourceFileInfo(inSource, info);
2241 121 then
2242 {Algorithm.makeWhile(cond_exp, cond_prop, branch, source)};
2243
2244 case SCode.ALG_WHEN_A(info = info)
2245 algorithm
2246 // When may not be used in a function.
2247
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
115 if ClassInfUtil.isFunction(inState) then
2248 ✗ Error.addSourceMessageAndFail(Error.FUNCTION_ELEMENT_WRONG_KIND, {"when"}, info);
2249 end if;
2250
2251 115 checkWhenAlgorithm(inStatement);
2252 114 source := ElementSource.addElementSourceFileInfo(inSource, info);
2253 when_stmt_opt := NONE();
2254
2255
2/2
✓ Branch 1 taken 141 times.
✓ Branch 2 taken 114 times.
369 for b in listReverse(inStatement.branches) loop
2256 141 (aexp, sstmts) := b;
2257
2258 141 (outCache, cond_exp, cond_prop) := instExp(outCache, inEnv, inIH,
2259 inPrefix, aexp, inImpl, info);
2260 141 (outCache, branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2261 inState, sstmts, inSource, inInitial, inImpl, inUnrollLoops);
2262
2263 141 when_stmt_opt := SOME(Algorithm.makeWhenA(cond_exp, cond_prop, branch, when_stmt_opt, source));
2264 end for;
2265
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 114 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 114 times.
114 SOME(when_stmt) := when_stmt_opt;
2266 then
2267 {when_stmt};
2268
2269 case SCode.ALG_ASSERT(info = info)
2270 algorithm
2271 552 (outCache, cond_exp, cond_prop) := instExp(outCache, inEnv, inIH,
2272 inPrefix, inStatement.condition, inImpl, info);
2273 552 (outCache, msg_exp, msg_prop) := instExp(outCache, inEnv, inIH,
2274 inPrefix, inStatement.message, inImpl, info);
2275 552 (outCache, level_exp, level_prop) := instExp(outCache, inEnv, inIH,
2276 inPrefix, inStatement.level, inImpl, info);
2277
2278 552 source := ElementSource.addElementSourceFileInfo(inSource, info);
2279 552 then
2280 Algorithm.makeAssert(cond_exp, msg_exp, level_exp, cond_prop, msg_prop, level_prop, source);
2281
2282 case SCode.ALG_TERMINATE(info = info)
2283 algorithm
2284 ✗ (outCache, msg_exp, msg_prop) := instExp(outCache, inEnv, inIH,
2285 inPrefix, inStatement.message, inImpl, info);
2286 ✗ source := ElementSource.addElementSourceFileInfo(inSource, info);
2287 ✗ then
2288 Algorithm.makeTerminate(msg_exp, msg_prop, source);
2289
2290 case SCode.ALG_REINIT(info = info)
2291 algorithm
2292 21 (outCache, cr_exp, cr_prop) := instExp(outCache, inEnv, inIH, inPrefix,
2293 inStatement.cref, inImpl, info);
2294 21 (outCache, exp, prop) := instExp(outCache, inEnv, inIH, inPrefix,
2295 inStatement.newValue, inImpl, info);
2296 21 source := ElementSource.addElementSourceFileInfo(inSource, info);
2297 21 then
2298 Algorithm.makeReinit(cr_exp, exp, cr_prop, prop, source);
2299
2300 case SCode.ALG_NORETCALL(info = info)
2301 algorithm
2302 771 (outCache, exp) := Static.elabExp(outCache, inEnv, inStatement.exp,
2303 inImpl, true, inPrefix, info);
2304 762 checkValidNoRetcall(exp, info);
2305 762 (outCache, exp) := PrefixUtil.prefixExp(outCache, inEnv, inIH, exp, inPrefix);
2306 762 source := ElementSource.addElementSourceFileInfo(inSource, info);
2307
1/2
✓ Branch 1 taken 762 times.
✗ Branch 2 not taken.
762 then
2308 if Expression.isTuple(exp) then {} else {DAE.STMT_NORETCALL(exp, source)};
2309
2310 case SCode.ALG_BREAK(info = info)
2311 algorithm
2312 30 source := ElementSource.addElementSourceFileInfo(inSource, info);
2313 30 then
2314 {DAE.STMT_BREAK(source)};
2315
2316 case SCode.ALG_CONTINUE(info = info)
2317 algorithm
2318 1 source := ElementSource.addElementSourceFileInfo(inSource, info);
2319 1 then
2320 {DAE.STMT_CONTINUE(source)};
2321
2322 case SCode.ALG_RETURN(info = info)
2323 algorithm
2324
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 if not ClassInfUtil.isFunction(inState) then
2325 ✗ Error.addSourceMessageAndFail(Error.RETURN_OUTSIDE_FUNCTION, {}, info);
2326 end if;
2327 84 source := ElementSource.addElementSourceFileInfo(inSource, info);
2328 84 then
2329 {DAE.STMT_RETURN(source)};
2330
2331 case SCode.ALG_FAILURE(info = info)
2332 algorithm
2333
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 true := Config.acceptMetaModelicaGrammar();
2334 5 (outCache, branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2335 inState, inStatement.stmts, inSource, inInitial, inImpl, inUnrollLoops);
2336 5 source := ElementSource.addElementSourceFileInfo(inSource, info);
2337 5 then
2338 {DAE.STMT_FAILURE(branch, source)};
2339
2340 // try-else becomes:
2341 // matchcontinue ()
2342 // case () equation *body* then ();
2343 // else equation *elseBody* then ();
2344 // end matchcontinue;
2345 case SCode.ALG_TRY(info = info)
2346 algorithm
2347
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 true := Config.acceptMetaModelicaGrammar();
2348 12 (outCache, if_branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2349 inState, inStatement.body, inSource, inInitial, inImpl, inUnrollLoops);
2350 12 (outCache, else_branch) := instStatements(outCache, inEnv, inIH, inPrefix,
2351 inState, inStatement.elseBody, inSource, inInitial, inImpl, inUnrollLoops);
2352 12 source := ElementSource.addElementSourceFileInfo(inSource, info);
2353
2354 12 cases := {
2355 DAE.CASE({}, NONE(), {}, if_branch, SOME(DAE.TUPLE({})), info, 0, info),
2356 DAE.CASE({}, NONE(), {}, else_branch, SOME(DAE.TUPLE({})), info, 0, info)
2357 };
2358
2359
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
22 exp := DAE.MATCHEXPRESSION(if SCodeUtil.commentHasBooleanNamedAnnotation(inStatement.comment, "__OpenModelica_stackOverflowCheckpoint") then DAE.TRY_STACKOVERFLOW() else DAE.MATCHCONTINUE(), {}, {}, {}, cases,
2360 DAE.T_NORETCALL_DEFAULT);
2361 12 then
2362 {DAE.STMT_NORETCALL(exp, source)};
2363
2364 end match;
2365 else
2366
1/2
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
69 true := num_errors == Error.getNumErrorMessages();
2367 ✗ Error.addSourceMessageAndFail(Error.STATEMENT_GENERIC_FAILURE,
2368 {SCodeDump.statementStr(inStatement)}, SCodeUtil.getStatementInfo(inStatement));
2369 end try;
2370 end instStatement;
2371
2372 protected function makeAssignment
2373 "Wrapper for Algorithm that calls either makeAssignment or makeTupleAssignment
2374 depending on whether the right side is a tuple or not. This makes it possible
2375 to do cref := function_that_returns_tuple(...)."
2376 input DAE.Exp inLhs;
2377 input DAE.Properties inLhsProps;
2378 input DAE.Exp inRhs;
2379 input DAE.Properties inRhsProps;
2380 input DAE.Attributes inAttributes;
2381 input SCode.Initial inInitial;
2382 input DAE.ElementSource inSource;
2383 output DAE.Statement outStatement;
2384 algorithm
2385 outStatement := match (inLhsProps, inRhs, inRhsProps)
2386 local
2387 list<DAE.Properties> wild_props;
2388 Integer wild_count;
2389 list<DAE.Exp> wilds;
2390 DAE.Exp wildCrefExp;
2391
2392 // If the RHS is a function that returns a tuple while the LHS is a single
2393 // value, make a tuple of the LHS and fill in the missing elements with
2394 // wildcards.
2395 case (DAE.PROP(), DAE.CALL(), DAE.PROP_TUPLE())
2396 algorithm
2397
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 65 times.
65 _ :: wild_props := Types.propTuplePropList(inRhsProps);
2398 65 wild_count := listLength(wild_props);
2399 65 wildCrefExp := Expression.makeCrefExp(DAE.WILD(), DAE.T_UNKNOWN_DEFAULT);
2400 65 wilds := List.fill(wildCrefExp, wild_count);
2401 65 wild_props := List.fill(DAE.PROP(DAE.T_ANYTYPE_DEFAULT, DAE.C_VAR()), wild_count);
2402 65 then
2403 Algorithm.makeTupleAssignment(inLhs :: wilds, inLhsProps :: wild_props, inRhs, inRhsProps, inInitial, inSource);
2404
2405 // Otherwise, call Algorithm.makeAssignment as usual.
2406 32910 else Algorithm.makeAssignment(inLhs, inLhsProps, inRhs, inRhsProps, inAttributes, inInitial, inSource);
2407 end match;
2408 end makeAssignment;
2409
2410 protected function containsWhenStatements
2411 "@author: adrpo
2412 this functions returns true if the given
2413 statement list contains when statements"
2414 input list<SCode.Statement> statementList;
2415 output Boolean hasWhenStatements;
2416 algorithm
2417 hasWhenStatements := matchcontinue statementList
2418 local
2419 list<SCode.Statement> rest, tb, eb, lst;
2420 list<tuple<Absyn.Exp, list<SCode.Statement>>> eib;
2421 Boolean b, b1, b2, b3, b4; list<Boolean> blst;
2422 list<list<SCode.Statement>> slst;
2423
2424 // handle nothingness
2425 case {} then false;
2426
2427 // yeha! we have a when!
2428 case SCode.ALG_WHEN_A()::_
2429 then true;
2430
2431 // search deeper inside if
2432 case SCode.ALG_IF(trueBranch=tb, elseIfBranch=eib, elseBranch=eb)::rest
2433 algorithm
2434 165 b1 := containsWhenStatements(tb);
2435 165 b2 := containsWhenStatements(eb);
2436 165 slst := List.map(eib, Util.tuple22);
2437 165 blst := List.map(slst, containsWhenStatements);
2438 // adrpo: add false to handle the case where list might be empty
2439 165 b3 := List.reduce(false::blst, boolOr);
2440 165 b4 := containsWhenStatements(rest);
2441
5/8
✓ Branch 0 taken 165 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 165 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 165 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 164 times.
✓ Branch 7 taken 1 time.
825 b := List.reduce({b1, b2, b3, b4}, boolOr);
2442 then b;
2443
2444 // search deeper inside for
2445 case SCode.ALG_FOR(forBody = lst)::rest
2446 algorithm
2447 25 b1 := containsWhenStatements(lst);
2448 25 b2 := containsWhenStatements(rest);
2449 25 b := boolOr(b1, b2);
2450 then b;
2451
2452 // search deeper inside parfor
2453 case SCode.ALG_PARFOR(parforBody = lst)::rest
2454 algorithm
2455 ✗ b1 := containsWhenStatements(lst);
2456 ✗ b2 := containsWhenStatements(rest);
2457 ✗ b := boolOr(b1, b2);
2458 then b;
2459
2460 // search deeper inside for
2461 case SCode.ALG_WHILE(whileBody = lst)::rest
2462 algorithm
2463 4 b1 := containsWhenStatements(lst);
2464 4 b2 := containsWhenStatements(rest);
2465 4 b := boolOr(b1, b2);
2466 then b;
2467
2468 // not a when, move along
2469 case _::rest
2470 1227 then containsWhenStatements(rest);
2471 end matchcontinue;
2472 end containsWhenStatements;
2473
2474 protected function loopOverRange
2475 "@author: adrpo
2476 Unrolling a for loop is explicitly repeating
2477 the body of the loop once for each iteration."
2478 input FCore.Cache inCache;
2479 input FCore.Graph inEnv;
2480 input InnerOuter.InstHierarchy inIH;
2481 input DAE.Prefix inPrefix;
2482 input ClassInf.State ci_state;
2483 input Ident inIdent;
2484 input Values.Value inValue;
2485 input list<SCode.Statement> inAlgItmLst;
2486 input DAE.ElementSource source;
2487 input SCode.Initial inInitial;
2488 input Boolean inImpl;
2489 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
2490 output FCore.Cache outCache;
2491 output list<DAE.Statement> outStatements "for statements can produce more statements than one by unrolling";
2492 algorithm
2493 (outCache,outStatements) :=
2494 matchcontinue (inCache, inEnv, inIH, inPrefix, inIdent, inValue, inAlgItmLst, inInitial, inImpl)
2495 local
2496 FCore.Graph env_1,env_2,env;
2497 DAE.Prefix pre;
2498 String i;
2499 Values.Value fst,v;
2500 list<Values.Value> rest;
2501 list<SCode.Statement> algs;
2502 SCode.Initial initial_;
2503 Boolean impl;
2504 FCore.Cache cache;
2505 list<Integer> dims;
2506 Integer dim;
2507 list<DAE.Statement> stmts, stmts1, stmts2;
2508 InstanceHierarchy ih;
2509
2510 // handle empty
2511 case (cache, _, _, _, _, Values.ARRAY(valueLst = {}), _, _, _)
2512 then (cache,{});
2513
2514 // array equation, use instAlgorithms
2515 case (cache, env, ih, pre, i, Values.ARRAY(valueLst = (fst :: rest), dimLst = dim :: dims), algs, initial_, impl)
2516 algorithm
2517 5 dim := dim-1;
2518 dims := dim::dims;
2519 5 env_1 := FGraph.openScope(env, SCode.NOT_ENCAPSULATED(), FCore.forScopeName,NONE());
2520 // the iterator is not constant but the range is constant
2521 5 env_2 := FGraph.addForIterator(env_1, i, DAE.T_INTEGER_DEFAULT, DAE.VALBOUND(fst, DAE.BINDING_FROM_DEFAULT_VALUE()), SCode.CONST(), SOME(DAE.C_CONST()));
2522 /* use instEquation*/
2523 5 (cache,stmts1) := instStatements(cache, env_2, ih, pre, ci_state, algs, source, initial_, impl, unrollForLoops);
2524 5 (cache,stmts2) := loopOverRange(cache, env, ih, pre, ci_state, i, Values.ARRAY(rest,dims), algs, source, initial_, impl, unrollForLoops);
2525 5 stmts := listAppend(stmts1, stmts2);
2526 then
2527 (cache,stmts);
2528
2529 case (_, _, _, _, _, v, _, _, _)
2530 algorithm
2531 ✗ true := Flags.isSet(Flags.FAILTRACE);
2532 ✗ Debug.traceln("- InstSection.loopOverRange failed to loop over range: " + ValuesDump.valString(v));
2533 ✗ then
2534 fail();
2535 end matchcontinue;
2536 end loopOverRange;
2537
2538 protected function rangeExpression "
2539 The function takes a tuple of Absyn.ComponentRef (an array variable) and an integer i
2540 and constructs the range expression (Absyn.Exp) for the ith dimension of the variable"
2541 input tuple<Absyn.ComponentRef, Integer> inTuple;
2542 output Absyn.Exp outExp;
2543 algorithm
2544 outExp := match inTuple
2545 local
2546 Absyn.Exp e;
2547 Absyn.ComponentRef acref;
2548 Integer dimNum;
2549
2550 case (acref,dimNum)
2551 algorithm
2552 ✗ e:=Absyn.RANGE(Absyn.INTEGER(1),NONE(),Absyn.CALL(Absyn.CREF_IDENT("size",{}),Absyn.FUNCTIONARGS({Absyn.CREF(acref),Absyn.INTEGER(dimNum)},{}),{}));
2553 then e;
2554 end match;
2555 end rangeExpression;
2556
2557 protected function instIfEqBranch
2558 input FCore.Cache inCache;
2559 input FCore.Graph inEnv;
2560 input InnerOuter.InstHierarchy inIH;
2561 input DAE.Prefix inPrefix;
2562 input ClassInf.State inState;
2563 input list<SCode.Equation> inEquations;
2564 input Boolean inImpl;
2565 output FCore.Cache outCache;
2566 output FCore.Graph outEnv;
2567 output InnerOuter.InstHierarchy outIH;
2568 output ClassInf.State outState;
2569 output list<DAE.Element> outEquations;
2570 algorithm
2571 960 checkForConnectInIfBranch(inEquations);
2572
1/2
✓ Branch 1 taken 960 times.
✗ Branch 2 not taken.
960 (outCache, outEnv, outIH, DAE.DAE(outEquations), _, outState, _) :=
2573 Inst.instList(inCache, inEnv, inIH, inPrefix, Connect.emptySet, inState,
2574 instEquation, inEquations, inImpl, alwaysUnroll, ConnectionGraph.EMPTY);
2575 end instIfEqBranch;
2576
2577 protected function instIfEqBranches
2578 input FCore.Cache inCache;
2579 input FCore.Graph inEnv;
2580 input InnerOuter.InstHierarchy inIH;
2581 input DAE.Prefix inPrefix;
2582 input ClassInf.State inState;
2583 input list<list<SCode.Equation>> inBranches;
2584 input Boolean inImpl;
2585 input list<list<DAE.Element>> inAccumEqs = {};
2586 output FCore.Cache outCache;
2587 output FCore.Graph outEnv;
2588 output InnerOuter.InstHierarchy outIH;
2589 output ClassInf.State outState;
2590 output list<list<DAE.Element>> outEquations;
2591 algorithm
2592 (outCache, outEnv, outIH, outState, outEquations) :=
2593 match(inCache, inEnv, inIH, inState, inBranches)
2594 local
2595 FCore.Cache cache;
2596 FCore.Graph env;
2597 InnerOuter.InstHierarchy ih;
2598 ClassInf.State state;
2599 list<SCode.Equation> seq;
2600 list<list<SCode.Equation>> rest_seq;
2601 list<DAE.Element> deq;
2602 list<list<DAE.Element>> branches;
2603
2604 case (cache, env, ih, state, seq :: rest_seq)
2605 algorithm
2606 563 (cache, env, ih, state, deq) :=
2607 instIfEqBranch(cache, env, ih, inPrefix, state, seq, inImpl);
2608 563 (cache, env, ih, state, branches) :=
2609 instIfEqBranches(cache, env, ih, inPrefix, state, rest_seq, inImpl, deq :: inAccumEqs);
2610 then
2611 (cache, env, ih, state, branches);
2612
2613 case (_, _, _, _, {})
2614 397 then (inCache, inEnv, inIH, inState, listReverse(inAccumEqs));
2615
2616 end match;
2617 end instIfEqBranches;
2618
2619 protected function instInitialIfEqBranch
2620 input FCore.Cache inCache;
2621 input FCore.Graph inEnv;
2622 input InnerOuter.InstHierarchy inIH;
2623 input DAE.Prefix inPrefix;
2624 input ClassInf.State inState;
2625 input list<SCode.Equation> inEquations;
2626 input Boolean inImpl;
2627 output FCore.Cache outCache;
2628 output FCore.Graph outEnv;
2629 output InnerOuter.InstHierarchy outIH;
2630 output ClassInf.State outState;
2631 output list<DAE.Element> outEquations;
2632 algorithm
2633 15 checkForConnectInIfBranch(inEquations);
2634
1/2
✓ Branch 1 taken 15 times.
✗ Branch 2 not taken.
15 (outCache, outEnv, outIH, DAE.DAE(outEquations), _, outState, _) :=
2635 Inst.instList(inCache, inEnv, inIH, inPrefix, Connect.emptySet, inState,
2636 instInitialEquation, inEquations, inImpl, alwaysUnroll, ConnectionGraph.EMPTY);
2637 end instInitialIfEqBranch;
2638
2639 protected function instInitialIfEqBranches
2640 input FCore.Cache inCache;
2641 input FCore.Graph inEnv;
2642 input InnerOuter.InstHierarchy inIH;
2643 input DAE.Prefix inPrefix;
2644 input ClassInf.State inState;
2645 input list<list<SCode.Equation>> inBranches;
2646 input Boolean inImpl;
2647 input list<list<DAE.Element>> inAccumEqs = {};
2648 output FCore.Cache outCache;
2649 output FCore.Graph outEnv;
2650 output InnerOuter.InstHierarchy outIH;
2651 output ClassInf.State outState;
2652 output list<list<DAE.Element>> outEquations;
2653 algorithm
2654 (outCache, outEnv, outIH, outState, outEquations) :=
2655 match(inCache, inEnv, inIH, inState, inBranches)
2656 local
2657 FCore.Cache cache;
2658 FCore.Graph env;
2659 InnerOuter.InstHierarchy ih;
2660 ClassInf.State state;
2661 list<SCode.Equation> seq;
2662 list<list<SCode.Equation>> rest_seq;
2663 list<DAE.Element> deq;
2664 list<list<DAE.Element>> branches;
2665
2666 case (cache, env, ih, state, seq :: rest_seq)
2667 algorithm
2668 8 (cache, env, ih, state, deq) :=
2669 instInitialIfEqBranch(cache, env, ih, inPrefix, state, seq, inImpl);
2670 8 (cache, env, ih, state, branches) :=
2671 instInitialIfEqBranches(cache, env, ih, inPrefix, state, rest_seq, inImpl, deq :: inAccumEqs);
2672 then
2673 (cache, env, ih, state, branches);
2674
2675 case (_, _, _, _, {})
2676 7 then (inCache, inEnv, inIH, inState, listReverse(inAccumEqs));
2677
2678 end match;
2679 end instInitialIfEqBranches;
2680
2681 protected function checkForConnectInIfBranch
2682 "Checks if an if-branch (a list of equations) contains any connects, and prints
2683 an error if it does. This is used to check that there are no connects in
2684 if-equations with non-parameter conditions."
2685 input list<SCode.Equation> inEquations;
2686 algorithm
2687 976 List.map_0(inEquations, checkForConnectInIfBranch2);
2688 end checkForConnectInIfBranch;
2689
2690 protected function checkForConnectInIfBranch2
2691 input SCode.Equation inEquation;
2692 algorithm
2693 () := match inEquation
2694 local
2695 Absyn.ComponentRef cr1, cr2;
2696 SourceInfo info;
2697 list<SCode.Equation> eqs;
2698 String cr1_str, cr2_str;
2699
2700 case SCode.EQ_CONNECT(crefLeft = cr1, crefRight = cr2, info = info)
2701 algorithm
2702 ✗ Error.addSourceMessage(Error.IN_NON_EVALUABLE_IF_OR_FOR, {"connect"}, info);
2703 ✗ then
2704 fail();
2705
2706 case SCode.EQ_FOR(eEquationLst = eqs)
2707 algorithm
2708 1 checkForConnectInIfBranch(eqs);
2709 then
2710 ();
2711
2712 // No need to recurse into if- or when-equations, they will be checked anyway.
2713 else ();
2714 end match;
2715 end checkForConnectInIfBranch2;
2716
2717 protected function instElseIfs
2718 "This function helps instStatement to handle elseif parts."
2719 input FCore.Cache inCache;
2720 input FCore.Graph inEnv;
2721 input InnerOuter.InstHierarchy inIH;
2722 input DAE.Prefix inPre;
2723 input ClassInf.State ci_state;
2724 input list<tuple<Absyn.Exp, list<SCode.Statement>>> inElseIfBranches;
2725 input DAE.ElementSource source;
2726 input SCode.Initial initial_;
2727 input Boolean inImpl;
2728 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
2729 input SourceInfo info;
2730 output FCore.Cache outCache;
2731 output list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> outElseIfBranches;
2732 algorithm
2733 (outCache,outElseIfBranches) :=
2734 matchcontinue (inCache, inEnv, inIH, inPre, inElseIfBranches, inImpl)
2735 local
2736 FCore.Graph env;
2737 Boolean impl;
2738 DAE.Exp e_1,e_2;
2739 DAE.Properties prop;
2740 list<DAE.Statement> stmts;
2741 list<tuple<DAE.Exp, DAE.Properties, list<DAE.Statement>>> tail_1;
2742 Absyn.Exp e;
2743 list<SCode.Statement> l;
2744 list<tuple<Absyn.Exp, list<SCode.Statement>>> tail;
2745 FCore.Cache cache;
2746 DAE.Prefix pre;
2747 InstanceHierarchy ih;
2748
2749 case (cache, _, _, _, {}, _) then (cache,{});
2750
2751 case (cache, env, ih, pre, ((e,l) :: tail), impl)
2752 algorithm
2753 ✗ (cache,e_1,prop) := Static.elabExp(cache, env, e, impl, true,pre,info);
2754 ✗ (cache, e_1, prop) := Ceval.cevalIfConstant(cache, env, e_1, prop, impl, info);
2755 ✗ (cache,e_2) := PrefixUtil.prefixExp(cache, env, ih, e_1, pre);
2756 ✗ (cache,stmts) := instStatements(cache, env, ih, pre, ci_state, l, source, initial_, impl, unrollForLoops);
2757 ✗ (cache,tail_1) := instElseIfs(cache,env,ih,pre,ci_state,tail, source, initial_, impl, unrollForLoops,info);
2758 ✗ then
2759 (cache,(e_2,prop,stmts) :: tail_1);
2760
2761 else
2762 algorithm
2763 ✗ true := Flags.isSet(Flags.FAILTRACE);
2764 ✗ Debug.trace("- InstSection.instElseIfs failed\n");
2765 ✗ then
2766 fail();
2767 end matchcontinue;
2768 end instElseIfs;
2769
2770 protected function instWhenEqBranch
2771 input FCore.Cache inCache;
2772 input FCore.Graph inEnv;
2773 input InnerOuter.InstHierarchy inIH;
2774 input DAE.Prefix inPrefix;
2775 input Connect.Sets inSets;
2776 input ClassInf.State inState;
2777 input tuple<Absyn.Exp, list<SCode.Equation>> inBranch;
2778 input Boolean inImpl;
2779 input Boolean inUnrollLoops;
2780 input ConnectionGraph.ConnectionGraph inGraph;
2781 input SourceInfo info;
2782 output FCore.Cache outCache = inCache;
2783 output FCore.Graph outEnv;
2784 output InnerOuter.InstHierarchy outIH;
2785 output DAE.Exp outCondition;
2786 output list<DAE.Element> outEquations;
2787 output ConnectionGraph.ConnectionGraph outGraph;
2788 protected
2789 Absyn.Exp cond;
2790 list<SCode.Equation> body;
2791 DAE.Properties prop;
2792 list<Absyn.Exp> aexps;
2793 list<DAE.Exp> dexps;
2794 DAE.Exp dexp;
2795 DAE.Type ty;
2796 Boolean isClock;
2797 algorithm
2798 142 (cond, body) := inBranch;
2799
2800 isClock := false;
2801 outCondition := match cond
2802 case Absyn.ARRAY(arrayExp=aexps)
2803 algorithm
2804 dexps := {};
2805
2/2
✓ Branch 0 taken 28 times.
✓ Branch 1 taken 13 times.
41 for aexp in aexps loop
2806 28 (outCache, dexp, prop) := instExp(inCache, inEnv, inIH, inPrefix, aexp, inImpl, info);
2807 28 ty := Types.getPropType(prop);
2808 28 dexp := checkWhenCondition(dexp, ty, aexp, info);
2809 dexps := dexp::dexps;
2810 end for;
2811 13 then Expression.makeArray(listReverse(dexps), DAE.T_BOOL_DEFAULT, true);
2812 else
2813 algorithm
2814 129 (outCache, dexp, prop) := instExp(inCache, inEnv, inIH, inPrefix, cond, inImpl, info);
2815 128 ty := Types.getPropType(prop);
2816
2/2
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 23 times.
128 if Types.isClockOrSubTypeClock(ty) then
2817 isClock := true;
2818 else
2819 105 dexp := checkWhenCondition(dexp, ty, cond, info);
2820 end if;
2821 128 then dexp;
2822 end match;
2823
2824
2/2
✓ Branch 0 taken 118 times.
✓ Branch 1 taken 23 times.
141 if not isClock then
2825 118 List.map_0(body, checkForNestedWhenInEq);
2826 end if;
2827
2828 // Instantiate the when body.
2829
1/2
✓ Branch 1 taken 139 times.
✗ Branch 2 not taken.
140 (outCache, outEnv, outIH, DAE.DAE(outEquations), _, _, outGraph) :=
2830 Inst.instList(outCache, inEnv, inIH, inPrefix, inSets, inState,
2831 instEquation, body, inImpl, alwaysUnroll, inGraph);
2832 end instWhenEqBranch;
2833
2834 protected function checkWhenCondition
2835 input output DAE.Exp exp;
2836 input DAE.Type ty;
2837 input Absyn.Exp aexp;
2838 input SourceInfo info;
2839 protected
2840 DAE.Type tyEl;
2841 algorithm
2842 try
2843
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 132 times.
133 if Types.isArray(ty) then
2844 1 tyEl := Types.arrayElementType(ty);
2845 else
2846 tyEl := ty;
2847 end if;
2848 133 exp := Types.matchType(exp, tyEl, DAE.T_BOOL_DEFAULT);
2849 else
2850 ✗ Error.addSourceMessage(Error.IF_CONDITION_TYPE_ERROR,{Dump.printExpStr(aexp),TypesDump.unparseType(ty)},info);
2851 ✗ fail();
2852 end try;
2853
2/2
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 2 times.
133 if Config.languageStandardAtLeast(Config.LanguageStandard._3_2) then
2854 () := match exp
2855 case DAE.CALL(path=Absyn.IDENT("initial")) then ();
2856 case DAE.CALL(path=Absyn.FULLYQUALIFIED(Absyn.IDENT("initial"))) then ();
2857 else
2858 algorithm
2859
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 125 times.
126 if Expression.expHasInitial(exp) then
2860 2 Error.addSourceMessage(Error.INITIAL_CALL_WARNING,{Dump.printExpStr(aexp)},info);
2861 end if;
2862 then ();
2863 end match;
2864 end if;
2865 end checkWhenCondition;
2866
2867 protected function instConnect "
2868 Generates connectionsets for connections.
2869 Parameters and constants in connectors should generate appropriate assert statements.
2870 Hence, a DAE.Element list is returned as well."
2871 input FCore.Cache inCache;
2872 input FCore.Graph inEnv;
2873 input InnerOuter.InstHierarchy inIH;
2874 input Connect.Sets inSets;
2875 input DAE.Prefix inPrefix;
2876 input Absyn.ComponentRef inComponentRefLeft;
2877 input Absyn.ComponentRef inComponentRefRight;
2878 input Boolean inImplicit;
2879 input ConnectionGraph.ConnectionGraph inGraph;
2880 input SourceInfo info;
2881 output FCore.Cache outCache;
2882 output FCore.Graph outEnv;
2883 output InnerOuter.InstHierarchy outIH;
2884 output Connect.Sets outSets;
2885 output DAE.DAElist outDae;
2886 output ConnectionGraph.ConnectionGraph outGraph;
2887 algorithm
2888 (outCache,outEnv,outIH,outSets,outDae,outGraph):=
2889 matchcontinue (inCache,inEnv,inIH,inSets,inPrefix,inComponentRefLeft,inComponentRefRight,inImplicit,inGraph)
2890 local
2891 DAE.ComponentRef c1_2,c2_2;
2892 DAE.Attributes attr1,attr2;
2893 DAE.ConnectorType ct1;
2894 Boolean impl;
2895 DAE.Type ty1,ty2;
2896 Connect.Face f1,f2;
2897 Connect.Sets sets;
2898 DAE.DAElist dae;
2899 FCore.Graph env;
2900 DAE.Prefix pre;
2901 Absyn.ComponentRef c1,c2;
2902 FCore.Cache cache;
2903 Absyn.InnerOuter io1,io2;
2904 SCode.Variability vt1,vt2;
2905 ConnectionGraph.ConnectionGraph graph;
2906 InstanceHierarchy ih;
2907 list<Absyn.Subscript> subs1,subs2;
2908 list<Absyn.ComponentRef> crefs1,crefs2;
2909 String s1,s2;
2910 Boolean del1, del2;
2911
2912 // adrpo: check for connect(A, A) as we should give a warning and remove it!
2913 case (cache,env,ih,sets,_,c1,c2,_,graph)
2914 algorithm
2915
2/2
✓ Branch 1 taken 11031 times.
✓ Branch 2 taken 1 time.
11032 true := AbsynUtil.crefEqual(c1, c2);
2916 1 s1 := Dump.printComponentRefStr(c1);
2917 1 s2 := Dump.printComponentRefStr(c1);
2918 1 Error.addSourceMessage(Error.SAME_CONNECT_INSTANCE, {s1, s2}, info);
2919 1 then
2920 (cache, env, ih, sets, DAE.emptyDae, graph);
2921
2922 // handle normal connectors!
2923 case (cache,env,ih,sets,pre,c1,c2,impl,graph)
2924 algorithm
2925 11031 (cache, c1_2, attr1, ct1, vt1, io1, f1, ty1, del1) :=
2926 instConnector(cache, env, ih, c1, impl, pre, info);
2927 11031 (cache, c2_2, attr2, _, vt2, io2, f2, ty2, del2) :=
2928 instConnector(cache, env, ih, c2, impl, pre, info);
2929
2930
4/4
✓ Branch 0 taken 10878 times.
✓ Branch 1 taken 153 times.
✓ Branch 2 taken 48 times.
✓ Branch 3 taken 10830 times.
11031 if del1 or del2 then
2931 // If either connector is a deleted conditional component, discard the connection.
2932 201 dae := DAE.emptyDae;
2933 elseif Types.isExpandableConnector(ty1) or Types.isExpandableConnector(ty2) then
2934 // If either connector is expandable, fail and use the next case.
2935 1875 fail();
2936 else
2937 // Otherwise it's a normal connection.
2938 8955 checkConnectTypes(c1_2, ty1, f1, attr1, c2_2, ty2, f2, attr2, info);
2939 8955 (cache, _, ih, sets, dae, graph) :=
2940 connectComponents(cache, env, ih, sets, pre, c1_2, f1, ty1, vt1, c2_2, f2, ty2, vt2, ct1, io1, io2, graph, info);
2941 8953 sets := ConnectUtil.increaseConnectRefCount(c1_2, c2_2, sets);
2942 end if;
2943 9154 then
2944 (cache,env,ih,sets,dae,graph);
2945
2946 // adrpo: handle expandable connectors!
2947 case (cache,env,ih,sets,pre,c1,c2,impl,graph)
2948 algorithm
2949 1877 ErrorExt.setCheckpoint("expandableConnectors");
2950
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1875 times.
1877 true := System.getHasExpandableConnectors();
2951 1875 (cache,env,ih,sets,dae,graph) := connectExpandableConnectors(cache, env, ih, sets, pre, c1, c2, impl, graph, info);
2952 1875 ErrorExt.rollBack("expandableConnectors");
2953 1875 then
2954 (cache,env,ih,sets,dae,graph);
2955
2956 // Case to display error for non constant subscripts in connectors
2957 case (cache,env,_,_,pre,c1,c2,_,_)
2958 algorithm
2959 2 ErrorExt.rollBack("expandableConnectors");
2960 2 subs1 := AbsynUtil.getSubsFromCref(c1,true,true);
2961 2 crefs1 := AbsynUtil.getCrefsFromSubs(subs1,true,true);
2962 2 subs2 := AbsynUtil.getSubsFromCref(c2,true,true);
2963 2 crefs2 := AbsynUtil.getCrefsFromSubs(subs2,true,true);
2964 //print("Crefs in " + Dump.printComponentRefStr(c1) + ": " + stringDelimitList(List.map(crefs1,Dump.printComponentRefStr),", ") + "\n");
2965 //print("Crefs in " + Dump.printComponentRefStr(c2) + ": " + stringDelimitList(List.map(crefs2,Dump.printComponentRefStr),", ") + "\n");
2966 2 s1 := Dump.printComponentRefStr(c1);
2967 2 s2 := Dump.printComponentRefStr(c2);
2968 2 s1 := "connect("+s1+", "+s2+")";
2969 2 checkConstantVariability(crefs1,cache,env,s1,pre,info);
2970 2 checkConstantVariability(crefs2,cache,env,s1,pre,info);
2971 2 then
2972 fail();
2973
2974 // Failed in graphics mode; just continue
2975 case (cache,env,ih,sets,_,_,_,_,graph) guard Config.getGraphicsExpMode()
2976 ✗ then (cache,env,ih,sets,DAE.emptyDae,graph);
2977
2978 case (_,_,_,_,_,c1,c2,_,_)
2979 algorithm
2980
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
2981 ✗ Debug.traceln("- InstSection.instConnect failed for: connect(" +
2982 Dump.printComponentRefStr(c1) + ", " +
2983 Dump.printComponentRefStr(c2) + ")");
2984 ✗ then
2985 fail();
2986 end matchcontinue;
2987 end instConnect;
2988
2989 protected function instConnector
2990 input FCore.Cache inCache;
2991 input FCore.Graph env;
2992 input InnerOuter.InstHierarchy ih;
2993 input Absyn.ComponentRef connectorCref;
2994 input Boolean impl;
2995 input DAE.Prefix prefix;
2996 input SourceInfo info;
2997 output FCore.Cache outCache = inCache;
2998 output DAE.ComponentRef outCref;
2999 output DAE.Attributes outAttr;
3000 output DAE.ConnectorType connectorType;
3001 output SCode.Variability variability;
3002 output Absyn.InnerOuter innerOuter;
3003 output Connect.Face face;
3004 output DAE.Type ty;
3005 output Boolean deleted;
3006 protected
3007 FCore.Status status;
3008 Boolean is_expandable;
3009 algorithm
3010 22062 outCref := ComponentReference.toExpCref(connectorCref);
3011 22062 (DAE.ATTR(connectorType = connectorType, variability = variability,
3012 innerOuter = innerOuter), ty, status, is_expandable) :=
3013 Lookup.lookupConnectorVar(env, outCref);
3014
3015 22062 deleted := FCore.isDeletedComp(status);
3016
3017
2/2
✓ Branch 0 taken 20168 times.
✓ Branch 1 taken 1894 times.
22062 if deleted or is_expandable then
3018 face := Connect.NO_FACE();
3019 outAttr := DAE.dummyAttrVar;
3020 else
3021
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 20168 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 20168 times.
20168 (outCache, DAE.CREF(componentRef = outCref), DAE.PROP(type_ = ty), outAttr) :=
3022 Static.elabCrefNoEval(inCache, env, connectorCref, impl, false, prefix, info);
3023 20168 (outCache, outCref) := Static.canonCref(outCache, env, outCref, impl);
3024 20168 validConnector(ty, outCref, info);
3025 20168 face := ConnectUtil.componentFace(env, outCref);
3026 20168 ty := sortConnectorType(ty);
3027 end if;
3028 end instConnector;
3029
3030 protected function sortConnectorType
3031 input DAE.Type inType;
3032 output DAE.Type outType;
3033 algorithm
3034 outType := match inType
3035 local
3036 DAE.Type ty;
3037 DAE.Dimensions dims;
3038 ClassInf.State ci_state;
3039 list<DAE.Var> vars;
3040 DAE.EqualityConstraint ec;
3041
3042 case DAE.T_ARRAY(ty, dims)
3043 algorithm
3044 242 ty := sortConnectorType(ty);
3045 242 then
3046 DAE.T_ARRAY(ty, dims);
3047
3048 case DAE.T_COMPLEX(ci_state, vars, ec)
3049 algorithm
3050 5529 vars := List.sort(vars, connectorCompGt);
3051 5529 then
3052 DAE.T_COMPLEX(ci_state, vars, ec, inType.usedExternally);
3053
3054 else inType;
3055
3056 end match;
3057 end sortConnectorType;
3058
3059 protected function connectorCompGt
3060 input DAE.Var inVar1;
3061 input DAE.Var inVar2;
3062 output Boolean outGt;
3063 protected
3064 DAE.Ident id1, id2;
3065 algorithm
3066 17982 DAE.TYPES_VAR(name = id1) := inVar1;
3067 17982 DAE.TYPES_VAR(name = id2) := inVar2;
3068 17982 outGt := (1 == stringCompare(id1, id2));
3069 end connectorCompGt;
3070
3071 protected function checkConstantVariability "
3072 Author BZ, 2009-09
3073 Helper function for instConnect, prints error message for the case with non constant(or parameter) subscript(/s)"
3074 input list<Absyn.ComponentRef> inrefs;
3075 input FCore.Cache cache;
3076 input FCore.Graph env;
3077 input String affectedConnector;
3078 input DAE.Prefix inPrefix;
3079 input SourceInfo info;
3080 algorithm
3081 () := matchcontinue(inrefs, inPrefix)
3082 local
3083 Absyn.ComponentRef cr;
3084 DAE.Properties prop;
3085 DAE.Const const;
3086 DAE.Prefix pre;
3087 String s1;
3088 list<Absyn.ComponentRef> refs;
3089
3090 case({}, _) then ();
3091 case(cr::refs, pre)
3092 algorithm
3093 ✗ (_,SOME((_,prop,_))) := Static.elabCref(cache,env,cr,false,false,pre,info);
3094 ✗ const := Types.propertiesListToConst({prop});
3095 ✗ true := Types.isParameterOrConstant(const);
3096 ✗ checkConstantVariability(refs,cache,env,affectedConnector,pre,info);
3097 then
3098 ();
3099 case(cr::_, pre)
3100 algorithm
3101 ✗ (_,SOME((_,prop,_))) := Static.elabCref(cache,env,cr,false,false,pre,info);
3102 ✗ const := Types.propertiesListToConst({prop});
3103 ✗ false := Types.isParameterOrConstant(const);
3104 //print(" error for: " + affectedConnector + " subscript: " + Dump.printComponentRefStr(cr) + " non constant \n");
3105 ✗ s1 := Dump.printComponentRefStr(cr);
3106 ✗ Error.addSourceMessage(Error.CONNECTOR_ARRAY_NONCONSTANT, {affectedConnector,s1}, info);
3107 then
3108 ();
3109 end matchcontinue;
3110 end checkConstantVariability;
3111
3112 protected function connectExpandableConnectors
3113 "@author: adrpo
3114 this function handle the connections of expandable connectors"
3115 input FCore.Cache inCache;
3116 input FCore.Graph inEnv;
3117 input InnerOuter.InstHierarchy inIH;
3118 input Connect.Sets inSets;
3119 input DAE.Prefix inPrefix;
3120 input Absyn.ComponentRef inComponentRefLeft;
3121 input Absyn.ComponentRef inComponentRefRight;
3122 input Boolean inImpl;
3123 input ConnectionGraph.ConnectionGraph inGraph;
3124 input SourceInfo info;
3125 output FCore.Cache outCache;
3126 output FCore.Graph outEnv;
3127 output InnerOuter.InstHierarchy outIH;
3128 output Connect.Sets outSets;
3129 output DAE.DAElist outDae;
3130 output ConnectionGraph.ConnectionGraph outGraph;
3131 algorithm
3132 (outCache,outEnv,outIH,outSets,outDae,outGraph) :=
3133 matchcontinue (inCache, inEnv, inIH, inSets, inPrefix, inComponentRefLeft, inComponentRefRight, inImpl, inGraph)
3134 local
3135 DAE.ComponentRef c1_1,c2_1,c1_2,c2_2, c1p,c2p;
3136 DAE.Attributes attr1,attr2,attr;
3137 DAE.ConnectorType ct1, ct2;
3138 Boolean impl;
3139 DAE.Type ty1,ty2,ty;
3140 Connect.Sets sets;
3141 DAE.DAElist dae, daeExpandable;
3142 FCore.Graph env, envExpandable, envComponent, env1, env2, envComponentEmpty;
3143 DAE.Prefix pre;
3144 Absyn.ComponentRef c1,c2,c1_prefix;
3145 FCore.Cache cache;
3146 Absyn.InnerOuter io1,io2;
3147 SCode.Variability vt1,vt2;
3148 SCode.Parallelism prl1,prl2;
3149 ConnectionGraph.ConnectionGraph graph;
3150 InstanceHierarchy ih;
3151 String componentName;
3152 DAE.Binding binding;
3153 Option<DAE.Const> cnstForRange;
3154 ClassInf.State state;
3155 list<String> variables1, variables2, variablesUnion;
3156 DAE.ElementSource source;
3157 SCode.Visibility vis1, vis2;
3158 Absyn.ArrayDim arrDims;
3159 DAE.Dimensions daeDims;
3160
3161 // both c1 and c2 are expandable
3162 case (cache, env, ih, sets, pre, c1, c2, impl, graph)
3163 algorithm
3164
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 2685 times.
✓ Branch 3 taken 1692 times.
✓ Branch 4 taken 993 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 993 times.
3495 (cache,SOME((DAE.CREF(c1_1,_),_,attr1))) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3165
4/6
✗ Branch 1 not taken.
✓ Branch 2 taken 993 times.
✓ Branch 3 taken 810 times.
✓ Branch 4 taken 183 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 183 times.
993 (cache,SOME((DAE.CREF(c2_1,_),_,attr2))) := Static.elabCref(cache, env, c2, impl, false, pre, info);
3166 183 (cache,c1_2) := Static.canonCref(cache, env, c1_1, impl);
3167 183 (cache,c2_2) := Static.canonCref(cache, env, c2_1, impl);
3168 183 (attr1,ty1) := Lookup.lookupConnectorVar(env,c1_2);
3169 183 (attr2,ty2) := Lookup.lookupConnectorVar(env,c2_2);
3170
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 183 times.
183 DAE.ATTR(connectorType = DAE.POTENTIAL()) := attr1;
3171
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 183 times.
183 DAE.ATTR(connectorType = DAE.POTENTIAL()) := attr2;
3172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 true := Types.isExpandableConnector(ty1);
3173
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 183 times.
183 true := Types.isExpandableConnector(ty2);
3174
3175 // do the union of the connectors by adding the missing
3176 // components from one to the other and vice-versa.
3177 // fprintln(Flags.SHOW_EXPANDABLE_INFO, ">>>> connect(expandable, expandable)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")" );
3178
3179 // get the environments of the expandable connectors
3180 // which contain all the virtual components.
3181 183 (_,_,_,_,_,_,_,env1,_) := Lookup.lookupVar(cache, env, c1_2);
3182 183 (_,_,_,_,_,_,_,env2,_) := Lookup.lookupVar(cache, env, c2_2);
3183
3184 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "1 connect(expandable, expandable)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")" );
3185
3186 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env ===>\n" + FGraph.printGraphStr(env));
3187 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env(c1) ===>\n" + FGraph.printGraphStr(env1));
3188 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env(c2) ===>\n" + FGraph.printGraphStr(env2));
3189
3190 // get the virtual components
3191 183 variables1 := FGraph.getVariablesFromGraphScope(env1);
3192 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "Variables1: " + stringDelimitList(variables1, ", "));
3193 183 variables2 := FGraph.getVariablesFromGraphScope(env2);
3194 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "Variables2: " + stringDelimitList(variables2, ", "));
3195 183 variablesUnion := List.union(variables1, variables2);
3196 // sort so we have them in order
3197 183 variablesUnion := List.sort(variablesUnion, Util.strcmpBool);
3198 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "Union of expandable connector variables: " + stringDelimitList(variablesUnion, ", "));
3199
3200 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "2 connect(expandable, expandable)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3201
3202 // then connect each of the components normally.
3203 183 (cache,env,ih,sets,dae,graph) := connectExpandableVariables(cache,env,ih,sets,pre,c1,c2,variablesUnion,impl,graph,info);
3204
3205 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "<<<< connect(expandable, expandable)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3206
3207 then
3208 (cache,env,ih,sets,dae,graph);
3209
3210 // c2 is expandable, forward to c1 expandable by switching arguments.
3211 case (cache, env, ih, sets, pre, c1, c2, impl, graph)
3212 algorithm
3213 // c2 is expandable
3214
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2502 times.
✓ Branch 3 taken 810 times.
✓ Branch 4 taken 1692 times.
2502 (cache,NONE()) := Static.elabCref(cache, env, c2, impl, false, pre, info);
3215
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 810 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 810 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 810 times.
810 (cache,SOME((DAE.CREF(_,_),_,_))) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3216 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "connect(existing, expandable)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3217 810 (cache,env,ih,sets,dae,graph) := connectExpandableConnectors(cache,env,ih,sets,pre,c2,c1,impl,graph,info);
3218 then
3219 (cache,env,ih,sets,dae,graph);
3220
3221 // c1 is expandable, catch error that c1 is an IDENT! it should be at least a.x
3222 case (cache, env, _, _, pre, c1 as Absyn.CREF_IDENT(), c2, impl, _)
3223 algorithm
3224 // c1 is expandable
3225 ✗ (cache,NONE()) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3226 // adrpo: TODO! FIXME! add this as an Error not as a print!
3227 ✗ print("Error: The marked virtual expandable component reference in connect([" +
3228 PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + "], " +
3229 PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + "); should be qualified, i.e. expandableConnectorName.virtualName!\n");
3230 ✗ then
3231 fail();
3232
3233 // c1 is expandable and c2 is existing BUT contains MORE THAN 1 component
3234 // c1 is expandable and SHOULD be qualified!
3235 case (cache, env, ih, sets, pre, c1 as Absyn.CREF_QUAL(), c2, impl, graph)
3236 algorithm
3237 // c1 is expandable
3238
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
3384 (cache,NONE()) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3239
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1692 times.
1692 (cache,SOME((DAE.CREF(c2_1,_),_,attr2))) := Static.elabCref(cache, env, c2, impl, false, pre, info);
3240
3241 // fprintln(Flags.SHOW_EXPANDABLE_INFO, ">>>> connect(expandable, existing)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3242
3243 // lookup the existing connector
3244 1692 (cache,c2_2) := Static.canonCref(cache,env, c2_1, impl);
3245 1692 (attr2,ty2) := Lookup.lookupConnectorVar(env,c2_2);
3246 // bind the attributes
3247 1692 DAE.ATTR(ct2,prl2,vt2,_,io2,vis2) := attr2;
3248
3249 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "1 connect(expandable, existing)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3250
3251 // strip the last prefix!
3252 1692 c1_prefix := AbsynUtil.crefStripLast(c1);
3253 // elab expandable connector
3254
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1692 times.
1692 (cache,SOME((DAE.CREF(c1_1,_),_,_))) := Static.elabCref(cache,env,c1_prefix,impl,false,pre,info);
3255 // lookup the expandable connector
3256 1692 (cache,c1_2) := Static.canonCref(cache, env, c1_1, impl);
3257 1692 (_,ty1) := Lookup.lookupConnectorVar(env, c1_2);
3258 // make sure is expandable!
3259
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
1692 true := Types.isExpandableConnector(ty1);
3260 // strip last subs to get the full type!
3261 1692 c1_2 := ComponentReferenceBasics.crefStripLastSubs(c1_2);
3262 1692 (_,attr,ty,binding,cnstForRange,_,_,envExpandable,_) := Lookup.lookupVar(cache, env, c1_2);
3263 1692 (_,_,_,_,_,_,_,envComponent,_) := Lookup.lookupVar(cache, env, c2_2);
3264
3265 // we have more than 1 variables in the envComponent, we need to add an empty environment for c1
3266 // and dive into!
3267 1692 variablesUnion := FGraph.getVariablesFromGraphScope(envComponent);
3268 // more than 1 variables
3269
1/2
✓ Branch 1 taken 1692 times.
✗ Branch 2 not taken.
1692 true := listLength(variablesUnion) > 1;
3270 // print("VARS MULTIPLE: [" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "/" + ComponentReferenceBasics.printComponentRefStr(c2_2) + "] " + stringDelimitList(variablesUnion, ", ") + "\n");
3271
3272 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "2 connect(expandable, existing[MULTIPLE])(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3273
3274 // get the virtual component name
3275 ✗ componentName := AbsynUtil.crefGetLastIdent(c1);
3276
3277 ✗ envComponentEmpty := FGraph.removeComponentsFromScope(envComponent);
3278
3279 // get the dimensions from the type!
3280 ✗ daeDims := TypesDump.getDimensions(ty2);
3281 ✗ arrDims := List.map(daeDims,Expression.unelabDimension);
3282 // add to the environment of the expandable
3283 // connector the new virtual variable.
3284 ✗ envExpandable := FGraph.cloneLastScopeRef(envExpandable);
3285 ✗ envExpandable := FGraph.mkComponentNode(
3286 envExpandable,
3287 DAE.TYPES_VAR(componentName,
3288 DAE.ATTR(ct2,prl2,vt2,Absyn.BIDIR(),io2,vis2),
3289 ty2,DAE.UNBOUND(),false, NONE()),
3290 SCode.COMPONENT(
3291 componentName,
3292 SCode.defaultPrefixes,
3293 SCode.ATTR(arrDims, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(), Absyn.BIDIR(),Absyn.NONFIELD()),
3294 Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(),
3295 SCode.noComment, NONE(), Absyn.dummyInfo),
3296 DAE.NOMOD(),
3297 FCore.VAR_TYPED(),
3298 // add empty here to connect individual components!
3299 envComponentEmpty);
3300 // ******************************************************************************
3301 // here we need to update the correct environment.
3302 // walk the cref: c1_2 and update all the corresponding environments on the path:
3303 // Example: c1_2 = a.b.c -> update env c, update env b with c, update env a with b!
3304 ✗ env := updateEnvComponentsOnQualPath(
3305 cache,
3306 env,
3307 c1_2,
3308 attr,
3309 ty,
3310 binding,
3311 cnstForRange,
3312 envExpandable);
3313 // ******************************************************************************
3314
3315 // c1 = AbsynUtil.joinCrefs(ComponentReference.unelabCref(c1_2), Absyn.CREF_IDENT(componentName, {}));
3316 // then connect each of the components normally.
3317 ✗ (cache,env,ih,sets,dae,graph) := connectExpandableVariables(cache,env,ih,sets,pre,c1,c2,variablesUnion,impl,graph,info);
3318 then
3319 (cache,env,ih,sets,dae,graph);
3320
3321 // c1 is expandable and SHOULD be qualified!
3322 case (cache, env, ih, sets, pre, c1 as Absyn.CREF_QUAL(), c2, impl, graph)
3323 algorithm
3324 // c1 is expandable
3325
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
1692 (cache,NONE()) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3326
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1692 times.
1692 (cache,SOME((DAE.CREF(c2_1,_),_,attr2))) := Static.elabCref(cache, env, c2, impl, false, pre, info);
3327
3328 // fprintln(Flags.SHOW_EXPANDABLE_INFO, ">>>> connect(expandable, existing)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3329
3330 // lookup the existing connector
3331 1692 (cache,c2_2) := Static.canonCref(cache,env, c2_1, impl);
3332 1692 (attr2,ty2) := Lookup.lookupConnectorVar(env,c2_2);
3333 // bind the attributes
3334 1692 DAE.ATTR(ct2,prl2,vt2,_,io2,vis2) := attr2;
3335
3336 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "1 connect(expandable, existing)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3337
3338 // strip the last prefix!
3339 1692 c1_prefix := AbsynUtil.crefStripLast(c1);
3340 // elab expandable connector
3341
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1692 times.
1692 (cache,SOME((DAE.CREF(c1_1,_),_,_))) := Static.elabCref(cache, env, c1_prefix, impl, false, pre, info);
3342 // lookup the expandable connector
3343 1692 (cache,c1_2) := Static.canonCref(cache, env, c1_1, impl);
3344 1692 (attr1,ty1) := Lookup.lookupConnectorVar(env, c1_2);
3345 // make sure is expandable!
3346
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
1692 true := Types.isExpandableConnector(ty1);
3347 // strip last subs to get the full type!
3348 1692 c1_2 := ComponentReferenceBasics.crefStripLastSubs(c1_2);
3349 1692 (_,attr,ty,binding,cnstForRange,_,_,envExpandable,_) := Lookup.lookupVar(cache, env, c1_2);
3350 1692 (_,_,_,_,_,_,_,envComponent,_) := Lookup.lookupVar(cache, env, c2_2);
3351
3352 // we have more than 1 variables in the envComponent, we need to add an empty environment for c1
3353 // and dive into!
3354 1692 variablesUnion := FGraph.getVariablesFromGraphScope(envComponent);
3355 // max 1 variable, should check for empty!
3356
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
1692 false := listLength(variablesUnion) > 1;
3357 // print("VARS SINGLE: [" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "/" + ComponentReferenceBasics.printComponentRefStr(c2_2) + "] " + stringDelimitList(variablesUnion, ", ") + "\n");
3358
3359 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "2 connect(expandable, existing[SINGLE])(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3360
3361 // get the virtual component name
3362 1692 componentName := AbsynUtil.crefGetLastIdent(c1);
3363
3364 1692 envComponentEmpty := FGraph.removeComponentsFromScope(envComponent);
3365
3366 // get the dimensions from the type!
3367 1692 daeDims := TypesDump.getDimensions(ty2);
3368 1692 arrDims := List.map(daeDims,Expression.unelabDimension);
3369 // add to the environment of the expandable
3370 // connector the new virtual variable.
3371 1692 envExpandable := FGraph.mkComponentNode(
3372 envExpandable,
3373 DAE.TYPES_VAR(
3374 componentName,
3375 DAE.ATTR(ct2,prl2,vt2,Absyn.BIDIR(),io2,vis2),
3376 ty2,DAE.UNBOUND(),false,NONE()),
3377 SCode.COMPONENT(
3378 componentName,
3379 SCode.defaultPrefixes,
3380 SCode.ATTR(arrDims, SCode.POTENTIAL(), SCode.NON_PARALLEL(), SCode.VAR(), Absyn.BIDIR(), Absyn.NONFIELD()),
3381 Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(),
3382 SCode.noComment, NONE(), Absyn.dummyInfo),
3383 DAE.NOMOD(),
3384 FCore.VAR_TYPED(),
3385 envComponentEmpty);
3386 // ******************************************************************************
3387 // here we need to update the correct environment.
3388 // walk the cref: c1_2 and update all the corresponding environments on the path:
3389 // Example: c1_2 = a.b.c -> update env c, update env b with c, update env a with b!
3390 1692 env := updateEnvComponentsOnQualPath(
3391 cache,
3392 env,
3393 c1_2,
3394 attr,
3395 ty,
3396 binding,
3397 cnstForRange,
3398 envExpandable);
3399 // ******************************************************************************
3400
3401 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "3 connect(expandable, existing[SINGLE])(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")");
3402
3403 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env expandable: " + FGraph.printGraphStr(envExpandable));
3404 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env component: " + FGraph.printGraphStr(envComponent));
3405 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "env: " + FGraph.printGraphStr(env));
3406
3407 // use the cannon cref here as we will NOT find [i] in this environment!!!!
3408 // c1 = AbsynUtil.joinCrefs(ComponentReference.unelabCref(c1_2), Absyn.CREF_IDENT(componentName, {}));
3409 // now it should be in the Env, fetch the info!
3410
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1692 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1692 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 1692 times.
1692 (cache,SOME((DAE.CREF(c1_1,_),_,_))) := Static.elabCref(cache, env, c1, impl, false, pre,info);
3411 1692 (cache,c1_2) := Static.canonCref(cache,env, c1_1, impl);
3412 1692 (attr1,ty1) := Lookup.lookupConnectorVar(env,c1_2);
3413 // bind the attributes
3414 1692 DAE.ATTR(ct1,prl1,vt1,_,io1,vis1) := attr1;
3415
3416 // then connect the components normally.
3417 1692 (cache,env,ih,sets,dae,graph) := instConnect(cache,env,ih,sets,pre,c1,c2,impl,graph,info);
3418
3419 // adrpo: TODO! FIXME! check if is OK
3420 state := ClassInf.CONNECTOR(Absyn.IDENT("expandable connector"), true);
3421 1692 (cache,c1p) := PrefixUtil.prefixCref(cache, env, ih, pre, c1_2);
3422 1692 (cache,c2p) := PrefixUtil.prefixCref(cache, env, ih, pre, c2_2);
3423 1692 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1p,c2p));
3424 // declare the added component in the DAE!
3425 1692 (cache,c1_2) := PrefixUtil.prefixCref(cache, env, ih, pre, c1_2);
3426
3427 // get the dimensions from the ty1 type!
3428 1692 daeDims := TypesDump.getDimensions(ty1);
3429 1692 arrDims := List.map(daeDims,Expression.unelabDimension);
3430 1692 daeExpandable := generateExpandableDAE(cache,env,envExpandable,
3431 c1_2,
3432 state,
3433 ty1,
3434 SCode.ATTR(arrDims, DAEUtil.toSCodeConnectorType(ct1), prl1, vt1, Absyn.BIDIR(), Absyn.NONFIELD()),
3435 vis1,
3436 io1,
3437 source);
3438
3439 1692 dae := DAEUtil.joinDaes(dae, daeExpandable);
3440 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "<<<< connect(expandable, existing)(" + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c1) + ", " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "." + Dump.printComponentRefStr(c2) + ")"); // \nDAE:" + DAEDump.dumpStr(daeExpandable, AvlTreePathFunction.Tree.EMPTY()));
3441 1692 then
3442 (cache,env,ih,sets,dae,graph);
3443
3444 // both c1 and c2 are non expandable!
3445 case (cache, env, _, _, pre, c1, c2, impl, _)
3446 algorithm
3447 // both of these are OK
3448 ✗ (cache,SOME((DAE.CREF(c1_1,_),_,_))) := Static.elabCref(cache, env, c1, impl, false, pre, info);
3449 ✗ (cache,SOME((DAE.CREF(c2_1,_),_,_))) := Static.elabCref(cache, env, c2, impl, false, pre, info);
3450
3451 ✗ (cache,c1_2) := Static.canonCref(cache,env, c1_1, impl);
3452 ✗ (cache,c2_2) := Static.canonCref(cache,env, c2_1, impl);
3453 ✗ (_,ty1) := Lookup.lookupConnectorVar(env,c1_2);
3454 ✗ (_,ty2) := Lookup.lookupConnectorVar(env,c2_2);
3455
3456 // non-expandable
3457 ✗ false := Types.isExpandableConnector(ty1);
3458 ✗ false := Types.isExpandableConnector(ty2);
3459
3460 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "connect(non-expandable, non-expandable)(" + Dump.printComponentRefStr(c1) + ", " + Dump.printComponentRefStr(c2) + ")");
3461 // then connect the components normally.
3462 ✗ then
3463 fail(); // fail to enter connect normally
3464
3465 /*/ failtrace
3466 case (cache,env,_,_,pre,c1,c2,impl,_,_)
3467 algorithm
3468 true = Flags.isSet(Flags.SHOW_EXPANDABLE_INFO);
3469 (cache,_) = Static.elabCref(cache, env, c1, impl, false, pre, info);
3470 (cache,_) = Static.elabCref(cache, env, c2, impl, false, pre, info);
3471
3472 fprintln(Flags.SHOW_EXPANDABLE_INFO,
3473 "connect(?, ?)(" +
3474 Dump.printComponentRefStr(c1) + ", " +
3475 Dump.printComponentRefStr(c2) + ")"
3476 );
3477 then
3478 fail();*/
3479 end matchcontinue;
3480 end connectExpandableConnectors;
3481
3482 protected function generateExpandableDAE
3483 "@author: adrpo
3484 connect(expandable, non-expandable)
3485 should generate a DAE for the expandable part.
3486 Expand the array if needed."
3487 input FCore.Cache inCache;
3488 input FCore.Graph inParentEnv;
3489 input FCore.Graph inClassEnv;
3490 input DAE.ComponentRef cref;
3491 input ClassInf.State state;
3492 input DAE.Type ty;
3493 input SCode.Attributes attrs;
3494 input SCode.Visibility vis;
3495 input Absyn.InnerOuter io;
3496 input DAE.ElementSource source;
3497 output DAE.DAElist outDAE;
3498 algorithm
3499 outDAE := match source
3500 local
3501 DAE.Dimensions daeDims;
3502 DAE.DAElist daeExpandable;
3503 list<DAE.ComponentRef> crefs;
3504
3505 // scalars and arrays
3506 case _
3507 algorithm
3508 // get the dimensions from the type!
3509 1692 daeDims := TypesDump.getDimensions(ty);
3510
1/2
✓ Branch 0 taken 1692 times.
✗ Branch 1 not taken.
1692 if listEmpty(daeDims)
3511 then // empty dimensions
3512 1692 daeExpandable := InstDAE.daeDeclare(inCache, inParentEnv, inClassEnv, cref, state, ty,
3513 attrs,
3514 vis, NONE(), {}, NONE(), NONE(),
3515 SOME(SCode.COMMENT(NONE(), SOME("virtual variable in expandable connector"))),
3516 io, SCode.NOT_FINAL(), source, true);
3517 else // not empty list
3518 ✗ crefs := ComponentReference.expandCref(cref, false);
3519 // print(" crefs: " + stringDelimitList(List.map(crefs, ComponentReferenceBasics.printComponentRefStr),", ") + "\n");
3520 ✗ daeExpandable := daeDeclareList(inCache, inParentEnv, inClassEnv, listReverse(crefs), state, ty, attrs, vis, io, source, DAE.emptyDae);
3521 end if;
3522 then
3523 daeExpandable;
3524
3525 end match;
3526 end generateExpandableDAE;
3527
3528 protected function daeDeclareList
3529 "declare a list of crefs, one for each array element"
3530 input FCore.Cache inCache;
3531 input FCore.Graph inParentEnv;
3532 input FCore.Graph inClassEnv;
3533 input list<DAE.ComponentRef> crefs;
3534 input ClassInf.State state;
3535 input DAE.Type ty;
3536 input SCode.Attributes attrs;
3537 input SCode.Visibility vis;
3538 input Absyn.InnerOuter io;
3539 input DAE.ElementSource source;
3540 input DAE.DAElist acc;
3541 output DAE.DAElist outDAE;
3542 algorithm
3543 outDAE := match crefs
3544 local
3545 DAE.DAElist daeExpandable;
3546 list<DAE.ComponentRef> lst;
3547 DAE.ComponentRef cref;
3548
3549 case {} then acc;
3550
3551 case cref::lst
3552 algorithm
3553 ✗ daeExpandable := InstDAE.daeDeclare(inCache, inParentEnv, inClassEnv, cref, state, ty,
3554 attrs,
3555 vis, NONE(), {}, NONE(), NONE(),
3556 SOME(SCode.COMMENT(NONE(), SOME("virtual variable in expandable connector"))),
3557 io, SCode.NOT_FINAL(), source, true);
3558 ✗ daeExpandable := DAEUtil.joinDaes(daeExpandable, acc);
3559 ✗ daeExpandable := daeDeclareList(inCache, inParentEnv, inClassEnv, lst, state, ty, attrs, vis, io, source, daeExpandable);
3560 then
3561 daeExpandable;
3562 end match;
3563 end daeDeclareList;
3564
3565 protected function updateEnvComponentsOnQualPath
3566 "@author: adrpo 2010-10-05
3567 This function will fetch the environments on the
3568 cref path and update the last one with the given input,
3569 then update all the environment back to the root.
3570 Example:
3571 input: env[a], a.b.c.d, env[d]
3572 update env[c] with env[d]
3573 update env[b] with env[c]
3574 update env[a] with env[b]"
3575 input FCore.Cache inCache "cache";
3576 input FCore.Graph inEnv "the environment we should update!";
3577 input DAE.ComponentRef virtualExpandableCref;
3578 input DAE.Attributes virtualExpandableAttr;
3579 input DAE.Type virtualExpandableTy;
3580 input DAE.Binding virtualExpandableBinding;
3581 input Option<DAE.Const> virtualExpandableCnstForRange;
3582 input FCore.Graph virtualExpandableEnv "the virtual component environment!";
3583 output FCore.Graph outEnv "the returned updated environment";
3584 algorithm
3585 outEnv :=
3586 match(inCache, inEnv, virtualExpandableCref, virtualExpandableAttr, virtualExpandableTy,
3587 virtualExpandableBinding, virtualExpandableCnstForRange, virtualExpandableEnv)
3588 local
3589 FCore.Cache cache;
3590 FCore.Graph topEnv "the environment we should update!";
3591 DAE.ComponentRef veCref, qualCref;
3592 DAE.Attributes veAttr,currentAttr;
3593 DAE.Type veTy,currentTy;
3594 DAE.Binding veBinding,currentBinding;
3595 Option<DAE.Const> veCnstForRange,currentCnstForRange;
3596 FCore.Graph veEnv "the virtual component environment!";
3597 FCore.Graph updatedEnv "the returned updated environment";
3598 FCore.Graph currentEnv, realEnv;
3599 FCore.Scope forLoopScope;
3600 String currentName;
3601
3602 // we have reached the top, update and return!
3603 case (_, topEnv, DAE.CREF_IDENT(ident = currentName), veAttr, veTy, veBinding, veCnstForRange, veEnv)
3604 algorithm
3605 1692 (realEnv, forLoopScope) := FGraph.splitGraphScope(topEnv);
3606 // update the topEnv
3607 1692 updatedEnv := FGraph.updateComp(
3608 realEnv,
3609 DAE.TYPES_VAR(currentName, veAttr, veTy, veBinding, false, veCnstForRange),
3610 FCore.VAR_TYPED(),
3611 veEnv);
3612 1692 updatedEnv := FGraph.pushScope(updatedEnv, forLoopScope);
3613 then
3614 updatedEnv;
3615
3616 // if we have a.b.x, update b with x and call us recursively with a.b
3617 case (cache, topEnv, veCref as DAE.CREF_QUAL(), veAttr, veTy, veBinding, veCnstForRange, veEnv)
3618 algorithm
3619 // get the last one
3620 1102 currentName := ComponentReferenceBasics.crefLastIdent(veCref);
3621 // strip the last one
3622 1102 qualCref := ComponentReference.crefStripLastIdent(veCref);
3623 // strip the last subs
3624 1102 qualCref := ComponentReferenceBasics.crefStripLastSubs(qualCref);
3625 // find the correct environment to update
3626 1102 (_,currentAttr,currentTy,currentBinding,currentCnstForRange,_,_,currentEnv,_) := Lookup.lookupVar(cache, topEnv, qualCref);
3627
3628 1102 (realEnv, forLoopScope) := FGraph.splitGraphScope(currentEnv);
3629 // update the current environment!
3630 1102 currentEnv := FGraph.updateComp(
3631 realEnv,
3632 DAE.TYPES_VAR(currentName, veAttr, veTy, veBinding, false, veCnstForRange),
3633 FCore.VAR_TYPED(),
3634 veEnv);
3635 1102 currentEnv := FGraph.pushScope(currentEnv, forLoopScope);
3636
3637 // call us recursively to reach the top!
3638 1102 updatedEnv := updateEnvComponentsOnQualPath(
3639 cache,
3640 topEnv,
3641 qualCref,
3642 currentAttr,
3643 currentTy,
3644 currentBinding,
3645 currentCnstForRange,
3646 currentEnv);
3647 then
3648 updatedEnv;
3649 end match;
3650 end updateEnvComponentsOnQualPath;
3651
3652 protected function connectExpandableVariables
3653 "@author: adrpo
3654 this function handle the connections of expandable connectors
3655 that contain components"
3656 input FCore.Cache inCache;
3657 input FCore.Graph inEnv;
3658 input InnerOuter.InstHierarchy inIH;
3659 input Connect.Sets inSets;
3660 input DAE.Prefix inPrefix;
3661 input Absyn.ComponentRef inComponentRefLeft;
3662 input Absyn.ComponentRef inComponentRefRight;
3663 input list<String> inVariablesUnion;
3664 input Boolean inImpl;
3665 input ConnectionGraph.ConnectionGraph inGraph;
3666 input SourceInfo info;
3667 output FCore.Cache outCache;
3668 output FCore.Graph outEnv;
3669 output InnerOuter.InstHierarchy outIH;
3670 output Connect.Sets outSets;
3671 output DAE.DAElist outDae;
3672 output ConnectionGraph.ConnectionGraph outGraph;
3673 algorithm
3674 (outCache,outEnv,outIH,outSets,outDae,outGraph) :=
3675 match (inCache, inEnv, inIH, inSets, inPrefix, inComponentRefLeft, inComponentRefRight, inVariablesUnion, inImpl, inGraph)
3676 local
3677 Boolean impl;
3678 Connect.Sets sets;
3679 DAE.DAElist dae, dae1, dae2;
3680 FCore.Graph env;
3681 DAE.Prefix pre;
3682 Absyn.ComponentRef c1,c2,c1_full,c2_full;
3683 FCore.Cache cache;
3684 ConnectionGraph.ConnectionGraph graph;
3685 InstanceHierarchy ih;
3686 list<String> names;
3687 String name;
3688
3689 // handle empty case
3690 case (cache, env, ih, sets, _, _, _, {}, _, graph)
3691 then (cache,env,ih,sets,DAE.emptyDae,graph);
3692
3693 // handle recursive call
3694 case (cache, env, ih, sets, pre, c1, c2, name::names, impl, graph)
3695 algorithm
3696 // add name to both c1 and c2, then connect normally
3697 5028 c1_full := AbsynUtil.joinCrefs(c1, Absyn.CREF_IDENT(name, {}));
3698 5028 c2_full := AbsynUtil.joinCrefs(c2, Absyn.CREF_IDENT(name, {}));
3699 // fprintln(Flags.SHOW_EXPANDABLE_INFO, "connect(full_expandable, full_expandable)(" + Dump.printComponentRefStr(c1_full) + ", " + Dump.printComponentRefStr(c2_full) + ")");
3700
3701 5028 (cache,env,ih,sets,dae1,graph) := instConnect(cache,env,ih,sets,pre,c1_full,c2_full,impl,graph,info);
3702
3703 5028 (cache,env,ih,sets,dae2,graph) := connectExpandableVariables(cache,env,ih,sets,pre,c1,c2,names,impl,graph,info);
3704 5028 dae := DAEUtil.joinDaes(dae1, dae2);
3705 5028 then
3706 (cache,env,ih,sets,dae,graph);
3707 end match;
3708 end connectExpandableVariables;
3709
3710 protected function getStateFromType
3711 "@author: adrpo
3712 this function gets the ClassInf.State from the given type.
3713 it will fail if the type is not a complex type."
3714 input DAE.Type ty;
3715 output ClassInf.State outState;
3716 algorithm
3717 outState := match ty
3718 local
3719 ClassInf.State state;
3720 case DAE.T_COMPLEX(complexClassType = state) then state;
3721 // TODO! check if subtype is needed here
3722 case DAE.T_SUBTYPE_BASIC(complexClassType = state) then state;
3723 // adpo: TODO! FIXME! add a debug print here!
3724 else fail();
3725 end match;
3726 end getStateFromType;
3727
3728 protected function isConnectorType
3729 "@author: adrpo
3730 this function checks if the given type is an expandable connector"
3731 input DAE.Type ty;
3732 output Boolean isConnector;
3733 algorithm
3734 isConnector := match ty
3735 case DAE.T_COMPLEX(complexClassType = ClassInf.CONNECTOR(_,false)) then true;
3736 // TODO! check if subtype is needed here
3737 case DAE.T_SUBTYPE_BASIC(complexClassType = ClassInf.CONNECTOR(_,false)) then true;
3738 else false;
3739 end match;
3740 end isConnectorType;
3741
3742 protected function flipDirection
3743 "@author: adrpo
3744 this function will flip direction:
3745 input -> output
3746 output -> input
3747 bidir -> bidir"
3748 input Absyn.Direction inDir;
3749 output Absyn.Direction outDir;
3750 algorithm
3751 outDir := match inDir
3752 case Absyn.INPUT() then Absyn.OUTPUT();
3753 case Absyn.OUTPUT() then Absyn.INPUT();
3754 case Absyn.BIDIR() then Absyn.BIDIR();
3755 end match;
3756 end flipDirection;
3757
3758 protected function validConnector
3759 "This function tests whether a type is a eligible to be used in connections."
3760 input DAE.Type inType;
3761 input DAE.ComponentRef inCref;
3762 input SourceInfo inInfo;
3763 algorithm
3764 () := matchcontinue inType
3765 local
3766 ClassInf.State state;
3767 DAE.Type tp;
3768 String str;
3769
3770 case DAE.T_REAL() then ();
3771 case DAE.T_INTEGER() then ();
3772 case DAE.T_STRING() then ();
3773 case DAE.T_BOOL() then ();
3774 case DAE.T_ENUMERATION() then ();
3775 // clocks TODO! FIXME! check if +std=3.3
3776 case DAE.T_CLOCK() then ();
3777
3778 case DAE.T_COMPLEX(complexClassType = state)
3779 algorithm
3780 5529 ClassInfUtil.valid(state, SCode.R_CONNECTOR(false));
3781 then
3782 ();
3783
3784 case DAE.T_COMPLEX(complexClassType = state)
3785 algorithm
3786 370 ClassInfUtil.valid(state, SCode.R_CONNECTOR(true));
3787 then
3788 ();
3789
3790 // TODO, check if subtype is needed here
3791 case DAE.T_SUBTYPE_BASIC(complexClassType = state)
3792 algorithm
3793 47 ClassInfUtil.valid(state, SCode.R_CONNECTOR(false));
3794 then
3795 ();
3796
3797 // TODO, check if subtype is needed here
3798 case DAE.T_SUBTYPE_BASIC(complexClassType = state)
3799 algorithm
3800 ✗ ClassInfUtil.valid(state, SCode.R_CONNECTOR(true));
3801 then
3802 ();
3803
3804 case DAE.T_ARRAY(ty = tp)
3805 algorithm
3806 242 validConnector(tp, inCref, inInfo);
3807 then
3808 ();
3809
3810 // everything in expandable is a connector!
3811 case _
3812 algorithm
3813 ✗ true := ConnectUtil.isExpandable(inCref);
3814 then
3815 ();
3816
3817 else
3818 algorithm
3819 ✗ str := ComponentReferenceBasics.printComponentRefStr(inCref);
3820 ✗ Error.addSourceMessage(Error.INVALID_CONNECTOR_TYPE, {str}, inInfo);
3821 ✗ then
3822 fail();
3823 end matchcontinue;
3824 end validConnector;
3825
3826 protected function checkConnectTypes
3827 input DAE.ComponentRef inLhsCref;
3828 input DAE.Type inLhsType;
3829 input Connect.Face inLhsFace;
3830 input DAE.Attributes inLhsAttributes;
3831 input DAE.ComponentRef inRhsCref;
3832 input DAE.Type inRhsType;
3833 input Connect.Face inRhsFace;
3834 input DAE.Attributes inRhsAttributes;
3835 input SourceInfo inInfo;
3836 protected
3837 DAE.ConnectorType lhs_ct, rhs_ct;
3838 Absyn.Direction lhs_dir, rhs_dir;
3839 Absyn.InnerOuter lhs_io, rhs_io;
3840 SCode.Visibility lhs_vis, rhs_vis;
3841 algorithm
3842 18212 ComponentReference.checkCrefSubscriptsBounds(inLhsCref, inInfo);
3843 18212 ComponentReference.checkCrefSubscriptsBounds(inRhsCref, inInfo);
3844 18212 DAE.ATTR(connectorType = lhs_ct, direction = lhs_dir, innerOuter = lhs_io,
3845 visibility = lhs_vis) := inLhsAttributes;
3846 18212 DAE.ATTR(connectorType = rhs_ct, direction = rhs_dir, innerOuter = rhs_io,
3847 visibility = rhs_vis) := inRhsAttributes;
3848 18212 checkConnectTypesType(inLhsType, inRhsType, inLhsCref, inRhsCref, inInfo);
3849 18212 checkConnectTypesFlowStream(lhs_ct, rhs_ct, inLhsCref, inRhsCref, inInfo);
3850 18210 checkConnectTypesDirection(lhs_dir, inLhsFace, lhs_vis, rhs_dir, inRhsFace,
3851 rhs_vis, inLhsCref, inRhsCref, inInfo);
3852 18210 checkConnectTypesInnerOuter(lhs_io, rhs_io, inLhsCref, inRhsCref, inInfo);
3853 end checkConnectTypes;
3854
3855 protected function checkConnectTypesType
3856 input DAE.Type inLhsType;
3857 input DAE.Type inRhsType;
3858 input DAE.ComponentRef inLhsCref;
3859 input DAE.ComponentRef inRhsCref;
3860 input SourceInfo inInfo;
3861 algorithm
3862 () := matchcontinue inInfo
3863 local
3864 DAE.Type t1, t2;
3865 String cs1, cs2, cref_str1, cref_str2, str1, str2;
3866 list<DAE.Dimension> dims1, dims2;
3867
3868 case _
3869 algorithm
3870
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18212 times.
18212 true := Types.equivtypesOrRecordSubtypeOf(inLhsType, inRhsType);
3871 then
3872 ();
3873
3874 // The type is not identical hence error.
3875 case _
3876 algorithm
3877 ✗ t1 := Types.arrayElementType(inLhsType);
3878 ✗ t2 := Types.arrayElementType(inRhsType);
3879 ✗ false := Types.equivtypesOrRecordSubtypeOf(t1, t2);
3880 ✗ (_, cs1) := TypesDump.printConnectorTypeStr(t1);
3881 ✗ (_, cs2) := TypesDump.printConnectorTypeStr(t2);
3882 ✗ cref_str1 := ComponentReferenceBasics.printComponentRefStr(inLhsCref);
3883 ✗ cref_str2 := ComponentReferenceBasics.printComponentRefStr(inRhsCref);
3884 ✗ Error.addSourceMessage(Error.CONNECT_INCOMPATIBLE_TYPES,
3885 {cref_str1, cref_str2, cref_str1, cs1, cref_str2, cs2}, inInfo);
3886 ✗ then
3887 fail();
3888
3889 // Different dimensionality.
3890 case _
3891 algorithm
3892 ✗ dims1 := TypesDump.getDimensions(inLhsType);
3893 ✗ dims2 := TypesDump.getDimensions(inRhsType);
3894 ✗ false := List.isEqualOnTrue(dims1, dims2, Expression.dimensionsEqual);
3895 ✗ false := (listEmpty(dims1) and listEmpty(dims2));
3896 ✗ cref_str1 := ComponentReferenceBasics.printComponentRefStr(inLhsCref);
3897 ✗ cref_str2 := ComponentReferenceBasics.printComponentRefStr(inRhsCref);
3898 ✗ str1 := "[" + ExpressionBasics.dimensionsString(dims1) + "]";
3899 ✗ str2 := "[" + ExpressionBasics.dimensionsString(dims2) + "]";
3900 ✗ Error.addSourceMessage(Error.CONNECTOR_ARRAY_DIFFERENT,
3901 {cref_str1, cref_str2, str1, str2}, inInfo);
3902 ✗ then
3903 fail();
3904
3905 end matchcontinue;
3906 end checkConnectTypesType;
3907
3908 protected function checkConnectTypesFlowStream
3909 input DAE.ConnectorType inLhsConnectorType;
3910 input DAE.ConnectorType inRhsConnectorType;
3911 input DAE.ComponentRef inLhsCref;
3912 input DAE.ComponentRef inRhsCref;
3913 input SourceInfo inInfo;
3914 algorithm
3915 () := matchcontinue inInfo
3916 local
3917 String cref_str1, cref_str2, pre_str1, pre_str2;
3918 list<String> err_strl;
3919
3920 case _
3921 algorithm
3922
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18210 times.
18212 true := DAEUtil.connectorTypeEqual(inLhsConnectorType, inRhsConnectorType);
3923 then
3924 ();
3925
3926 else
3927 algorithm
3928 2 cref_str1 := ComponentReferenceBasics.printComponentRefStr(inLhsCref);
3929 2 cref_str2 := ComponentReferenceBasics.printComponentRefStr(inRhsCref);
3930 2 pre_str1 := DAEUtil.connectorTypeStr(inLhsConnectorType);
3931 2 pre_str2 := DAEUtil.connectorTypeStr(inRhsConnectorType);
3932
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1 time.
2 err_strl := if DAEUtil.potentialBool(inLhsConnectorType)
3933 then {pre_str2, cref_str2, cref_str1}
3934 else {pre_str1, cref_str1, cref_str2};
3935 2 Error.addSourceMessage(Error.CONNECT_PREFIX_MISMATCH, err_strl, inInfo);
3936 2 then
3937 fail();
3938
3939 end matchcontinue;
3940 end checkConnectTypesFlowStream;
3941
3942 protected function checkConnectTypesDirection
3943 input Absyn.Direction inLhsDirection;
3944 input Connect.Face inLhsFace;
3945 input SCode.Visibility inLhsVisibility;
3946 input Absyn.Direction inRhsDirection;
3947 input Connect.Face inRhsFace;
3948 input SCode.Visibility inRhsVisibility;
3949 input DAE.ComponentRef inLhsCref;
3950 input DAE.ComponentRef inRhsCref;
3951 input SourceInfo inInfo;
3952 algorithm
3953 // Two connectors with the same directions but different faces or different
3954 // directions may be connected.
3955
3/4
✓ Branch 1 taken 17308 times.
✓ Branch 2 taken 902 times.
✓ Branch 4 taken 902 times.
✗ Branch 5 not taken.
18210 if isSignalSource(inLhsDirection, inLhsFace, inLhsVisibility) and
3956 isSignalSource(inRhsDirection, inRhsFace, inRhsVisibility) then
3957 ✗ Error.addSourceMessage(Error.CONNECT_TWO_SOURCES,
3958 {ComponentReferenceBasics.printComponentRefStr(inLhsCref),
3959 ComponentReferenceBasics.printComponentRefStr(inRhsCref)}, inInfo);
3960 end if;
3961 end checkConnectTypesDirection;
3962
3963 protected function isSignalSource
3964 input Absyn.Direction inDirection;
3965 input Connect.Face inFace;
3966 input SCode.Visibility inVisibility;
3967 output Boolean outIsSignal;
3968 algorithm
3969 outIsSignal := match(inDirection, inFace, inVisibility)
3970 case (Absyn.OUTPUT(), Connect.INSIDE(), _) then true;
3971 case (Absyn.INPUT(), Connect.OUTSIDE(), SCode.PUBLIC()) then true;
3972 else false;
3973 end match;
3974 end isSignalSource;
3975
3976 protected function checkConnectTypesInnerOuter
3977 input Absyn.InnerOuter inLhsIO;
3978 input Absyn.InnerOuter inRhsIO;
3979 input DAE.ComponentRef inLhsCref;
3980 input DAE.ComponentRef inRhsCref;
3981 input SourceInfo inInfo;
3982 algorithm
3983 () := match(inLhsIO, inRhsIO)
3984 local
3985 String cref_str1, cref_str2;
3986
3987 case (Absyn.OUTER(), Absyn.OUTER())
3988 algorithm
3989 ✗ cref_str1 := ComponentReferenceBasics.printComponentRefStr(inLhsCref);
3990 ✗ cref_str2 := ComponentReferenceBasics.printComponentRefStr(inRhsCref);
3991 ✗ Error.addSourceMessage(Error.CONNECT_OUTER_OUTER,
3992 {cref_str1, cref_str2}, inInfo);
3993 ✗ then
3994 fail();
3995
3996 else ();
3997
3998 end match;
3999 end checkConnectTypesInnerOuter;
4000
4001 public function connectComponents "
4002 This function connects two components and generates connection
4003 sets along the way. For simple components (of type Real) it
4004 adds the components to the set, and for complex types it traverses
4005 the subcomponents and recursively connects them to each other.
4006 A DAE.Element list is returned for assert statements."
4007 input FCore.Cache inCache;
4008 input FCore.Graph inEnv;
4009 input InnerOuter.InstHierarchy inIH;
4010 input Connect.Sets inSets;
4011 input DAE.Prefix inPrefix3;
4012 input DAE.ComponentRef cr1;
4013 input Connect.Face inFace5;
4014 input DAE.Type inType6;
4015 input SCode.Variability vt1;
4016 input DAE.ComponentRef cr2;
4017 input Connect.Face inFace8;
4018 input DAE.Type inType9;
4019 input SCode.Variability vt2;
4020 input DAE.ConnectorType inConnectorType;
4021 input Absyn.InnerOuter io1;
4022 input Absyn.InnerOuter io2;
4023 input ConnectionGraph.ConnectionGraph inGraph;
4024 input SourceInfo info;
4025 output FCore.Cache outCache;
4026 output FCore.Graph outEnv;
4027 output InnerOuter.InstHierarchy outIH;
4028 output Connect.Sets outSets;
4029 output DAE.DAElist outDae;
4030 output ConnectionGraph.ConnectionGraph outGraph;
4031 algorithm
4032 (outCache,outEnv,outIH,outSets,outDae,outGraph) :=
4033 matchcontinue (inCache, inEnv, inIH, inSets, inPrefix3, cr1, inFace5, inType6, cr2, inFace8, inType9, inConnectorType, inGraph)
4034 local
4035 DAE.ComponentRef c1_1,c2_1,c1,c2,c1p,c2p;
4036 Connect.Sets sets_1,sets;
4037 FCore.Graph env;
4038 DAE.Prefix pre;
4039 Connect.Face f1,f2;
4040 DAE.Type t1, t2, bc_tp1, bc_tp2, equalityConstraintFunctionReturnType;
4041 DAE.Dimension dim1,dim2;
4042 DAE.DAElist dae;
4043 list<DAE.Var> l1,l2;
4044 DAE.ConnectorType ct;
4045 String c1_str,t1_str,t2_str,c2_str;
4046 FCore.Cache cache;
4047 ConnectionGraph.ConnectionGraph graph;
4048 InstanceHierarchy ih;
4049 DAE.ElementSource source "the origin of the element";
4050 DAE.InlineType inlineType1;
4051 Absyn.Path fpath1;
4052 Integer idim1;
4053 DAE.Exp zeroVector, crefExp1, crefExp2;
4054 list<DAE.Element> breakDAEElements, elts;
4055 SCode.Element equalityConstraintFunction;
4056 DAE.Dimensions dims,dims2;
4057 list<DAE.ComponentRef> crefs1, crefs2;
4058 DAE.Const const1,const2;
4059 list<DAE.Exp> lhsl, rhsl;
4060
4061 // connections to outer components
4062 case(cache, env, ih, sets, pre, c1, f1, _, c2, f2, _, ct, graph)
4063 algorithm
4064
2/2
✓ Branch 1 taken 163 times.
✓ Branch 2 taken 19205 times.
38563 false := DAEUtil.streamBool(ct);
4065 // print("Connecting components: " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "/" +
4066 // ComponentReferenceBasics.printComponentRefStr(c1) + "[" + Dump.unparseInnerouterStr(io1) + "]" + " = " +
4067 // ComponentReferenceBasics.printComponentRefStr(c2) + "[" + Dump.unparseInnerouterStr(io2) + "]\n");
4068
2/2
✓ Branch 1 taken 19195 times.
✓ Branch 2 taken 10 times.
19205 true := InnerOuter.outerConnection(io1,io2);
4069
4070
4071 // prefix outer with the prefix of the inner directly!
4072
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 (cache, DAE.CREF(c1_1, _)) :=
4073 PrefixUtil.prefixExp(cache, env, ih, Expression.crefExp(c1), pre);
4074
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
10 (cache, DAE.CREF(c2_1, _)) :=
4075 PrefixUtil.prefixExp(cache, env, ih, Expression.crefExp(c2), pre);
4076
4077 // set the source of this element
4078 10 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4079
4080 // print("CONNECT: " + PrefixUtil.printPrefixStrIgnoreNoPre(pre) + "/" +
4081 // ComponentReferenceBasics.printComponentRefStr(c1_1) + "[" + Dump.unparseInnerouterStr(io1) + "]" + " = " +
4082 // ComponentReferenceBasics.printComponentRefStr(c2_1) + "[" + Dump.unparseInnerouterStr(io2) + "]\n");
4083
4084 10 sets := ConnectUtil.addOuterConnection(pre,sets,c1_1,c2_1,io1,io2,f1,f2,source);
4085 10 then
4086 (cache,env,ih,sets,DAE.emptyDae,graph);
4087
4088 // Non-flow and Non-stream type Parameters and constants generate assert statements
4089 case (cache, env, ih, sets, pre, c1, _, t1, c2, _, t2, DAE.POTENTIAL(), graph)
4090 algorithm
4091
3/4
✓ Branch 1 taken 99 times.
✓ Branch 2 taken 15728 times.
✓ Branch 4 taken 99 times.
✗ Branch 5 not taken.
15827 true := SCodeUtil.isParameterOrConst(vt1) and SCodeUtil.isParameterOrConst(vt2) ;
4092
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 99 times.
99 true := Types.basicType(Types.arrayElementType(t1));
4093
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 99 times.
99 true := Types.basicType(Types.arrayElementType(t2));
4094
4095 99 (cache,c1_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c1);
4096 99 (cache,c2_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c2);
4097
4098 // set the source of this element
4099 99 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4100
4101 99 crefExp1 := Expression.crefExp(c1_1);
4102 99 crefExp2 := Expression.crefExp(c2_1);
4103 // Evaluate constant crefs away
4104 99 const1 := Types.variabilityToConst(vt1);
4105 99 const2 := Types.variabilityToConst(vt2);
4106 99 (cache, crefExp1) := Ceval.cevalIfConstant(cache, env, crefExp1, DAE.PROP(t1,const1), true, info);
4107 99 (cache, crefExp2) := Ceval.cevalIfConstant(cache, env, crefExp2, DAE.PROP(t2,const2), true, info);
4108
4109 99 lhsl := Expression.arrayElements(crefExp1);
4110 99 rhsl := Expression.arrayElements(crefExp2);
4111 99 elts := List.threadMap1(lhsl, rhsl, generateConnectAssert, source);
4112 99 then
4113 (cache,env,ih,sets,DAE.DAE(elts),graph);
4114
4115 // Connection of two components of basic type.
4116 case (cache, env, ih, sets, pre, c1, f1, t1, c2, f2, t2, _, graph)
4117 algorithm
4118
2/2
✓ Branch 1 taken 8837 times.
✓ Branch 2 taken 10422 times.
19259 true := Types.basicType(t1);
4119
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 10403 times.
10422 true := Types.basicType(t2);
4120
4121 // TODO: FIXME!
4122 // adrpo 2012-10-14: should we not prefix here??!!
4123 10403 (cache,c1_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c1);
4124 10403 (cache,c2_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c2);
4125
4126 // set the source of this element
4127 10403 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4128
4129 10403 sets_1 := ConnectUtil.addConnection(sets, c1, f1, c2, f2, inConnectorType, source);
4130 10403 then
4131 (cache,env,ih,sets_1,DAE.emptyDae,graph);
4132
4133 /* - weird, seems not to be needed
4134 // Connection of arrays of size zero!
4135 case (cache,env,ih,sets,pre,
4136 c1,f1,t1 as DAE.T_ARRAY(dims = {dim1}, ty = _),_,
4137 c2,f2,t2 as DAE.T_ARRAY(dims = {dim2}, ty = _),_,
4138 ct,_,_,graph,_)
4139 algorithm
4140 0 = Expression.dimensionSize(dim1);
4141 0 = Expression.dimensionSize(dim2);
4142 (cache,_) = PrefixUtil.prefixCref(cache,env,ih,pre,c1);
4143 (cache,_) = PrefixUtil.prefixCref(cache,env,ih,pre,c2);
4144 c1_str = Types.connectorTypeStr(ct) + ComponentReferenceBasics.printComponentRefStr(c1);
4145 (t1, _) = TypesDump.stripTypeVars(t1);
4146 t1_str = TypesDump.unparseType(t1);
4147 c2_str = Types.connectorTypeStr(ct) + ComponentReferenceBasics.printComponentRefStr(c2);
4148 (t2, _) = TypesDump.stripTypeVars(t2);
4149 t2_str = TypesDump.unparseType(t2);
4150 c1_str = stringAppendList({c1_str," type: ",t1_str});
4151 c2_str = stringAppendList({c2_str," type: ",t2_str});
4152 Error.addSourceMessage(Error.CONNECT_ARRAY_SIZE_ZERO, {c1_str,c2_str},info);
4153 then
4154 (cache,env,ih,sets,DAE.emptyDae,graph);*/
4155
4156 // Connection of arrays of complex types
4157 case (cache, env, ih, sets, pre, c1, f1, DAE.T_ARRAY(dims = {dim1}, ty = t1), c2, f2, DAE.T_ARRAY(dims = {dim2}, ty = t2), ct as DAE.POTENTIAL(), graph)
4158 algorithm
4159
2/2
✓ Branch 1 taken 2616 times.
✓ Branch 2 taken 82 times.
2698 DAE.T_COMPLEX() := Types.arrayElementType(t1);
4160
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 DAE.T_COMPLEX() := Types.arrayElementType(t2);
4161
4162
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 true := Expression.dimensionsKnownAndEqual(dim1, dim2);
4163 82 Expression.dimensionSize(dim1);
4164
4165 82 crefs1 := ComponentReference.expandCref(c1,false);
4166 82 crefs2 := ComponentReference.expandCref(c2,false);
4167 82 (cache, _, ih, sets_1, dae, graph) := connectArrayComponents(cache, env,
4168 ih, sets, pre, crefs1, f1, t1, vt1, io1, crefs2, f2, t2, vt2, io2, ct,
4169 graph, info);
4170 82 then
4171 (cache,env,ih,sets_1,dae,graph);
4172
4173 // Connection of arrays of subtype basic types with equality constraint
4174 case (cache, env, ih, sets, pre, c1, f1, DAE.T_ARRAY(dims = {dim1}, ty = t1), c2, f2, DAE.T_ARRAY(dims = {dim2}, ty = t2), ct as DAE.POTENTIAL(), graph)
4175 algorithm
4176
4/6
✓ Branch 1 taken 2615 times.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
2616 DAE.T_SUBTYPE_BASIC(equalityConstraint = SOME(_)) := Types.arrayElementType(t1);
4177 ✗ DAE.T_SUBTYPE_BASIC(equalityConstraint = SOME(_)) := Types.arrayElementType(t2);
4178
4179 ✗ true := Expression.dimensionsKnownAndEqual(dim1, dim2);
4180 ✗ Expression.dimensionSize(dim1);
4181
4182 ✗ crefs1 := ComponentReference.expandCref(c1,false);
4183 ✗ crefs2 := ComponentReference.expandCref(c2,false);
4184 ✗ (cache, _, ih, sets_1, dae, graph) := connectArrayComponents(cache, env,
4185 ih, sets, pre, crefs1, f1, t1, vt1, io1, crefs2, f2, t2, vt2, io2, ct,
4186 graph, info);
4187 ✗ then
4188 (cache,env,ih,sets_1,dae,graph);
4189
4190 // Connection of arrays
4191 case (cache, env, ih, sets, pre, c1, f1, t1 as DAE.T_ARRAY(), c2, f2, t2 as DAE.T_ARRAY(), ct, graph)
4192 algorithm
4193 4359 dims := TypesDump.getDimensions(t1);
4194 4359 dims2 := TypesDump.getDimensions(t2);
4195
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4359 times.
4359 true := List.isEqualOnTrue(dims, dims2, Expression.dimensionsKnownAndEqual);
4196
4197 // set the source of this element
4198 4359 (cache,c1p) := PrefixUtil.prefixCref(cache, env, ih, pre, c1);
4199 4359 (cache,c2p) := PrefixUtil.prefixCref(cache, env, ih, pre, c2);
4200 4359 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1p,c2p));
4201
4202 4359 sets_1 := ConnectUtil.addArrayConnection(sets, c1, f1, c2, f2, source, ct);
4203 4359 then
4204 (cache,env,ih,sets_1,DAE.emptyDae,graph);
4205
4206 // Connection of connectors with an equality constraint.
4207 case (cache, env, ih, sets, pre, c1, f1, t1 as DAE.T_COMPLEX(equalityConstraint=SOME((fpath1,idim1,inlineType1))), c2, f2, t2 as DAE.T_COMPLEX(equalityConstraint=SOME(_)), ct as DAE.POTENTIAL(), (graph as ConnectionGraph.GRAPH(updateGraph = true)))
4208 algorithm
4209 806 (cache,c1_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c1);
4210 806 (cache,c2_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c2);
4211 // Connect components ignoring equality constraints
4212 806 (cache,env,ih,sets_1,dae,_) :=
4213 connectComponents(cache, env, ih, sets, pre, c1, f1, t1, vt1, c2, f2,
4214 t2, vt2, ct, io1, io2, ConnectionGraph.NOUPDATE_EMPTY, info);
4215
4216 // set the source of this element
4217 806 source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4218
4219 // Add an edge to connection graph. The edge contains the
4220 // dae to be added in the case where the edge is broken.
4221 806 zeroVector := Expression.makeRealArrayOfZeros(idim1);
4222 806 crefExp1 := Expression.crefExp(c1_1);
4223 806 crefExp2 := Expression.crefExp(c2_1);
4224 1612 equalityConstraintFunctionReturnType :=
4225 DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_INTEGER(idim1)});
4226
4227 806 source := ElementSource.addAdditionalComment(source, " equation generated by overconstrained connection graph breaking");
4228
4229 1612 breakDAEElements :=
4230 {DAE.ARRAY_EQUATION({DAE.DIM_INTEGER(idim1)}, zeroVector,
4231 DAE.CALL(fpath1,{crefExp1, crefExp2},
4232 DAE.CALL_ATTR(
4233 equalityConstraintFunctionReturnType,
4234 false, false, false, false, inlineType1, DAE.NO_TAIL(), DAE.NoReturn.RETURNS)), // use the inline type
4235 source // set the origin of the element
4236 )};
4237 806 graph := ConnectionGraph.addConnection(graph, c1_1, c2_1, breakDAEElements);
4238
4239 // deal with equalityConstraint function!
4240 // instantiate and add the equalityConstraint function to the dae function tree!
4241 806 (cache,equalityConstraintFunction,env) := Lookup.lookupClass(cache,env,fpath1);
4242 806 (cache,fpath1) := Inst.makeFullyQualified(cache,env,fpath1);
4243 806 cache := FCore.addCachedInstFuncGuard(cache,fpath1);
4244 806 (cache,env,ih) :=
4245 InstFunction.implicitFunctionInstantiation(cache,env,ih,DAE.NOMOD(),DAE.NOPRE(),equalityConstraintFunction,{});
4246 806 then
4247 (cache,env,ih,sets_1,dae,graph);
4248
4249 // Connection of connectors with an equality constraint extending BASIC TYPES
4250 case (cache, env, ih, sets, pre, c1, f1, DAE.T_SUBTYPE_BASIC(complexType = t1, equalityConstraint=SOME((fpath1,idim1,inlineType1))), c2, f2, DAE.T_SUBTYPE_BASIC(complexType = t2, equalityConstraint=SOME(_)), ct as DAE.POTENTIAL(), (graph as ConnectionGraph.GRAPH(updateGraph = true)))
4251 algorithm
4252 ✗ (cache,c1_1) := PrefixUtil.prefixCref(cache, env, ih, pre, c1);
4253 ✗ (cache,c2_1) := PrefixUtil.prefixCref(cache, env, ih, pre, c2);
4254 // Connect components ignoring equality constraints
4255 ✗ (cache,env,ih,sets_1,dae,_) :=
4256 connectComponents(cache, env, ih, sets, pre, c1, f1, t1, vt1, c2, f2,
4257 t2, vt2, ct, io1, io2, ConnectionGraph.NOUPDATE_EMPTY, info);
4258
4259 // set the source of this element
4260 ✗ source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4261
4262 // Add an edge to connection graph. The edge contains the
4263 // dae to be added in the case where the edge is broken.
4264 ✗ zeroVector := Expression.makeRealArrayOfZeros(idim1);
4265 ✗ crefExp1 := Expression.crefExp(c1_1);
4266 ✗ crefExp2 := Expression.crefExp(c2_1);
4267 ✗ equalityConstraintFunctionReturnType :=
4268 DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_INTEGER(idim1)});
4269
4270 ✗ source := ElementSource.addAdditionalComment(source, " equation generated by overconstrained connection graph breaking");
4271
4272 ✗ breakDAEElements :=
4273 {DAE.ARRAY_EQUATION({DAE.DIM_INTEGER(idim1)}, zeroVector,
4274 DAE.CALL(fpath1,{crefExp1, crefExp2},
4275 DAE.CALL_ATTR(
4276 equalityConstraintFunctionReturnType,
4277 false, false, false, false, inlineType1, DAE.NO_TAIL(), DAE.NoReturn.RETURNS)), // use the inline type
4278 source // set the origin of the element
4279 )};
4280 ✗ graph := ConnectionGraph.addConnection(graph, ComponentReferenceBasics.crefStripLastSubs(c1_1), ComponentReferenceBasics.crefStripLastSubs(c2_1), breakDAEElements);
4281
4282 // deal with equalityConstraint function!
4283 // instantiate and add the equalityConstraint function to the dae function tree!
4284 ✗ (cache,equalityConstraintFunction,env) := Lookup.lookupClass(cache,env,fpath1);
4285 ✗ (cache,fpath1) := Inst.makeFullyQualified(cache,env,fpath1);
4286 ✗ cache := FCore.addCachedInstFuncGuard(cache,fpath1);
4287 ✗ (cache,env,ih) :=
4288 InstFunction.implicitFunctionInstantiation(cache,env,ih,DAE.NOMOD(),DAE.NOPRE(),equalityConstraintFunction,{});
4289 ✗ then
4290 (cache,env,ih,sets_1,dae,graph);
4291
4292 // Complex types t1 extending basetype
4293 case (cache, env, ih, sets, pre, c1, f1, DAE.T_SUBTYPE_BASIC(complexType = bc_tp1), c2, f2, t2, ct, graph)
4294 algorithm
4295 23 (cache,_,ih,sets_1,dae,graph) := connectComponents(cache, env, ih, sets,
4296 pre, c1, f1, bc_tp1, vt1, c2, f2, t2, vt2, ct, io1, io2, graph, info);
4297 23 then
4298 (cache,env,ih,sets_1,dae,graph);
4299
4300 // Complex types t2 extending basetype
4301 case (cache, env, ih, sets, pre, c1, f1, t1, c2, f2, DAE.T_SUBTYPE_BASIC(complexType = bc_tp2), ct, graph)
4302 algorithm
4303 23 (cache,_,ih,sets_1,dae,graph) := connectComponents(cache, env, ih, sets,
4304 pre, c1, f1, t1, vt1, c2, f2, bc_tp2, vt2, ct, io1, io2, graph, info);
4305 23 then
4306 (cache,env,ih,sets_1,dae,graph);
4307
4308 // Connection of ExternalObject!
4309 case (cache, env, ih, sets, pre, c1, f1, DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(), varLst = {}), c2, f2, DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(), varLst = {}), _, graph)
4310 algorithm
4311 ✗ (cache,c1_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c1);
4312 ✗ (cache,c2_1) := PrefixUtil.prefixCref(cache,env,ih,pre, c2);
4313
4314 // set the source of this element
4315 ✗ source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre, (c1_1,c2_1));
4316
4317 ✗ sets_1 := ConnectUtil.addConnection(sets, c1, f1, c2, f2, inConnectorType, source);
4318 ✗ then
4319 (cache,env,ih,sets_1,DAE.emptyDae,graph);
4320
4321 // Connection of complex connector, e.g. Pin
4322 case (cache, env, ih, sets, pre, c1, f1, DAE.T_COMPLEX(varLst = l1), c2, f2, DAE.T_COMPLEX(varLst = l2), ct, graph)
4323 algorithm
4324 3563 (cache,_,ih,sets_1,dae,graph) := connectVars(cache, env, ih, sets, pre,
4325 c1, f1, l1, vt1, c2, f2, l2, vt2, ct, io1, io2, graph, info);
4326 3561 then
4327 (cache,env,ih,sets_1,dae,graph);
4328
4329 // Error
4330 case (cache, env, ih, _, pre, c1, _, t1, c2, _, t2, _, _)
4331 algorithm
4332 2 (cache,_) := PrefixUtil.prefixCref(cache,env,ih,pre, c1);
4333 2 (cache,_) := PrefixUtil.prefixCref(cache,env,ih,pre, c2);
4334 2 c1_str := ComponentReferenceBasics.printComponentRefStr(c1);
4335 2 t1_str := TypesDump.unparseType(t1);
4336 2 c2_str := ComponentReferenceBasics.printComponentRefStr(c2);
4337 2 t2_str := TypesDump.unparseType(t2);
4338 2 c1_str := stringAppendList({"\n",c1_str," type:\n",t1_str});
4339 2 c2_str := stringAppendList({"\n",c2_str," type:\n",t2_str});
4340 2 Error.addSourceMessage(Error.INVALID_CONNECTOR_VARIABLE, {c1_str,c2_str},info);
4341 2 then
4342 fail();
4343
4344 else
4345 algorithm
4346
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
4347 ✗ Debug.trace("- InstSection.connectComponents failed\n");
4348 ✗ then
4349 fail();
4350 end matchcontinue;
4351 end connectComponents;
4352
4353 protected function generateConnectAssert
4354 input DAE.Exp inLhsExp;
4355 input DAE.Exp inRhsExp;
4356 input DAE.ElementSource inSource;
4357 output DAE.Element outAssert;
4358 protected
4359 DAE.Exp exp;
4360 algorithm
4361 99 exp := DAE.RELATION(inLhsExp, DAE.EQUAL(DAE.T_BOOL_DEFAULT), inRhsExp, -1, NONE());
4362 99 (exp, _) := ExpressionSimplify.simplify(exp);
4363 99 outAssert := DAE.ASSERT(exp, DAE.SCONST("automatically generated from connect"),
4364 DAE.ASSERTIONLEVEL_ERROR, inSource);
4365 end generateConnectAssert;
4366
4367 protected function connectArrayComponents
4368 input FCore.Cache inCache;
4369 input FCore.Graph inEnv;
4370 input InnerOuter.InstHierarchy inIH;
4371 input Connect.Sets inSets;
4372 input DAE.Prefix inPrefix;
4373 input list<DAE.ComponentRef> inLhsCrefs;
4374 input Connect.Face inLhsFace;
4375 input DAE.Type inLhsType;
4376 input SCode.Variability inLhsVar;
4377 input Absyn.InnerOuter inLhsIO;
4378 input list<DAE.ComponentRef> inRhsCrefs;
4379 input Connect.Face inRhsFace;
4380 input DAE.Type inRhsType;
4381 input SCode.Variability inRhsVar;
4382 input Absyn.InnerOuter inRhsIO;
4383 input DAE.ConnectorType inConnectorType;
4384 input ConnectionGraph.ConnectionGraph inGraph;
4385 input SourceInfo inInfo;
4386 output FCore.Cache outCache;
4387 output FCore.Graph outEnv;
4388 output InnerOuter.InstHierarchy outIH;
4389 output Connect.Sets outSets;
4390 output DAE.DAElist outDae;
4391 output ConnectionGraph.ConnectionGraph outGraph;
4392 algorithm
4393 (outCache, outEnv, outIH, outSets, outDae, outGraph) :=
4394 match(inLhsCrefs, inRhsCrefs)
4395 local
4396 DAE.ComponentRef lhs, rhs;
4397 list<DAE.ComponentRef> rest_lhs, rest_rhs;
4398 FCore.Cache cache;
4399 FCore.Graph env;
4400 InstanceHierarchy ih;
4401 Connect.Sets sets;
4402 DAE.DAElist dae1, dae2;
4403 ConnectionGraph.ConnectionGraph graph;
4404
4405 case (lhs :: rest_lhs, rhs :: rest_rhs)
4406 algorithm
4407 296 (cache, env, ih, sets, dae1, graph) := connectComponents(inCache, inEnv,
4408 inIH, inSets, inPrefix, lhs, inLhsFace, inLhsType, inLhsVar, rhs,
4409 inRhsFace, inRhsType, inRhsVar, inConnectorType, inLhsIO, inRhsIO,
4410 inGraph, inInfo);
4411 296 (cache, env, ih, sets, dae2, graph) := connectArrayComponents(cache,
4412 env, ih, sets, inPrefix, rest_lhs, inLhsFace, inLhsType, inLhsVar,
4413 inLhsIO, rest_rhs, inRhsFace, inRhsType, inRhsVar, inRhsIO,
4414 inConnectorType, graph, inInfo);
4415 296 dae1 := DAEUtil.joinDaes(dae1, dae2);
4416 296 then
4417 (cache, env, ih, sets, dae1, graph);
4418
4419 else (inCache, inEnv, inIH, inSets, DAE.emptyDae, inGraph);
4420
4421 end match;
4422 end connectArrayComponents;
4423
4424 protected function connectVars
4425 "This function connects two subcomponents by adding the component
4426 name to the current path and recursively connecting the components
4427 using the function connectComponents."
4428 input FCore.Cache inCache;
4429 input FCore.Graph inEnv;
4430 input InnerOuter.InstHierarchy inIH;
4431 input Connect.Sets inSets;
4432 input DAE.Prefix inPrefix;
4433 input DAE.ComponentRef inComponentRef3;
4434 input Connect.Face inFace4;
4435 input list<DAE.Var> inTypesVarLst5;
4436 input SCode.Variability vt1;
4437 input DAE.ComponentRef inComponentRef6;
4438 input Connect.Face inFace7;
4439 input list<DAE.Var> inTypesVarLst8;
4440 input SCode.Variability vt2;
4441 input DAE.ConnectorType inConnectorType;
4442 input Absyn.InnerOuter io1;
4443 input Absyn.InnerOuter io2;
4444 input ConnectionGraph.ConnectionGraph inGraph;
4445 input SourceInfo info;
4446 output FCore.Cache outCache;
4447 output FCore.Graph outEnv;
4448 output InnerOuter.InstHierarchy outIH;
4449 output Connect.Sets outSets;
4450 output DAE.DAElist outDae;
4451 output ConnectionGraph.ConnectionGraph outGraph;
4452 algorithm
4453 (outCache,outEnv,outIH,outSets,outDae,outGraph):=
4454 match (inCache, inEnv, inIH, inSets, inComponentRef3, inFace4, inTypesVarLst5, inComponentRef6, inFace7, inTypesVarLst8, inGraph)
4455 local
4456 Connect.Sets sets,sets_1,sets_2;
4457 FCore.Graph env;
4458 DAE.ComponentRef c1_1,c2_1,c1,c2;
4459 DAE.DAElist dae,dae2,dae_1;
4460 Connect.Face f1,f2;
4461 String n;
4462 DAE.Attributes attr1,attr2;
4463 DAE.ConnectorType ct;
4464 DAE.Type ty1,ty2;
4465 list<DAE.Var> xs1,xs2;
4466 SCode.Variability vta,vtb;
4467 DAE.Type ty_2;
4468 FCore.Cache cache;
4469 ConnectionGraph.ConnectionGraph graph;
4470 InstanceHierarchy ih;
4471
4472 case (cache, env, ih, sets, _, _, {}, _, _, {}, graph)
4473 then (cache,env,ih,sets,DAE.emptyDae,graph);
4474 case (cache, env, ih, sets, c1, f1, (DAE.TYPES_VAR(name = n,attributes =(attr1 as DAE.ATTR(connectorType = ct,variability = vta)),ty = ty1) :: xs1), c2, f2, (DAE.TYPES_VAR(attributes = (attr2 as DAE.ATTR(variability = vtb)),ty = ty2) :: xs2), graph)
4475 algorithm
4476 9257 ty_2 := Types.simplifyType(ty1);
4477 9257 ct := propagateConnectorType(inConnectorType, ct);
4478 9257 c1_1 := ComponentReference.crefPrependIdent(c1, n, {}, ty_2);
4479 9257 c2_1 := ComponentReference.crefPrependIdent(c2, n, {}, ty_2);
4480 9257 checkConnectTypes(c1_1, ty1, f1, attr1, c2_1, ty2, f2, attr2, info);
4481 9255 (cache,_,ih,sets_1,dae,graph) := connectComponents(cache,env,ih,sets, inPrefix, c1_1, f1, ty1, vta, c2_1, f2, ty2, vtb, ct, io1, io2, graph, info);
4482 9255 (cache,_,ih,sets_2,dae2,graph) := connectVars(cache,env,ih,sets_1, inPrefix, c1, f1, xs1,vt1, c2, f2, xs2, vt2, inConnectorType, io1, io2, graph, info);
4483 9255 dae_1 := DAEUtil.joinDaes(dae, dae2);
4484 9255 then
4485 (cache,env,ih,sets_2,dae_1,graph);
4486 end match;
4487 end connectVars;
4488
4489 protected function propagateConnectorType
4490 input DAE.ConnectorType inConnectorType;
4491 input DAE.ConnectorType inSubConnectorType;
4492 output DAE.ConnectorType outSubConnectorType;
4493 algorithm
4494 outSubConnectorType := match inConnectorType
4495 case DAE.POTENTIAL() then inSubConnectorType;
4496 else inConnectorType;
4497 end match;
4498 end propagateConnectorType;
4499
4500 protected function expandArrayDimension
4501 "Expands an array into elements given a dimension, i.e.
4502 (3, x) => {x[1], x[2], x[3]}"
4503 input DAE.Dimension inDim;
4504 input DAE.Exp inArray;
4505 output list<DAE.Exp> outExpl;
4506 algorithm
4507 outExpl := matchcontinue(inDim, inArray)
4508 local
4509 list<DAE.Exp> expl;
4510 Integer sz;
4511 list<Integer> ints;
4512 Absyn.Path name;
4513 list<String> ls;
4514
4515 case (_, DAE.ARRAY(array = outExpl)) then outExpl;
4516
4517 // Empty integer list. List.intRange is not defined for size < 1,
4518 // so we need to handle empty lists here.
4519 case (DAE.DIM_INTEGER(integer = 0), _) then {};
4520 case (DAE.DIM_INTEGER(integer = sz), _)
4521 algorithm
4522 14165 ints := List.intRange(sz);
4523 14165 expl := List.map1(ints, makeAsubIndex, inArray);
4524 then
4525 expl;
4526 case (DAE.DIM_BOOLEAN(), _)
4527 algorithm
4528 ✗ expl := {ExpressionSimplify.simplify1(Expression.makeASUB(inArray, {DAE.BCONST(false)})),
4529 ExpressionSimplify.simplify1(Expression.makeASUB(inArray, {DAE.BCONST(true)}))};
4530 then
4531 expl;
4532 case (DAE.DIM_ENUM(enumTypeName = name, literals = ls), _)
4533 algorithm
4534 ✗ expl := makeEnumLiteralIndices(name, ls, 1, inArray);
4535 then
4536 expl;
4537 /* adrpo: these are completly wrong!
4538 will result in equations 1 = 1!
4539 case (DAE.DIM_EXP(exp = _), _) then {DAE.ICONST(1)};
4540 case (DAE.DIM_UNKNOWN(), _) then {DAE.ICONST(1)};
4541 */
4542 case (DAE.DIM_UNKNOWN(), _)
4543 algorithm
4544
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
12 true := Flags.getConfigBool(Flags.CHECK_MODEL);
4545 2 ints := List.intRange(1); // try to make an array index of 1 when we don't know the dimension
4546 2 expl := List.map1(ints, makeAsubIndex, inArray);
4547 then
4548 expl;
4549 end matchcontinue;
4550 end expandArrayDimension;
4551
4552 protected function makeAsubIndex
4553 "Creates an ASUB expression given an expression and an integer index."
4554 input Integer index;
4555 input DAE.Exp expr;
4556 output DAE.Exp asub;
4557 algorithm
4558 84728 (asub,_) := ExpressionSimplify.simplify1(Expression.makeASUB(expr, {DAE.ICONST(index)}));
4559 end makeAsubIndex;
4560
4561 protected function makeEnumLiteralIndices
4562 "Creates a list of enumeration literal expressions from an enumeration."
4563 input Absyn.Path enumTypeName;
4564 input list<String> enumLiterals;
4565 input Integer enumIndex;
4566 input DAE.Exp expr;
4567 output list<DAE.Exp> enumIndices;
4568 algorithm
4569 enumIndices := match enumLiterals
4570 local
4571 String l;
4572 list<String> ls;
4573 DAE.Exp e;
4574 list<DAE.Exp> expl;
4575 Absyn.Path enum_type_name;
4576 Integer index;
4577 case {} then {};
4578 case l :: ls
4579 algorithm
4580 ✗ enum_type_name := AbsynUtil.joinPaths(enumTypeName, Absyn.IDENT(l));
4581 ✗ e := DAE.ENUM_LITERAL(enum_type_name, enumIndex);
4582 ✗ (e,_) := ExpressionSimplify.simplify1(Expression.makeASUB(expr, {e}));
4583 ✗ e := if Expression.isCref(e) then Expression.unliftExp(e) else e;
4584 ✗ index := enumIndex + 1;
4585 ✗ expl := makeEnumLiteralIndices(enumTypeName, ls, index, expr);
4586 then
4587 e :: expl;
4588 end match;
4589 end makeEnumLiteralIndices;
4590
4591 protected function getVectorizedCref
4592 "for a vectorized cref, return the originial cref without vector subscripts"
4593 input DAE.Exp crefOrArray;
4594 output DAE.Exp cref;
4595 algorithm
4596 cref := match crefOrArray
4597 local
4598 DAE.ComponentRef cr;
4599 DAE.Type t;
4600 DAE.Exp crefExp;
4601
4602 case cref as DAE.CREF(_,_) then cref;
4603
4604 case DAE.ARRAY(_,_,DAE.CREF(cr,t)::_)
4605 algorithm
4606 ✗ cr := ComponentReferenceBasics.crefStripLastSubs(cr);
4607 ✗ crefExp := Expression.makeCrefExp(cr, t);
4608 then crefExp;
4609 end match;
4610 end getVectorizedCref;
4611
4612
4613 protected function checkWhenAlgorithm
4614 "@author: adrpo
4615 checks when equation for:
4616 - when alg in when alg is not allowed
4617 - reinit in when with initial condition is not allowed
4618 when (initial()) then
4619 reinit(x, y);
4620 end when;
4621 "
4622 input SCode.Statement inWhenAlgorithm;
4623 algorithm
4624
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 115 times.
115 true := checkForReinitInWhenInitialAlg(inWhenAlgorithm);
4625 115 checkForNestedWhenInStatements(inWhenAlgorithm);
4626 end checkWhenAlgorithm;
4627
4628 protected function checkForReinitInWhenInitialAlg
4629 "Fails if a when (initial()) alg contains
4630 reinit which is not allowed in Modelica."
4631 input SCode.Statement inWhenAlgorithm;
4632 output Boolean outOK;
4633 algorithm
4634 outOK := matchcontinue inWhenAlgorithm
4635 local
4636 Absyn.Exp exp;
4637 SourceInfo info;
4638 list<SCode.Statement> algs;
4639
4640 // add an error
4641 case SCode.ALG_WHEN_A(branches = (exp, algs)::_ , info = info)
4642 algorithm
4643
2/2
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 6 times.
115 true := AbsynUtil.expContainsInitial(exp);
4644
1/2
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
6 true := SCodeUtil.algorithmsContainReinit(algs);
4645 ✗ Error.addSourceMessage(Error.REINIT_IN_WHEN_INITIAL, {}, info);
4646 then false;
4647
4648 else true;
4649
4650 end matchcontinue;
4651 end checkForReinitInWhenInitialAlg;
4652
4653 protected function checkForNestedWhenInStatements
4654 "Fails if a when alg contains nested when
4655 alg, which are not allowed in Modelica.
4656 An error message is added when failing."
4657 input SCode.Statement inWhenAlgorithm;
4658 protected
4659 list<tuple<Absyn.Exp, list<SCode.Statement>>> branches;
4660 SourceInfo info;
4661 list<SCode.Statement> body;
4662 algorithm
4663
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 115 times.
115 SCode.ALG_WHEN_A(branches = branches, info = info) := inWhenAlgorithm;
4664
4665
2/2
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 114 times.
256 for branch in branches loop
4666 142 (_, body) := branch;
4667
4668
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 141 times.
142 if containsWhenStatements(body) then
4669 1 Error.addSourceMessageAndFail(Error.NESTED_WHEN, {}, info);
4670 end if;
4671 end for;
4672 end checkForNestedWhenInStatements;
4673
4674 protected function checkWhenEquation
4675 "@author: adrpo
4676 checks when equation for:
4677 - when equation in when equation is not allowed
4678 - reinit in when with initial condition is not allowed
4679 when (initial()) then
4680 reinit(x, y);
4681 end when;"
4682 input SCode.Equation inWhenEq;
4683 algorithm
4684 ✗ true := checkForReinitInWhenInitialEq(inWhenEq);
4685 ✗ checkForNestedWhenInEquation(inWhenEq);
4686 end checkWhenEquation;
4687
4688 protected function checkForReinitInWhenInitialEq
4689 "Fails if a when (initial()) equation contains
4690 reinit which is not allowed in Modelica."
4691 input SCode.Equation inWhenEq;
4692 output Boolean outOK;
4693 algorithm
4694 outOK := matchcontinue inWhenEq
4695 local
4696 Absyn.Exp exp;
4697 SourceInfo info;
4698 list<SCode.Equation> el;
4699
4700 // Add an error for when initial() then reinit().
4701 case SCode.EQ_WHEN(condition = exp, eEquationLst = el, info = info)
4702 algorithm
4703 ✗ true := AbsynUtil.expContainsInitial(exp);
4704 ✗ true := SCodeUtil.equationsContainReinit(el);
4705 ✗ Error.addSourceMessage(Error.REINIT_IN_WHEN_INITIAL, {}, info);
4706 then
4707 false;
4708
4709 else true;
4710
4711 end matchcontinue;
4712 end checkForReinitInWhenInitialEq;
4713
4714 protected function checkForNestedWhenInEquation
4715 "Fails if a when equation contains nested when
4716 equations, which are not allowed in Modelica.
4717 An error message is added when failing."
4718 input SCode.Equation inWhenEq;
4719 algorithm
4720 () := match inWhenEq
4721 local
4722 list<SCode.Equation> eqs;
4723 list<list<SCode.Equation>> eqs_lst;
4724 list<tuple<Absyn.Exp, list<SCode.Equation>>> tpl_el;
4725
4726 // continue if when equations are not nested
4727 case SCode.EQ_WHEN(eEquationLst = eqs, elseBranches = tpl_el)
4728 algorithm
4729 ✗ checkForNestedWhenInEqList(eqs);
4730 ✗ eqs_lst := List.map(tpl_el, Util.tuple22);
4731 ✗ List.map_0(eqs_lst, checkForNestedWhenInEqList);
4732 then
4733 ();
4734
4735 end match;
4736 end checkForNestedWhenInEquation;
4737
4738 protected function checkForNestedWhenInEqList
4739 "Helper function to checkForNestedWhen. Searches for nested when equations in
4740 a list of equations."
4741 input list<SCode.Equation> inEqs;
4742 algorithm
4743 ✗ List.map_0(inEqs, checkForNestedWhenInEq);
4744 end checkForNestedWhenInEqList;
4745
4746 protected function checkForNestedWhenInEq
4747 "Helper function to checkForNestedWhen. Searches for nested when equations in
4748 an equation."
4749 input SCode.Equation inEq;
4750 algorithm
4751 () := match inEq
4752 local
4753 list<SCode.Equation> eqs;
4754 list<list<SCode.Equation>> eqs_lst;
4755 Absyn.ComponentRef cr1, cr2;
4756 SourceInfo info;
4757 String cr1_str, cr2_str;
4758
4759 case SCode.EQ_WHEN(info = info)
4760 algorithm
4761 ✗ Error.addSourceMessage(Error.NESTED_WHEN, {}, info);
4762 ✗ then
4763 fail();
4764
4765 case SCode.EQ_IF(thenBranch = eqs_lst, elseBranch = eqs)
4766 algorithm
4767 ✗ List.map_0(eqs_lst, checkForNestedWhenInEqList);
4768 ✗ checkForNestedWhenInEqList(eqs);
4769 then
4770 ();
4771
4772 case SCode.EQ_FOR(eEquationLst = eqs)
4773 algorithm
4774 ✗ checkForNestedWhenInEqList(eqs);
4775 then
4776 ();
4777
4778 case SCode.EQ_EQUALS() then ();
4779 case SCode.EQ_PDE() then ();
4780
4781 // connect is not allowed in when equations.
4782 case SCode.EQ_CONNECT(crefLeft = cr1, crefRight = cr2, info = info)
4783 algorithm
4784 1 cr1_str := Dump.printComponentRefStr(cr1);
4785 1 cr2_str := Dump.printComponentRefStr(cr2);
4786 1 Error.addSourceMessage(Error.CONNECT_IN_WHEN, {cr1_str, cr2_str}, info);
4787 1 then
4788 fail();
4789
4790 case SCode.EQ_ASSERT() then ();
4791 case SCode.EQ_TERMINATE() then ();
4792 case SCode.EQ_REINIT() then ();
4793 case SCode.EQ_NORETCALL() then ();
4794
4795 case _
4796 algorithm
4797 ✗ true := Flags.isSet(Flags.FAILTRACE);
4798 ✗ Debug.trace("- InstSection.checkForNestedWhenInEq failed.\n");
4799 ✗ then
4800 fail();
4801
4802 end match;
4803 end checkForNestedWhenInEq;
4804
4805 protected function instAssignment
4806 input FCore.Cache inCache;
4807 input FCore.Graph inEnv;
4808 input InnerOuter.InstHierarchy ih;
4809 input DAE.Prefix inPre;
4810 input SCode.Statement alg;
4811 input DAE.ElementSource source;
4812 input SCode.Initial initial_;
4813 input Boolean impl;
4814 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
4815 input Integer numError;
4816 output FCore.Cache outCache;
4817 output list<DAE.Statement> stmts "more statements due to loop unrolling";
4818 algorithm
4819 (outCache,stmts) := matchcontinue (inCache, inEnv, inPre, alg)
4820 local
4821 FCore.Cache cache;
4822 FCore.Graph env;
4823 DAE.Exp e_1;
4824 DAE.Properties eprop;
4825 DAE.Prefix pre;
4826 Absyn.Exp var;
4827 Absyn.Exp value;
4828 SourceInfo info;
4829 String str;
4830
4831 case (cache, env, pre, SCode.ALG_ASSIGN(assignComponent=var,value=value,info=info))
4832 algorithm
4833 34597 (cache,e_1,eprop) := Static.elabExp(cache,env,value,impl,true,pre,info);
4834 34558 (cache,stmts) := instAssignment2(cache,env,ih,pre,var,value,e_1,eprop,info,ElementSource.addAnnotation(source, alg.comment),initial_,impl,unrollForLoops,numError);
4835 then (cache,stmts);
4836
4837 case (cache, env, pre, SCode.ALG_ASSIGN(value=value,info=info))
4838 algorithm
4839
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 true := numError == Error.getNumErrorMessages();
4840 ✗ failure(Static.elabExp(cache,env,value,impl,true,pre,info));
4841 ✗ str := Dump.unparseAlgorithmStr(SCodeUtil.statementToAlgorithmItem(alg));
4842 ✗ Error.addSourceMessage(Error.ASSIGN_RHS_ELABORATION,{str},info);
4843 ✗ then fail();
4844 end matchcontinue;
4845 end instAssignment;
4846
4847 protected function instAssignment2
4848 input FCore.Cache inCache;
4849 input FCore.Graph inEnv;
4850 input InnerOuter.InstHierarchy inIH;
4851 input DAE.Prefix inPre;
4852 input Absyn.Exp var;
4853 input Absyn.Exp inRhs;
4854 input DAE.Exp value;
4855 input DAE.Properties props;
4856 input SourceInfo info;
4857 input DAE.ElementSource inSource;
4858 input SCode.Initial initial_;
4859 input Boolean inImpl;
4860 input Boolean unrollForLoops "we should unroll for loops if they are part of an algorithm in a model";
4861 input Integer numError;
4862 output FCore.Cache outCache;
4863 output list<DAE.Statement> stmts "more statements due to loop unrolling";
4864 protected
4865 Absyn.Exp varNoComment, inRhsNoComment;
4866 algorithm
4867 34558 varNoComment := AbsynUtil.stripCommentExpressions(var);
4868 34558 inRhsNoComment := AbsynUtil.stripCommentExpressions(inRhs);
4869 () := match varNoComment
4870 local
4871 Absyn.Exp lhs;
4872 case Absyn.TUPLE({lhs})
4873 algorithm
4874 ✗ (outCache,stmts) := instAssignment2(inCache,inEnv,inIH,inPre,lhs,inRhsNoComment,value,props,info,inSource,initial_,inImpl,unrollForLoops,numError);
4875 ✗ return;
4876 then ();
4877 else ();
4878 end match;
4879 (outCache,stmts) := matchcontinue (inCache,varNoComment,value,props)
4880 local
4881 DAE.ComponentRef ce,ce_1;
4882 DAE.Properties cprop,eprop,prop,prop1,prop2;
4883 DAE.Exp e_1, e_2, cre, cre2, e2_2, e2_2_2, lhs, rhs;
4884 DAE.Statement stmt;
4885 Absyn.ComponentRef cr;
4886 Absyn.Exp e,e1,e2, left;
4887 list<Absyn.Exp> expl;
4888 list<DAE.Exp> expl_1,expl_2;
4889 list<DAE.Properties> cprops, eprops;
4890 list<DAE.Attributes> attrs;
4891 DAE.Type lt,rt,ty,t;
4892 String s,lhs_str,rhs_str,lt_str,rt_str,s1,s2;
4893 FCore.Cache cache;
4894 DAE.Pattern pattern;
4895 DAE.Attributes attr;
4896 DAE.ElementSource source;
4897 DAE.Dimension lhs_dim, rhs_dim;
4898
4899 // v := expr; where v or expr are size 0
4900 case (cache,Absyn.CREF(cr),e_1,_)
4901 algorithm
4902
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 32975 times.
65887 (cache,lhs as DAE.CREF(_,t),_,attr) :=
4903 Static.elabCrefNoEval(cache, inEnv, cr, inImpl, false, inPre, info);
4904
5/6
✓ Branch 0 taken 32226 times.
✓ Branch 1 taken 749 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 749 times.
✓ Branch 4 taken 140 times.
✓ Branch 5 taken 609 times.
32975 DAE.T_ARRAY( dims = {_}) := t;
4905 609 rhs := e_1;
4906 609 Static.checkAssignmentToInput(varNoComment, attr, inEnv, false, info);
4907
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 609 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 609 times.
609 DAE.T_ARRAY(dims = lhs_dim :: _) := Expression.typeof(lhs);
4908
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 609 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 609 times.
609 DAE.T_ARRAY(dims = rhs_dim :: _) := Expression.typeof(rhs);
4909
2/2
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 3 times.
609 {} := expandArrayDimension(lhs_dim, lhs);
4910
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
3 {} := expandArrayDimension(rhs_dim, rhs);
4911 then
4912 (cache,{});
4913
4914 // v := expr;
4915 case (cache,Absyn.CREF(cr),e_1,eprop)
4916 algorithm
4917
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 32973 times.
32980 (cache,DAE.CREF(ce,t),cprop,attr) :=
4918 Static.elabCrefNoEval(cache, inEnv, cr, inImpl, false, inPre, info);
4919 32973 Static.checkAssignmentToInput(varNoComment, attr, inEnv, false, info);
4920 32968 (cache, ce_1) := Static.canonCref(cache, inEnv, ce, inImpl);
4921 32939 (cache, ce_1) := PrefixUtil.prefixCrefInnerOuter(cache, inEnv, inIH, ce_1, inPre);
4922
4923 1 (cache, t) := PrefixUtil.prefixExpressionsInType(cache, inEnv, inIH, inPre, t);
4924
4925 1 lt := Types.getPropType(cprop);
4926 1 (cache, lt) := PrefixUtil.prefixExpressionsInType(cache, inEnv, inIH, inPre, lt);
4927 1 cprop := Types.setPropType(cprop, lt);
4928
4929 1 (cache, e_1, eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
4930 1 (cache, e_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e_1, inPre);
4931
4932 1 rt := Types.getPropType(eprop);
4933 1 (cache, rt) := PrefixUtil.prefixExpressionsInType(cache, inEnv, inIH, inPre, rt);
4934 1 eprop := Types.setPropType(eprop, rt);
4935
4936 1 source := ElementSource.addElementSourceFileInfo(inSource, info);
4937 1 stmt := makeAssignment(Expression.makeCrefExp(ce_1,t), cprop, e_2, eprop, attr, initial_, source);
4938 then
4939 (cache,{stmt});
4940
4941 // der(x) := ...
4942 case (cache,e2 as Absyn.CALL(function_ = Absyn.CREF_IDENT(name="der"),functionArgs=(Absyn.FUNCTIONARGS(args={Absyn.CREF(cr)})) ),e_1,eprop)
4943 algorithm
4944 ✗ (cache,_,cprop,attr) :=
4945 Static.elabCrefNoEval(cache,inEnv, cr, inImpl,false,inPre,info);
4946 ✗ (cache,(e2_2 as DAE.CALL()),_) :=
4947 Static.elabExp(cache,inEnv, e2, inImpl,true,inPre,info);
4948 ✗ (cache,e2_2_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e2_2, inPre);
4949 ✗ (cache, e_1, eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
4950 ✗ (cache,e_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e_1, inPre);
4951 ✗ source := ElementSource.addElementSourceFileInfo(inSource, info);
4952 ✗ stmt := makeAssignment(e2_2_2, cprop, e_2, eprop, attr /*SCode.RW()*/, initial_, source);
4953 then
4954 (cache,{stmt});
4955
4956 // v[i] := expr (in e.g. for loops)
4957 case (cache,Absyn.CREF(cr),e_1,eprop)
4958 algorithm
4959 32979 (cache,cre,cprop,attr) :=
4960 Static.elabCrefNoEval(cache,inEnv, cr, inImpl,false,inPre,info);
4961 32979 Static.checkAssignmentToInput(varNoComment, attr, inEnv, false, info);
4962 32974 (cache,cre2) := PrefixUtil.prefixExp(cache, inEnv, inIH, cre, inPre);
4963 32974 (cache, e_1, eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
4964 32974 (cache,e_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e_1, inPre);
4965 32974 source := ElementSource.addElementSourceFileInfo(inSource, info);
4966 32974 stmt := makeAssignment(cre2, cprop, e_2, eprop, attr, initial_, source);
4967 then
4968 (cache,{stmt});
4969
4970 // (v1,v2,..,vn) := func(...)
4971 case (cache,Absyn.TUPLE(expressions = expl),e_1,eprop)
4972 algorithm
4973
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 984 times.
1227 true := List.all(expl, AbsynUtil.isCref);
4974
2/2
✓ Branch 1 taken 218 times.
✓ Branch 2 taken 766 times.
984 (cache, e_1 as DAE.CALL(), eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
4975 766 (cache,e_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e_1, inPre);
4976 766 (cache,expl_1,cprops,attrs) :=
4977 Static.elabExpCrefNoEvalList(cache, inEnv, expl, inImpl, false, inPre, info);
4978 766 Static.checkAssignmentToInputs(expl, attrs, inEnv, info);
4979 766 checkNoDuplicateAssignments(expl_1, info);
4980 759 (cache,expl_2) := PrefixUtil.prefixExpList(cache, inEnv, inIH, expl_1, inPre);
4981 759 source := ElementSource.addElementSourceFileInfo(inSource, info);
4982 759 stmt := Algorithm.makeTupleAssignment(expl_2, cprops, e_2, eprop, initial_, source);
4983 then
4984 (cache,{stmt});
4985
4986 // (v1,v2,..,vn) := match...
4987 case (cache,Absyn.TUPLE(expressions = expl),e_1,eprop)
4988 algorithm
4989
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 245 times.
360 true := Config.acceptMetaModelicaGrammar();
4990
2/2
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 220 times.
245 true := List.all(expl, AbsynUtil.isCref);
4991
2/2
✓ Branch 2 taken 80 times.
✓ Branch 3 taken 140 times.
220 true := Types.isTuple(Types.getPropType(eprop));
4992
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 139 times.
140 (cache, e_1 as DAE.MATCHEXPRESSION(), eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
4993 139 (cache,e_2) := PrefixUtil.prefixExp(cache, inEnv, inIH, e_1, inPre);
4994 139 (cache,expl_1,cprops,attrs) :=
4995 Static.elabExpCrefNoEvalList(cache, inEnv, expl, inImpl, false, inPre, info);
4996 139 Static.checkAssignmentToInputs(expl, attrs, inEnv, info);
4997 139 checkNoDuplicateAssignments(expl_1, info);
4998 139 (cache,expl_2) := PrefixUtil.prefixExpList(cache, inEnv, inIH, expl_1, inPre);
4999 139 source := ElementSource.addElementSourceFileInfo(inSource, info);
5000 139 stmt := Algorithm.makeTupleAssignment(expl_2, cprops, e_2, eprop, initial_, source);
5001 then
5002 (cache,{stmt});
5003
5004 case (cache,left,e_1,prop)
5005 algorithm
5006
2/2
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 675 times.
687 true := Config.acceptMetaModelicaGrammar();
5007 675 ty := Types.getPropType(prop);
5008 675 (e_1,ty) := Types.convertTupleToMetaTuple(e_1,ty);
5009 675 (cache,pattern) := Patternm.elabPatternCheckDuplicateBindings(cache,inEnv,left,ty,info);
5010 667 source := ElementSource.addElementSourceFileInfo(inSource, info);
5011
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 667 times.
667 stmt := if Types.isEmptyOrNoRetcall(ty) then DAE.STMT_NORETCALL(e_1,source) else DAE.STMT_ASSIGN(DAE.T_UNKNOWN_DEFAULT,DAE.PATTERN(pattern),e_1,source);
5012 then (cache,{stmt});
5013
5014 /* Tuple with rhs constant */
5015 case (cache,Absyn.TUPLE(expressions = expl),e_1,eprop)
5016 algorithm
5017
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 time.
9 (cache, e_1 as DAE.TUPLE(PR = expl_1), eprop) := Ceval.cevalIfConstant(cache, inEnv, e_1, eprop, inImpl, info);
5018 1 (cache,expl_2,cprops,attrs) :=
5019 Static.elabExpCrefNoEvalList(cache,inEnv, expl, inImpl,false,inPre,info);
5020 1 Static.checkAssignmentToInputs(expl, attrs, inEnv, info);
5021 1 checkNoDuplicateAssignments(expl_2, info);
5022 1 (cache,expl_2) := PrefixUtil.prefixExpList(cache, inEnv, inIH, expl_2, inPre);
5023 1 eprops := Types.propTuplePropList(eprop);
5024 1 source := ElementSource.addElementSourceFileInfo(inSource, info);
5025 1 stmts := Algorithm.makeAssignmentsList(expl_2, cprops, expl_1, eprops, /* SCode.RW() */ DAE.dummyAttrVar, initial_, source);
5026 then
5027 (cache,stmts);
5028
5029 /* Tuple with lhs being a tuple NOT of crefs => Error */
5030 case (_,e as Absyn.TUPLE(expressions = expl),_,_)
5031 algorithm
5032
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 false := List.all(expl, AbsynUtil.isCref);
5033 ✗ s := Dump.printExpStr(e);
5034 ✗ Error.addSourceMessage(Error.TUPLE_ASSIGN_CREFS_ONLY, {s}, info);
5035 ✗ then
5036 fail();
5037
5038 case (cache,e1 as Absyn.TUPLE(expressions = expl),_,prop2)
5039 algorithm
5040
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 Absyn.CALL() := inRhsNoComment;
5041
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 true := List.all(expl, AbsynUtil.isCref);
5042 8 (cache,e_1,prop1) := Static.elabExpLHS(cache,inEnv,e1,inImpl,false,inPre,info);
5043 8 lt := Types.getPropType(prop1);
5044 8 rt := Types.getPropType(prop2);
5045
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 false := Types.subtype(lt, rt);
5046 ✗ lhs_str := ExpressionBasics.printExpStr(e_1);
5047 ✗ rhs_str := Dump.printExpStr(inRhs);
5048 ✗ lt_str := TypesDump.unparseTypeNoAttr(lt);
5049 ✗ rt_str := TypesDump.unparseTypeNoAttr(rt);
5050 ✗ Types.typeErrorSanityCheck(lt_str, rt_str, info);
5051 ✗ Error.addSourceMessage(Error.ASSIGN_TYPE_MISMATCH_ERROR,{lhs_str,rhs_str,lt_str,rt_str}, info);
5052 ✗ then
5053 fail();
5054
5055 /* Tuple with rhs not CALL or CONSTANT => Error */
5056 case (_,Absyn.TUPLE(expressions = expl),e_1,_)
5057 algorithm
5058
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 true := List.all(expl, AbsynUtil.isCref);
5059
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
8 failure(Absyn.CALL() := inRhsNoComment);
5060 ✗ s := ExpressionBasics.printExpStr(e_1);
5061 ✗ Error.addSourceMessage(Error.TUPLE_ASSIGN_FUNCALL_ONLY, {s}, info);
5062 ✗ then
5063 fail();
5064
5065 else
5066 algorithm
5067
1/2
✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
19 true := numError == Error.getNumErrorMessages();
5068 ✗ s1 := Dump.printExpStr(var);
5069 ✗ s2 := ExpressionBasics.printExpStr(value);
5070 ✗ Error.addSourceMessage(Error.ASSIGN_UNKNOWN_ERROR, {s1,s2}, info);
5071 ✗ then
5072 fail();
5073 end matchcontinue;
5074 end instAssignment2;
5075
5076 function checkNoDuplicateAssignments
5077 input list<DAE.Exp> inExps;
5078 input SourceInfo info;
5079 protected
5080 DAE.Exp exp;
5081 list<DAE.Exp> exps=inExps;
5082 algorithm
5083
2/2
✓ Branch 0 taken 2025 times.
✓ Branch 1 taken 943 times.
2968 while not listEmpty(exps) loop
5084 2025 exp::exps := exps;
5085
2/2
✓ Branch 1 taken 66 times.
✓ Branch 2 taken 1959 times.
2025 if Expression.isWild(exp) then
5086 66 continue;
5087 elseif listMember(exp, exps) then
5088 18 Error.addSourceMessage(Error.DUPLICATE_DEFINITION, {ExpressionBasics.printExpStr(exp)}, info);
5089 9 fail();
5090 end if;
5091 end while;
5092 end checkNoDuplicateAssignments;
5093
5094 protected function getIteratorType
5095 input DAE.Type ty;
5096 input String id;
5097 input SourceInfo info;
5098 output DAE.Type oty;
5099 algorithm
5100 oty := match ty
5101 local
5102 String str;
5103 case DAE.T_ARRAY(ty = DAE.T_ARRAY())
5104 algorithm
5105 1 str := TypesDump.unparseType(ty);
5106 1 Error.addSourceMessage(Error.ITERATOR_NON_ARRAY,{id,str},info);
5107 1 then fail();
5108 case DAE.T_ARRAY(ty = oty) then oty;
5109 251 case DAE.T_METALIST(ty = oty) then Types.boxIfUnboxedType(oty);
5110 3 case DAE.T_METAARRAY(ty = oty) then Types.boxIfUnboxedType(oty);
5111 ✗ case DAE.T_METATYPE(ty = oty) then getIteratorType(ty.ty, id, info);
5112 else
5113 algorithm
5114 ✗ str := TypesDump.unparseType(ty);
5115 ✗ Error.addSourceMessage(Error.ITERATOR_NON_ARRAY,{id,str},info);
5116 ✗ then fail();
5117 end match;
5118 end getIteratorType;
5119
5120 protected function instParForStatement
5121 input FCore.Cache inCache;
5122 input FCore.Graph inEnv;
5123 input InnerOuter.InstHierarchy inIH;
5124 input DAE.Prefix inPrefix;
5125 input ClassInf.State inState;
5126 input SCode.Statement inForStatement;
5127 input DAE.ElementSource inSource;
5128 input SCode.Initial inInitial;
5129 input Boolean inImpl;
5130 input Boolean inUnrollLoops;
5131 output FCore.Cache outCache;
5132 output list<DAE.Statement> outStatements "For statements can produce multiple statements due to unrolling.";
5133 protected
5134 String iterator;
5135 Option<Absyn.Exp> oarange;
5136 Absyn.Exp arange;
5137 DAE.Exp range;
5138 DAE.Properties prop;
5139 list<SCode.Statement> body;
5140 SourceInfo info;
5141 list<AbsynUtil.IteratorIndexedCref> iter_crefs;
5142 algorithm
5143 ✗ SCode.ALG_PARFOR(index = iterator, range = oarange, parforBody = body, info = info) := inForStatement;
5144
5145 ✗ if isSome(oarange) then
5146 ✗ SOME(arange) := oarange;
5147 ✗ (outCache, range, prop) :=
5148 Static.elabExp(inCache, inEnv, arange, inImpl, true, inPrefix, info);
5149 else
5150 ✗ iter_crefs := SCodeUtil.findIteratorIndexedCrefsInStatements(body, iterator);
5151 ✗ (range, prop, outCache) :=
5152 Static.deduceIterationRange(iterator, iter_crefs, inEnv, inCache, info);
5153 end if;
5154
5155 // Always unroll for-loops containing when-statements.
5156 ✗ if containsWhenStatements(body) then
5157 ✗ (outCache, outStatements) := unrollForLoop(inCache, inEnv, inIH, inPrefix,
5158 inState, iterator, range, prop, body, inForStatement, info, inSource,
5159 inInitial, inImpl, inUnrollLoops);
5160 else
5161 ✗ (outCache, outStatements) := instParForStatement_dispatch(inCache, inEnv, inIH,
5162 inPrefix, inState, iterator, range, prop, body, info, inSource, inInitial, inImpl, inUnrollLoops);
5163 end if;
5164 end instParForStatement;
5165
5166 protected function instParForStatement_dispatch
5167 input FCore.Cache inCache;
5168 input FCore.Graph inEnv;
5169 input InnerOuter.InstHierarchy inIH;
5170 input DAE.Prefix inPrefix;
5171 input ClassInf.State inState;
5172 input String inIterator;
5173 input DAE.Exp inRange;
5174 input DAE.Properties inRangeProps;
5175 input list<SCode.Statement> inBody;
5176 input SourceInfo inInfo;
5177 input DAE.ElementSource inSource;
5178 input SCode.Initial inInitial;
5179 input Boolean inImpl;
5180 input Boolean inUnrollLoops;
5181 output FCore.Cache outCache = inCache;
5182 output list<DAE.Statement> outStatements;
5183 protected
5184 DAE.Type ty;
5185 DAE.Const c;
5186 FCore.Graph env;
5187 DAE.ElementSource source;
5188 list<tuple<DAE.ComponentRef, SourceInfo>> loop_prl_vars;
5189 DAE.ComponentRef parfor_iter;
5190 DAE.Exp range;
5191 algorithm
5192 ✗ c := Types.getPropConst(inRangeProps);
5193
5194 // Remove the for-loop if the range is empty.
5195 ✗ if Types.isParameterOrConstant(c) then
5196 try
5197 ✗ (outCache, Values.ARRAY(valueLst = {})) :=
5198 Ceval.ceval(outCache, inEnv, inRange, inImpl, Absyn.MSG(inInfo), 0);
5199 ✗ outStatements := {};
5200 ✗ return;
5201 else
5202 end try;
5203 end if;
5204
5205 ✗ ty := Types.getPropType(inRangeProps);
5206 ✗ ty := getIteratorType(ty, inIterator, inInfo);
5207 ✗ (outCache, range) :=
5208 Ceval.cevalRangeIfConstant(outCache, inEnv, inRange, inRangeProps, inImpl, inInfo);
5209 ✗ (outCache, range) := PrefixUtil.prefixExp(outCache, inEnv, inIH, range, inPrefix);
5210 ✗ env := addParForLoopScope(inEnv, inIterator, ty, SCode.VAR(), SOME(c));
5211 ✗ (outCache, outStatements) := instStatements(outCache, env, inIH, inPrefix,
5212 inState, inBody, inSource, inInitial, inImpl, inUnrollLoops);
5213
5214 // this is where we check the parfor loop for data parallel specific
5215 // situations. Start with empty list and collect all variables cref'ed
5216 // in the loop body.
5217 ✗ loop_prl_vars := collectParallelVariables({}, outStatements);
5218
5219 // Remove the parfor loop iterator from the list(implicitly declared).
5220 ✗ parfor_iter := DAE.CREF_IDENT(inIterator, ty, {});
5221 ✗ loop_prl_vars := List.deleteMemberOnTrue(parfor_iter, loop_prl_vars, crefInfoListCrefsEqual);
5222
5223 // Check the cref's in the list one by one to make
5224 // sure that they are parallel variables.
5225 // checkParallelVariables(cache,env_1,loopPrlVars);
5226 ✗ List.map2_0(loop_prl_vars, isCrefParGlobalOrForIterator, outCache, env);
5227
5228 ✗ source := ElementSource.addElementSourceFileInfo(inSource, inInfo);
5229 ✗ outStatements :=
5230 {Algorithm.makeParFor(inIterator, range, inRangeProps, outStatements, loop_prl_vars, source)};
5231 end instParForStatement_dispatch;
5232
5233 protected function isCrefParGlobalOrForIterator
5234 "Checks if a component reference is referencing a parglobal
5235 variable or the loop iterator(implicitly declared is OK).
5236 All other references are errors."
5237 input tuple<DAE.ComponentRef,SourceInfo> inCrefInfo;
5238 input FCore.Cache inCache;
5239 input FCore.Graph inEnv;
5240 algorithm
5241 () := matchcontinue inCrefInfo
5242 local
5243 String errorString;
5244 DAE.ComponentRef cref;
5245 SourceInfo info;
5246 SCode.Parallelism prl;
5247 Boolean isParglobal;
5248
5249 case (cref,_)
5250 algorithm
5251 // Look up the variable
5252 ✗ (_, DAE.ATTR(parallelism = prl),_,_,_,_,_,_,_) := Lookup.lookupVar(inCache, inEnv, cref);
5253
5254 // is it parglobal var?
5255 ✗ isParglobal := SCodeUtil.parallelismEqual(prl, SCode.PARGLOBAL());
5256
5257 // Now the iterator is already removed. No need for this.
5258 // is it the iterator of the parfor loop(implicitly declared)?
5259 // isForiterator = isSome(cnstForRange);
5260
5261 //is it either a parglobal var or for iterator
5262 //true = isParglobal or isForiterator;
5263
5264 ✗ true := isParglobal;
5265
5266 then ();
5267
5268 case (cref,info)
5269 algorithm
5270 ✗ errorString := "\n" +
5271 "- Component '" + AbsynUtil.pathString(ComponentReference.crefToPath(cref)) +
5272 "' is used in a parallel for loop." + "\n" +
5273 "- Parallel for loops can only contain references to parglobal variables."
5274 ;
5275 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
5276 {errorString}, info);
5277 ✗ then fail();
5278
5279 end matchcontinue;
5280 end isCrefParGlobalOrForIterator;
5281
5282
5283 protected function crefInfoListCrefsEqual
5284 "Compares if two <DAE.ComponentRef,SourceInfo> tuples have
5285 are the same in the sense that they have the same cref (which
5286 means they are references to the same component).
5287 The info is
5288 just for error messages."
5289 input DAE.ComponentRef inFoundCref;
5290 input tuple<DAE.ComponentRef,SourceInfo> inCrefInfos;
5291 output Boolean outBoolean;
5292 algorithm
5293 outBoolean := match inCrefInfos
5294 local
5295 DAE.ComponentRef cref1;
5296
5297 ✗ case (cref1,_) then ComponentReferenceBasics.crefEqualWithoutSubs(cref1,inFoundCref);
5298 end match;
5299 end crefInfoListCrefsEqual;
5300
5301
5302 protected function collectParallelVariables
5303 "Traverses the body of a parallel for loop and collects
5304 all variable references. the list should not include implictly
5305 declared variables like loop iterators. Only references to
5306 components declared to outside of the parfor loop need to be
5307 collected.
5308 We need the list of referenced variables for Code generation in the backend.
5309 EXPENSIVE operation but needs to be done."
5310 input list<tuple<DAE.ComponentRef,SourceInfo>> inCrefInfos;
5311 input list<DAE.Statement> inStatments;
5312 output list<tuple<DAE.ComponentRef,SourceInfo>> outCrefInfos;
5313
5314 algorithm
5315 outCrefInfos := matchcontinue(inCrefInfos,inStatments)
5316 local
5317 list<DAE.Statement> restStmts, stmtList;
5318 list<tuple<DAE.ComponentRef,SourceInfo>> crefInfoList;
5319 DAE.ComponentRef foundCref;
5320 DAE.Exp exp1,exp2;
5321 SourceInfo info;
5322 DAE.Ident iter;
5323 DAE.Type iterType;
5324
5325 case(_,{}) then inCrefInfos;
5326
5327 case(crefInfoList,DAE.STMT_ASSIGN(_, exp1, exp2, DAE.SOURCE(info = info))::restStmts)
5328 algorithm
5329 //check the lhs and rhs.
5330 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1,exp2},info);
5331
5332 //check the rest
5333 ✗ crefInfoList := collectParallelVariables(crefInfoList,restStmts);
5334 then crefInfoList;
5335
5336 // for statment
5337 case(crefInfoList, DAE.STMT_FOR(type_=iterType, iter=iter, range=exp1, statementLst=stmtList, source=DAE.SOURCE(info = info))::restStmts)
5338 algorithm
5339 //check the range exp.
5340 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},info);
5341
5342 // check the body of the loop.
5343 // crefInfoList_tmp = collectParallelVariables(crefInfoList,stmtList);
5344 ✗ crefInfoList := collectParallelVariables(crefInfoList,stmtList);
5345 // We need to remove the iterator from
5346 // the list generated for the loop bofy. For iterators are implicitly declared.
5347 // This should be done here since the iterator is in scope only as long as we
5348 // are in the loop body.
5349 ✗ foundCref := DAE.CREF_IDENT(iter, iterType,{});
5350 // (crefInfoList_tmp,_) = List.deleteMemberOnTrue(foundCref,crefInfoList_tmp,crefInfoListCrefsEqual);
5351 ✗ (crefInfoList,_) := List.deleteMemberOnTrue(foundCref,crefInfoList,crefInfoListCrefsEqual);
5352
5353 // Now that the iterator is removed cocatenate the two lists
5354 // crefInfoList = listAppend(expandableEqs(crefInfoList_tmp,crefInfoList);
5355
5356 //check the rest
5357 ✗ crefInfoList := collectParallelVariables(crefInfoList,restStmts);
5358 then crefInfoList;
5359
5360 // If statment
5361 // mahge TODO: Fix else Exps.
5362 case(crefInfoList, DAE.STMT_IF(exp1, stmtList, _, DAE.SOURCE(info = info))::restStmts)
5363 algorithm
5364 //check the condition exp.
5365 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},info);
5366 //check the body of the if statment
5367 ✗ crefInfoList := collectParallelVariables(crefInfoList,stmtList);
5368
5369 //check the rest
5370 ✗ crefInfoList := collectParallelVariables(crefInfoList,restStmts);
5371 then crefInfoList;
5372
5373 case(crefInfoList, DAE.STMT_WHILE(exp1, stmtList, DAE.SOURCE(info = info))::restStmts)
5374 algorithm
5375 //check the condition exp.
5376 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},info);
5377 //check the body of the while loop
5378 ✗ crefInfoList := collectParallelVariables(crefInfoList,stmtList);
5379
5380 //check the rest
5381 ✗ crefInfoList := collectParallelVariables(crefInfoList,restStmts);
5382 then crefInfoList;
5383
5384 case(crefInfoList,_::restStmts)
5385 ✗ then collectParallelVariables(crefInfoList,restStmts);
5386
5387 end matchcontinue;
5388 end collectParallelVariables;
5389
5390
5391
5392 protected function collectParallelVariablesinExps
5393 input list<tuple<DAE.ComponentRef,SourceInfo>> inCrefInfos;
5394 input list<DAE.Exp> inExps;
5395 input SourceInfo inInfo;
5396 output list<tuple<DAE.ComponentRef,SourceInfo>> outCrefInfos;
5397
5398 algorithm
5399 outCrefInfos := matchcontinue(inCrefInfos, inExps)
5400 local
5401 list<DAE.Exp> restExps;
5402 list<tuple<DAE.ComponentRef,SourceInfo>> crefInfoList;
5403 DAE.ComponentRef foundCref;
5404 DAE.Exp exp1,exp2,exp3;
5405 list<DAE.Exp> expLst1;
5406 list<DAE.Subscript> subscriptLst;
5407 Boolean alreadyInList;
5408 list<DAE.Subscript> subs;
5409
5410 case(_, {}) then inCrefInfos;
5411
5412 case(crefInfoList, DAE.CREF(foundCref, _)::restExps)
5413 algorithm
5414 // Check if the cref is already added to the list
5415 // avoid repeated lookup.
5416 // and we don't care about subscript differences.
5417
5418 ✗ alreadyInList := List.isMemberOnTrue(foundCref,crefInfoList,crefInfoListCrefsEqual);
5419
5420 // add it to the list if it is not in there
5421 ✗ crefInfoList := if alreadyInList then crefInfoList else ((foundCref,inInfo)::crefInfoList);
5422
5423 //check the subscripts (that is: if they are crefs)
5424 ✗ DAE.CREF_IDENT(_,_,subscriptLst) := foundCref;
5425 ✗ crefInfoList := collectParallelVariablesInSubscriptList(crefInfoList,subscriptLst,inInfo);
5426
5427 // check the rest
5428 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5429 then crefInfoList;
5430
5431 // Array subscripting
5432 case(crefInfoList, DAE.ASUB(exp1,subs)::restExps)
5433 algorithm
5434 ✗ expLst1 := list(Expression.getSubscriptExp(sub) for sub in subs);
5435 //check the ASUB specific expressions
5436 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,exp1::expLst1,inInfo);
5437
5438 // check the rest
5439 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5440 then crefInfoList;
5441
5442 // Binary Operations
5443 case(crefInfoList, DAE.BINARY(exp1,_, exp2)::restExps)
5444 algorithm
5445 //check the lhs and rhs
5446 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1,exp2},inInfo);
5447
5448 // check the rest
5449 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5450 then crefInfoList;
5451
5452 // Unary Operations
5453 case(crefInfoList, DAE.UNARY(_, exp1)::restExps)
5454 algorithm
5455 //check the exp
5456 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},inInfo);
5457
5458 // check the rest
5459 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5460 then crefInfoList;
5461
5462 // Logical Binary Operations
5463 case(crefInfoList, DAE.LBINARY(exp1,_, exp2)::restExps)
5464 algorithm
5465 //check the lhs and rhs
5466 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1,exp2},inInfo);
5467
5468 // check the rest
5469 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5470 then crefInfoList;
5471
5472 // Logical Unary Operations
5473 case(crefInfoList, DAE.LUNARY(_, exp1)::restExps)
5474 algorithm
5475 //check the exp
5476 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},inInfo);
5477
5478 // check the rest
5479 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5480 then crefInfoList;
5481
5482 // range with step value.
5483 case(crefInfoList, DAE.RANGE(_, exp1, SOME(exp2), exp3)::restExps)
5484 algorithm
5485 //check the range specific expressions
5486 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1,exp2,exp3},inInfo);
5487
5488 // check the rest
5489 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5490 then crefInfoList;
5491
5492 // range withOUT step value.
5493 case(crefInfoList, DAE.RANGE(_, exp1, NONE(), exp3)::restExps)
5494 algorithm
5495 //check the range specific expressions
5496 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1,exp3},inInfo);
5497
5498 // check the rest
5499 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5500 then crefInfoList;
5501
5502 // cast stmt
5503 case(crefInfoList, DAE.CAST(_, exp1)::restExps)
5504 algorithm
5505 //check the range specific expressions
5506 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},inInfo);
5507
5508 // check the rest
5509 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5510 then crefInfoList;
5511
5512
5513
5514 // ICONST, RCONST, SCONST, BCONST, ENUM_LITERAL
5515 //
5516 case(crefInfoList, _::restExps)
5517 ✗ then collectParallelVariablesinExps(crefInfoList,restExps,inInfo);
5518
5519 end matchcontinue;
5520 end collectParallelVariablesinExps;
5521
5522
5523 protected function collectParallelVariablesInSubscriptList
5524 input list<tuple<DAE.ComponentRef,SourceInfo>> inCrefInfos;
5525 input list<DAE.Subscript> inSubscriptLst;
5526 input SourceInfo inInfo;
5527 output list<tuple<DAE.ComponentRef,SourceInfo>> outCrefInfos;
5528
5529 algorithm
5530 outCrefInfos := matchcontinue(inCrefInfos, inSubscriptLst)
5531 local
5532 list<DAE.Subscript> restSubs;
5533 list<tuple<DAE.ComponentRef,SourceInfo>> crefInfoList;
5534 DAE.Exp exp1;
5535
5536
5537 case(_, {}) then inCrefInfos;
5538
5539 case(crefInfoList, DAE.INDEX(exp1)::restSubs)
5540 algorithm
5541 //check the sub exp.
5542 ✗ crefInfoList := collectParallelVariablesinExps(crefInfoList,{exp1},inInfo);
5543
5544 //check the rest
5545 ✗ crefInfoList := collectParallelVariablesInSubscriptList(crefInfoList,restSubs,inInfo);
5546 then crefInfoList;
5547
5548 case(crefInfoList, _::restSubs)
5549 ✗ then collectParallelVariablesInSubscriptList(crefInfoList,restSubs,inInfo);
5550
5551 end matchcontinue;
5552 end collectParallelVariablesInSubscriptList;
5553
5554 protected function checkValidNoRetcall
5555 input DAE.Exp exp;
5556 input SourceInfo info;
5557 algorithm
5558 () := match exp
5559 local
5560 String str;
5561 case DAE.CALL() then ();
5562 case DAE.REDUCTION() then ();
5563 case DAE.TUPLE({}) then ();
5564 else
5565 algorithm
5566 ✗ str := ExpressionBasics.printExpStr(exp);
5567 ✗ Error.addSourceMessage(Error.NORETCALL_INVALID_EXP,{str},info);
5568 ✗ then fail();
5569 end match;
5570 end checkValidNoRetcall;
5571
5572 annotation(__OpenModelica_Interface="frontend");
5573 end InstSection;
5574