Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 72.3% 1986 / 0 / 2747
Functions: -% 0 / 1 / 1
Branches: 54.8% 1019 / 0 / 1860

OMCompiler/Compiler/FrontEnd/Static.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 Static
37 " file: Static.mo
38 package: Static
39 description: Static analysis of expressions
40
41
42 This module does static analysis on expressions.
43 The analyzed expressions are built using the
44 constructors in the Expression module from expressions defined in Absyn.
45 Also, a set of properties of the expressions is calculated during analysis.
46 Properties of expressions include type information and a boolean indicating if the
47 expression is constant or not.
48 If the expression is constant, the Ceval module is used to evaluate the expression
49 value. A value of an expression is described using the Values module.
50
51 The main function in this module is evalExp which takes an Absyn.Exp and transform it
52 into an DAE.Exp, while performing type checking and automatic type conversions, etc.
53 To determine types of builtin functions and operators, the module also contain an elaboration
54 handler for functions and operators. This function is called elabBuiltinHandler.
55 NOTE: These functions should only determine the type and properties of the builtin functions and
56 operators and not evaluate them. Constant evaluation is performed by the Ceval module.
57 The module also contain a function for deoverloading of operators, in the \'deoverload\' function.
58 It transforms operators like + to its specific form, ADD, ADD_ARR, etc.
59
60 Interactive function calls are also given their types by elabExp, which calls
61 elabCallInteractive.
62
63 Elaboration for functions involve checking the types of the arguments by filling slots of the
64 argument list with first positional and then named arguments to find a matching function. The
65 details of this mechanism can be found in the Modelica specification.
66 The elaboration also contain function deoverloading which will be added to Modelica in the future."
67
68 import Absyn;
69 import DAE;
70 import FCore;
71 import SCode;
72 import Values;
73
74 protected
75
76 import AbsynToSCode;
77 import AbsynUtil;
78 import FGraph;
79 import FNode;
80 import InstMeta;
81 import MetaUtil;
82 import Util;
83 import ValuesDump;
84
85
86 constant Integer SLOT_NOT_EVALUATED = 0;
87 constant Integer SLOT_EVALUATING = 1;
88 constant Integer SLOT_EVALUATED = 2;
89
90 uniontype Slot
91 record SLOT
92 DAE.FuncArg defaultArg "The slots default argument.";
93 Boolean slotFilled "True if the slot has been filled, otherwise false.";
94 Option<DAE.Exp> arg "The argument for the slot given by the function call.";
95 DAE.Dimensions dims "The dimensions of the slot.";
96 Integer idx "The index of the slot, 1 = first slot etc.";
97 Integer evalStatus;
98 end SLOT;
99 end Slot;
100
101 constant Option<tuple<DAE.Exp, DAE.Properties, DAE.Attributes>> BUILTIN_TIME =
102 SOME((DAE.CREF(DAE.CREF_IDENT("time", DAE.T_REAL_DEFAULT, {}), DAE.T_REAL_DEFAULT),
103 DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_VAR()),
104 DAE.dummyAttrInput));
105
106 import Array;
107 import BackendInterface;
108 import BackendCevalInterface;
109 import Ceval;
110 import ClassInf;
111 import ComponentReference;
112 protected import ComponentReferenceBasics;
113 import Config;
114 import DAEUtil;
115 import Debug;
116 import Dump;
117 import Error;
118 import ErrorExt;
119 import Expression;
120 protected import ExpressionBasics;
121 import ExpressionDump;
122 import ExpressionSimplify;
123 import Flags;
124 import Global;
125 import Inline;
126 import Inst;
127 import InstFunction;
128 import InstTypes;
129 import InnerOuter;
130 import List;
131 import Lookup;
132 import Mutable;
133 import OperatorOverloading;
134 import Patternm;
135 import PrefixUtil;
136 import Print;
137 import SCodeDump;
138 import SCodeUtil;
139 import System;
140 import Types;
141 import ValuesUtil;
142 import VarTransform;
143
144 public function elabExpList "Expression elaboration of Absyn.Exp list, i.e. lists of expressions."
145 input FCore.Cache inCache;
146 input FCore.Graph inEnv;
147 input list<Absyn.Exp> inExpl;
148 input Boolean inImplicit;
149 input Boolean inDoVect;
150 input DAE.Prefix inPrefix;
151 input SourceInfo inInfo;
152 input DAE.Type inLastType = DAE.T_UNKNOWN_DEFAULT "The type of the last evaluated expression; used to speed up instantiation of enumeration :)";
153 output FCore.Cache outCache = inCache;
154 output list<DAE.Exp> outExpl = {};
155 output list<DAE.Properties> outProperties = {};
156 protected
157 DAE.Exp exp;
158 DAE.Properties prop;
159 DAE.Type last_ty = inLastType;
160 Absyn.ComponentRef cr;
161 Absyn.Path path, path1, path2;
162 String name;
163 list<String> names;
164 Integer idx;
165 algorithm
166
2/2
✓ Branch 0 taken 234969 times.
✓ Branch 1 taken 61421 times.
296390 for e in inExpl loop
167 try
168 // Hack to make enumeration arrays elaborate a _lot_ faster
169
4/4
✓ Branch 0 taken 223168 times.
✓ Branch 1 taken 11801 times.
✓ Branch 2 taken 11717 times.
✓ Branch 3 taken 84 times.
235013 Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()) := e;
170
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 40 times.
84 DAE.T_ENUMERATION(path = path2, names = names) := last_ty;
171 40 path := AbsynUtil.crefToPath(cr);
172
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 (path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path);
173
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40 times.
40 true := AbsynUtil.pathEqual(path1, path2);
174 40 idx := List.position(name, names);
175 40 exp := DAE.ENUM_LITERAL(path, idx);
176 40 prop := DAE.PROP(last_ty, DAE.C_CONST());
177 else
178 234929 (outCache, exp, prop) := elabExpInExpression(outCache, inEnv,
179 e, inImplicit, inDoVect, inPrefix, inInfo);
180 234873 last_ty := Types.getPropType(prop);
181 end try;
182
183 234913 outExpl := exp :: outExpl;
184 234913 outProperties := prop :: outProperties;
185 end for;
186
187 61421 outExpl := listReverse(outExpl);
188 61421 outProperties := listReverse(outProperties);
189 end elabExpList;
190
191 protected function elabExpList_enum
192 input Absyn.Exp inExp;
193 input DAE.Type inLastType;
194 output Integer outIndex;
195 algorithm
196 outIndex := matchcontinue(inExp, inLastType)
197 local
198 Absyn.ComponentRef cr;
199 Absyn.Path path, path1, path2;
200 String name;
201 list<String> names;
202
203 case (Absyn.CREF(cr as Absyn.CREF_FULLYQUALIFIED()),
204 DAE.T_ENUMERATION(path = path2, names = names))
205 algorithm
206 ✗ path := AbsynUtil.crefToPath(cr);
207 ✗ (path1, Absyn.IDENT(name)) := AbsynUtil.splitQualAndIdentPath(path);
208 ✗ true := AbsynUtil.pathEqual(path1, path2);
209 ✗ then
210 List.position(name, names);
211
212 else -1;
213
214 end matchcontinue;
215 end elabExpList_enum;
216
217 public function elabExpListList
218 "Expression elaboration of lists of lists of expressions.
219 Used in for instance matrices, etc."
220 input FCore.Cache inCache;
221 input FCore.Graph inEnv;
222 input list<list<Absyn.Exp>> inExpl;
223 input Boolean inImplicit;
224 input Boolean inDoVect;
225 input DAE.Prefix inPrefix;
226 input SourceInfo inInfo;
227 input DAE.Type inLastType = DAE.T_UNKNOWN_DEFAULT "The type of the last evaluated expression; used to speed up instantiation of enumerations :)";
228 output FCore.Cache outCache = inCache;
229 output list<list<DAE.Exp>> outExpl = {};
230 output list<list<DAE.Properties>> outProperties = {};
231 protected
232 list<DAE.Exp> expl;
233 list<DAE.Properties> props;
234 DAE.Type last_ty = inLastType;
235 algorithm
236
2/2
✓ Branch 0 taken 1719 times.
✓ Branch 1 taken 645 times.
2364 for lst in inExpl loop
237 1719 (outCache, expl, props) := elabExpList(outCache, inEnv, lst,
238 inImplicit, inDoVect, inPrefix, inInfo, last_ty);
239 1719 outExpl := expl :: outExpl;
240 1719 outProperties := props :: outProperties;
241 1719 last_ty := Types.getPropType(listHead(props));
242 end for;
243
244 645 outExpl := listReverse(outExpl);
245 645 outProperties := listReverse(outProperties);
246 end elabExpListList;
247
248 protected function elabExpOptAndMatchType "
249 elabExp, but for Option<Absyn.Exp>,DAE.Type => Option<DAE.Exp>"
250 input FCore.Cache inCache;
251 input FCore.Graph inEnv;
252 input Option<Absyn.Exp> inExp;
253 input DAE.Type inDefaultType;
254 input Boolean inImplicit;
255 input Boolean inDoVect;
256 input DAE.Prefix inPrefix;
257 input SourceInfo inInfo;
258 output FCore.Cache outCache = inCache;
259 output Option<DAE.Exp> outExp;
260 output DAE.Properties outProperties;
261 protected
262 Absyn.Exp exp;
263 DAE.Exp dexp;
264 DAE.Properties prop;
265 algorithm
266 1509 outProperties := DAE.PROP(inDefaultType, DAE.C_CONST());
267
268
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1509 times.
✓ Branch 2 taken 332 times.
✓ Branch 3 taken 1177 times.
1509 if isSome(inExp) then
269 332 SOME(exp) := inExp;
270 332 (outCache, dexp, prop) := elabExpInExpression(outCache, inEnv,
271 exp, inImplicit, inDoVect, inPrefix, inInfo);
272 332 (dexp, outProperties) := Types.matchProp(dexp, prop, outProperties, true);
273 outExp := SOME(dexp);
274 else
275 outExp := NONE();
276 end if;
277 end elabExpOptAndMatchType;
278
279 public function elabExp "
280 function: elabExp
281 Static analysis of expressions means finding out the properties of
282 the expression. These properties are described by the
283 DAE.Properties type, and include the type and the variability of the
284 expression. This function performs analysis, and returns an
285 DAE.Exp and the properties."
286 extends PartialElabExpFunc;
287 protected
288 Absyn.Exp e;
289 Integer num_errmsgs;
290 PartialElabExpFunc elabfunc;
291 algorithm
292 // Apply any rewrite rules we have, if any.
293
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2357736 times.
2357736 e := if BackendInterface.noRewriteRulesFrontEnd() then inExp else
294 BackendInterface.rewriteFrontEnd(inExp);
295
296 2357736 num_errmsgs := Error.getNumErrorMessages();
297
298 try
299 elabfunc := match e
300 case Absyn.END()
301 algorithm
302 ✗ Error.addSourceMessage(Error.END_ILLEGAL_USE_ERROR, {}, inInfo);
303 ✗ then
304 fail();
305
306 case Absyn.CREF() then elabExp_Cref;
307 case Absyn.BINARY() then elabExp_Binary;
308 case Absyn.UNARY() then elabExp_Unary;
309 case Absyn.LBINARY() then elabExp_Binary;
310 case Absyn.LUNARY() then elabExp_LUnary;
311 case Absyn.RELATION() then elabExp_Binary;
312 case Absyn.IFEXP() then elabExp_If;
313 case Absyn.CALL() then elabExp_Call;
314 case Absyn.PARTEVALFUNCTION() then elabExp_PartEvalFunction;
315 case Absyn.TUPLE() then elabExp_Tuple;
316 case Absyn.RANGE() then elabExp_Range;
317 case Absyn.ARRAY() then elabExp_Array;
318 case Absyn.MATRIX() then elabExp_Matrix;
319 case Absyn.CODE() then elabExp_Code;
320 case Absyn.CONS() then elabExp_Cons;
321 case Absyn.LIST() then elabExp_List;
322 case Absyn.MATCHEXP() then Patternm.elabMatchExpression;
323 case Absyn.DOT() then elabExp_Dot;
324 case Absyn.EXPRESSIONCOMMENT() then elabExp_Comment;
325 case Absyn.UNITFUL_LITERAL() then elabExp_UnitfulLiteral;
326 else elabExp_BuiltinType;
327 end match;
328
329
5/10
✗ Branch 0 not taken.
✓ Branch 1 taken 2357736 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 7 taken 76179 times.
✓ Branch 8 taken 2281557 times.
✓ Branch 9 taken 1207340 times.
✓ Branch 10 taken 1150396 times.
3641255 (outCache, outExp, outProperties) :=
330 elabfunc(inCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo);
331 else
332
2/2
✓ Branch 1 taken 4774 times.
✓ Branch 2 taken 1 time.
4775 true := num_errmsgs == Error.getNumErrorMessages();
333 2 Error.addSourceMessage(Error.GENERIC_ELAB_EXPRESSION,
334 {Dump.printExpStr(e)}, inInfo);
335 1 fail();
336 end try;
337 end elabExp;
338
339 public partial function PartialElabExpFunc
340 input FCore.Cache inCache;
341 input FCore.Graph inEnv;
342 input Absyn.Exp inExp;
343 input Boolean inImplicit;
344 input Boolean inDoVect;
345 input DAE.Prefix inPrefix;
346 input SourceInfo inInfo;
347 output FCore.Cache outCache = inCache;
348 output DAE.Exp outExp;
349 output DAE.Properties outProperties;
350 end PartialElabExpFunc;
351
352 protected function elabExp_BuiltinType
353 extends PartialElabExpFunc;
354 algorithm
355 (outExp, outProperties) := match inExp
356 // The types below should contain the default values of the attributes of the builtin
357 // types. But since they are default, we can leave them out for now, unit=\"\" is not
358 // that interesting to find out.
359 case Absyn.INTEGER()
360 380558 then (DAE.ICONST(inExp.value),
361 DAE.PROP(DAE.T_INTEGER_DEFAULT, DAE.C_CONST()));
362
363 case Absyn.REAL()
364 414271 then (DAE.RCONST(stringReal(inExp.value)),
365 DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_CONST()));
366
367 case Absyn.STRING()
368 595704 then (DAE.SCONST(System.unescapedString(inExp.value)),
369 DAE.PROP(DAE.T_STRING_DEFAULT, DAE.C_CONST()));
370
371 case Absyn.BOOL()
372 56466 then (DAE.BCONST(inExp.value),
373 DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST()));
374
375 end match;
376 end elabExp_BuiltinType;
377
378 protected function elabExp_Cref
379 extends PartialElabExpFunc;
380 protected
381 Absyn.ComponentRef cr;
382 DAE.Type ty;
383 DAE.Const c;
384 algorithm
385
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 397145 times.
397145 Absyn.CREF(componentRef = cr) := inExp;
386
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 397145 times.
✓ Branch 3 taken 2914 times.
✓ Branch 4 taken 394231 times.
397145 (outCache, SOME((outExp, outProperties, _))) := elabCref(inCache, inEnv, cr,
387 inImplicit, inDoVect, inPrefix, inInfo);
388
389 // BoschRexroth specifics, convert param to var.
390
1/2
✓ Branch 1 taken 394231 times.
✗ Branch 2 not taken.
394231 if not Flags.getConfigBool(Flags.CEVAL_EQUATION) then
391 ✗ DAE.PROP(ty, c) := outProperties;
392 ✗ outProperties := if Types.isParameter(c) then
393 DAE.PROP(ty, DAE.C_VAR()) else outProperties;
394 end if;
395 end elabExp_Cref;
396
397 protected function elabExp_Binary
398 extends PartialElabExpFunc;
399 protected
400 Absyn.Exp e1, e2;
401 Absyn.Operator op;
402 DAE.Properties prop1, prop2;
403 DAE.Exp exp1, exp2;
404 algorithm
405 () := match inExp
406 case Absyn.BINARY(exp1 = e1, op = op, exp2 = e2) then ();
407 case Absyn.LBINARY(exp1 = e1, op = op, exp2 = e2) then ();
408 case Absyn.RELATION(exp1 = e1, op = op, exp2 = e2) then ();
409 end match;
410
411 203518 (outCache, exp1, prop1) := elabExpInExpression(inCache, inEnv,
412 e1, inImplicit, inDoVect, inPrefix, inInfo);
413 203515 (outCache, exp2, prop2) := elabExpInExpression(outCache, inEnv,
414 e2, inImplicit, inDoVect, inPrefix, inInfo);
415 203515 (outCache, outExp, outProperties) := OperatorOverloading.binary(outCache,
416 inEnv, op, prop1, exp1, prop2, exp2, inExp, e1, e2, inImplicit, inPrefix, inInfo);
417 end elabExp_Binary;
418
419 protected function elabExp_Unary
420 extends PartialElabExpFunc;
421 protected
422 Absyn.Exp e;
423 Absyn.Operator op;
424 DAE.Type ty;
425 DAE.Const c;
426 algorithm
427
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 95911 times.
95911 Absyn.UNARY(op = op, exp = e) := inExp;
428
429
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 95911 times.
95911 (outCache, outExp, outProperties as DAE.PROP(ty, c)) :=
430 elabExpInExpression(inCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo);
431
432
3/4
✓ Branch 1 taken 131 times.
✓ Branch 2 taken 95780 times.
✓ Branch 5 taken 131 times.
✗ Branch 6 not taken.
95911 if not (valueEq(op, Absyn.UPLUS()) and
433 Types.isIntegerOrRealOrSubTypeOfEither(Types.arrayElementType(ty)))
434 then
435 95780 (outCache, outExp, outProperties) := OperatorOverloading.unary(outCache, inEnv,
436 op, outProperties, outExp, inExp, e, inImplicit, inPrefix, inInfo);
437 end if;
438 end elabExp_Unary;
439
440 protected function elabExp_LUnary
441 extends PartialElabExpFunc;
442 protected
443 Absyn.Exp e;
444 Absyn.Operator op;
445 algorithm
446
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1744 times.
1744 Absyn.LUNARY(op = op, exp = e) := inExp;
447 1744 (outCache, outExp, outProperties) := elabExpInExpression(outCache, inEnv, e,
448 inImplicit, inDoVect, inPrefix, inInfo);
449 1744 (outCache, outExp, outProperties) := OperatorOverloading.unary(outCache,
450 inEnv, op, outProperties, outExp, inExp, e, inImplicit, inPrefix, inInfo);
451 end elabExp_LUnary;
452
453 protected function elabExp_If
454 "Elaborates an if-expression. If one of the branches can not be elaborated and
455 the condition is parameter or constant; it is evaluated and the correct branch is selected.
456 This is a dirty hack to make MSL CombiTable models work!
457 Note: Because of this, the function has to rollback or delete an ErrorExt checkpoint."
458 extends PartialElabExpFunc;
459 protected
460 Absyn.Exp cond_e, true_e, false_e;
461 DAE.Exp cond_exp, true_exp, false_exp;
462 DAE.Properties cond_prop, true_prop, false_prop;
463 FCore.Cache cache;
464 Boolean b;
465 algorithm
466
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8299 times.
8299 Absyn.IFEXP(ifExp = cond_e, trueBranch = true_e, elseBranch = false_e) :=
467 AbsynUtil.canonIfExp(inExp);
468 8299 (cache, cond_exp, cond_prop) := elabExpInExpression(inCache,
469 inEnv, cond_e, inImplicit, inDoVect, inPrefix, inInfo);
470
471 (outCache, outExp, outProperties) := matchcontinue()
472 case ()
473 algorithm
474 8299 ErrorExt.setCheckpoint("Static.elabExp:IFEXP");
475 8299 (outCache, true_exp, true_prop) := elabExpInExpression(cache,
476 inEnv, true_e, inImplicit, inDoVect, inPrefix, inInfo);
477 8299 (outCache, false_exp, false_prop) := elabExpInExpression(outCache,
478 inEnv, false_e, inImplicit, inDoVect, inPrefix, inInfo);
479 8298 (outCache, outExp, outProperties) := makeIfExp(outCache, inEnv, cond_exp,
480 cond_prop, true_exp, true_prop, false_exp, false_prop, inImplicit,
481 inPrefix, inInfo);
482 8296 ErrorExt.delCheckpoint("Static.elabExp:IFEXP");
483 8296 then
484 (outCache, outExp, outProperties);
485
486 case ()
487 algorithm
488 3 ErrorExt.setCheckpoint("Static.elabExp:IFEXP:HACK") "Extra rollback point so we get the regular error message only once if the hack fails";
489
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 true := Types.isParameterOrConstant(Types.propAllConst(cond_prop));
490
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 (outCache, Values.BOOL(b)) := Ceval.ceval(cache, inEnv, cond_exp,
491 inImplicit, Absyn.MSG(inInfo));
492
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 (outCache, outExp, outProperties) := elabExpInExpression(outCache, inEnv,
493 if b then true_e else false_e, inImplicit, inDoVect, inPrefix, inInfo);
494 3 ErrorExt.delCheckpoint("Static.elabExp:IFEXP:HACK");
495 3 ErrorExt.rollBack("Static.elabExp:IFEXP");
496 3 then
497 (outCache, outExp, outProperties);
498
499 else
500 algorithm
501 ✗ ErrorExt.rollBack("Static.elabExp:IFEXP:HACK");
502 ✗ ErrorExt.delCheckpoint("Static.elabExp:IFEXP");
503 ✗ then
504 fail();
505
506 end matchcontinue;
507 end elabExp_If;
508
509 protected function elabExp_Call
510 extends PartialElabExpFunc;
511 protected
512 Absyn.ComponentRef func_name;
513 Absyn.FunctionArgs args;
514 list<Absyn.Path> type_vars;
515 algorithm
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 96601 times.
96601 Absyn.CALL(function_ = func_name, functionArgs = args, typeVars = type_vars) := inExp;
517
518 () := match args
519 case Absyn.FUNCTIONARGS()
520 algorithm
521 95854 (outCache, outExp, outProperties) := elabCall(inCache, inEnv,
522 func_name, args.args, args.argNames, type_vars, inImplicit, inPrefix, inInfo);
523 94082 outExp := ExpressionSimplify.simplify1(outExp);
524 then
525 ();
526
527 case Absyn.FOR_ITER_FARG()
528 algorithm
529 747 (outCache, outExp, outProperties) := elabCallReduction(inCache,
530 inEnv, func_name, args.exp, args.iterType, args.iterators, inImplicit,
531 inDoVect, inPrefix, inInfo);
532 then
533 ();
534 end match;
535 end elabExp_Call;
536
537 protected function elabExp_Dot
538 extends PartialElabExpFunc;
539 algorithm
540 (outExp, outProperties) := match inExp
541 local
542 String s;
543 DAE.Type ty;
544 case Absyn.DOT()
545 algorithm
546 s := match inExp.index
547 case Absyn.CREF(Absyn.CREF_IDENT(name=s)) then s;
548 else
549 algorithm
550 ✗ Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator is only allowed when indexing using a single simple name, got: " + Dump.printExpStr(inExp.index)}, inInfo);
551 ✗ then fail();
552 end match;
553 4 (outCache,outExp,outProperties) := elabExp(inCache,inEnv,inExp.exp,inImplicit,inDoVect, inPrefix, inInfo);
554 4 ty := Types.getPropType(outProperties);
555 () := match ty
556 local
557 list<String> names;
558 Integer i;
559 case DAE.T_TUPLE(names=SOME(names))
560 algorithm
561
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 if not listMember(s, names) then
562 ✗ Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator could not find " + s + " in " + TypesDump.unparseType(ty)}, inInfo);
563 ✗ fail();
564 end if;
565 4 i := List.position(s, names);
566 4 outExp := DAE.TSUB(outExp, i, listGet(ty.types,i));
567 4 outProperties := DAE.PROP(listGet(ty.types,i), Types.propAllConst(outProperties));
568 then ();
569 else
570 algorithm
571 ✗ Error.addSourceMessage(Error.COMPILER_ERROR, {"Dot operator is only allowed when the expression returns a named tuple. Got expression: " + ExpressionBasics.printExpStr(outExp) + " with type " + TypesDump.unparseType(ty)}, inInfo);
572 ✗ then fail();
573 end match;
574
1/2
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
4 then (outExp, outProperties);
575
576 end match;
577 end elabExp_Dot;
578
579 protected function elabExp_Comment
580 extends PartialElabExpFunc;
581 protected
582 Absyn.Exp exp;
583 algorithm
584
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 155 times.
155 Absyn.EXPRESSIONCOMMENT(exp=exp) := inExp;
585 155 (outCache, outExp, outProperties) := elabExp(inCache,inEnv,exp,inImplicit,inDoVect, inPrefix, inInfo);
586 end elabExp_Comment;
587
588 protected function elabExp_UnitfulLiteral
589 extends PartialElabExpFunc;
590 protected
591 Absyn.Exp exp;
592 algorithm
593 ✗ Absyn.UNITFUL_LITERAL(value=exp) := inExp;
594 ✗ (outCache, outExp, outProperties) := elabExp(inCache,inEnv,exp,inImplicit,inDoVect, inPrefix, inInfo);
595 end elabExp_UnitfulLiteral;
596
597 protected function elabExp_PartEvalFunction
598 "turns an Absyn.PARTEVALFUNCTION into an DAE.PARTEVALFUNCTION"
599 extends PartialElabExpFunc;
600 protected
601 Absyn.ComponentRef cref;
602 list<Absyn.Exp> pos_args;
603 list<Absyn.NamedArg> named_args;
604 Absyn.Path path;
605 DAE.Type ty, tty, tty2;
606 list<DAE.Exp> args;
607 list<DAE.Const> consts;
608 list<Slot> slots;
609 DAE.Const c;
610 algorithm
611
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 35 times.
35 Absyn.PARTEVALFUNCTION(cref, Absyn.FUNCTIONARGS(pos_args, named_args)) := inExp;
612
613
2/4
✓ Branch 0 taken 35 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 35 times.
35 if listEmpty(pos_args) and listEmpty(named_args) then
614 ✗ (outCache, outExp, outProperties) := elabExpInExpression(inCache,
615 inEnv, Absyn.CREF(cref), inImplicit, inDoVect, inPrefix, inInfo);
616 else
617 35 path := AbsynUtil.crefToPath(cref);
618
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 35 times.
35 (outCache, {tty}) := Lookup.lookupFunctionsInEnv(inCache, inEnv, path, inInfo);
619 35 tty := Types.makeFunctionPolymorphicReference(tty);
620 35 (outCache, args, consts, _, tty, _, slots) := elabTypes(outCache, inEnv, pos_args,
621 named_args, {}, {tty}, true, true, inImplicit,
622 inPrefix, inInfo);
623
2/2
✓ Branch 1 taken 31 times.
✓ Branch 2 taken 4 times.
35 if not Types.isFunctionPointer(tty) then
624 31 (outCache, path) := Inst.makeFullyQualified(outCache, inEnv, path);
625
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 31 times.
31 (outCache, Util.SUCCESS()) := instantiateDaeFunction(outCache, inEnv,
626 path, false, NONE(), true);
627 end if;
628 35 tty2 := stripExtraArgsFromType(slots, tty);
629 35 tty2 := Types.makeFunctionPolymorphicReference(tty2);
630 35 ty := Types.simplifyType(tty2);
631 35 tty := Types.simplifyType(tty);
632 35 c := List.fold(consts, Types.constAnd, DAE.C_CONST());
633 35 outExp := DAE.PARTEVALFUNCTION(path, args, ty, tty);
634 35 outProperties := DAE.PROP(tty2, c);
635 end if;
636 end elabExp_PartEvalFunction;
637
638 protected function elabExp_Tuple
639 extends PartialElabExpFunc;
640 algorithm
641 47208 (outCache, outExp, outProperties) := elabExp_Tuple_LHS_RHS(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo);
642 end elabExp_Tuple;
643
644 protected function elabExp_Tuple_LHS_RHS
645 extends PartialElabExpFunc;
646 input Boolean isLhs=false;
647 protected
648 list<Absyn.Exp> el;
649 list<DAE.Exp> expl;
650 list<DAE.Properties> props;
651 list<DAE.Type> types;
652 list<DAE.TupleConst> consts;
653 algorithm
654
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 47293 times.
47293 Absyn.TUPLE(expressions = el) := inExp;
655
2/2
✓ Branch 1 taken 44143 times.
✓ Branch 2 taken 3150 times.
47293 if listLength(el) == 1 then
656 44143 (outCache, outExp, outProperties) := elabExp(outCache, inEnv, listGet(el,1), inImplicit, inDoVect, inPrefix, inInfo);
657 44143 return;
658 end if;
659 3150 (outCache, expl, props) := elabTuple(outCache, inEnv, el, inImplicit,
660 inDoVect, inPrefix, inInfo, isLhs);
661 3149 (types, consts) := splitProps(props);
662 3149 (outExp, outProperties) := fixTupleMetaModelica(expl, types, consts);
663 end elabExp_Tuple_LHS_RHS;
664
665 public function elabExpLHS "Special check for tuples, which only occur on the LHS"
666 extends PartialElabExpFunc;
667 algorithm
668 (outCache, outExp, outProperties) := match inExp
669 case Absyn.TUPLE()
670 algorithm
671 85 (outCache, outExp, outProperties) := elabExp_Tuple_LHS_RHS(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo, isLhs=true);
672 then (outCache, outExp, outProperties);
673 else
674 algorithm
675 20314 (outCache, outExp, outProperties) := elabExp(inCache, inEnv, inExp, inImplicit, inDoVect, inPrefix, inInfo);
676 then (outCache, outExp, outProperties);
677 end match;
678 end elabExpLHS;
679
680 protected function elabExp_Range
681 "Elaborates a range expression on the form start:stop or start:step:stop."
682 extends PartialElabExpFunc;
683 protected
684 Absyn.Exp start, step, stop;
685 Option<Absyn.Exp> ostep;
686 DAE.Exp start_exp, step_exp, stop_exp;
687 Option<DAE.Exp> ostep_exp = NONE();
688 DAE.Type start_ty, step_ty, stop_ty, ety, ty;
689 Option<DAE.Type> ostep_ty = NONE();
690 DAE.Const start_c, step_c, stop_c, c;
691 algorithm
692
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1947 times.
1947 Absyn.RANGE(start = start, step = ostep, stop = stop) := inExp;
693
694 // Elaborate start and stop of the range.
695
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
1947 (outCache, start_exp, DAE.PROP(start_ty, start_c)) :=
696 elabExpInExpression(inCache, inEnv, start, inImplicit, inDoVect, inPrefix, inInfo);
697
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
1947 (outCache, stop_exp, DAE.PROP(stop_ty, stop_c)) :=
698 elabExpInExpression(outCache, inEnv, stop, inImplicit, inDoVect, inPrefix, inInfo);
699 1947 c := Types.constAnd(start_c, stop_c);
700
701 // If step was given, elaborate it too.
702
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1947 times.
✓ Branch 2 taken 38 times.
✓ Branch 3 taken 1909 times.
1947 if isSome(ostep) then
703 38 SOME(step) := ostep;
704
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
38 (outCache, step_exp, DAE.PROP(step_ty, step_c)) :=
705 elabExpInExpression(outCache, inEnv, step, inImplicit, inDoVect, inPrefix, inInfo);
706 38 ostep_exp := SOME(step_exp);
707 ostep_ty := SOME(step_ty);
708 38 c := Types.constAnd(c, step_c);
709 end if;
710
711
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1947 times.
1947 if Types.isBoxedType(start_ty) then
712 ✗ (start_exp, start_ty) := Types.matchType(start_exp, start_ty, Types.unboxedType(start_ty), true);
713 end if;
714
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 1946 times.
1947 if Types.isBoxedType(stop_ty) then
715 1 (stop_exp, stop_ty) := Types.matchType(stop_exp, stop_ty, Types.unboxedType(stop_ty), true);
716 end if;
717
718 1947 (start_exp, ostep_exp, stop_exp, ety) :=
719 deoverloadRange(start_exp, start_ty, ostep_exp, ostep_ty, stop_exp, stop_ty, inInfo);
720 1947 (outCache, ty) := elabRangeType(outCache, inEnv, start_exp, ostep_exp,
721 stop_exp, start_ty, ety, c, inImplicit);
722
723 1947 outExp := DAE.RANGE(ty, start_exp, ostep_exp, stop_exp);
724 1947 outProperties := DAE.PROP(ty, c);
725 end elabExp_Range;
726
727 protected function elabExp_Array
728 extends PartialElabExpFunc;
729 protected
730 list<Absyn.Exp> es;
731 list<DAE.Exp> expl;
732 list<DAE.Properties> props;
733 DAE.Type ty, arr_ty;
734 DAE.Const c;
735 DAE.Exp exp;
736 algorithm
737 (outExp, outProperties) := matchcontinue inExp
738 // Part of the MetaModelica extension. This eliminates elabArray failed
739 // failtraces when using the empty list. sjoelund
740 case Absyn.ARRAY({}) guard(Config.acceptMetaModelicaGrammar())
741 then (DAE.LIST({}), DAE.PROP(DAE.T_METALIST_DEFAULT, DAE.C_CONST()));
742
743 // array expressions, e.g. {1,2,3}
744 case Absyn.ARRAY(arrayExp = es)
745 algorithm
746 51459 (outCache, expl, props) := elabExpList(inCache, inEnv, es, inImplicit,
747 inDoVect, inPrefix, inInfo);
748
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51407 times.
51407 (expl, DAE.PROP(ty, c)) := elabArray(expl, props, inPrefix, inInfo); // type-checking the array
749 102814 arr_ty := DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(listLength(expl))});
750
2/2
✓ Branch 1 taken 250 times.
✓ Branch 2 taken 51157 times.
51657 exp := DAE.ARRAY(Types.simplifyType(arr_ty), not Types.isArray(ty), expl);
751 51407 InstMeta.checkArrayType(ty);
752 50666 exp := elabMatrixToMatrixExp(exp);
753 50666 then
754 (exp, DAE.PROP(arr_ty, c));
755
756 // Part of the MetaModelica extension. KS
757 case Absyn.ARRAY(arrayExp = es) guard(Config.acceptMetaModelicaGrammar())
758 algorithm
759 741 (outCache, outExp, outProperties) := elabExpInExpression(inCache,
760 inEnv, Absyn.LIST(es), inImplicit, inDoVect, inPrefix, inInfo);
761 741 then
762 (outExp, outProperties);
763
764 end matchcontinue;
765 end elabExp_Array;
766
767 protected function elabExp_Matrix
768 extends PartialElabExpFunc;
769 protected
770 list<list<Absyn.Exp>> ess;
771 list<list<DAE.Exp>> dess;
772 list<list<DAE.Properties>> props;
773 list<DAE.Type> tys;
774 Integer nmax;
775 Boolean have_real;
776 DAE.Type ty;
777 DAE.Const c;
778 DAE.Dimension dim1, dim2;
779 algorithm
780 // Elaborate the individual expressions.
781
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 Absyn.MATRIX(matrix = ess) := inExp;
782 645 (outCache, dess, props) := elabExpListList(inCache, inEnv, ess, inImplicit,
783 inDoVect, inPrefix, inInfo);
784
785 // Check if any of the expressions is of Real type.
786
8/8
✓ Branch 0 taken 1719 times.
✓ Branch 1 taken 645 times.
✓ Branch 2 taken 1719 times.
✓ Branch 3 taken 645 times.
✓ Branch 4 taken 5443 times.
✓ Branch 5 taken 1719 times.
✓ Branch 6 taken 5443 times.
✓ Branch 7 taken 1719 times.
7807 tys := listAppend(list(Types.getPropType(p) for p in pl) for pl in props);
787 645 nmax := matrixConstrMaxDim(tys);
788 645 have_real := Types.containReal(tys);
789
790 // If we have any Real expressions, cast any Integer expressions to Real.
791
2/2
✓ Branch 0 taken 437 times.
✓ Branch 1 taken 208 times.
645 if have_real then
792 437 (dess, props) := List.threadMapList_2(dess, props, elabExp_Matrix_realCast);
793 end if;
794
795
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 645 times.
645 (outCache, outExp, DAE.PROP(ty, c), dim1, dim2) := elabMatrixSemi(outCache,
796 inEnv, dess, props, inImplicit, have_real, nmax, inDoVect, inPrefix, inInfo);
797
798 645 outExp := elabMatrixToMatrixExp(outExp);
799 645 ty := Types.unliftArray(Types.unliftArray(ty)); // All elts promoted to matrix, therefore unlifting.
800 645 ty := DAE.T_ARRAY(ty, {dim2});
801 645 ty := DAE.T_ARRAY(ty, {dim1});
802 645 outProperties := DAE.PROP(ty, c);
803 end elabExp_Matrix;
804
805 protected function elabExp_Matrix_realCast
806 "Casts an expression and property to Real if it's current type is Integer."
807 input DAE.Exp inExp;
808 input DAE.Properties inProperties;
809 output DAE.Exp outExp;
810 output DAE.Properties outProperties;
811 protected
812 DAE.Type ty;
813 algorithm
814 2749 ty := Types.getPropType(inProperties);
815
816
2/2
✓ Branch 1 taken 482 times.
✓ Branch 2 taken 2267 times.
2749 if Types.isInteger(ty) then
817 482 ty := Types.setArrayElementType(ty, DAE.T_REAL_DEFAULT);
818 482 outProperties := Types.setPropType(inProperties, ty);
819 482 ty := Types.simplifyType(ty);
820 482 outExp := ExpressionSimplify.simplify1(DAE.CAST(ty, inExp));
821 else
822 outExp := inExp;
823 outProperties := inProperties;
824 end if;
825 end elabExp_Matrix_realCast;
826
827 protected function elabExp_Code
828 extends PartialElabExpFunc;
829 protected
830 DAE.Type ty, ty2;
831 Absyn.CodeNode cn;
832 algorithm
833
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 955 times.
955 Absyn.CODE(code = cn) := inExp;
834 955 ty := elabCodeType(cn);
835 955 ty2 := Types.simplifyType(ty);
836 955 outExp := DAE.CODE(cn, ty2);
837 955 outProperties := DAE.PROP(ty, DAE.C_CONST());
838 end elabExp_Code;
839
840 protected function elabExp_Cons
841 extends PartialElabExpFunc;
842 protected
843 Absyn.Exp e1, e2;
844 DAE.Exp exp1, exp2;
845 DAE.Properties prop1;
846 DAE.Type ty, ty1, ty2;
847 DAE.Const c1, c2;
848 String exp_str, ty1_str, ty2_str;
849 algorithm
850
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 314 times.
314 Absyn.CONS(e1, e2) := inExp;
851
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 314 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 314 times.
314 {e1, e2} := MetaUtil.transformArrayNodesToListNodes({e1, e2});
852
853 // Elaborate both sides of the cons expression.
854 314 (outCache, exp1, prop1) := elabExpInExpression(outCache, inEnv, e1,
855 inImplicit, inDoVect, inPrefix, inInfo);
856
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 314 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 314 times.
314 (outCache, exp2, DAE.PROP(DAE.T_METALIST(ty = ty2), c2)) := elabExpInExpression(
857 outCache, inEnv, e2, inImplicit, inDoVect, inPrefix, inInfo);
858
859 try
860 // Replace all metarecords with uniontypes with.
861 314 ty1 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(Types.getPropType(prop1));
862 314 ty2 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(ty2);
863 314 c1 := Types.propAllConst(prop1);
864 314 ty := Types.getUniontypeIfMetarecordReplaceAllSubtypes(
865 Types.superType(Types.boxIfUnboxedType(ty1), Types.boxIfUnboxedType(ty2)));
866
867 // Make sure the operands have correct types.
868 314 exp1 := Types.matchType(exp1, ty1, ty, true);
869 314 ty := DAE.T_METALIST(ty);
870 314 exp2 := Types.matchType(exp2, ty, DAE.T_METALIST(ty2), true);
871
872 314 outExp := DAE.CONS(exp1, exp2);
873 314 outProperties := DAE.PROP(ty, Types.constAnd(c1, c2));
874 else
875 ✗ exp_str := Dump.printExpStr(inExp);
876 ✗ ty1_str := TypesDump.unparseType(Types.getPropType(prop1));
877 ✗ ty2_str := TypesDump.unparseType(ty2);
878 ✗ Error.addSourceMessage(Error.META_CONS_TYPE_MATCH, {exp_str, ty1_str, ty2_str}, inInfo);
879 ✗ fail();
880 end try;
881 end elabExp_Cons;
882
883 protected function elabExp_List
884 extends PartialElabExpFunc;
885 protected
886 list<Absyn.Exp> es;
887 list<DAE.Exp> expl;
888 list<DAE.Properties> props;
889 list<DAE.Type> types;
890 list<DAE.Const> consts;
891 DAE.Const c;
892 DAE.Type ty;
893 algorithm
894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 777 times.
777 Absyn.LIST(exps = es) := inExp;
895
896 // The Absyn.LIST() node is used for list expressions that are transformed
897 // from Absyn.ARRAY()
898
2/2
✓ Branch 0 taken 754 times.
✓ Branch 1 taken 23 times.
777 if listEmpty(es) then
899 outExp := DAE.LIST({});
900 outProperties := DAE.PROP(DAE.T_METALIST_DEFAULT, DAE.C_CONST());
901 else
902 754 (outCache, expl, props) := elabExpList(inCache, inEnv, es, inImplicit,
903 inDoVect, inPrefix, inInfo);
904
4/4
✓ Branch 0 taken 3293 times.
✓ Branch 1 taken 754 times.
✓ Branch 2 taken 3293 times.
✓ Branch 3 taken 754 times.
4047 types := list(Types.getPropType(p) for p in props);
905 754 consts := Types.getConstList(props);
906 754 c := List.fold(consts, Types.constAnd, DAE.C_CONST());
907 754 ty := Types.boxIfUnboxedType(List.reduce(types, Types.superType));
908 754 expl := Types.matchTypes(expl, types, ty, true);
909
910 754 outExp := DAE.LIST(expl);
911 754 outProperties := DAE.PROP(DAE.T_METALIST(ty), c);
912 end if;
913 end elabExp_List;
914
915 public function elabExpInExpression "Like elabExp but casts PROP_TUPLE to a PROP"
916 input FCore.Cache inCache;
917 input FCore.Graph inEnv;
918 input Absyn.Exp inExp;
919 input Boolean inImplicit;
920 input Boolean performVectorization;
921 input DAE.Prefix inPrefix;
922 input SourceInfo info;
923 output FCore.Cache outCache;
924 output DAE.Exp outExp;
925 output DAE.Properties outProperties;
926 algorithm
927 1065358 (outCache,outExp,outProperties) := elabExp(inCache,inEnv,inExp,inImplicit,performVectorization,inPrefix,info);
928 1062269 (outExp,outProperties) := elabExpInExpression2(outExp,outProperties);
929 end elabExpInExpression;
930
931 protected function elabExpInExpression2
932 input DAE.Exp inExp;
933 input DAE.Properties inProperties;
934 output DAE.Exp outExp;
935 output DAE.Properties outProperties;
936 algorithm
937 (outExp,outProperties) := match inProperties
938 local
939 DAE.Type ty;
940 DAE.Const c;
941 case DAE.PROP_TUPLE(type_ = DAE.T_TUPLE(types = ty :: _), tupleConst = DAE.TUPLE_CONST(tupleConstLst = DAE.SINGLE_CONST(const = c) :: _))
942 16 then (DAE.TSUB(inExp, 1, ty), DAE.PROP(ty,c));
943 else (inExp,inProperties);
944 end match;
945 end elabExpInExpression2;
946
947 public function checkAssignmentToInput
948 input Absyn.Exp inExp;
949 input DAE.Attributes inAttributes;
950 input FCore.Graph inEnv;
951 input Boolean inAllowTopLevelInputs;
952 input SourceInfo inInfo;
953 algorithm
954 // If we don't allow top level inputs and we're in a function scope and not
955 // using parmodelica, check for assignment to input.
956
4/6
✗ Branch 0 not taken.
✓ Branch 1 taken 74679 times.
✓ Branch 3 taken 1727 times.
✓ Branch 4 taken 72952 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 72952 times.
74679 if not inAllowTopLevelInputs and FGraph.inFunctionScope(inEnv) and
957 not Config.acceptParModelicaGrammar() then
958 72952 checkAssignmentToInput2(inExp, inAttributes, inInfo);
959 end if;
960 end checkAssignmentToInput;
961
962 protected function checkAssignmentToInput2
963 input Absyn.Exp inExp;
964 input DAE.Attributes inAttributes;
965 input SourceInfo inInfo;
966 algorithm
967 () := match(inExp, inAttributes)
968 local
969 Absyn.ComponentRef cr;
970 String cr_str;
971
972 case (Absyn.CREF(cr), DAE.ATTR(direction = Absyn.INPUT()))
973 algorithm
974 12 cr_str := Dump.printComponentRefStr(cr);
975 12 Error.addSourceMessage(Error.ASSIGN_READONLY_ERROR,
976 {"input", cr_str}, inInfo);
977 12 then
978 fail();
979
980 else ();
981
982 end match;
983 end checkAssignmentToInput2;
984
985 public function checkAssignmentToInputs
986 input list<Absyn.Exp> inExpCrefs;
987 input list<DAE.Attributes> inAttributes;
988 input FCore.Graph inEnv;
989 input SourceInfo inInfo;
990 algorithm
991
2/2
✓ Branch 1 taken 22 times.
✓ Branch 2 taken 884 times.
906 if FGraph.inFunctionScope(inEnv) then
992 884 List.threadMap1_0(inExpCrefs, inAttributes, checkAssignmentToInput2, inInfo);
993 end if;
994 end checkAssignmentToInputs;
995
996 public function elabExpCrefNoEvalList
997 "elaborates a list of expressions that are only component references."
998 input FCore.Cache inCache;
999 input FCore.Graph inEnv;
1000 input list<Absyn.Exp> inExpl;
1001 input Boolean inImplicit;
1002 input Boolean inDoVect;
1003 input DAE.Prefix inPrefix;
1004 input SourceInfo inInfo;
1005 output FCore.Cache outCache = inCache;
1006 output list<DAE.Exp> outExpl = {};
1007 output list<DAE.Properties> outProperties = {};
1008 output list<DAE.Attributes> outAttributes = {};
1009 protected
1010 Integer num_err = Error.getNumErrorMessages();
1011 DAE.Exp exp;
1012 DAE.Properties prop;
1013 list<DAE.Properties> props = {};
1014 DAE.Attributes attr;
1015 Absyn.ComponentRef cr;
1016 DAE.Type ty;
1017 DAE.Const c;
1018 algorithm
1019
2/2
✓ Branch 0 taken 1917 times.
✓ Branch 1 taken 906 times.
2823 for e in inExpl loop
1020 try
1021
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1917 times.
1917 Absyn.CREF(componentRef = cr) := e;
1022 1917 (outCache, exp, prop, attr) :=
1023 elabCrefNoEval(outCache, inEnv, cr, inImplicit, inDoVect, inPrefix, inInfo);
1024 1917 outExpl := exp :: outExpl;
1025 1917 outAttributes := attr :: outAttributes;
1026 1917 props := prop :: props;
1027 else
1028 ✗ true := num_err == Error.getNumErrorMessages();
1029 ✗ Error.addSourceMessage(Error.GENERIC_ELAB_EXPRESSION,
1030 {Dump.printExpStr(e)}, inInfo);
1031 end try;
1032 end for;
1033
1034 // BoschRexroth specifics, convert all params to vars.
1035
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 906 times.
906 if not Flags.getConfigBool(Flags.CEVAL_EQUATION) then
1036 ✗ for p in props loop
1037 ✗ DAE.PROP(ty, c) := p;
1038 ✗ p := if Types.isParameter(c) then DAE.PROP(ty, DAE.C_VAR()) else p;
1039 outProperties := p :: outProperties;
1040 end for;
1041 else
1042 906 outProperties := listReverse(props);
1043 end if;
1044
1045 906 outExpl := listReverse(outExpl);
1046 906 outAttributes := listReverse(outAttributes);
1047 end elabExpCrefNoEvalList;
1048
1049 // Part of MetaModelica extension
1050 public function elabListExp "Function that elaborates the MetaModelica list type,
1051 for instance list<Integer>.
1052 This is used by Inst.mo when handling a var := {...} statement"
1053 input FCore.Cache inCache;
1054 input FCore.Graph inEnv;
1055 input list<Absyn.Exp> inExpList;
1056 input DAE.Properties inProp;
1057 input Boolean inImplicit;
1058 input Boolean inDoVect;
1059 input DAE.Prefix inPrefix;
1060 input SourceInfo inInfo;
1061 output FCore.Cache outCache;
1062 output DAE.Exp outExp;
1063 output DAE.Properties outProperties;
1064 algorithm
1065 (outCache, outExp, outProperties) := matchcontinue inExpList
1066 local
1067 list<DAE.Exp> expl;
1068 list<DAE.Properties> props;
1069 list<DAE.Type> types;
1070 DAE.Const c;
1071 DAE.Type ty;
1072
1073 case {} then (inCache, DAE.LIST({}), inProp);
1074
1075 case _
1076 algorithm
1077 ✗ DAE.PROP(DAE.T_METALIST(), c) := inProp;
1078 ✗ (outCache, expl, props) := elabExpList(inCache, inEnv,
1079 inExpList, inImplicit, inDoVect, inPrefix, inInfo);
1080 ✗ types := list(Types.getPropType(p) for p in props);
1081 ✗ (expl, ty) := Types.listMatchSuperType(expl, types, true);
1082 ✗ outProperties := DAE.PROP(DAE.T_METALIST(ty), c);
1083 ✗ then
1084 (outCache, DAE.LIST(expl), outProperties);
1085
1086 else
1087 algorithm
1088 ✗ true := Flags.isSet(Flags.FAILTRACE);
1089 ✗ Debug.traceln("- Static.elabListExp failed, non-matching args in list constructor?");
1090 ✗ then
1091 fail();
1092 end matchcontinue;
1093 end elabListExp;
1094
1095 /* ------------------------------- */
1096
1097 public function fromEquationsToAlgAssignments " Converts equations to algorithm assignments.
1098 Matchcontinue expressions may contain statements that you won't find
1099 in a normal equation section. For instance:
1100
1101 case(...)
1102 local
1103 algorithm
1104 (var1,_,MYREC(...)) = func(...);
1105 fail();
1106 then 1;"
1107 input Absyn.ClassPart cp;
1108 output list<Absyn.AlgorithmItem> algsOut;
1109 algorithm
1110 algsOut := match cp
1111 local
1112 list<Absyn.EquationItem> rest;
1113 list<Absyn.AlgorithmItem> alg;
1114 String str;
1115
1116 case Absyn.ALGORITHMS(alg) then alg;
1117 2558 case Absyn.EQUATIONS(rest) then fromEquationsToAlgAssignmentsWork(rest);
1118 else
1119 algorithm
1120 ✗ str := Dump.unparseClassPart(cp);
1121 ✗ Error.addInternalError("Static.fromEquationsToAlgAssignments: Unknown classPart in match expression:\n" + str, sourceInfo());
1122 ✗ then
1123 fail();
1124 end match;
1125 end fromEquationsToAlgAssignments;
1126
1127 protected function fromEquationsToAlgAssignmentsWork
1128 "Converts equations to algorithm assignments.
1129 Matchcontinue expressions may contain statements that you won't find
1130 in a normal equation section. For instance:
1131
1132 case(...)
1133 algorithm
1134 (var1, _, MYREC(...)) = func(...);
1135 fail();
1136 then
1137 1;"
1138 input list<Absyn.EquationItem> eqsIn;
1139 output list<Absyn.AlgorithmItem> algsOut = {};
1140 algorithm
1141
2/2
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 2562 times.
2617 for ei in eqsIn loop
1142 () := match ei
1143 local
1144 Absyn.Equation eq;
1145 Option<Absyn.Comment> comment;
1146 SourceInfo info;
1147 list<Absyn.AlgorithmItem> algs;
1148
1149 case Absyn.EQUATIONITEM(equation_ = eq, comment = comment, info = info)
1150 algorithm
1151 53 algs := fromEquationToAlgAssignment(eq, comment, info);
1152 53 algsOut := listAppend(algs, algsOut);
1153 then
1154 ();
1155
1156 case Absyn.EQUATIONITEMCOMMENT() then ();
1157 end match;
1158 end for;
1159
1160 2562 algsOut := listReverse(algsOut);
1161 end fromEquationsToAlgAssignmentsWork;
1162
1163 protected function fromEquationBranchesToAlgBranches
1164 "Converts equations to algorithm assignments."
1165 input list<tuple<Absyn.Exp,list<Absyn.EquationItem>>> eqsIn;
1166 output list<tuple<Absyn.Exp,list<Absyn.AlgorithmItem>>> algsOut = {};
1167 protected
1168 Absyn.Exp e;
1169 list<Absyn.EquationItem> eqs;
1170 list<Absyn.AlgorithmItem> algs;
1171 algorithm
1172
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 for branch in eqsIn loop
1173 ✗ (e, eqs) := branch;
1174 ✗ algs := fromEquationsToAlgAssignmentsWork(eqs);
1175 ✗ algsOut := (e, algs) :: algsOut;
1176 end for;
1177
1178 2 algsOut := listReverse(algsOut);
1179 end fromEquationBranchesToAlgBranches;
1180
1181 protected function fromEquationToAlgAssignment "function: fromEquationToAlgAssignment"
1182 input Absyn.Equation eq;
1183 input Option<Absyn.Comment> comment;
1184 input SourceInfo info;
1185 output list<Absyn.AlgorithmItem> algStatement;
1186 algorithm
1187 algStatement := matchcontinue eq
1188 local
1189 String str,strLeft,strRight;
1190 Absyn.Exp left,right,e;
1191 Absyn.AlgorithmItem algItem,algItem1,algItem2;
1192 Absyn.Equation eq2;
1193 Option<Absyn.Comment> comment2;
1194 SourceInfo info2;
1195 Absyn.AlgorithmItem res;
1196 Absyn.ComponentRef cref;
1197 Absyn.FunctionArgs fargs;
1198 list<Absyn.AlgorithmItem> algs, algTrueItems, algElseItems;
1199 list<tuple<Absyn.Exp,list<Absyn.AlgorithmItem>>> algBranches;
1200 list<Absyn.EquationItem> eqTrueItems, eqElseItems;
1201 list<tuple<Absyn.Exp,list<Absyn.EquationItem>>> eqBranches;
1202
1203 case Absyn.EQ_EQUALS(Absyn.CREF(Absyn.CREF_IDENT(strLeft,{})),Absyn.CREF(Absyn.CREF_IDENT(strRight,{})))
1204 algorithm
1205
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
3 true := strLeft == strRight;
1206 // match x case x then ... produces equation x = x; we save a bit of time by removing it here :)
1207 then {};
1208
1209 // The syntax n>=0 = true; is also used
1210 case Absyn.EQ_EQUALS(left,right)
1211 algorithm
1212
1/4
✓ Branch 1 taken 29 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
29 Absyn.BOOL(true) := AbsynUtil.stripCommentExpressions(right);
1213 ✗ failure(Absyn.CREF(_) := left); // If lhs is a CREF, it should be an assignment
1214 ✗ algItem1 := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info);
1215 ✗ algItem2 := Absyn.ALGORITHMITEM(Absyn.ALG_IF(Absyn.LUNARY(Absyn.NOT(),left),{algItem1},{},{}),comment,info);
1216 then {algItem2};
1217
1218 case Absyn.EQ_EQUALS(left,Absyn.BOOL(false))
1219 algorithm
1220 ✗ failure(Absyn.CREF(_) := left); // If lhs is a CREF, it should be an assignment
1221 ✗ algItem1 := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info);
1222 ✗ algItem2 := Absyn.ALGORITHMITEM(Absyn.ALG_IF(left,{algItem1},{},{}),comment,info);
1223 then {algItem2};
1224
1225 case Absyn.EQ_PDE()
1226 algorithm
1227 // fail("PDE in Static.fromEquationToAlgAssignment() not handled");
1228 then fail();
1229
1230 case Absyn.EQ_NORETCALL(Absyn.CREF_IDENT("fail",_),_)
1231 algorithm
1232 3 algItem := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(Absyn.CREF_IDENT("fail",{}),Absyn.FUNCTIONARGS({},{})),comment,info);
1233 then {algItem};
1234
1235 case Absyn.EQ_NORETCALL(cref,fargs)
1236 algorithm
1237 19 algItem := Absyn.ALGORITHMITEM(Absyn.ALG_NORETCALL(cref,fargs),comment,info);
1238 then {algItem};
1239
1240 case Absyn.EQ_EQUALS(left,right)
1241 algorithm
1242 29 algItem := Absyn.ALGORITHMITEM(Absyn.ALG_ASSIGN(left,right),comment,info);
1243 then {algItem};
1244
1245 case Absyn.EQ_FAILURE(Absyn.EQUATIONITEM(eq2,comment2,info2))
1246 algorithm
1247 2 algs := fromEquationToAlgAssignment(eq2,comment2,info2);
1248 2 res := Absyn.ALGORITHMITEM(Absyn.ALG_FAILURE(algs),comment,info);
1249 then {res};
1250
1251 case Absyn.EQ_IF(ifExp = e, equationTrueItems = eqTrueItems, elseIfBranches = eqBranches, equationElseItems = eqElseItems)
1252 algorithm
1253 2 algTrueItems := fromEquationsToAlgAssignmentsWork(eqTrueItems);
1254 2 algElseItems := fromEquationsToAlgAssignmentsWork(eqElseItems);
1255 2 algBranches := fromEquationBranchesToAlgBranches(eqBranches);
1256 2 res := Absyn.ALGORITHMITEM(Absyn.ALG_IF(e, algTrueItems, algBranches, algElseItems),comment,info);
1257 then {res};
1258
1259 else
1260 algorithm
1261 ✗ str := Dump.equationName(eq);
1262 ✗ Error.addSourceMessage(Error.META_MATCH_EQUATION_FORBIDDEN, {str}, info);
1263 ✗ then fail();
1264 end matchcontinue;
1265 end fromEquationToAlgAssignment;
1266
1267 protected function elabMatrixToMatrixExp
1268 "Convert an 2-dimensional array expression to a matrix expression."
1269 input DAE.Exp inExp;
1270 output DAE.Exp outExp;
1271 algorithm
1272 outExp := matchcontinue inExp
1273 local
1274 list<list<DAE.Exp>> mexpl;
1275 DAE.Type a;
1276 Integer d1;
1277 list<DAE.Exp> expl;
1278
1279 // Convert a 2-dimensional array to a matrix.
1280 case DAE.ARRAY(ty = a as DAE.T_ARRAY(dims = _ :: _ :: {}), array = expl)
1281 algorithm
1282 1957 mexpl := List.map(expl, Expression.arrayContent);
1283 1954 d1 := listLength(mexpl);
1284
2/2
✓ Branch 3 taken 24 times.
✓ Branch 4 taken 1930 times.
1954 true := Expression.typeBuiltin(Expression.unliftArray(Expression.unliftArray(a)));
1285 1930 then
1286 DAE.MATRIX(a, d1, mexpl);
1287
1288 // if fails, skip conversion, use generic array expression as is.
1289 else inExp;
1290 end matchcontinue;
1291 end elabMatrixToMatrixExp;
1292
1293 protected function matrixConstrMaxDim
1294 "Helper function to elabExp (MATRIX).
1295 Determines the maximum dimension of the array arguments to the matrix
1296 constructor as.
1297 max(2, ndims(A), ndims(B), ndims(C),..) for matrix constructor arguments
1298 A, B, C, ..."
1299 input list<DAE.Type> inTypes;
1300 output Integer outMaxDim = 2;
1301 algorithm
1302
2/2
✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 645 times.
6088 for ty in inTypes loop
1303 5443 outMaxDim := max(Types.numberOfDimensions(ty), outMaxDim);
1304 end for;
1305 end matrixConstrMaxDim;
1306
1307 protected function elabCallReduction
1308 "This function elaborates reduction expressions that look like function
1309 calls. For example an array constructor."
1310 input FCore.Cache inCache;
1311 input FCore.Graph inEnv;
1312 input Absyn.ComponentRef inReductionFn;
1313 input Absyn.Exp inReductionExp;
1314 input Absyn.ReductionIterType inIterType;
1315 input Absyn.ForIterators inIterators;
1316 input Boolean inImplicit;
1317 input Boolean inDoVect;
1318 input DAE.Prefix inPrefix;
1319 input SourceInfo inInfo;
1320 output FCore.Cache outCache;
1321 output DAE.Exp outExp;
1322 output DAE.Properties outProperties;
1323 protected
1324 FCore.Graph env, fold_env;
1325 list<DAE.ReductionIterator> reduction_iters;
1326 list<DAE.Dimension> dims;
1327 DAE.Const iter_const, exp_const, c;
1328 Boolean has_guard_exp;
1329 DAE.Exp exp;
1330 Option<Absyn.Exp> afold_exp;
1331 Option<DAE.Exp> fold_exp;
1332 DAE.Type exp_ty, res_ty;
1333 Absyn.Path fn;
1334 Option<Values.Value> v;
1335 String fold_id, res_id;
1336 algorithm
1337 try
1338 747 env := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(),
1339 FCore.forIterScopeName, NONE());
1340
1341 // Elaborate the iterators.
1342 747 (outCache, env, reduction_iters, dims, iter_const, has_guard_exp) :=
1343 elabCallReductionIterators(inCache, env, inIterators,
1344 inReductionExp, inImplicit, inDoVect, inPrefix, inInfo);
1345 745 dims := fixDimsIterType(inIterType, dims);
1346
1347 // Elaborate the expression.
1348
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 745 times.
745 (outCache, exp, DAE.PROP(exp_ty, exp_const)) :=
1349 elabExpInExpression(outCache, env, inReductionExp, inImplicit,
1350 inDoVect, inPrefix, inInfo);
1351
1352 // Figure out the type of the reduction.
1353 745 c := Types.constAnd(exp_const, iter_const);
1354 fn := match inReductionFn
1355 case Absyn.CREF_IDENT("$array",{}) then Absyn.IDENT("array");
1356 436 else AbsynUtil.crefToPath(inReductionFn);
1357 end match;
1358 745 (outCache, exp, exp_ty, res_ty, v, fn) := reductionType(outCache, inEnv, fn,
1359 exp, exp_ty, Types.unboxedType(exp_ty), dims, has_guard_exp, inInfo);
1360 745 outProperties := DAE.PROP(exp_ty, c);
1361
1362 // Construct the reduction expression.
1363 745 fold_id := Util.getTempVariableIndex();
1364 745 res_id := Util.getTempVariableIndex();
1365 745 (fold_env, afold_exp) := makeReductionFoldExp(env, fn, exp_ty, res_ty, fold_id, res_id);
1366 745 (outCache, fold_exp, _) := elabExpOptAndMatchType(outCache, fold_env,
1367 afold_exp, res_ty, inImplicit, inDoVect, inPrefix, inInfo);
1368
1369 745 outExp := DAE.REDUCTION(
1370 DAE.REDUCTIONINFO(fn, inIterType, exp_ty, v, fold_id, res_id, fold_exp),
1371 exp,
1372 reduction_iters);
1373 else
1374
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if listLength(inIterators) > 1 then
1375 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {"Reductions using multiple iterators is not yet implemented. Try rewriting the expression using nested reductions (e.g. array(i+j for i, j) => array(array(i+j for i) for j)."}, inInfo);
1376 else
1377
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
1378 ✗ Debug.traceln("Static.elabCallReduction - failed!");
1379 end if;
1380 ✗ fail();
1381 end try;
1382 end elabCallReduction;
1383
1384 protected function fixDimsIterType
1385 input Absyn.ReductionIterType iterType;
1386 input list<DAE.Dimension> dims;
1387 output list<DAE.Dimension> outDims;
1388 algorithm
1389 outDims := match iterType
1390 case Absyn.COMBINE() then dims;
1391
1392 // TODO: Get the best dimension (if several, choose the one that is integer
1393 // constant; we do run-time checks to assert they are all equal)
1394 8 else {listHead(dims)};
1395 end match;
1396 end fixDimsIterType;
1397
1398 protected function elabCallReductionIterators
1399 input FCore.Cache inCache;
1400 input FCore.Graph inEnv;
1401 input Absyn.ForIterators inIterators;
1402 input Absyn.Exp inReductionExp;
1403 input Boolean inImpl;
1404 input Boolean inDoVect;
1405 input DAE.Prefix inPrefix;
1406 input SourceInfo inInfo;
1407 output FCore.Cache outCache = inCache;
1408 output FCore.Graph outIteratorsEnv = inEnv;
1409 output list<DAE.ReductionIterator> outIterators = {};
1410 output list<DAE.Dimension> outDims = {};
1411 output DAE.Const outConst = DAE.C_CONST();
1412 output Boolean outHasGuard = false;
1413 protected
1414 String iter_name;
1415 Absyn.Exp aiter_exp;
1416 Option<Absyn.Exp> oaguard_exp, oaiter_exp;
1417 DAE.Exp iter_exp;
1418 Option<DAE.Exp> guard_exp;
1419 DAE.Type full_iter_ty, iter_ty;
1420 DAE.Const iter_const, guard_const, c;
1421 DAE.Dimension dim;
1422 FCore.Graph env;
1423 algorithm
1424
2/2
✓ Branch 0 taken 766 times.
✓ Branch 1 taken 745 times.
1511 for iter in inIterators loop
1425 766 Absyn.ITERATOR(iter_name, oaguard_exp, oaiter_exp) := iter;
1426
1427
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 766 times.
✓ Branch 2 taken 13 times.
✓ Branch 3 taken 753 times.
766 if isSome(oaiter_exp) then
1428 // An explicit iteration range, elaborate it.
1429 753 SOME(aiter_exp) := oaiter_exp;
1430
1431
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 753 times.
753 (outCache, iter_exp, DAE.PROP(full_iter_ty, iter_const)) :=
1432 elabExpInExpression(outCache, inEnv, aiter_exp, inImpl, inDoVect, inPrefix, inInfo);
1433 else
1434 // An implicit iteration range, try to deduce the range based on how the
1435 // iterator is used.
1436
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 11 times.
13 (iter_exp, DAE.PROP(full_iter_ty, iter_const), outCache) := deduceIterationRange(iter_name,
1437 AbsynUtil.findIteratorIndexedCrefs(inReductionExp, iter_name), inEnv, outCache, inInfo);
1438 end if;
1439
1440 // We need to evaluate the iterator because the rest of the compiler is stupid.
1441
2/2
✓ Branch 1 taken 449 times.
✓ Branch 2 taken 315 times.
764 c := if FGraph.inFunctionScope(inEnv) then iter_const else DAE.C_CONST();
1442 764 (outCache, iter_exp, _) :=
1443 Ceval.cevalIfConstant(outCache, inEnv, iter_exp, DAE.PROP(full_iter_ty, c), inImpl, inInfo);
1444
1445 764 (iter_ty, dim) := Types.unliftArrayOrList(full_iter_ty);
1446 // The iterator needs to be added to two different environments, to hide the
1447 // iterators from the different guard-expressions.
1448 764 env := FGraph.addForIterator(inEnv, iter_name, iter_ty, DAE.UNBOUND(),
1449 SCode.CONST(), SOME(iter_const));
1450 764 outIteratorsEnv := FGraph.addForIterator(outIteratorsEnv, iter_name, iter_ty, DAE.UNBOUND(),
1451 SCode.CONST(), SOME(iter_const));
1452
1453 // Elaborate the guard expression.
1454
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 764 times.
764 (outCache, guard_exp, DAE.PROP(_, guard_const)) := elabExpOptAndMatchType(
1455 outCache, env, oaguard_exp, DAE.T_BOOL_DEFAULT, inImpl, inDoVect, inPrefix, inInfo);
1456
1457 // If we have a guard expression we don't determine the dimension, since the
1458 // number of elements depend on the guard.
1459
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 764 times.
✓ Branch 2 taken 41 times.
✓ Branch 3 taken 723 times.
764 if isSome(guard_exp) then
1460 outHasGuard := true;
1461 41 dim := DAE.DIM_UNKNOWN();
1462 end if;
1463
1464 764 outConst := Types.constAnd(outConst, Types.constAnd(guard_const, iter_const));
1465 764 outIterators := DAE.REDUCTIONITER(iter_name, iter_exp, guard_exp, iter_ty) :: outIterators;
1466 764 outDims := dim :: outDims;
1467 end for;
1468
1469 745 outIterators := listReverse(outIterators);
1470 745 outDims := listReverse(outDims);
1471 end elabCallReductionIterators;
1472
1473 public function deduceIterationRange
1474 "This function tries to deduce the size of an iteration range for a reduction
1475 based on how an iterator is used. It does this by analysing the reduction
1476 expression to find out where the iterator is used as a subscript, and uses
1477 the subscripted components' dimensions to determine the size of the range."
1478 input String inIterator;
1479 input list<AbsynUtil.IteratorIndexedCref> inCrefs;
1480 input FCore.Graph inEnv;
1481 input FCore.Cache inCache;
1482 input Absyn.Info inInfo;
1483 output DAE.Exp outRange = DAE.ICONST(0);
1484 output DAE.Properties outProperties = DAE.PROP(DAE.T_UNKNOWN_DEFAULT, DAE.C_UNKNOWN());
1485 output FCore.Cache outCache = inCache;
1486 protected
1487 Absyn.ComponentRef acref;
1488 DAE.ComponentRef cref;
1489 Integer idx, i1, i2;
1490 DAE.Type ty;
1491 list<DAE.Dimension> dims;
1492 DAE.Dimension dim;
1493 DAE.Exp range;
1494 list<DAE.Exp> ranges = {};
1495 String cr_str1, cr_str2;
1496 algorithm
1497 // Check that we have some crefs, otherwise we print an error and fail.
1498
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 16 times.
17 if listEmpty(inCrefs) then
1499 1 Error.addSourceMessageAndFail(Error.IMPLICIT_ITERATOR_NOT_FOUND_IN_LOOP_BODY,
1500 {inIterator}, inInfo);
1501 end if;
1502
1503 // For each cref-index pair, figure out the range of the subscripted dimension.
1504
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 15 times.
32 for cr in inCrefs loop
1505 17 (acref, idx) := cr;
1506 17 cref := ComponentReference.toExpCref(acref);
1507
1508 // Look the cref up to get its type.
1509 try
1510 17 (outCache, _, ty) := Lookup.lookupVar(outCache, inEnv, cref);
1511 else
1512 2 Error.addSourceMessageAndFail(Error.LOOKUP_VARIABLE_ERROR,
1513 {Dump.printComponentRefStr(acref), ""}, inInfo);
1514 end try;
1515
1516 // Get the cref's dimensions.
1517 16 dims := TypesDump.getDimensions(ty);
1518
1519 // Check that the indexed dimension actually exists.
1520
1/2
✓ Branch 1 taken 16 times.
✗ Branch 2 not taken.
16 if idx <= listLength(dims) then
1521 // Get the indexed dimension and construct a range from it.
1522 16 dim := listGet(dims, idx);
1523 16 (range, outProperties) := deduceReductionIterationRange2(dim, cref, ty, idx);
1524 else
1525 // The indexed dimension doesn't exist, i.e. we have too many subscripts.
1526 // Return some dummy variables, and let elabCallReduction handle the error
1527 // reporting since we don't know how many subscripts were used here.
1528 range := DAE.ICONST(0);
1529 ✗ outProperties := DAE.PROP(DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(0)}), DAE.C_UNKNOWN());
1530 end if;
1531
1532 ranges := range :: ranges;
1533 end for;
1534
1535 // If we have more than one range we must check that they are all equal,
1536 // otherwise it's not possible to determine the actual iteration range.
1537 // If they are equal we can just return anyone of them.
1538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 outRange :: ranges := ranges;
1539 idx := 2;
1540
1541
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 15 times.
16 for r in ranges loop
1542
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not ExpressionBasics.expEqual(r, outRange) then
1543 ✗ (acref, i1) := listHead(inCrefs);
1544 ✗ cr_str1 := Dump.printComponentRefStr(acref);
1545 ✗ (acref, i2) := listGet(inCrefs, idx);
1546 ✗ cr_str2 := Dump.printComponentRefStr(acref);
1547 ✗ Error.addSourceMessageAndFail(Error.INCOMPATIBLE_IMPLICIT_RANGES,
1548 {intString(i2), cr_str2, intString(i1), cr_str1}, inInfo);
1549 end if;
1550 1 idx := idx + 1;
1551 end for;
1552 end deduceIterationRange;
1553
1554 protected function iteratorIndexedCrefsEqual
1555 "Checks whether two cref-index pairs are equal."
1556 input tuple<Absyn.ComponentRef, Integer> inCref1;
1557 input tuple<Absyn.ComponentRef, Integer> inCref2;
1558 output Boolean outEqual;
1559 protected
1560 Absyn.ComponentRef cr1, cr2;
1561 Integer idx1, idx2;
1562 algorithm
1563 ✗ (cr1, idx1) := inCref1;
1564 ✗ (cr2, idx2) := inCref2;
1565 ✗ outEqual := idx1 == idx2 and AbsynUtil.crefEqual(cr1, cr2);
1566 end iteratorIndexedCrefsEqual;
1567
1568 protected function deduceReductionIterationRange_traverser
1569 "Traversal function used by deduceReductionIterationRange. Used to find crefs
1570 which are subscripted by a given iterator."
1571 input Absyn.Exp inExp;
1572 input list<tuple<Absyn.ComponentRef, Integer>> inCrefs;
1573 input String inIterator;
1574 output Absyn.Exp outExp = inExp;
1575 output list<tuple<Absyn.ComponentRef, Integer>> outCrefs;
1576 algorithm
1577 outCrefs := match inExp
1578 local
1579 Absyn.ComponentRef cref;
1580
1581 case Absyn.CREF(componentRef = cref)
1582 ✗ then getIteratorIndexedCrefs(cref, inIterator, inCrefs);
1583
1584 else inCrefs;
1585 end match;
1586 end deduceReductionIterationRange_traverser;
1587
1588 protected function getIteratorIndexedCrefs
1589 "Checks if the given component reference is subscripted by the given iterator.
1590 Only cases where a subscript consists of only the iterator is considered.
1591 If so it adds a cref-index pair to the list, where the cref is the subscripted
1592 cref without subscripts, and the index is the subscripted dimension. E.g. for
1593 iterator i:
1594 a[i] => (a, 1), b[1, i] => (b, 2), c[i+1] => (), d[2].e[i] => (d[2].e, 1)"
1595 input Absyn.ComponentRef inCref;
1596 input String inIterator;
1597 input list<tuple<Absyn.ComponentRef, Integer>> inCrefs;
1598 output list<tuple<Absyn.ComponentRef, Integer>> outCrefs = inCrefs;
1599 protected
1600 list<tuple<Absyn.ComponentRef, Integer>> crefs;
1601 algorithm
1602 outCrefs := match inCref
1603 local
1604 list<Absyn.Subscript> subs;
1605 Integer idx;
1606 String name, id;
1607 Absyn.ComponentRef cref;
1608
1609 case Absyn.CREF_IDENT(name = id, subscripts = subs)
1610 algorithm
1611 // For each subscript, check if the subscript consists of only the
1612 // iterator we're looking for.
1613 idx := 1;
1614 ✗ for sub in subs loop
1615 () := match sub
1616 case Absyn.SUBSCRIPT(subscript = Absyn.CREF(componentRef =
1617 Absyn.CREF_IDENT(name = name, subscripts = {})))
1618 algorithm
1619 ✗ if name == inIterator then
1620 ✗ outCrefs := (Absyn.CREF_IDENT(id, {}), idx) :: outCrefs;
1621 end if;
1622 then
1623 ();
1624
1625 else ();
1626 end match;
1627
1628 ✗ idx := idx + 1;
1629 end for;
1630 then
1631 outCrefs;
1632
1633 case Absyn.CREF_QUAL(name = id, subscripts = subs, componentRef = cref)
1634 algorithm
1635 ✗ crefs := getIteratorIndexedCrefs(cref, inIterator, {});
1636
1637 // Append the prefix from the qualified cref to any matches, and add
1638 // them to the result list.
1639 ✗ for cr in crefs loop
1640 ✗ (cref, idx) := cr;
1641 ✗ outCrefs := (Absyn.CREF_QUAL(id, subs, cref), idx) :: outCrefs;
1642 end for;
1643 ✗ then
1644 getIteratorIndexedCrefs(Absyn.CREF_IDENT(id, subs), inIterator, outCrefs);
1645
1646 case Absyn.CREF_FULLYQUALIFIED(componentRef = cref)
1647 algorithm
1648 ✗ crefs := getIteratorIndexedCrefs(cref, inIterator, {});
1649
1650 // Make any matches fully qualified, and add the to the result list.
1651 ✗ for cr in crefs loop
1652 ✗ (cref, idx) := cr;
1653 ✗ outCrefs := (Absyn.CREF_FULLYQUALIFIED(cref), idx) :: outCrefs;
1654 end for;
1655 then
1656 outCrefs;
1657
1658 else inCrefs;
1659 end match;
1660 end getIteratorIndexedCrefs;
1661
1662 protected function deduceReductionIterationRange2
1663 "Helper function to deduceReductionIterationRange. Constructs a range based on
1664 the given dimension."
1665 input DAE.Dimension inDimension;
1666 input DAE.ComponentRef inCref "The subscripted component without subscripts.";
1667 input DAE.Type inType "The type of the subscripted component.";
1668 input Integer inIndex "The index of the dimension.";
1669 output DAE.Exp outRange "The range expression.";
1670 output DAE.Properties outProperties "The properties of the range expression.";
1671 protected
1672 DAE.Type range_ty;
1673 DAE.Const range_const;
1674 Absyn.Path enum_path, enum_start, enum_end;
1675 list<String> enum_lits;
1676 Integer sz;
1677 DAE.Exp size_exp;
1678 algorithm
1679 outRange := match inDimension
1680 // Boolean dimension => false:true
1681 case DAE.DIM_BOOLEAN()
1682 algorithm
1683 1 range_ty := DAE.T_ARRAY(DAE.T_BOOL_DEFAULT, {inDimension});
1684 range_const := DAE.C_CONST();
1685 1 then
1686 DAE.RANGE(range_ty, DAE.BCONST(false), NONE(), DAE.BCONST(true));
1687
1688 // Enumeration dimension => Enum.first:Enum.last
1689 case DAE.DIM_ENUM(enumTypeName = enum_path, literals = enum_lits)
1690 algorithm
1691 4 enum_start := AbsynUtil.suffixPath(enum_path, listHead(enum_lits));
1692 4 enum_end := AbsynUtil.suffixPath(enum_path, List.last(enum_lits));
1693 4 range_ty := DAE.T_ENUMERATION(NONE(), enum_path, enum_lits, {}, {});
1694 4 range_ty := DAE.T_ARRAY(range_ty, {inDimension});
1695 range_const := DAE.C_CONST();
1696 4 then
1697 DAE.RANGE(range_ty, DAE.ENUM_LITERAL(enum_start, 1), NONE(),
1698 DAE.ENUM_LITERAL(enum_end, listLength(enum_lits)));
1699
1700 // Integer dimension => 1:size
1701 case DAE.DIM_INTEGER(integer = sz)
1702 algorithm
1703 11 range_ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {inDimension});
1704 range_const := DAE.C_CONST();
1705 11 then
1706 DAE.RANGE(range_ty, DAE.ICONST(1), NONE(), DAE.ICONST(sz));
1707
1708 // Any other kind of dimension => 1:size(cref, index)
1709 else
1710 algorithm
1711 ✗ size_exp := DAE.SIZE(DAE.CREF(inCref, inType), SOME(DAE.ICONST(inIndex)));
1712 ✗ range_ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {inDimension});
1713 range_const := DAE.C_PARAM();
1714 ✗ then
1715 DAE.RANGE(range_ty, DAE.ICONST(1), NONE(), size_exp);
1716
1717 end match;
1718
1719 // Set the properties of the range expression.
1720 16 outProperties := DAE.PROP(range_ty, range_const);
1721 end deduceReductionIterationRange2;
1722
1723 protected function makeReductionFoldExp
1724 input FCore.Graph inEnv;
1725 input Absyn.Path path;
1726 input DAE.Type expty;
1727 input DAE.Type resultTy;
1728 input String foldId;
1729 input String resultId;
1730 output FCore.Graph outEnv;
1731 output Option<Absyn.Exp> afoldExp;
1732 algorithm
1733 (outEnv, afoldExp) := match AbsynUtil.makeNotFullyQualified(path)
1734 local
1735 Absyn.Exp exp;
1736 Absyn.ComponentRef cr, cr1, cr2;
1737 FCore.Graph env;
1738
1739 case Absyn.IDENT("$array") then (inEnv, NONE());
1740 case Absyn.IDENT("array") then (inEnv, NONE());
1741 case Absyn.IDENT("list") then (inEnv, NONE());
1742 case Absyn.IDENT("listReverse") then (inEnv, NONE());
1743
1744 case Absyn.IDENT("sum")
1745 algorithm
1746 224 env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1747 224 env := FGraph.addForIterator(env, resultId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1748 224 cr1 := Absyn.CREF_IDENT(foldId, {});
1749 224 cr2 := Absyn.CREF_IDENT(resultId, {});
1750 224 exp := Absyn.BINARY(Absyn.CREF(cr2), Absyn.ADD(), Absyn.CREF(cr1));
1751 then
1752 (env, SOME(exp));
1753
1754 case Absyn.IDENT("product")
1755 algorithm
1756 15 env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1757 15 env := FGraph.addForIterator(env, resultId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1758 15 cr1 := Absyn.CREF_IDENT(foldId, {});
1759 15 cr2 := Absyn.CREF_IDENT(resultId, {});
1760 15 exp := Absyn.BINARY(Absyn.CREF(cr2), Absyn.MUL(), Absyn.CREF(cr1));
1761 then
1762 (env, SOME(exp));
1763
1764 else
1765 algorithm
1766 52 cr := AbsynUtil.pathToCref(path);
1767 // print("makeReductionFoldExp => " + AbsynUtil.pathString(path) + TypesDump.unparseType(expty) + "\n");
1768 52 env := FGraph.addForIterator(inEnv, foldId, expty, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1769 52 env := FGraph.addForIterator(env, resultId, resultTy, DAE.UNBOUND(), SCode.VAR(), SOME(DAE.C_VAR()));
1770 52 cr1 := Absyn.CREF_IDENT(foldId, {});
1771 52 cr2 := Absyn.CREF_IDENT(resultId, {});
1772 104 exp := Absyn.CALL(cr, Absyn.FUNCTIONARGS({Absyn.CREF(cr1), Absyn.CREF(cr2)}, {}), {});
1773 then
1774 (env, SOME(exp));
1775 end match;
1776 end makeReductionFoldExp;
1777
1778 protected function reductionType
1779 input FCore.Cache inCache;
1780 input FCore.Graph inEnv;
1781 input Absyn.Path inFn;
1782 input DAE.Exp inExp;
1783 input DAE.Type inType;
1784 input DAE.Type unboxedType;
1785 input DAE.Dimensions dims;
1786 input Boolean hasGuardExp;
1787 input SourceInfo info;
1788 output FCore.Cache outCache = inCache;
1789 output DAE.Exp outExp;
1790 output DAE.Type outType;
1791 output DAE.Type resultType;
1792 output Option<Values.Value> defaultValue;
1793 output Absyn.Path outPath;
1794 protected
1795 Absyn.Path fn = AbsynUtil.makeNotFullyQualified(inFn);
1796 algorithm
1797 (outExp, outType, resultType, defaultValue, outPath) := match(fn, unboxedType)
1798 local
1799 Integer i;
1800 Real r;
1801 list<DAE.Type> fnTypes;
1802 DAE.Type ty,ty2,typeA,typeB,resType;
1803 Absyn.Path path;
1804 Values.Value v;
1805 DAE.Exp exp;
1806 InstTypes.PolymorphicBindings bindings;
1807 Option<Values.Value> defaultBinding;
1808
1809 case (Absyn.IDENT(name = "array"), _)
1810 algorithm
1811 335 ty := List.foldr(dims, Types.liftArray, inType);
1812 then
1813 (inExp, ty, ty, SOME(Values.ARRAY({},{0})), fn);
1814
1815 case (Absyn.IDENT(name = "$array"), _)
1816 algorithm
1817 ✗ ty := List.foldr(dims, Types.liftArray, inType);
1818 then
1819 (inExp, ty, ty, SOME(Values.ARRAY({},{0})), fn);
1820
1821 case (Absyn.IDENT(name = "list"), _)
1822 algorithm
1823 111 (exp, ty) := Types.matchType(inExp, inType, DAE.T_METABOXED_DEFAULT, true);
1824 111 ty := List.foldr(dims, Types.liftList, ty);
1825 then
1826 (exp, ty, ty, SOME(Values.LIST({})), fn);
1827
1828 case (Absyn.IDENT(name = "listReverse"), _)
1829 algorithm
1830 8 (exp, ty) := Types.matchType(inExp, inType, DAE.T_METABOXED_DEFAULT, true);
1831 8 ty := List.foldr(dims, Types.liftList, ty);
1832 then
1833 (exp, ty, ty, SOME(Values.LIST({})), fn);
1834
1835 case (Absyn.IDENT("min"), DAE.T_REAL())
1836 algorithm
1837 4 r := System.realMaxLit();
1838 4 v := Values.REAL(r);
1839 4 (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true);
1840 4 then
1841 (exp, ty, ty, SOME(v), fn);
1842
1843 case (Absyn.IDENT("min"), DAE.T_INTEGER())
1844 algorithm
1845 3 i := System.intMaxLit();
1846 3 v := Values.INTEGER(i);
1847 3 (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true);
1848 3 then
1849 (exp, ty, ty, SOME(v), fn);
1850
1851 case (Absyn.IDENT("min"), DAE.T_BOOL())
1852 algorithm
1853 v := Values.BOOL(true);
1854 3 (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true);
1855 3 then
1856 (exp, ty, ty, SOME(v), fn);
1857
1858 case (Absyn.IDENT("min"), DAE.T_STRING())
1859 algorithm
1860 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true);
1861 ✗ then
1862 (exp, ty, ty, NONE(), fn);
1863
1864 case (Absyn.IDENT("min"), DAE.T_ENUMERATION())
1865 algorithm
1866 ✗ v := Values.ENUM_LITERAL(AbsynUtil.suffixPath(unboxedType.path,
1867 List.last(unboxedType.names)), listLength(unboxedType.names));
1868 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_ENUMERATION_DEFAULT, true);
1869 ✗ then
1870 (exp, ty, ty, SOME(v), fn);
1871
1872 case (Absyn.IDENT("max"), DAE.T_REAL())
1873 algorithm
1874 5 r := realNeg(System.realMaxLit());
1875 5 v := Values.REAL(r);
1876 5 (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true);
1877 5 then
1878 (exp, ty, ty, SOME(v), fn);
1879
1880 case (Absyn.IDENT("max"), DAE.T_INTEGER())
1881 algorithm
1882 2 i := intNeg(System.intMaxLit());
1883 2 v := Values.INTEGER(i);
1884 2 (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true);
1885 2 then
1886 (exp, ty, ty, SOME(v), fn);
1887
1888 case (Absyn.IDENT("max"), DAE.T_BOOL())
1889 algorithm
1890 v := Values.BOOL(false);
1891 ✗ (exp,ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true);
1892 ✗ then
1893 (exp, ty, ty, SOME(v), fn);
1894
1895 case (Absyn.IDENT("max"), DAE.T_STRING())
1896 algorithm
1897 v := Values.STRING("");
1898 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true);
1899 ✗ then
1900 (exp, ty, ty, SOME(v), fn);
1901
1902 case (Absyn.IDENT("max"), DAE.T_ENUMERATION())
1903 algorithm
1904 ✗ v := Values.ENUM_LITERAL(AbsynUtil.suffixPath(unboxedType.path, listHead(unboxedType.names)), 1);
1905 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_ENUMERATION_DEFAULT, true);
1906 ✗ then
1907 (exp, ty, ty, SOME(v), fn);
1908
1909 case (Absyn.IDENT("sum"), DAE.T_REAL())
1910 algorithm
1911 v := Values.REAL(0.0);
1912 71 (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true);
1913 71 then
1914 (exp, ty, ty, SOME(v), fn);
1915
1916 case (Absyn.IDENT("sum"), DAE.T_INTEGER())
1917 algorithm
1918 v := Values.INTEGER(0);
1919 6 (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true);
1920 6 then
1921 (exp, ty, ty, SOME(v), fn);
1922
1923 case (Absyn.IDENT("sum"), DAE.T_BOOL())
1924 algorithm
1925 v := Values.BOOL(false);
1926 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true);
1927 ✗ then
1928 (exp, ty, ty, SOME(v), fn);
1929
1930 case (Absyn.IDENT("sum"), DAE.T_STRING())
1931 algorithm
1932 v := Values.STRING("");
1933 146 (exp, ty) := Types.matchType(inExp, inType, DAE.T_STRING_DEFAULT, true);
1934 146 then
1935 (exp, ty, ty, SOME(v), fn);
1936
1937 case (Absyn.IDENT("sum"), DAE.T_ARRAY())
1938 then (inExp, inType, inType, NONE(), fn);
1939
1940 case (Absyn.IDENT("product"), DAE.T_REAL())
1941 algorithm
1942 v := Values.REAL(1.0);
1943 4 (exp, ty) := Types.matchType(inExp, inType, DAE.T_REAL_DEFAULT, true);
1944 4 then
1945 (exp, ty, ty, SOME(v), fn);
1946
1947 case (Absyn.IDENT("product"), DAE.T_INTEGER())
1948 algorithm
1949 v := Values.INTEGER(1);
1950 11 (exp, ty) := Types.matchType(inExp, inType, DAE.T_INTEGER_DEFAULT, true);
1951 11 then
1952 (exp, ty, ty, SOME(v), fn);
1953
1954 case (Absyn.IDENT("product"), DAE.T_BOOL())
1955 algorithm
1956 v := Values.BOOL(true);
1957 ✗ (exp, ty) := Types.matchType(inExp, inType, DAE.T_BOOL_DEFAULT, true);
1958 ✗ then
1959 (exp, ty, ty, SOME(v), fn);
1960
1961 case (Absyn.IDENT("product"), DAE.T_STRING())
1962 algorithm
1963 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {"product reduction not defined for String"},info);
1964 ✗ then
1965 fail();
1966
1967 case (Absyn.IDENT("product"), DAE.T_ARRAY())
1968 then (inExp, inType, inType, NONE(), fn);
1969
1970 else
1971 algorithm
1972 35 (outCache, fnTypes) := Lookup.lookupFunctionsInEnv(inCache, inEnv, inFn, info);
1973 35 (typeA,typeB,resType,defaultBinding,path) := checkReductionType1(inEnv,inFn,fnTypes,info);
1974
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 14 times.
35 ty2 := if isSome(defaultBinding) then typeB else inType;
1975 35 (exp,typeA,bindings) := Types.matchTypePolymorphicWithError(inExp, inType,typeA,SOME(path),{},info);
1976 35 (_,typeB,bindings) := Types.matchTypePolymorphicWithError(DAE.CREF(DAE.CREF_IDENT("$result",DAE.T_ANYTYPE_DEFAULT,{}),DAE.T_ANYTYPE_DEFAULT),ty2,typeB,SOME(path),bindings,info);
1977 35 bindings := Types.solvePolymorphicBindings(bindings, info, path);
1978 35 typeA := Types.fixPolymorphicRestype(typeA, bindings, info);
1979 35 typeB := Types.fixPolymorphicRestype(typeB, bindings, info);
1980 35 resType := Types.fixPolymorphicRestype(resType, bindings, info);
1981
4/6
✓ Branch 2 taken 9 times.
✓ Branch 3 taken 26 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 9 times.
35 (exp,ty) := checkReductionType2(exp, inType,typeA,typeB,resType,Types.equivtypes(typeA,typeB) or isSome(defaultBinding),Types.equivtypes(typeB,resType),info);
1982
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 (outCache, Util.SUCCESS()) := instantiateDaeFunction(outCache, inEnv, path, false, NONE(), true);
1983
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
35 Error.assertionOrAddSourceMessage(Config.acceptMetaModelicaGrammar() or Flags.isSet(Flags.EXPERIMENTAL_REDUCTIONS), Error.COMPILER_NOTIFICATION, {"Custom reduction functions are an OpenModelica extension to the Modelica Specification. Do not use them if you need your model to compile using other tools or if you are concerned about using experimental features. Use -d=experimentalReductions to disable this message."}, info);
1984 35 then
1985 (exp, ty, typeB, defaultBinding, path);
1986 end match;
1987 end reductionType;
1988
1989 protected function checkReductionType1
1990 input FCore.Graph inEnv;
1991 input Absyn.Path inPath;
1992 input list<DAE.Type> fnTypes;
1993 input SourceInfo info;
1994 output DAE.Type typeA;
1995 output DAE.Type typeB;
1996 output DAE.Type resType;
1997 output Option<Values.Value> startValue;
1998 output Absyn.Path outPath;
1999 algorithm
2000 (typeA, typeB, resType, startValue, outPath) := match fnTypes
2001 local
2002 String str1, str2;
2003 Absyn.Path path;
2004 DAE.Exp e;
2005 Values.Value v;
2006
2007 case {}
2008 algorithm
2009 ✗ str1 := AbsynUtil.pathString(inPath);
2010 ✗ str2 := FGraph.printGraphPathStr(inEnv);
2011 ✗ Error.addSourceMessage(Error.LOOKUP_FUNCTION_ERROR, {str1, str2}, info);
2012 ✗ then
2013 fail();
2014
2015 case {DAE.T_FUNCTION(funcArg={DAE.FUNCARG(ty = typeA, const = DAE.C_VAR()),
2016 DAE.FUNCARG(ty = typeB, const = DAE.C_VAR(), defaultBinding=SOME(e))},
2017 funcResultType = resType, path = path)}
2018 algorithm
2019 21 v := Ceval.cevalSimple(e);
2020 then
2021 (typeA, typeB, resType, SOME(v), path);
2022
2023 case {DAE.T_FUNCTION(funcArg={DAE.FUNCARG(ty = typeA, const = DAE.C_VAR()),
2024 DAE.FUNCARG(ty = typeB, const = DAE.C_VAR(), defaultBinding=NONE())},
2025 funcResultType = resType, path = path)}
2026 then (typeA, typeB, resType, NONE(), path);
2027
2028 else
2029 algorithm
2030 ✗ str1 := stringDelimitList(List.map(fnTypes, TypesDump.unparseType), ",");
2031 ✗ Error.addSourceMessage(Error.UNSUPPORTED_REDUCTION_TYPE, {str1}, info);
2032 ✗ then
2033 fail();
2034
2035 end match;
2036 end checkReductionType1;
2037
2038 protected function checkReductionType2
2039 input DAE.Exp inExp;
2040 input DAE.Type expType;
2041 input DAE.Type typeA;
2042 input DAE.Type typeB;
2043 input DAE.Type typeC;
2044 input Boolean equivAB;
2045 input Boolean equivBC;
2046 input SourceInfo info;
2047 output DAE.Exp outExp;
2048 output DAE.Type outTy;
2049 algorithm
2050 (outExp,outTy) := match(equivAB,equivBC)
2051 local
2052 String str1,str2;
2053
2054 case (true, true)
2055 // (exp,outTy) = Types.matchType(exp,expType,typeA,true);
2056 then (inExp, typeA);
2057
2058 case (_, false)
2059 algorithm
2060 ✗ str1 := TypesDump.unparseType(typeB);
2061 ✗ str2 := TypesDump.unparseType(typeC);
2062 ✗ Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"second argument", "result-type", "identical", str1, str2},info);
2063 ✗ then
2064 fail();
2065
2066 case (false,true)
2067 algorithm
2068 ✗ str1 := TypesDump.unparseType(typeA);
2069 ✗ str2 := TypesDump.unparseType(typeB);
2070 ✗ Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"first", "second arguments", "identical", str1, str2},info);
2071 ✗ then
2072 fail();
2073
2074 case (true,true)
2075 algorithm
2076 ✗ str1 := TypesDump.unparseType(expType);
2077 ✗ str2 := TypesDump.unparseType(typeA);
2078 ✗ Error.addSourceMessage(Error.REDUCTION_TYPE_ERROR,{"reduction expression", "first argument", "compatible", str1, str2},info);
2079 ✗ then
2080 fail();
2081 end match;
2082 end checkReductionType2;
2083
2084 protected function constToVariability "translates an DAE.Const to a SCode.Variability"
2085 input DAE.Const const;
2086 output SCode.Variability variability;
2087 algorithm
2088 variability := match const
2089 case DAE.C_VAR() then SCode.VAR();
2090 case DAE.C_PARAM() then SCode.PARAM();
2091 case DAE.C_CONST() then SCode.CONST();
2092 case DAE.C_UNKNOWN()
2093 algorithm
2094 ✗ true := Flags.isSet(Flags.FAILTRACE);
2095 ✗ Debug.trace("- Static.constToVariability failed on DAE.C_UNKNOWN()\n");
2096 ✗ then
2097 fail();
2098 end match;
2099 end constToVariability;
2100
2101 protected function constructArrayType
2102 "Helper function for elabCallReduction. Combines the type of the expression in
2103 an array constructor with the type of the generated array by replacing the
2104 placeholder T_UNKNOWN in arrayType with expType. Example:
2105 r[i] for i in 1:5 =>
2106 arrayType = type(i in 1:5) = (T_ARRAY(DIM(5), T_UNKNOWN),NONE())
2107 expType = type(r[i]) = (T_REAL,NONE())
2108 => resType = (T_ARRAY(DIM(5), (T_REAL,NONE())),NONE())"
2109 input DAE.Type arrayType;
2110 input DAE.Type expType;
2111 output DAE.Type resType;
2112 algorithm
2113 resType := match arrayType
2114 local
2115 DAE.Type ty;
2116 DAE.Dimension dim;
2117
2118 case DAE.T_UNKNOWN() then expType;
2119
2120 case DAE.T_ARRAY(dims = {dim}, ty = ty)
2121 algorithm
2122 ✗ ty := constructArrayType(ty, expType);
2123 ✗ then
2124 DAE.T_ARRAY(ty, {dim});
2125 end match;
2126 end constructArrayType;
2127
2128 protected function elabCodeType
2129 "This function will construct the correct type for the given Code expression.
2130 The types are built-in classes of different types. E.g. the class TypeName is
2131 the type of Code expressions corresponding to a type name Code expression."
2132 input Absyn.CodeNode inCode;
2133 output DAE.Type outType;
2134 algorithm
2135 outType := match inCode
2136 case Absyn.C_TYPENAME()
2137 then DAE.T_CODE(DAE.C_TYPENAME());
2138
2139 case Absyn.C_VARIABLENAME()
2140 then DAE.T_CODE(DAE.C_VARIABLENAME());
2141
2142 case Absyn.C_EQUATIONSECTION()
2143 then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("EquationSection")),{},NONE(), false);
2144
2145 case Absyn.C_ALGORITHMSECTION()
2146 then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("AlgorithmSection")),{},NONE(), false);
2147
2148 case Absyn.C_ELEMENT()
2149 then DAE.T_COMPLEX(ClassInf.UNKNOWN(Absyn.IDENT("Element")),{},NONE(), false);
2150
2151 case Absyn.C_EXPRESSION()
2152 then DAE.T_CODE(DAE.C_EXPRESSION());
2153
2154 case Absyn.C_MODIFICATION()
2155 then DAE.T_CODE(DAE.C_EXPRESSION_OR_MODIFICATION());
2156 end match;
2157 end elabCodeType;
2158
2159 public function elabGraphicsExp
2160 "investigating Modelica 2.0 graphical annotations.
2161 These have an array of records representing graphical objects. These
2162 elements can have different types, therefore elab_graphic_exp will allow
2163 arrays with elements of varying types. "
2164 input FCore.Cache inCache;
2165 input FCore.Graph inEnv;
2166 input Absyn.Exp inExp;
2167 input Boolean inBoolean;
2168 input DAE.Prefix inPrefix;
2169 input SourceInfo info;
2170 output FCore.Cache outCache;
2171 output DAE.Exp outExp;
2172 output DAE.Properties outProperties;
2173 algorithm
2174 (outCache,outExp,outProperties):=
2175 matchcontinue (inCache, inEnv, inExp, inBoolean, inPrefix)
2176 local
2177 Integer i,l,nmax;
2178 Real r;
2179 DAE.Dimension dim1,dim2;
2180 Boolean b,impl,a,havereal;
2181 String s,ps;
2182 DAE.Exp dexp,e1_1,e2_1,e_1,e3_1,start_1,stop_1,start_2,stop_2,step_1,step_2,mexp;
2183 DAE.Properties prop,prop1,prop2,prop3;
2184 FCore.Graph env;
2185 Absyn.ComponentRef cr,fn;
2186 DAE.Type t,start_t,stop_t,step_t,t_1,t_2;
2187 DAE.Const c1,c,c_start,c_stop,const,c_step;
2188 Absyn.Exp e,e1,e2,e3,start,stop,step,exp;
2189 Absyn.Operator op;
2190 list<Absyn.Exp> args,es;
2191 list<Absyn.NamedArg> nargs;
2192 list<DAE.Exp> es_1;
2193 list<DAE.Properties> props;
2194 list<DAE.Type> types,tps_2;
2195 list<DAE.TupleConst> consts;
2196 DAE.Type rt,at;
2197 list<list<DAE.Properties>> tps;
2198 list<list<DAE.Type>> tps_1;
2199 FCore.Cache cache;
2200 DAE.Prefix pre;
2201 list<list<Absyn.Exp>> ess;
2202 list<list<DAE.Exp>> dess;
2203
2204 ✗ case (cache, _, Absyn.INTEGER(value = i), _, _) then (cache,DAE.ICONST(i),DAE.PROP(DAE.T_INTEGER_DEFAULT,DAE.C_CONST())); /* impl */
2205
2206 case (cache, _, Absyn.REAL(value = s), _, _)
2207 algorithm
2208 ✗ r := stringReal(s);
2209 ✗ then
2210 (cache,DAE.RCONST(r),DAE.PROP(DAE.T_REAL_DEFAULT,DAE.C_CONST()));
2211
2212 case (cache, _, Absyn.STRING(value = s), _, _)
2213 algorithm
2214 17 s := System.unescapedString(s);
2215 17 then
2216 (cache,DAE.SCONST(s),DAE.PROP(DAE.T_STRING_DEFAULT,DAE.C_CONST()));
2217
2218 case (cache, _, Absyn.BOOL(value = b), _, _)
2219 ✗ then
2220 (cache,DAE.BCONST(b),DAE.PROP(DAE.T_BOOL_DEFAULT,DAE.C_CONST()));
2221
2222 // adrpo: 2010-11-17 this is now fixed!
2223 // adrpo, if we have useHeatPort, return false.
2224 // this is a workaround for handling Modelica.Electrical.Analog.Basic.Resistor
2225 // case (cache,env,Absyn.CREF(componentRef = cr as Absyn.CREF_IDENT("useHeatPort", _)),impl,pre,info)
2226 // equation
2227 // dexp = DAE.BCONST(false);
2228 // prop = DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST());
2229 // then
2230 // (cache,dexp,prop);
2231 case (cache, env, Absyn.CREF(componentRef = cr), impl, pre)
2232 algorithm
2233 ✗ (cache,SOME((dexp,prop,_))) := elabCref(cache,env, cr, impl,true /*perform vectorization*/,pre,info);
2234 ✗ then
2235 (cache,dexp,prop);
2236
2237 // Binary and unary operations
2238 case (cache, env, (exp as Absyn.BINARY(exp1 = e1,op = op,exp2 = e2)), impl, pre)
2239 algorithm
2240 ✗ (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info);
2241 ✗ (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info);
2242 ✗ (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info);
2243 then
2244 (cache, dexp, prop);
2245 case (cache, env, (e as Absyn.UNARY(op = Absyn.UPLUS())), impl, pre)
2246 algorithm
2247 ✗ (cache,e_1,DAE.PROP(t,c)) := elabGraphicsExp(cache,env, e, impl,pre,info);
2248 ✗ true := Types.isRealOrSubTypeReal(Types.arrayElementType(t));
2249 ✗ prop := DAE.PROP(t,c);
2250 ✗ then
2251 (cache,e_1,prop);
2252 case (cache, env, (exp as Absyn.UNARY(op = op,exp = e)), impl, pre)
2253 algorithm
2254 ✗ (cache,e_1,prop1) := elabGraphicsExp(cache,env, e, impl,pre,info);
2255 ✗ (cache, dexp, prop) := OperatorOverloading.unary(cache,env, op, prop1, e_1, exp, e, impl, pre, info);
2256 then
2257 (cache, dexp, prop);
2258
2259 // Logical binary expressions
2260 case (cache, env, (exp as Absyn.LBINARY(exp1 = e1,op = op,exp2 = e2)), impl, pre)
2261 algorithm
2262 ✗ (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info);
2263 ✗ (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info);
2264 ✗ (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info);
2265 then
2266 (cache, dexp, prop);
2267
2268 // Logical unary expressions
2269 case (cache, env, (exp as Absyn.LUNARY(op = op,exp = e)), impl, pre)
2270 algorithm
2271 ✗ (cache,e_1,prop1) := elabGraphicsExp(cache,env, e, impl,pre,info);
2272 ✗ (cache, dexp, prop) := OperatorOverloading.unary(cache,env, op, prop1, e_1, exp, e, impl, pre, info);
2273 then
2274 (cache, dexp, prop);
2275
2276 // Relation expressions
2277 case (cache, env, (exp as Absyn.RELATION(exp1 = e1,op = op,exp2 = e2)), impl, pre)
2278 algorithm
2279 ✗ (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info);
2280 ✗ (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info);
2281 ✗ (cache, dexp, prop) := OperatorOverloading.binary(cache, env, op, prop1, e1_1, prop2, e2_1, exp, e1, e2, impl, pre, info);
2282 then
2283 (cache, dexp, prop);
2284
2285 // Conditional expressions
2286 case (cache, env, e as Absyn.IFEXP(), impl, pre)
2287 algorithm
2288 ✗ Absyn.IFEXP(ifExp = e1,trueBranch = e2,elseBranch = e3) := AbsynUtil.canonIfExp(e);
2289 ✗ (cache,e1_1,prop1) := elabGraphicsExp(cache,env, e1, impl,pre,info);
2290 ✗ (cache,e2_1,prop2) := elabGraphicsExp(cache,env, e2, impl,pre,info);
2291 ✗ (cache,e3_1,prop3) := elabGraphicsExp(cache,env, e3, impl,pre,info);
2292 ✗ (cache,e_1,prop) := makeIfExp(cache,env, e1_1, prop1, e2_1, prop2, e3_1, prop3, impl,pre, info);
2293 then
2294 (cache,e_1,prop);
2295
2296 // Function calls
2297 case (cache, env, Absyn.CALL(function_ = fn,functionArgs = Absyn.FUNCTIONARGS(args = args,argNames = nargs)), _, pre)
2298 algorithm
2299 13 (cache,e_1,prop) := elabCall(cache,env, fn, args, nargs, inExp.typeVars, true,pre,info);
2300 then
2301 (cache,e_1,prop);
2302
2303 // PR. Get the properties for each expression in the tuple.
2304 // Each expression has its own constflag.
2305 // The output from functions does just have one const flag. Fix this!!
2306 case (cache, env, Absyn.TUPLE(expressions = (es as (_ :: _))), impl, pre)
2307 algorithm
2308 ✗ (cache,es_1,props) := elabTuple(cache,env,es,impl,false,pre,info,false);
2309 ✗ (types,consts) := splitProps(props);
2310 ✗ then
2311 (cache,DAE.TUPLE(es_1),DAE.PROP_TUPLE(DAE.T_TUPLE(types,NONE()),DAE.TUPLE_CONST(consts)));
2312
2313 // array-related expressions
2314 case (cache, env, Absyn.RANGE(start = start,step = NONE(),stop = stop), impl, pre)
2315 algorithm
2316 ✗ (cache,start_1,DAE.PROP(start_t,c_start)) := elabGraphicsExp(cache,env, start, impl,pre,info);
2317 ✗ (cache,stop_1,DAE.PROP(stop_t,c_stop)) := elabGraphicsExp(cache,env, stop, impl,pre,info);
2318 ✗ (_,NONE(),_,rt) := deoverloadRange(start_1,start_t,NONE(),NONE(),stop_1,stop_t,info);
2319 ✗ const := Types.constAnd(c_start, c_stop);
2320 ✗ (cache, t) := elabRangeType(cache, env, start_1, NONE(), stop_1, start_t, rt, const, impl);
2321 ✗ then
2322 (cache,DAE.RANGE(t,start_1,NONE(),stop_1),DAE.PROP(t,const));
2323
2324 case (cache, env, Absyn.RANGE(start = start,step = SOME(step),stop = stop), impl, pre)
2325 algorithm
2326 ✗ (cache,start_1,DAE.PROP(start_t,c_start)) := elabGraphicsExp(cache,env, start, impl,pre,info) "fprintln(\"setr\", \"elab_graphics_exp_range2\") &" ;
2327 ✗ (cache,step_1,DAE.PROP(step_t,c_step)) := elabGraphicsExp(cache,env, step, impl,pre,info);
2328 ✗ (cache,stop_1,DAE.PROP(stop_t,c_stop)) := elabGraphicsExp(cache,env, stop, impl,pre,info);
2329 ✗ (start_2,SOME(step_2),stop_2,rt) := deoverloadRange(start_1,start_t, SOME(step_1),SOME(step_t), stop_1,stop_t,info);
2330 ✗ c1 := Types.constAnd(c_start, c_step);
2331 ✗ const := Types.constAnd(c1, c_stop);
2332 ✗ (cache, t) := elabRangeType(cache, env, start_1, SOME(step_1), stop_1, start_t, rt, const, impl);
2333 ✗ then
2334 (cache,DAE.RANGE(t,start_2,SOME(step_2),stop_2),DAE.PROP(t,const));
2335
2336 case (cache, env, Absyn.ARRAY(arrayExp = es), impl, pre)
2337 algorithm
2338 ✗ (cache,es_1,DAE.PROP(t,const)) := elabGraphicsArray(cache,env, es, impl,pre,info);
2339 ✗ l := listLength(es_1);
2340 ✗ at := Types.simplifyType(t);
2341 ✗ a := Types.isArray(t);
2342 ✗ then
2343 (cache,DAE.ARRAY(at,a,es_1),DAE.PROP(DAE.T_ARRAY(t, {DAE.DIM_INTEGER(l)}),const));
2344
2345 case (cache, env, Absyn.MATRIX(matrix = ess), impl, pre)
2346 algorithm
2347 ✗ (cache,dess,tps) := elabExpListList(cache,env,ess,impl,true,pre,info);
2348 ✗ tps_1 := List.mapList(tps, Types.getPropType);
2349 ✗ tps_2 := List.flatten(tps_1);
2350 ✗ nmax := matrixConstrMaxDim(tps_2);
2351 ✗ havereal := Types.containReal(tps_2);
2352 ✗ (cache,mexp,DAE.PROP(t,c),dim1,dim2) := elabMatrixSemi(cache,env,dess,tps,impl,havereal,nmax,true,pre,info);
2353 ✗ elabMatrixToMatrixExp(mexp); // TODO: Does this do anything?
2354 ✗ t_1 := Types.unliftArray(t);
2355 ✗ t_2 := Types.unliftArray(t_1);
2356 ✗ then
2357 (cache,mexp,DAE.PROP(DAE.T_ARRAY(DAE.T_ARRAY(t_2, {dim2}), {dim1}),c));
2358
2359 case (_, _, e, _, pre)
2360 algorithm
2361 ✗ true := Flags.isSet(Flags.FAILTRACE);
2362 ✗ Print.printErrorBuf("- Inst.elabGraphicsExp failed: ");
2363 ✗ ps := PrefixUtil.printPrefixStr2(pre);
2364 ✗ s := Dump.printExpStr(e);
2365 ✗ Print.printErrorBuf(ps+s);
2366 ✗ Print.printErrorBuf("\n");
2367 ✗ then
2368 fail();
2369 end matchcontinue;
2370 end elabGraphicsExp;
2371
2372 protected function deoverloadRange "Does deoverloading of range expressions.
2373 They can be both Integer ranges and Real ranges.
2374 This function determines which one to use."
2375 input DAE.Exp inStartExp;
2376 input DAE.Type inStartType;
2377 input Option<DAE.Exp> inStepExp;
2378 input Option<DAE.Type> inStepType;
2379 input DAE.Exp inStopExp;
2380 input DAE.Type inStopType;
2381 input SourceInfo inInfo;
2382 output DAE.Exp outStart;
2383 output Option<DAE.Exp> outStep;
2384 output DAE.Exp outStop;
2385 output DAE.Type outRangeType;
2386 algorithm
2387 (outStart, outStep, outStop, outRangeType) := match(inStartType, inStepType, inStopType)
2388 local
2389 DAE.Exp step_exp;
2390 DAE.Type step_ty, et;
2391 list<String> ns,ne;
2392 String e1_str, e2_str, t1_str;
2393
2394 // Boolean range has no step value.
2395 case (DAE.T_BOOL(), NONE(), DAE.T_BOOL())
2396 then (inStartExp, NONE(), inStopExp, DAE.T_BOOL_DEFAULT);
2397
2398 case (DAE.T_INTEGER(), NONE(), DAE.T_INTEGER())
2399 then (inStartExp, inStepExp, inStopExp, DAE.T_INTEGER_DEFAULT);
2400
2401 case (DAE.T_INTEGER(), SOME(DAE.T_INTEGER()), DAE.T_INTEGER())
2402 then (inStartExp, inStepExp, inStopExp, DAE.T_INTEGER_DEFAULT);
2403
2404 // Enumeration range has no step value.
2405 case (DAE.T_ENUMERATION(names = ns), NONE(), DAE.T_ENUMERATION(names = ne))
2406 algorithm
2407 // check if enumtype start and end are equal
2408
1/2
✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
4 if List.isEqual(ns,ne,true) then
2409 // convert vars
2410 4 et := Types.simplifyType(inStartType);
2411 else
2412 // Print an error if the enumerations are different for start and stop.
2413 ✗ e1_str := ExpressionBasics.printExpStr(inStartExp);
2414 ✗ e2_str := ExpressionBasics.printExpStr(inStopExp);
2415 ✗ t1_str := TypesDump.unparseTypeNoAttr(inStartType);
2416 ✗ Error.addSourceMessageAndFail(Error.UNRESOLVABLE_TYPE,
2417 {e1_str + ":" + e2_str, t1_str + ", " + t1_str, ""}, inInfo);
2418 end if;
2419 then
2420 (inStartExp, NONE(), inStopExp, et);
2421
2422 case (_, NONE(), _)
2423 algorithm
2424
3/6
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
4 ({outStart, outStop},_) := OperatorOverloading.elabArglist(
2425 {DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT},
2426 {(inStartExp, inStartType), (inStopExp, inStopType)});
2427 then
2428 (outStart, NONE(), outStop, DAE.T_REAL_DEFAULT);
2429
2430 case (_, SOME(step_ty), _)
2431 algorithm
2432
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
3 SOME(step_exp) := inStepExp;
2433
4/8
✗ Branch 4 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 3 times.
6 ({outStart, step_exp, outStop},_) := OperatorOverloading.elabArglist(
2434 {DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT, DAE.T_REAL_DEFAULT},
2435 {(inStartExp, inStartType), (step_exp, step_ty), (inStopExp, inStopType)});
2436 then
2437 (outStart, SOME(step_exp), outStop, DAE.T_REAL_DEFAULT);
2438
2439 end match;
2440 end deoverloadRange;
2441
2442 protected function elabRangeType
2443 "This function creates a type for a range expression given by a start, stop,
2444 and optional step expression. This function always succeeds, but may return an
2445 array-type of unknown size if the expressions can't be constant evaluated."
2446 input FCore.Cache inCache;
2447 input FCore.Graph inEnv;
2448 input DAE.Exp inStart;
2449 input Option<DAE.Exp> inStep;
2450 input DAE.Exp inStop;
2451 input DAE.Type inType;
2452 input DAE.Type inExpType;
2453 input DAE.Const co;
2454 input Boolean inImpl;
2455 output FCore.Cache outCache;
2456 output DAE.Type outType;
2457 algorithm
2458 (outCache, outType) := matchcontinue(inStep, co)
2459 local
2460 DAE.Exp step_exp;
2461 Values.Value start_val, step_val, stop_val;
2462 Integer dim;
2463 FCore.Cache cache;
2464
2465 case (_, DAE.C_VAR())
2466 187 then (inCache, DAE.T_ARRAY(inType, {DAE.DIM_UNKNOWN()}));
2467
2468 // No step value.
2469 case (NONE(), _)
2470 algorithm
2471 1742 (cache, start_val) := Ceval.ceval(inCache, inEnv, inStart, inImpl);
2472 1742 (cache, stop_val) := Ceval.ceval(cache, inEnv, inStop, inImpl);
2473 1739 dim := elabRangeSize(start_val, NONE(), stop_val);
2474 3478 then
2475 (cache, DAE.T_ARRAY(inType, {DAE.DIM_INTEGER(dim)}));
2476
2477 // Some step value.
2478 case (SOME(step_exp), _)
2479 algorithm
2480 18 (cache, start_val) := Ceval.ceval(inCache, inEnv, inStart, inImpl);
2481 18 (cache, step_val) := Ceval.ceval(cache, inEnv, step_exp, inImpl);
2482 18 (cache, stop_val) := Ceval.ceval(cache, inEnv, inStop, inImpl);
2483 18 dim := elabRangeSize(start_val, SOME(step_val), stop_val);
2484 36 then
2485 (cache, DAE.T_ARRAY(inType, {DAE.DIM_INTEGER(dim)}));
2486
2487 // Ceval failed in previous cases, return an array of unknown size.
2488 3 else (inCache, DAE.T_ARRAY(inType, {DAE.DIM_UNKNOWN()}));
2489 end matchcontinue;
2490 end elabRangeType;
2491
2492 protected function elabRangeSize
2493 "Returns the size of a range, given a start, stop, and optional step value."
2494 input Values.Value inStartValue;
2495 input Option<Values.Value> inStepValue;
2496 input Values.Value inStopValue;
2497 output Integer outSize;
2498 algorithm
2499 outSize := matchcontinue(inStartValue, inStepValue, inStopValue)
2500 local
2501 Integer int_start, int_step, int_stop, dim;
2502 Real real_start, real_step, real_stop;
2503
2504 // start:stop where start > stop gives an empty vector.
2505 case (_, NONE(), _)
2506 algorithm
2507 // start > stop == not (start <= stop)
2508
2/2
✓ Branch 1 taken 1617 times.
✓ Branch 2 taken 122 times.
1739 false := ValuesUtil.safeLessEq(inStartValue, inStopValue);
2509 then
2510 0;
2511
2512 case (Values.INTEGER(int_start), NONE(), Values.INTEGER(int_stop))
2513 algorithm
2514 1610 dim := int_stop - int_start + 1;
2515 then
2516 dim;
2517
2518 case (Values.INTEGER(int_start), SOME(Values.INTEGER(int_step)),
2519 Values.INTEGER(int_stop))
2520 algorithm
2521 15 dim := int_stop - int_start;
2522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
15 dim := intDiv(dim, int_step) + 1;
2523 then
2524 dim;
2525
2526 case (Values.REAL(real_start), NONE(), Values.REAL(real_stop))
2527 ✗ then Util.realRangeSize(real_start, 1.0, real_stop);
2528
2529 case (Values.REAL(real_start), SOME(Values.REAL(real_step)),
2530 Values.REAL(real_stop))
2531 3 then Util.realRangeSize(real_start, real_step, real_stop);
2532
2533 case (Values.ENUM_LITERAL(index = int_start), NONE(),
2534 Values.ENUM_LITERAL(index = int_stop))
2535 algorithm
2536 4 dim := int_stop - int_start + 1;
2537 then
2538 dim;
2539
2540 case (Values.BOOL(true), NONE(), Values.BOOL(false)) then 0;
2541 case (Values.BOOL(false), NONE(), Values.BOOL(true)) then 2;
2542 case (Values.BOOL(_), NONE(), Values.BOOL(_)) then 1;
2543 end matchcontinue;
2544 end elabRangeSize;
2545
2546 protected function elabTuple
2547 "This function does elaboration of tuples, i.e. function calls returning several values."
2548 input FCore.Cache inCache;
2549 input FCore.Graph inEnv;
2550 input list<Absyn.Exp> inExpl;
2551 input Boolean inImplicit;
2552 input Boolean inDoVect;
2553 input DAE.Prefix inPrefix;
2554 input SourceInfo inInfo;
2555 input Boolean isLhs;
2556 output FCore.Cache outCache = inCache;
2557 output list<DAE.Exp> outExpl = {};
2558 output list<DAE.Properties> outProperties = {};
2559 protected
2560 DAE.Exp exp;
2561 DAE.Properties prop;
2562 algorithm
2563
2564
4/4
✓ Branch 0 taken 3068 times.
✓ Branch 1 taken 82 times.
✓ Branch 3 taken 3067 times.
✓ Branch 4 taken 1 time.
3150 if if not isLhs then not Config.acceptMetaModelicaGrammar() else false then
2565 2 Error.addSourceMessage(Error.RHS_TUPLE_EXPRESSION, {Dump.printExpStr(Absyn.TUPLE(inExpl))}, inInfo);
2566 1 fail();
2567 end if;
2568
2569
2/2
✓ Branch 0 taken 6300 times.
✓ Branch 1 taken 3149 times.
9449 for e in inExpl loop
2570 6300 (outCache, exp, prop) :=
2571 elabExp(outCache, inEnv, e, inImplicit, inDoVect, inPrefix, inInfo);
2572
2573
2/2
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 6209 times.
6300 if AbsynUtil.isTuple(e) then
2574 91 (exp, prop) := Types.matchProp(exp, prop,
2575 DAE.PROP(DAE.T_METABOXED_DEFAULT, DAE.C_CONST()), true);
2576 end if;
2577
2578 6300 outExpl := exp :: outExpl;
2579 6300 outProperties := prop :: outProperties;
2580 end for;
2581
2582 3149 outExpl := listReverse(outExpl);
2583 3149 outProperties := listReverse(outProperties);
2584 end elabTuple;
2585
2586 protected function stripExtraArgsFromType
2587 input list<Slot> slots;
2588 input DAE.Type inType;
2589 output DAE.Type outType = inType;
2590 algorithm
2591 outType := matchcontinue outType
2592 case DAE.T_FUNCTION()
2593 algorithm
2594 35 outType.funcArg := stripExtraArgsFromType2(slots, outType.funcArg);
2595 then
2596 outType;
2597
2598 else
2599 algorithm
2600 ✗ true := Flags.isSet(Flags.FAILTRACE);
2601 ✗ Debug.trace("- Static.stripExtraArgsFromType failed\n");
2602 ✗ then
2603 fail();
2604 end matchcontinue;
2605 end stripExtraArgsFromType;
2606
2607 protected function stripExtraArgsFromType2
2608 input list<Slot> inSlots;
2609 input list<DAE.FuncArg> inType;
2610 input list<DAE.FuncArg> inAccumType = {};
2611 output list<DAE.FuncArg> outType;
2612 algorithm
2613 outType := match(inSlots, inType)
2614 local
2615 list<Slot> slotsRest;
2616 list<DAE.FuncArg> rest;
2617 DAE.FuncArg arg;
2618
2619 case (SLOT(slotFilled = true) :: slotsRest, _ :: rest)
2620 60 then stripExtraArgsFromType2(slotsRest, rest, inAccumType);
2621
2622 case (SLOT(slotFilled = false) :: slotsRest, arg :: rest)
2623 35 then stripExtraArgsFromType2(slotsRest, rest, arg :: inAccumType);
2624
2625 35 case ({}, {}) then listReverse(inAccumType);
2626 end match;
2627 end stripExtraArgsFromType2;
2628
2629 protected function elabArray
2630 "This function elaborates on array expressions.
2631
2632 All types of an array should be equivalent. However, mixed Integer and Real
2633 elements are allowed in an array and in that case the Integer elements are
2634 converted to Real elements."
2635 input list<DAE.Exp> inExpl;
2636 input list<DAE.Properties> inProps;
2637 input DAE.Prefix inPrefix;
2638 input SourceInfo inInfo;
2639 output list<DAE.Exp> outExpLst;
2640 output DAE.Properties outProperties;
2641 protected
2642 list<DAE.Type> types = {};
2643 DAE.Type ty;
2644 DAE.Const c = DAE.C_CONST(), c2;
2645 Boolean mixed;
2646 algorithm
2647 // Empty array constructors are not allowed in Modelica.
2648
1/2
✓ Branch 0 taken 51407 times.
✗ Branch 1 not taken.
51407 if listEmpty(inExpl) then
2649 ✗ Error.addSourceMessage(Error.EMPTY_ARRAY, {}, inInfo);
2650 ✗ fail();
2651 end if;
2652
2653 // Get the types of all elements, and the array's variability.
2654
2/2
✓ Branch 0 taken 216889 times.
✓ Branch 1 taken 51407 times.
268296 for p in inProps loop
2655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 216889 times.
216889 DAE.PROP(type_ = ty, constFlag = c2) := p;
2656 types := ty :: types;
2657 216889 c := Types.constAnd(c, c2);
2658 end for;
2659 51407 types := listReverse(types);
2660
2661 // Check if the array contains a mix of ints and reals.
2662 51407 (ty, mixed) := elabArrayHasMixedIntReals(types);
2663
2664
2/2
✓ Branch 0 taken 999 times.
✓ Branch 1 taken 50408 times.
51407 if mixed then
2665 999 outExpLst := elabArrayReal2(inExpl, types, ty);
2666 else
2667 50408 (outExpLst, ty) := elabArray2(inExpl, types, inPrefix, inInfo);
2668 end if;
2669
2670 51407 outProperties := DAE.PROP(ty, c);
2671 end elabArray;
2672
2673 protected function elabArrayHasMixedIntReals
2674 "Helper function to elabArray. Checks if a list of types contains both
2675 Integer and Real types, and returns the first Real type if it does."
2676 input list<DAE.Type> inTypes;
2677 output DAE.Type outType;
2678 output Boolean outIsMixed = true;
2679 protected
2680 DAE.Type ty;
2681 list<DAE.Type> rest_tys;
2682 algorithm
2683
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51407 times.
51407 outType :: rest_tys := inTypes;
2684
2685 // If the first element is a Real, search for an Integer.
2686
2/2
✓ Branch 1 taken 31532 times.
✓ Branch 2 taken 19875 times.
51407 if Types.isReal(outType) then
2687
2/2
✓ Branch 0 taken 118953 times.
✓ Branch 1 taken 31114 times.
150067 while not listEmpty(rest_tys) loop
2688 118953 ty :: rest_tys := rest_tys;
2689
2690
2/2
✓ Branch 1 taken 118535 times.
✓ Branch 2 taken 418 times.
118953 if Types.isInteger(ty) then
2691 418 return;
2692 end if;
2693 end while;
2694 // If the first element is an Integer, search for a Real.
2695 elseif Types.isInteger(outType) then
2696
2/2
✓ Branch 0 taken 37942 times.
✓ Branch 1 taken 15358 times.
53300 while not listEmpty(rest_tys) loop
2697 37942 outType :: rest_tys := rest_tys;
2698
2699
2/2
✓ Branch 1 taken 37361 times.
✓ Branch 2 taken 581 times.
37942 if Types.isReal(outType) then
2700 581 return;
2701 end if;
2702 end while;
2703 end if;
2704
2705 outIsMixed := false;
2706 end elabArrayHasMixedIntReals;
2707
2708 protected function elabArrayConst
2709 "Constructs a const value from a list of properties, using constAnd."
2710 input list<DAE.Properties> inProperties;
2711 output DAE.Const outConst = DAE.C_CONST();
2712 algorithm
2713
2/2
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
225 for prop in inProperties loop
2714 156 outConst := Types.constAnd(outConst, Types.getPropConst(prop));
2715 end for;
2716 end elabArrayConst;
2717
2718 protected function elabArrayReal2
2719 "Applies type_convert to all expressions in a list to the type given as
2720 argument."
2721 input list<DAE.Exp> inExpl;
2722 input list<DAE.Type> inTypes;
2723 input DAE.Type inExpectedType;
2724 output list<DAE.Exp> outExpl = {};
2725 protected
2726 DAE.Exp exp;
2727 list<DAE.Exp> rest_expl = inExpl;
2728 algorithm
2729
2/2
✓ Branch 0 taken 4764 times.
✓ Branch 1 taken 999 times.
5763 for ty in inTypes loop
2730
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4764 times.
4764 exp :: rest_expl := rest_expl;
2731
2732 // If the types are not equivalent, type convert the expression.
2733
2/2
✓ Branch 1 taken 3155 times.
✓ Branch 2 taken 1609 times.
4764 if not Types.equivtypes(ty, inExpectedType) then
2734 3155 exp := Types.matchType(exp, ty, inExpectedType, true);
2735 end if;
2736
2737 outExpl := exp :: outExpl;
2738 end for;
2739
2740 999 outExpl := listReverse(outExpl);
2741 end elabArrayReal2;
2742
2743 protected function elabArray2
2744 "Helper function to elabArray, checks that all elements are equivalent."
2745 input list<DAE.Exp> inExpl;
2746 input list<DAE.Type> inTypes;
2747 input DAE.Prefix inPrefix;
2748 input SourceInfo inInfo;
2749 output list<DAE.Exp> outExpl;
2750 output DAE.Type outType;
2751 protected
2752 DAE.Type ty2;
2753 list<DAE.Type> rest_tys;
2754 DAE.Exp exp1;
2755 list<DAE.Exp> rest_expl;
2756 String pre_str, exp_str, expl_str, ty1_str, ty2_str;
2757 algorithm
2758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50408 times.
50408 exp1 :: rest_expl := inExpl;
2759
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 50408 times.
50408 outType :: rest_tys := inTypes;
2760
2761 50408 outExpl := {exp1};
2762 50408 outType := Types.getUniontypeIfMetarecordReplaceAllSubtypes(outType);
2763
2764
2/2
✓ Branch 0 taken 161717 times.
✓ Branch 1 taken 50408 times.
212125 for exp2 in rest_expl loop
2765
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 161717 times.
161717 ty2 :: rest_tys := rest_tys;
2766 161717 ty2 := Types.getUniontypeIfMetarecordReplaceAllSubtypes(ty2);
2767
2768 // If the types are not equivalent, try type conversion.
2769
2/2
✓ Branch 1 taken 445 times.
✓ Branch 2 taken 161272 times.
161717 if not Types.equivtypes(outType, ty2) then
2770 try
2771 445 (exp2, outType) := Types.matchType(exp2, outType, ty2, false);
2772 else
2773 ✗ ty1_str := TypesDump.unparseTypeNoAttr(outType);
2774 ✗ ty2_str := TypesDump.unparseTypeNoAttr(ty2);
2775 ✗ Types.typeErrorSanityCheck(ty1_str, ty2_str, inInfo);
2776 ✗ pre_str := PrefixUtil.printPrefixStr(inPrefix);
2777 ✗ exp_str := ExpressionBasics.printExpStr(exp2);
2778 ✗ expl_str := List.toStringCustom(inExpl, ExpressionBasics.printExpStr, "", "[", ",", "]", true);
2779 ✗ Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_ARRAY_EXP,
2780 {pre_str, exp_str, ty1_str, expl_str, ty2_str}, inInfo);
2781 end try;
2782 end if;
2783
2784 outExpl := exp2 :: outExpl;
2785 end for;
2786
2787 50408 outExpl := listReverse(outExpl);
2788 end elabArray2;
2789
2790 protected function elabGraphicsArray
2791 "This function elaborates array expressions for graphics elaboration."
2792 input FCore.Cache inCache;
2793 input FCore.Graph inEnv;
2794 input list<Absyn.Exp> inExpl;
2795 input Boolean inImplicit;
2796 input DAE.Prefix inPrefix;
2797 input SourceInfo inInfo;
2798 output FCore.Cache outCache = inCache;
2799 output list<DAE.Exp> outExpl = {};
2800 output DAE.Properties outProperties;
2801 protected
2802 DAE.Const c = DAE.C_CONST(), c2;
2803 DAE.Exp exp;
2804 DAE.Type ty;
2805 algorithm
2806 // Empty array constructors are not allowed in Modelica.
2807 ✗ if listEmpty(inExpl) then
2808 ✗ Error.addSourceMessage(Error.EMPTY_ARRAY, {}, inInfo);
2809 ✗ fail();
2810 end if;
2811
2812 ✗ for e in inExpl loop
2813 ✗ (outCache, exp, DAE.PROP(ty, c2)) :=
2814 elabGraphicsExp(outCache, inEnv, e, inImplicit, inPrefix, inInfo);
2815 outExpl := exp :: outExpl;
2816 ✗ c := Types.constAnd(c, c2);
2817 end for;
2818
2819 ✗ outExpl := listReverse(outExpl);
2820 ✗ outProperties := DAE.PROP(ty, c);
2821 end elabGraphicsArray;
2822
2823 protected function elabMatrixComma "This function is a helper function for elabMatrixSemi.
2824 It elaborates one matrix row of a matrix."
2825 input list<DAE.Exp> inExpl;
2826 input list<DAE.Properties> inProps;
2827 input Boolean inHaveReal;
2828 input Integer inDims;
2829 input SourceInfo inInfo;
2830 output DAE.Exp outExp;
2831 output DAE.Properties outProperties;
2832 output DAE.Dimension outDim1;
2833 output DAE.Dimension outDim2;
2834 protected
2835 DAE.Exp exp;
2836 list<DAE.Exp> rest_expl, accum_expl = {};
2837 DAE.Properties prop;
2838 list<DAE.Properties> rest_props;
2839 DAE.Type ty, sty;
2840 DAE.Dimension dim1, dim2;
2841 algorithm
2842 try
2843
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
1719 exp :: rest_expl := inExpl;
2844
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
1719 prop :: rest_props := inProps;
2845
2846
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1719 times.
1719 (exp, outProperties as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims);
2847 1719 accum_expl := exp :: accum_expl;
2848
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1719 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1719 times.
1719 outDim1 :: outDim2 :: _ := TypesDump.getDimensions(ty);
2849
2850
2/2
✓ Branch 0 taken 3724 times.
✓ Branch 1 taken 1719 times.
5443 while not listEmpty(rest_expl) loop
2851 3724 exp :: rest_expl := rest_expl;
2852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3724 times.
3724 prop :: rest_props := rest_props;
2853
2854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
3724 (exp, prop as DAE.PROP(type_ = ty)) := promoteExp(exp, prop, inDims);
2855 3724 accum_expl := exp :: accum_expl;
2856
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3724 times.
3724 dim1 :: dim2 :: _ := TypesDump.getDimensions(ty);
2857
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3724 times.
3724 if not Expression.dimensionsEqual(dim1, outDim1) then
2858 ✗ Error.addSourceMessageAndFail(Error.COMMA_OPERATOR_DIFFERENT_SIZES, {ExpressionBasics.printExpStr(listHead(inExpl)), ExpressionBasics.dimensionString(outDim1), ExpressionBasics.printExpStr(exp), ExpressionBasics.dimensionString(dim1)}, inInfo);
2859 end if;
2860 // Comma between matrices => concatenation along second dimension.
2861 3724 outDim2 := Expression.dimensionsAdd(dim2, outDim2);
2862 3724 outProperties := Types.matchWithPromote(prop, outProperties, inHaveReal);
2863 end while;
2864
2865 1719 sty := Expression.liftArrayLeftList(Expression.unliftArrayX(ty, 2), {outDim1, outDim2});
2866 1719 outExp := DAE.ARRAY(sty, false, listReverse(accum_expl));
2867 else
2868 ✗ true := Flags.isSet(Flags.FAILTRACE);
2869 ✗ Debug.traceln("- Static.elabMatrixComma failed");
2870 ✗ fail();
2871 end try;
2872 end elabMatrixComma;
2873
2874 protected function elabMatrixCatTwoExp "author: PA
2875 This function takes an array expression of dimension >=3 and
2876 concatenates each array element along the second dimension.
2877 For instance
2878 elab_matrix_cat_two( {{1,2;5,6}, {3,4;7,8}}) => {1,2,3,4;5,6,7,8}"
2879 input DAE.Exp inExp;
2880 output DAE.Exp outExp;
2881 protected
2882 list<DAE.Exp> expl;
2883 algorithm
2884 try
2885
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1719 times.
1719 DAE.ARRAY(array = expl) := inExp;
2886 1719 expl := ExpressionSimplify.simplifyList(expl);
2887
4/4
✓ Branch 0 taken 5443 times.
✓ Branch 1 taken 1719 times.
✓ Branch 2 taken 5443 times.
✓ Branch 3 taken 1719 times.
7162 expl := list(Expression.matrixToArray(e) for e in expl);
2888 1719 outExp := elabMatrixCatTwo(expl);
2889 else
2890 ✗ true := Flags.isSet(Flags.FAILTRACE);
2891 ✗ Debug.traceln("- Static.elabMatrixCatTwoExp failed");
2892 ✗ fail();
2893 end try;
2894 end elabMatrixCatTwoExp;
2895
2896 protected function elabMatrixCatTwo "author: PA
2897 Concatenates a list of matrix(or higher dim) expressions along
2898 the second dimension."
2899 input list<DAE.Exp> inExpl;
2900 output DAE.Exp outExp;
2901 protected
2902 DAE.Type ty;
2903 algorithm
2904 try
2905
7/8
✓ Branch 1 taken 5443 times.
✓ Branch 2 taken 1716 times.
✓ Branch 3 taken 5443 times.
✓ Branch 4 taken 1716 times.
✓ Branch 5 taken 1719 times.
✓ Branch 6 taken 3724 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 1716 times.
8878 outExp := elabMatrixCatTwo2(e for e in listReverse(inExpl));
2906 else
2907 3 ty := Expression.typeof(listHead(inExpl));
2908 3 outExp := Expression.makePureBuiltinCall("cat", DAE.ICONST(2) :: inExpl, ty);
2909 end try;
2910 end elabMatrixCatTwo;
2911
2912 protected function elabMatrixCatTwo2 "Helper function to elabMatrixCatTwo
2913 Concatenates two array expressions that are matrices (or higher dimension)
2914 along the first dimension (row)."
2915 input DAE.Exp inExp1;
2916 input DAE.Exp inExp2;
2917 output DAE.Exp outExp;
2918 protected
2919 list<DAE.Exp> expl1, expl2;
2920 Boolean sc;
2921 DAE.Type ty;
2922 algorithm
2923
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3721 times.
3724 DAE.ARRAY(scalar = sc, array = expl1) := inExp1;
2924
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3721 times.
3721 DAE.ARRAY(array = expl2) := inExp2;
2925
7/8
✓ Branch 0 taken 3783 times.
✓ Branch 1 taken 3721 times.
✓ Branch 2 taken 3783 times.
✓ Branch 3 taken 3721 times.
✓ Branch 4 taken 3783 times.
✓ Branch 5 taken 3721 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3721 times.
7504 expl1 := list(elabMatrixCatTwo3(e1, e2) threaded for e1 in expl1, e2 in expl2);
2926 3721 ty := Expression.typeof(listHead(expl1));
2927 3721 ty := Expression.liftArrayLeft(ty, DAE.DIM_INTEGER(listLength(expl1)));
2928
1/2
✓ Branch 0 taken 3721 times.
✗ Branch 1 not taken.
7442 outExp := DAE.ARRAY(ty, sc, expl1);
2929 end elabMatrixCatTwo2;
2930
2931 protected function elabMatrixCatTwo3
2932 input DAE.Exp inExp1;
2933 input DAE.Exp inExp2;
2934 output DAE.Exp outExp;
2935 protected
2936 DAE.Type ty1, ty2;
2937 Boolean sc;
2938 list<DAE.Exp> expl1, expl2;
2939 algorithm
2940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
3783 DAE.ARRAY(ty = ty1, scalar = sc, array = expl1) := inExp1;
2941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
3783 DAE.ARRAY(ty = ty2, array = expl2) := inExp2;
2942 3783 expl2 := listAppend(expl1, expl2);
2943 3783 ty1 := Expression.concatArrayType(ty1, ty2);
2944
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3783 times.
3783 outExp := DAE.ARRAY(ty1, sc, expl2);
2945 end elabMatrixCatTwo3;
2946
2947 protected function elabMatrixCatOne "author: PA
2948 Concatenates a list of matrix(or higher dim) expressions along
2949 the first dimension.
2950 i.e. elabMatrixCatOne( { {1,2;3,4}, {5,6;7,8} }) => {1,2;3,4;5,6;7,8}"
2951 input list<DAE.Exp> inExpl;
2952 output DAE.Exp outExp;
2953 protected
2954 DAE.Type ty;
2955 algorithm
2956 try
2957 1074 outExp := List.reduce(inExpl, elabMatrixCatOne2);
2958 else
2959 4 ty := Expression.typeof(listHead(inExpl));
2960 4 outExp := Expression.makePureBuiltinCall("cat", DAE.ICONST(1) :: inExpl, ty);
2961 end try;
2962 end elabMatrixCatOne;
2963
2964 protected function elabMatrixCatOne2
2965 "Helper function to elabMatrixCatOne. Concatenates two arrays along the
2966 first dimension."
2967 input DAE.Exp inArray1;
2968 input DAE.Exp inArray2;
2969 output DAE.Exp outExp;
2970 protected
2971 DAE.Type ety;
2972 Boolean at;
2973 DAE.Dimension dim, dim1, dim2;
2974 DAE.Dimensions dim_rest;
2975 list<DAE.Exp> expl, expl1, expl2;
2976 algorithm
2977
4/6
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 1070 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1070 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1070 times.
1074 DAE.ARRAY(DAE.T_ARRAY(ety, dim1 :: dim_rest), at, expl1) := inArray1;
2978
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1070 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 1070 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 1070 times.
1070 DAE.ARRAY(ty = DAE.T_ARRAY(dims = dim2 :: _), array = expl2) := inArray2;
2979 1070 expl := listAppend(expl1, expl2);
2980 1070 dim := Expression.dimensionsAdd(dim1, dim2);
2981
1/2
✓ Branch 1 taken 1070 times.
✗ Branch 2 not taken.
2140 outExp := DAE.ARRAY(DAE.T_ARRAY(ety, dim :: dim_rest), at, expl);
2982 end elabMatrixCatOne2;
2983
2984 protected function promoteExp
2985 "Wrapper function for Expression.promoteExp which also handles Properties."
2986 input DAE.Exp inExp;
2987 input DAE.Properties inProperties;
2988 input Integer inDims;
2989 output DAE.Exp outExp;
2990 output DAE.Properties outProperties;
2991 protected
2992 DAE.Type ty;
2993 DAE.Const c;
2994 algorithm
2995 try
2996
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5482 times.
5482 DAE.PROP(ty, c) := inProperties;
2997 5482 (outExp, ty) := Expression.promoteExp(inExp, ty, inDims);
2998 5482 outProperties := DAE.PROP(ty, c);
2999 else
3000 ✗ true := Flags.isSet(Flags.FAILTRACE);
3001 ✗ Debug.traceln("- Static.promoteExp failed");
3002 ✗ fail();
3003 end try;
3004 end promoteExp;
3005
3006 protected function elabMatrixSemi
3007 "This function elaborates Matrix expressions, e.g. {1,0;2,1}
3008 A row is elaborated with elabMatrixComma."
3009 input FCore.Cache inCache;
3010 input FCore.Graph inEnv;
3011 input list<list<DAE.Exp>> inMatrix;
3012 input list<list<DAE.Properties>> inProperties;
3013 input Boolean inImpl;
3014 input Boolean inHaveReal;
3015 input Integer inDims;
3016 input Boolean inDoVectorization;
3017 input DAE.Prefix inPrefix;
3018 input SourceInfo inInfo;
3019 output FCore.Cache outCache = inCache;
3020 output DAE.Exp outExp;
3021 output DAE.Properties outProperties;
3022 output DAE.Dimension outDim1;
3023 output DAE.Dimension outDim2;
3024 protected
3025 list<DAE.Exp> expl;
3026 list<list<DAE.Exp>> rest_expl;
3027 list<DAE.Properties> props;
3028 list<list<DAE.Properties>> rest_props;
3029 DAE.Exp exp;
3030 DAE.Properties prop;
3031 DAE.Dimension dim1, dim2;
3032 String dim1_str, dim2_str, pre_str, el_str, ty1_str, ty2_str;
3033 algorithm
3034 // Elaborate the first row so we have something to compare against.
3035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 expl :: rest_expl := inMatrix;
3036
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 645 times.
645 props :: rest_props := inProperties;
3037
3038 645 (outExp, outProperties, outDim1, outDim2) :=
3039 elabMatrixComma(expl, props, inHaveReal, inDims, inInfo);
3040 645 outExp := elabMatrixCatTwoExp(outExp);
3041
3042 // Elaborate the rest of the rows (if any).
3043
2/2
✓ Branch 0 taken 1074 times.
✓ Branch 1 taken 645 times.
1719 while not listEmpty(rest_expl) loop
3044
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1074 times.
1074 expl :: rest_expl := rest_expl;
3045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1074 times.
1074 props :: rest_props := rest_props;
3046
3047 1074 (exp, prop, dim1, dim2) := elabMatrixComma(expl, props, inHaveReal, inDims, inInfo);
3048
3049 // Check that all rows have the same size, otherwise print an error and fail.
3050
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1074 times.
1074 if not Expression.dimensionsEqual(dim2, outDim2) then
3051 ✗ dim1_str := ExpressionBasics.dimensionString(dim1);
3052 ✗ dim2_str := ExpressionBasics.dimensionString(dim2);
3053 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
3054 ✗ el_str := List.toStringCustom(expl, ExpressionBasics.printExpStr, "", "{", ", ", "}", true);
3055 ✗ Error.addSourceMessageAndFail(Error.MATRIX_EXP_ROW_SIZE,
3056 {pre_str, el_str, dim1_str, dim2_str}, inInfo);
3057 end if;
3058
3059 // Check that all rows are of the same type, otherwise print an error and fail.
3060 try
3061 1074 outProperties := Types.matchWithPromote(outProperties, prop, inHaveReal);
3062 else
3063 ✗ ty1_str := TypesDump.unparsePropTypeNoAttr(outProperties);
3064 ✗ ty2_str := TypesDump.unparsePropTypeNoAttr(prop);
3065 ✗ Types.typeErrorSanityCheck(ty1_str, ty2_str, inInfo);
3066 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
3067 ✗ el_str := List.toStringCustom(expl, ExpressionBasics.printExpStr, "", "{", ", ", "}", true);
3068 ✗ Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_MATRIX_EXP,
3069 {pre_str, el_str, ty1_str, ty2_str}, inInfo);
3070 end try;
3071
3072 // Add the row to the matrix.
3073 1074 exp := elabMatrixCatTwoExp(exp);
3074 1074 outExp := elabMatrixCatOne({outExp, exp});
3075 1074 outDim1 := Expression.dimensionsAdd(dim1, outDim1);
3076 end while;
3077 end elabMatrixSemi;
3078
3079 protected function verifyBuiltInHandlerType "
3080 Author BZ, 2009-02
3081 This function validates that arguments to function are of a correct type.
3082 Then call elabCallArgs to vectorize/type-match."
3083 input FCore.Cache inCache;
3084 input FCore.Graph inEnv;
3085 input list<Absyn.Exp> inExpl;
3086 input Boolean inImplicit;
3087 input extraFunc inTypeChecker;
3088 input String inFnName;
3089 input DAE.Prefix inPrefix;
3090 input SourceInfo inInfo;
3091 output FCore.Cache outCache;
3092 output DAE.Exp outExp;
3093 output DAE.Properties outProperties;
3094
3095 partial function extraFunc
3096 input DAE.Type inp1;
3097 output Boolean outp1;
3098 end extraFunc;
3099 protected
3100 Absyn.Exp e;
3101 DAE.Type ty;
3102 algorithm
3103
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 {e} := inExpl;
3104 2 (outCache, _, outProperties) := elabExpInExpression(inCache, inEnv, e,
3105 inImplicit, true, inPrefix, inInfo);
3106 2 ty := Types.getPropType(outProperties);
3107 2 ty := Types.arrayElementType(ty);
3108
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
2 true := inTypeChecker(ty);
3109
2/4
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
4 (outCache, outExp, outProperties as DAE.PROP()) := elabCallArgs(outCache,
3110 inEnv, Absyn.FULLYQUALIFIED(Absyn.IDENT(inFnName)), {e}, {}, {}, inImplicit,
3111 inPrefix, inInfo);
3112 end verifyBuiltInHandlerType;
3113
3114 protected function elabBuiltinCardinality
3115 "author: PA
3116 This function elaborates the cardinality operator."
3117 input FCore.Cache inCache;
3118 input FCore.Graph inEnv;
3119 input list<Absyn.Exp> inPosArgs;
3120 input list<Absyn.NamedArg> inNamedArgs;
3121 input Boolean inImplicit;
3122 input DAE.Prefix inPrefix;
3123 input SourceInfo inInfo;
3124 output FCore.Cache outCache;
3125 output DAE.Exp outExp;
3126 output DAE.Properties outProperties;
3127 protected
3128 DAE.Type ty;
3129 Absyn.Exp e;
3130 algorithm
3131 762 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "cardinality", inInfo);
3132
3133
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 762 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 762 times.
762 {e} := inPosArgs;
3134 762 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e,
3135 inImplicit, true, inPrefix, inInfo);
3136
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 762 times.
762 DAE.PROP(type_ = ty) := outProperties;
3137 762 ty := Types.liftArrayListDims(DAE.T_INTEGER_DEFAULT, TypesDump.getDimensions(ty));
3138 762 outExp := Expression.makePureBuiltinCall("cardinality", {outExp}, ty);
3139 762 outProperties := DAE.PROP(ty, DAE.C_CONST());
3140 end elabBuiltinCardinality;
3141
3142 protected function elabBuiltinSmooth
3143 "This function elaborates the smooth operator.
3144 smooth(p,expr) - If p>=0 smooth(p, expr) returns expr and states that expr is p times
3145 continuously differentiable, i.e.: expr is continuous in all real variables appearing in
3146 the expression and all partial derivatives with respect to all appearing real variables
3147 exist and are continuous up to order p.
3148 The only allowed types for expr in smooth are: real expressions, arrays of
3149 allowed expressions, and records containing only components of allowed
3150 expressions."
3151 input FCore.Cache inCache;
3152 input FCore.Graph inEnv;
3153 input list<Absyn.Exp> inPosArgs;
3154 input list<Absyn.NamedArg> inNamedArgs;
3155 input Boolean inImplicit;
3156 input DAE.Prefix inPrefix;
3157 input SourceInfo inInfo;
3158 output FCore.Cache outCache;
3159 output DAE.Exp outExp;
3160 output DAE.Properties outProperties;
3161 protected
3162 String msg_str;
3163 Absyn.Exp p, expr;
3164 DAE.Exp dp, dexpr;
3165 DAE.Type ty;
3166 DAE.Const c;
3167 algorithm
3168
2/4
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
50 if listLength(inPosArgs) <> 2 or not listEmpty(inNamedArgs) then
3169 msg_str := ", expected smooth(p, expr)";
3170 ✗ printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo);
3171 end if;
3172
3173
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 50 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 50 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 50 times.
50 {p, expr} := inPosArgs;
3174
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 (outCache, dp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv, p,
3175 inImplicit, true, inPrefix, inInfo);
3176
3177
2/4
✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 50 times.
50 if not Types.isParameterOrConstant(c) or not Types.isInteger(ty) then
3178 msg_str := ", first argument must be a constant or parameter expression of type Integer";
3179 ✗ printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo);
3180 end if;
3181
3182
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
50 (outCache, dexpr, outProperties as DAE.PROP(ty, c)) :=
3183 elabExpInExpression(outCache, inEnv, expr, inImplicit, true, inPrefix, inInfo);
3184
3185
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 50 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
50 if not (Types.isReal(ty) or Types.isRecordWithOnlyReals(ty)) then
3186 msg_str := ", second argument must be a Real, array of Reals or record only containing Reals";
3187 ✗ printBuiltinFnArgError("smooth", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo);
3188 end if;
3189
3190 50 ty := Types.simplifyType(ty);
3191 50 outExp := Expression.makePureBuiltinCall("smooth", {dp, dexpr}, ty);
3192 end elabBuiltinSmooth;
3193
3194 protected function printBuiltinFnArgError
3195 input String inFnName;
3196 input String inMsg;
3197 input list<Absyn.Exp> inPosArgs;
3198 input list<Absyn.NamedArg> inNamedArgs;
3199 input DAE.Prefix inPrefix;
3200 input SourceInfo inInfo;
3201 protected
3202 String args_str, pre_str, msg_str;
3203 list<String> pos_args, named_args;
3204 algorithm
3205 ✗ pos_args := list(Dump.printExpStr(arg) for arg in inPosArgs);
3206 ✗ named_args := list(Dump.printNamedArgStr(arg) for arg in inNamedArgs);
3207 ✗ args_str := stringDelimitList(listAppend(pos_args, named_args), ", ");
3208 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
3209 ✗ msg_str := inFnName + "(" + args_str + ")" + inMsg;
3210 ✗ Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS, {msg_str, pre_str}, inInfo);
3211 end printBuiltinFnArgError;
3212
3213 protected function elabBuiltinSize
3214 "This function elaborates the size operator.
3215 Input is the list of arguments to size as Absyn.Exp
3216 expressions and the environment, FCore.Graph."
3217 input FCore.Cache inCache;
3218 input FCore.Graph inEnv;
3219 input list<Absyn.Exp> inAbsynExpLst;
3220 input list<Absyn.NamedArg> inNamedArg;
3221 input Boolean inBoolean;
3222 input DAE.Prefix inPrefix;
3223 input SourceInfo info;
3224 output FCore.Cache outCache;
3225 output DAE.Exp outExp;
3226 output DAE.Properties outProperties;
3227 algorithm
3228 (outCache,outExp,outProperties) := match (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix)
3229 local
3230 DAE.Exp dimp,arraycrefe,exp;
3231 DAE.Type arrtp;
3232 DAE.Properties prop;
3233 Boolean impl;
3234 FCore.Graph env;
3235 Absyn.Exp arraycr,dim;
3236 FCore.Cache cache;
3237 DAE.Prefix pre;
3238 DAE.Type ety;
3239 DAE.Dimensions dims, dims1, dims2;
3240
3241 case (cache, env, {arraycr, dim}, impl, pre)
3242 algorithm
3243 2665 (cache, dimp, _) :=
3244 elabExpInExpression(cache, env, dim, impl, true, pre, info);
3245 2665 (cache, arraycrefe, prop) :=
3246 elabExpInExpression(cache, env, arraycr, impl, false, pre, info);
3247 2573 ety := Expression.typeof(arraycrefe);
3248 2573 dims1 := Expression.arrayDimension(ety);
3249 2573 (,dims2) := TypesDump.flattenArrayType(Types.getPropType(prop));
3250
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 2573 times.
2573 dims := if listLength(dims1) >= listLength(dims2) then dims1 else dims2 "In case there is a zero-size array somewhere...";
3251 // sent in the props of the arraycrefe as if the array is constant then the size(x, 1) is constant!
3252 // see Modelica.Media.Incompressible.Examples.Glycol47 and Modelica.Media.Incompressible.TableBased (hasDensity)
3253
5/8
✗ Branch 1 not taken.
✓ Branch 2 taken 2573 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 2572 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2572 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2572 times.
2573 (SOME(exp), SOME(prop)) := elabBuiltinSizeIndex(arraycrefe, prop, ety, dimp, dims, env, info);
3254 then
3255 (cache, exp, prop);
3256
3257 case (cache, env, {arraycr}, impl, pre)
3258 algorithm
3259
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 (cache, arraycrefe, DAE.PROP(arrtp, _)) :=
3260 elabExpInExpression(cache, env, arraycr, impl, false, pre, info);
3261 3 ety := Expression.typeof(arraycrefe);
3262 3 dims := Expression.arrayDimension(ety);
3263 3 (exp, prop) := elabBuiltinSizeNoIndex(arraycrefe, ety, dims, arrtp, info);
3264 3 then
3265 (cache, exp, prop);
3266
3267 end match;
3268 end elabBuiltinSize;
3269
3270 protected function elabBuiltinSizeNoIndex
3271 "Helper function to elabBuiltinSize. Elaborates the size(A) operator."
3272 input DAE.Exp inArrayExp;
3273 input DAE.Type inArrayExpType;
3274 input DAE.Dimensions inDimensions;
3275 input DAE.Type inArrayType;
3276 input SourceInfo inInfo;
3277 output DAE.Exp outSizeExp;
3278 output DAE.Properties outProperties;
3279 algorithm
3280 (outSizeExp, outProperties) := matchcontinue inDimensions
3281 local
3282 list<DAE.Exp> dim_expl;
3283 Integer dim_int;
3284 DAE.Exp exp;
3285 DAE.Properties prop;
3286 Boolean b;
3287 DAE.Const cnst;
3288 DAE.Type ty;
3289 String exp_str, size_str;
3290
3291 // size of a scalar is not allowed.
3292 case {}
3293 algorithm
3294 // Make sure that we have a proper type here. We might get DAE.T_UNKNOWN if
3295 // the size expression is part of a modifier, in which case we can't
3296 // determine if it's a scalar or array.
3297 ✗ false := Types.isUnknownType(inArrayExpType);
3298 ✗ exp_str := ExpressionBasics.printExpStr(inArrayExp);
3299 ✗ size_str := "size(" + exp_str + ")";
3300 ✗ Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {size_str}, inInfo);
3301 ✗ then
3302 fail();
3303
3304 // size(A) for an array A with known dimensions.
3305 // Returns an array of all dimensions of A.
3306 case _ :: _
3307 algorithm
3308 3 dim_expl := List.map(inDimensions, Expression.dimensionSizeExp);
3309 2 dim_int := listLength(dim_expl);
3310 4 ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim_int)});
3311 2 exp := DAE.ARRAY(ty, true, dim_expl);
3312 2 prop := DAE.PROP(ty, DAE.C_CONST());
3313 then
3314 (exp, prop);
3315
3316 // If we couldn't evaluate the size expression or find any problems with it,
3317 // just generate a call to size and let the runtime sort it out.
3318 case _ :: _
3319 algorithm
3320 1 b := Types.dimensionsKnown(inArrayType);
3321 1 cnst := Types.boolConstSize(b);
3322 1 exp := DAE.SIZE(inArrayExp,NONE());
3323 ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_UNKNOWN()});
3324 1 prop := DAE.PROP(ty, cnst);
3325 then
3326 (exp, prop);
3327
3328 end matchcontinue;
3329 end elabBuiltinSizeNoIndex;
3330
3331 protected function elabBuiltinSizeIndex
3332 "Helper function to elabBuiltinSize. Elaborates the size(A, x) operator."
3333 input DAE.Exp inArrayExp;
3334 input DAE.Properties inArrayProp;
3335 input DAE.Type inArrayType;
3336 input DAE.Exp inIndexExp;
3337 input DAE.Dimensions inDimensions;
3338 input FCore.Graph inEnv;
3339 input SourceInfo inInfo;
3340 output Option<DAE.Exp> outSizeExp;
3341 output Option<DAE.Properties> outProperties;
3342 algorithm
3343 (outSizeExp, outProperties) := matchcontinue inDimensions
3344 local
3345 Integer dim_int, dim_count;
3346 DAE.Exp exp;
3347 DAE.Dimension dim;
3348 DAE.Properties prop;
3349 DAE.Const cnst;
3350 String exp_str, index_str, size_str, dim_str;
3351
3352 // size of a scalar is not allowed.
3353 case {}
3354 algorithm
3355 // Make sure that we have a proper type here. We might get T_UNKNOWN if
3356 // the size expression is part of a modifier, in which case we can't
3357 // determine if it's a scalar or array.
3358
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 false := Types.isUnknownType(inArrayType);
3359 ✗ exp_str := ExpressionBasics.printExpStr(inArrayExp);
3360 ✗ index_str := ExpressionBasics.printExpStr(inIndexExp);
3361 ✗ size_str := "size(" + exp_str + ", " + index_str + ")";
3362 ✗ Error.addSourceMessage(Error.INVALID_ARGUMENT_TYPE_FIRST_ARRAY, {size_str}, inInfo);
3363 then
3364 (NONE(), NONE());
3365
3366 // size(A, x) for an array A with known dimensions and constant x.
3367 // Returns the size of the x:th dimension.
3368 case _
3369 algorithm
3370 2573 dim_int := Expression.expInt(inIndexExp);
3371 2573 dim_count := listLength(inDimensions);
3372
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 2570 times.
2573 true := (dim_int > 0 and dim_int <= dim_count);
3373 2570 dim := listGet(inDimensions, dim_int);
3374 2570 exp := Expression.dimensionSizeConstantExp(dim);
3375 prop := DAE.PROP(DAE.T_INTEGER_DEFAULT, DAE.C_CONST());
3376 then
3377 (SOME(exp), SOME(prop));
3378
3379 // The index is out of bounds.
3380 case _
3381 algorithm
3382
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 1001 times.
1003 false := Types.isUnknownType(inArrayType);
3383 1001 dim_int := Expression.expInt(inIndexExp);
3384 1001 dim_count := listLength(inDimensions);
3385
2/2
✓ Branch 0 taken 1000 times.
✓ Branch 1 taken 1 time.
1001 true := (dim_int <= 0 or dim_int > dim_count);
3386 1 index_str := intString(dim_int);
3387 1 exp_str := ExpressionBasics.printExpStr(inArrayExp);
3388 1 dim_str := intString(dim_count);
3389 1 Error.addSourceMessage(Error.INVALID_SIZE_INDEX,
3390 {index_str, exp_str, dim_str}, inInfo);
3391 then
3392 (NONE(), NONE());
3393
3394 // If we couldn't evaluate the size expression or find any problems with it,
3395 // just generate a call to size and let the runtime sort it out.
3396 else
3397 algorithm
3398 1002 exp := DAE.SIZE(inArrayExp, SOME(inIndexExp));
3399 cnst := DAE.C_PARAM(); // Types.getPropConst(inArrayProp);
3400
2/2
✓ Branch 1 taken 960 times.
✓ Branch 2 taken 42 times.
1002 cnst := if FGraph.inFunctionScope(inEnv) then DAE.C_VAR() else cnst;
3401 1002 prop := DAE.PROP(DAE.T_INTEGER_DEFAULT, cnst);
3402 then
3403 (SOME(exp), SOME(prop));
3404
3405 end matchcontinue;
3406 end elabBuiltinSizeIndex;
3407
3408 protected function elabBuiltinNDims
3409 "@author Stefan Vorkoetter <svorkoetter@maplesoft.com>
3410 ndims(A) : Returns the number of dimensions k of array expression A, with k >= 0.
3411 "
3412 input FCore.Cache inCache;
3413 input FCore.Graph inEnv;
3414 input list<Absyn.Exp> inAbsynExpLst;
3415 input list<Absyn.NamedArg> inNamedArg;
3416 input Boolean inBoolean;
3417 input DAE.Prefix inPrefix;
3418 input SourceInfo info;
3419 output FCore.Cache outCache;
3420 output DAE.Exp outExp;
3421 output DAE.Properties outProperties;
3422 algorithm
3423 (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix)
3424 local
3425 DAE.Exp exp;
3426 DAE.Type arrtp;
3427 Boolean impl;
3428 FCore.Graph env;
3429 Absyn.Exp arraycr;
3430 FCore.Cache cache;
3431 list<Absyn.Exp> expl;
3432 Integer nd;
3433 DAE.Prefix pre;
3434 String sp;
3435
3436 case (cache, env, {arraycr}, impl, pre)
3437 algorithm
3438 ✗ (cache,_,DAE.PROP(arrtp,_)) := elabExpInExpression(cache,env, arraycr, impl,true,pre,info);
3439 ✗ nd := Types.numberOfDimensions(arrtp);
3440 ✗ exp := DAE.ICONST(nd);
3441 then
3442 (cache,exp,DAE.PROP(DAE.T_INTEGER_DEFAULT,DAE.C_CONST()));
3443
3444 case (_, _, expl, _, pre)
3445 algorithm
3446 ✗ true := Flags.isSet(Flags.FAILTRACE);
3447 ✗ sp := PrefixUtil.printPrefixStr3(pre);
3448 ✗ Debug.traceln("- Static.elabBuiltinNdims failed for: ndims(" + Dump.printExpLstStr(expl) + " in component: " + sp);
3449 ✗ then
3450 fail();
3451 end matchcontinue;
3452 end elabBuiltinNDims;
3453
3454 protected function elabBuiltinFill "This function elaborates the builtin operator fill.
3455 The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph"
3456 input FCore.Cache inCache;
3457 input FCore.Graph inEnv;
3458 input list<Absyn.Exp> inAbsynExpLst;
3459 input list<Absyn.NamedArg> inNamedArg;
3460 input Boolean inBoolean;
3461 input DAE.Prefix inPrefix;
3462 input SourceInfo info;
3463 output FCore.Cache outCache;
3464 output DAE.Exp outExp;
3465 output DAE.Properties outProperties;
3466 algorithm
3467 (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix)
3468 local
3469 DAE.Exp s_1,exp;
3470 DAE.Properties prop;
3471 list<DAE.Exp> dims_1;
3472 list<DAE.Properties> dimprops;
3473 DAE.Type sty;
3474 list<Values.Value> dimvals;
3475 FCore.Graph env;
3476 Absyn.Exp s;
3477 list<Absyn.Exp> dims;
3478 Boolean impl;
3479 String implstr,expstr,str,sp;
3480 list<String> expstrs;
3481 FCore.Cache cache;
3482 DAE.Const c1;
3483 DAE.Prefix pre;
3484 DAE.Type exp_type;
3485
3486 // try to constant evaluate dimensions
3487 case (cache, env, (s :: dims), impl, pre)
3488 algorithm
3489 4568 (cache,s_1,prop) := elabExpInExpression(cache, env, s, impl,true, pre, info);
3490 4568 (cache,dims_1,dimprops) := elabExpList(cache, env, dims, impl, true, pre, info);
3491 4568 (dims_1,_) := Types.matchTypes(dims_1, List.map(dimprops,Types.getPropType), DAE.T_INTEGER_DEFAULT, false);
3492 4568 c1 := Types.propertiesListToConst(dimprops);
3493
3/4
✓ Branch 0 taken 4568 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4550 times.
✓ Branch 3 taken 18 times.
4568 failure(DAE.C_VAR() := c1);
3494 4550 c1 := Types.constAnd(c1,Types.propAllConst(prop));
3495 4550 sty := Types.getPropType(prop);
3496 4550 (cache,dimvals) := Ceval.cevalList(cache, env, dims_1, impl, Absyn.NO_MSG(),0);
3497 4550 (cache,exp,prop) := ExpressionSimplify.elabBuiltinFill2(cache, s_1, sty, dimvals, c1, dims, info);
3498 then
3499 (cache, exp, prop);
3500
3501 // If the previous case failed we probably couldn't constant evaluate the
3502 // dimensions. Create a function call to fill instead, and let the compiler sort it out later.
3503 case (cache, env, (s :: dims), impl, pre)
3504 algorithm
3505 18 c1 := unevaluatedFunctionVariability(env);
3506 18 (cache, s_1, prop) := elabExpInExpression(cache, env, s, impl,true, pre, info);
3507 18 (cache, dims_1, dimprops) := elabExpList(cache, env, dims, impl,true, pre, info);
3508 18 (dims_1,_) := Types.matchTypes(dims_1, List.map(dimprops,Types.getPropType), DAE.T_INTEGER_DEFAULT, false);
3509 18 sty := Types.getPropType(prop);
3510 18 sty := Types.liftTypeWithDimExps(sty, dims_1);
3511 18 exp_type := Types.simplifyType(sty);
3512 18 prop := DAE.PROP(sty, c1);
3513 18 exp := Expression.makePureBuiltinCall("fill", s_1 :: dims_1, exp_type);
3514 18 then
3515 (cache, exp, prop);
3516
3517 // Non-constant dimensons are also allowed in the case of non-expanded arrays
3518 // TODO: check that the diemnsions are parametric?
3519 case (cache, env, (s :: dims), impl, pre)
3520 algorithm
3521 ✗ false := Config.splitArrays();
3522 ✗ (cache, s_1, DAE.PROP(sty, c1)) := elabExpInExpression(cache, env, s, impl, true, pre, info);
3523 ✗ (cache, dims_1,_) := elabExpList(cache, env, dims, impl, true, pre, info);
3524 ✗ sty := Types.liftTypeWithDimExps(sty, dims_1);
3525 ✗ exp_type := Types.simplifyType(sty);
3526 ✗ c1 := Types.constAnd(c1, DAE.C_PARAM());
3527 ✗ prop := DAE.PROP(sty, c1);
3528 ✗ exp := Expression.makePureBuiltinCall("fill", s_1 :: dims_1, exp_type);
3529 ✗ then
3530 (cache, exp, prop);
3531
3532 case (_, env, dims, _, _)
3533 algorithm
3534 ✗ str := "Static.elabBuiltinFill failed in component" + PrefixUtil.printPrefixStr3(inPrefix) +
3535 " and scope: " + FGraph.printGraphPathStr(env) +
3536 " for expression: fill(" + Dump.printExpLstStr(dims) + ")";
3537 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR, {str}, info);
3538 ✗ then
3539 fail();
3540
3541 case (_, _, dims, impl, pre)
3542 algorithm
3543 ✗ true := Flags.isSet(Flags.FAILTRACE);
3544 ✗ Debug.trace("- Static.elabBuiltinFill: Couldn't elaborate fill(): ");
3545 ✗ implstr := boolString(impl);
3546 ✗ expstrs := List.map(dims, Dump.printExpStr);
3547 ✗ expstr := stringDelimitList(expstrs, ", ");
3548 ✗ sp := PrefixUtil.printPrefixStr3(pre);
3549 ✗ str := stringAppendList({expstr," impl=",implstr,", in component: ",sp});
3550 ✗ Debug.traceln(str);
3551 ✗ then
3552 fail();
3553 end matchcontinue;
3554 end elabBuiltinFill;
3555
3556 protected function elabBuiltinSymmetric "This function elaborates the builtin operator symmetric"
3557 input FCore.Cache inCache;
3558 input FCore.Graph inEnv;
3559 input list<Absyn.Exp> inAbsynExpLst;
3560 input list<Absyn.NamedArg> inNamedArg;
3561 input Boolean inBoolean;
3562 input DAE.Prefix inPrefix;
3563 input SourceInfo info;
3564 output FCore.Cache outCache;
3565 output DAE.Exp outExp;
3566 output DAE.Properties outProperties;
3567 algorithm
3568 (outCache,outExp,outProperties) := match (inCache, inEnv, inAbsynExpLst, inBoolean, inPrefix)
3569 local
3570 DAE.Type tp;
3571 Boolean impl;
3572 DAE.Dimension d1,d2;
3573 DAE.Type eltp,newtp;
3574 DAE.Properties prop;
3575 DAE.Const c;
3576 FCore.Graph env;
3577 Absyn.Exp matexp;
3578 DAE.Exp exp_1,exp;
3579 FCore.Cache cache;
3580 DAE.Prefix pre;
3581
3582 case (cache, env, {matexp}, impl, pre)
3583 algorithm
3584
7/14
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
✗ Branch 9 not taken.
✓ Branch 10 taken 1 time.
✗ Branch 11 not taken.
✓ Branch 12 taken 1 time.
✗ Branch 13 not taken.
✓ Branch 14 taken 1 time.
1 (cache,exp_1,DAE.PROP(DAE.T_ARRAY(dims = {d1}, ty = DAE.T_ARRAY(dims = {d2}, ty = eltp)), c))
3585 := elabExpInExpression(cache,env,matexp,impl,true,pre,info);
3586 2 newtp := DAE.T_ARRAY(DAE.T_ARRAY(eltp, {d1}), {d2});
3587 1 tp := Types.simplifyType(newtp);
3588 1 exp := Expression.makePureBuiltinCall("symmetric", {exp_1}, tp);
3589 1 prop := DAE.PROP(newtp,c);
3590 then
3591 (cache,exp,prop);
3592 end match;
3593 end elabBuiltinSymmetric;
3594
3595 protected function elabBuiltinClassDirectory
3596 input FCore.Cache inCache;
3597 input FCore.Graph inEnv;
3598 input list<Absyn.Exp> inAbsynExpLst;
3599 input list<Absyn.NamedArg> inNamedArg;
3600 input Boolean inBoolean;
3601 input DAE.Prefix inPrefix;
3602 input SourceInfo info;
3603 output FCore.Cache outCache;
3604 output DAE.Exp outExp;
3605 output DAE.Properties outProperties;
3606 algorithm
3607 (outCache,outExp,outProperties) := match info
3608 local
3609 String str,fileName;
3610
3611 case SOURCEINFO(fileName=fileName)
3612 algorithm
3613 ✗ str := stringAppend(System.dirname(fileName),"/");
3614 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR_CLASS_DIRECTORY, {}, info);
3615 ✗ then
3616 (inCache,DAE.SCONST(str),DAE.PROP(DAE.T_STRING_DEFAULT,DAE.C_CONST()));
3617 end match;
3618 end elabBuiltinClassDirectory;
3619
3620 protected function elabBuiltinSourceInfo
3621 input FCore.Cache inCache;
3622 input FCore.Graph inEnv;
3623 input list<Absyn.Exp> inAbsynExpLst;
3624 input list<Absyn.NamedArg> inNamedArg;
3625 input Boolean inBoolean;
3626 input DAE.Prefix inPrefix;
3627 input SourceInfo info;
3628 output FCore.Cache outCache;
3629 output DAE.Exp outExp;
3630 output DAE.Properties outProperties;
3631 algorithm
3632
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 {} := inAbsynExpLst;
3633 (outCache,outExp,outProperties) := match info
3634 local
3635 list<DAE.Exp> args;
3636
3637 case SOURCEINFO()
3638 algorithm
3639 19 args := {
3640 DAE.SCONST(info.fileName),
3641 DAE.BCONST(info.isReadOnly),
3642 DAE.ICONST(info.lineNumberStart),
3643 DAE.ICONST(info.columnNumberStart),
3644 DAE.ICONST(info.lineNumberEnd),
3645 DAE.ICONST(info.columnNumberEnd),
3646 // Deliberately not info.lastModification. This record is constant folded
3647 // into the generated C, so the mtime of the source file would be baked in
3648 // as a literal and the output would depend on when the file happened to be
3649 // checked out. Nothing ever reads the field back off a sourceInfo() value
3650 // (the mtime of a *class* is read from its Absyn.CLASS instead, see
3651 // reloadClass and getTimeStamp in CevalScript), so pin it to 0.0.
3652 // See OpenModelica#14399.
3653 DAE.RCONST(0.0)
3654 };
3655 19 outExp := DAE.METARECORDCALL(Absyn.QUALIFIED("SourceInfo",Absyn.IDENT("SOURCEINFO")),args,{"fileName","isReadOnly","lineNumberStart","columnNumberStart","lineNumberEnd","columnNumberEnd","lastEditTime"},0,{});
3656 then (inCache,outExp,DAE.PROP(DAE.T_SOURCEINFO_DEFAULT,DAE.C_CONST()));
3657 end match;
3658 end elabBuiltinSourceInfo;
3659
3660 protected function elabBuiltinSome
3661 input FCore.Cache inCache;
3662 input FCore.Graph inEnv;
3663 input list<Absyn.Exp> inPosArgs;
3664 input list<Absyn.NamedArg> inNamedArgs;
3665 input Boolean inImplicit;
3666 input DAE.Prefix inPrefix;
3667 input SourceInfo inInfo;
3668 output FCore.Cache outCache;
3669 output DAE.Exp outExp;
3670 output DAE.Properties outProperties;
3671 protected
3672 DAE.Exp arg;
3673 DAE.Properties prop;
3674 DAE.Type ty;
3675 DAE.Const c;
3676 algorithm
3677 // SOME should have exactly one positional argument.
3678
2/4
✓ Branch 1 taken 374 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 374 times.
374 if listLength(inPosArgs) <> 1 or not listEmpty(inNamedArgs) then
3679 ✗ Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS,
3680 {"SOME", ""}, inInfo);
3681 else
3682 374 (outCache, arg, prop) := elabExpInExpression(inCache, inEnv,
3683 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
3684 374 ty := Types.getPropType(prop);
3685 374 (arg, ty) := Types.matchType(arg, ty, DAE.T_METABOXED_DEFAULT, true);
3686 374 c := Types.propAllConst(prop);
3687 374 outExp := DAE.META_OPTION(SOME(arg));
3688 374 outProperties := DAE.PROP(DAE.T_METAOPTION(ty), c);
3689 end if;
3690 end elabBuiltinSome;
3691
3692 protected function elabBuiltinNone
3693 input FCore.Cache inCache;
3694 input FCore.Graph inEnv;
3695 input list<Absyn.Exp> inPosArgs;
3696 input list<Absyn.NamedArg> inNamedArgs;
3697 input Boolean inImplicit;
3698 input DAE.Prefix inPrefix;
3699 input SourceInfo inInfo;
3700 output FCore.Cache outCache = inCache;
3701 output DAE.Exp outExp;
3702 output DAE.Properties outProperties;
3703 protected
3704 algorithm
3705 // NONE shouldn't have any arguments.
3706
2/4
✓ Branch 0 taken 3391 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3391 times.
3391 if not listEmpty(inPosArgs) or not listEmpty(inNamedArgs) then
3707 ✗ Error.addSourceMessageAndFail(Error.WRONG_TYPE_OR_NO_OF_ARGS,
3708 {"NONE", ""}, inInfo);
3709 else
3710 outExp := DAE.META_OPTION(NONE());
3711 outProperties := DAE.PROP(DAE.T_METAOPTION(DAE.T_UNKNOWN_DEFAULT), DAE.C_CONST());
3712 end if;
3713 end elabBuiltinNone;
3714
3715 protected function elabBuiltinHomotopy
3716 input FCore.Cache inCache;
3717 input FCore.Graph inEnv;
3718 input list<Absyn.Exp> inPosArgs;
3719 input list<Absyn.NamedArg> inNamedArgs;
3720 input Boolean inImplicit;
3721 input DAE.Prefix inPrefix;
3722 input SourceInfo inInfo;
3723 output FCore.Cache outCache = inCache;
3724 output DAE.Exp outExp;
3725 output DAE.Properties outProperties;
3726 protected
3727 String replaceWith;
3728 Absyn.Exp e, e1, e2;
3729 algorithm
3730 43 replaceWith := Flags.getConfigString(Flags.REPLACE_HOMOTOPY);
3731
3732 // Replace homotopy if Flags.REPLACE_HOMOTOPY is "actual" or "simplified"
3733
2/8
✗ Branch 0 not taken.
✓ Branch 1 taken 43 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 43 times.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
43 if replaceWith == "actual" or replaceWith == "simplified" then
3734 ✗ {e1, e2} := getHomotopyArguments(inPosArgs, inNamedArgs);
3735 ✗ e := if replaceWith == "actual" then e1 else e2;
3736
3737 ✗ (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e,
3738 inImplicit, true, inPrefix, inInfo);
3739 else
3740 // Otherwise, handle it like a normal function.
3741 43 (outCache, outExp, outProperties) := elabCallArgs(inCache, inEnv,
3742 Absyn.IDENT("homotopy"), inPosArgs, inNamedArgs, {}, inImplicit,
3743 inPrefix, inInfo);
3744 end if;
3745 end elabBuiltinHomotopy;
3746
3747 protected function getHomotopyArguments
3748 input list<Absyn.Exp> args;
3749 input list<Absyn.NamedArg> nargs;
3750 output list<Absyn.Exp> outPositionalArgs;
3751 algorithm
3752 outPositionalArgs := match(args, nargs)
3753 local
3754 Absyn.Exp e1, e2;
3755
3756 // only positional
3757 case ({e1, e2}, _) then {e1, e2};
3758 // only named
3759 case ({}, {Absyn.NAMEDARG("actual", e1), Absyn.NAMEDARG("simplified", e2)}) then {e1, e2};
3760 case ({}, {Absyn.NAMEDARG("simplified", e2), Absyn.NAMEDARG("actual", e1)}) then {e1, e2};
3761 // combination
3762 case ({e1}, {Absyn.NAMEDARG("simplified", e2)}) then {e1, e2};
3763 else
3764 algorithm
3765 ✗ Error.addCompilerError("+replaceHomotopy: homotopy called with wrong arguments: " +
3766 Dump.printFunctionArgsStr(Absyn.FUNCTIONARGS(args, nargs)));
3767 ✗ then
3768 fail();
3769 end match;
3770 end getHomotopyArguments;
3771
3772 protected function elabBuiltinDynamicSelect
3773 "Elaborates DynamicSelect statements in annotations for OMEdit."
3774 input FCore.Cache inCache;
3775 input FCore.Graph inEnv;
3776 input list<Absyn.Exp> inPosArgs;
3777 input list<Absyn.NamedArg> inNamedArgs;
3778 input Boolean inImplicit;
3779 input DAE.Prefix inPrefix;
3780 input SourceInfo inInfo;
3781 output FCore.Cache outCache = inCache;
3782 output DAE.Exp outExp;
3783 output DAE.Properties outProperties;
3784 protected
3785 String msg_str;
3786 Absyn.Exp astatic, adynamic;
3787 DAE.Exp dstatic, ddynamic;
3788 DAE.Type ty;
3789 algorithm
3790 ✗ if listLength(inPosArgs) <> 2 or not listEmpty(inNamedArgs) then
3791 msg_str := ", expected DynamicSelect(staticExp, dynamicExp)";
3792 ✗ printBuiltinFnArgError("DynamicSelect", msg_str, inPosArgs, inNamedArgs, inPrefix, inInfo);
3793 end if;
3794
3795 ✗ {astatic, adynamic} := inPosArgs;
3796 ✗ (outCache, dstatic, outProperties as DAE.PROP(ty, _)) :=
3797 elabExpInExpression(inCache, inEnv, astatic, inImplicit, true, inPrefix, inInfo);
3798
3799 try
3800 ✗ (outCache, ddynamic, _) :=
3801 elabExpInExpression(outCache, inEnv, adynamic, inImplicit, true, inPrefix, inInfo);
3802 ✗ outExp := Expression.makePureBuiltinCall("DynamicSelect", {dstatic, ddynamic}, ty);
3803 else
3804 ✗ outExp := dstatic;
3805 end try;
3806 end elabBuiltinDynamicSelect;
3807
3808 protected function elabBuiltinTranspose
3809 "Elaborates the builtin operator transpose."
3810 input FCore.Cache inCache;
3811 input FCore.Graph inEnv;
3812 input list<Absyn.Exp> inPosArgs;
3813 input list<Absyn.NamedArg> inNamedArg;
3814 input Boolean inImpl;
3815 input DAE.Prefix inPrefix;
3816 input SourceInfo inInfo;
3817 output FCore.Cache outCache;
3818 output DAE.Exp outExp;
3819 output DAE.Properties outProperties;
3820 protected
3821 Absyn.Exp aexp;
3822 DAE.Exp exp;
3823 DAE.Type ty, el_ty;
3824 DAE.Const c;
3825 DAE.Dimension d1, d2;
3826 algorithm
3827
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
103 {aexp} := inPosArgs;
3828
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 103 times.
103 (outCache, exp, DAE.PROP(ty, c)) :=
3829 elabExpInExpression(inCache, inEnv, aexp, inImpl, true, inPrefix, inInfo);
3830 // Transpose the type.
3831
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 103 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 103 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 103 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 103 times.
✗ Branch 12 not taken.
✓ Branch 13 taken 103 times.
✗ Branch 15 not taken.
✓ Branch 16 taken 103 times.
103 DAE.T_ARRAY(DAE.T_ARRAY(el_ty, {d1}), {d2}) := ty;
3832 206 ty := DAE.T_ARRAY(DAE.T_ARRAY(el_ty, {d2}), {d1});
3833 103 outProperties := DAE.PROP(ty, c);
3834 // Simplify the type and make a call to transpose.
3835 103 ty := Types.simplifyType(ty);
3836 103 outExp := Expression.makePureBuiltinCall("transpose", {exp}, ty);
3837 end elabBuiltinTranspose;
3838
3839 protected function elabBuiltinSum "This function elaborates the builtin operator sum.
3840 The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph"
3841 input FCore.Cache inCache;
3842 input FCore.Graph inEnv;
3843 input list<Absyn.Exp> inAbsynExpLst;
3844 input list<Absyn.NamedArg> inNamedArg;
3845 input Boolean inBoolean;
3846 input DAE.Prefix inPrefix;
3847 input SourceInfo info;
3848 output FCore.Cache outCache;
3849 output DAE.Exp outExp;
3850 output DAE.Properties outProperties;
3851 algorithm
3852 (outCache,outExp,outProperties) := match (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix)
3853 local
3854 DAE.Exp exp_1,exp_2;
3855 DAE.Type t,tp;
3856 DAE.Const c;
3857 FCore.Graph env;
3858 Absyn.Exp arrexp;
3859 Boolean impl,b;
3860 FCore.Cache cache;
3861 DAE.Prefix pre;
3862 String estr,tstr;
3863 DAE.Type etp;
3864
3865 case (cache,env,{arrexp},impl,pre)
3866 algorithm
3867
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 312 times.
312 (cache,exp_1,DAE.PROP(t,c)) := elabExpInExpression(cache,env,arrexp,impl,true,pre,info);
3868 312 tp := Types.arrayElementType(t);
3869 312 etp := Types.simplifyType(tp);
3870 312 b := Types.isArray(t);
3871
2/4
✓ Branch 0 taken 312 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 312 times.
312 b := b and Types.isSimpleType(tp);
3872 312 estr := Dump.printExpStr(arrexp);
3873 312 tstr := TypesDump.unparseType(t);
3874 312 Error.assertionOrAddSourceMessage(b,Error.SUM_EXPECTED_ARRAY,{estr,tstr},info);
3875 312 exp_2 := Expression.makePureBuiltinCall("sum", {exp_1}, etp);
3876 312 then
3877 (cache,exp_2,DAE.PROP(tp,c));
3878 end match;
3879 end elabBuiltinSum;
3880
3881 protected function elabBuiltinProduct "This function elaborates the builtin operator product.
3882 The input is the arguments to fill as Absyn.Exp expressions and the environment FCore.Graph"
3883 input FCore.Cache inCache;
3884 input FCore.Graph inEnv;
3885 input list<Absyn.Exp> inAbsynExpLst;
3886 input list<Absyn.NamedArg> inNamedArg;
3887 input Boolean inBoolean;
3888 input DAE.Prefix inPrefix;
3889 input SourceInfo info;
3890 output FCore.Cache outCache;
3891 output DAE.Exp outExp;
3892 output DAE.Properties outProperties;
3893 algorithm
3894 (outCache,outExp,outProperties):=
3895 matchcontinue (inCache,inEnv,inAbsynExpLst,inBoolean,inPrefix)
3896 local
3897 DAE.Exp exp_1,exp_2;
3898 DAE.Type t,tp;
3899 DAE.Const c;
3900 FCore.Graph env;
3901 Absyn.Exp arrexp;
3902 Boolean impl;
3903 DAE.Type ty;
3904 FCore.Cache cache;
3905 DAE.Prefix pre;
3906 String str_exp,str_pre;
3907 DAE.Type etp;
3908
3909 case (cache,env,{arrexp},impl,pre)
3910 algorithm
3911
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 (cache,exp_1,DAE.PROP(ty,c)) := elabExpInExpression(cache,env,arrexp,impl,true,pre,info);
3912 3 (exp_1,_) := Types.matchType(exp_1, ty, DAE.T_INTEGER_DEFAULT, true);
3913 ✗ str_exp := "product(" + Dump.printExpStr(arrexp) + ")";
3914 ✗ str_pre := PrefixUtil.printPrefixStr3(pre);
3915 ✗ Error.addSourceMessage(Error.BUILTIN_FUNCTION_PRODUCT_HAS_SCALAR_PARAMETER, {str_exp, str_pre}, info);
3916 ✗ then
3917 (cache,exp_1,DAE.PROP(DAE.T_INTEGER_DEFAULT,c));
3918
3919 case (cache,env,{arrexp},impl,pre)
3920 algorithm
3921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 (cache,exp_1,DAE.PROP(ty,c)) := elabExpInExpression(cache,env, arrexp, impl,true,pre,info);
3922 3 (exp_1,_) := Types.matchType(exp_1, ty, DAE.T_REAL_DEFAULT, true);
3923 ✗ str_exp := "product(" + Dump.printExpStr(arrexp) + ")";
3924 ✗ str_pre := PrefixUtil.printPrefixStr3(pre);
3925 ✗ Error.addSourceMessage(Error.BUILTIN_FUNCTION_PRODUCT_HAS_SCALAR_PARAMETER, {str_exp, str_pre}, info);
3926 ✗ then
3927 (cache,exp_1,DAE.PROP(DAE.T_REAL_DEFAULT,c));
3928
3929 case (cache,env,{arrexp},impl,pre)
3930 algorithm
3931
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 3 times.
3 (cache,exp_1,DAE.PROP(t as DAE.T_ARRAY(dims = {_}, ty = tp),c)) := elabExpInExpression(cache,env, arrexp, impl,true,pre,info);
3932 3 tp := Types.arrayElementType(t);
3933 3 etp := Types.simplifyType(tp);
3934 3 exp_2 := Expression.makePureBuiltinCall("product", {exp_1}, etp);
3935
3936
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 if not Types.arrayHasUnknownDims(t) then
3937 3 exp_2 := elabBuiltinProduct2(exp_2);
3938 end if;
3939 3 then
3940 (cache,exp_2,DAE.PROP(tp,c));
3941 end matchcontinue;
3942 end elabBuiltinProduct;
3943
3944 protected function elabBuiltinProduct2
3945 "Replaces product({a1,a2,...an}) with a1*a2*...*an} and
3946 product([a11,a12,...,a1n;...,am1,am2,..amn]) with a11*a12*...*amn"
3947 input DAE.Exp inExp;
3948 output DAE.Exp outExp;
3949 algorithm
3950 outExp := matchcontinue inExp
3951 local
3952 DAE.Exp array_exp;
3953
3954 case DAE.CALL(expLst = {array_exp})
3955 3 then Expression.makeProductLst(Expression.arrayElements(array_exp));
3956
3957 else inExp;
3958 end matchcontinue;
3959 end elabBuiltinProduct2;
3960
3961 protected function elabBuiltinPre "This function elaborates the builtin operator pre.
3962 Input is the arguments to the pre operator and the environment, FCore.Graph."
3963 input FCore.Cache inCache;
3964 input FCore.Graph inEnv;
3965 input list<Absyn.Exp> inPosArgs;
3966 input list<Absyn.NamedArg> inNamedArgs;
3967 input Boolean inImplicit;
3968 input DAE.Prefix inPrefix;
3969 input SourceInfo inInfo;
3970 output FCore.Cache outCache;
3971 output DAE.Exp outExp;
3972 output DAE.Properties outProperties;
3973 protected
3974 DAE.Exp exp;
3975 DAE.Type ty, ty2;
3976 DAE.Const c;
3977 list<DAE.Exp> expl;
3978 Boolean sc;
3979 String exp_str, pre_str;
3980 algorithm
3981 424 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "pre", inInfo);
3982
3983
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 424 times.
424 (outCache, exp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv,
3984 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
3985
3986 // A matrix?
3987
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 424 times.
424 if Expression.isMatrix(exp) then
3988 ✗ DAE.T_ARRAY(ty = ty2) := ty;
3989 ✗ ty2 := Types.unliftArray(ty2);
3990 ✗ outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty2));
3991 ✗ outExp := elabBuiltinPreMatrix(outExp, ty2);
3992 // An array?
3993 elseif Types.isArray(ty) then
3994 13 ty2 := Types.unliftArray(ty);
3995 13 outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty2));
3996 13 (expl, sc) := elabBuiltinPre2(outExp, ty2);
3997
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
13 outExp := DAE.ARRAY(Types.simplifyType(ty), sc, expl);
3998 // A scalar?
3999 else
4000 411 ty := Types.arrayElementType(ty);
4001
4002
1/2
✓ Branch 1 taken 411 times.
✗ Branch 2 not taken.
411 if Types.basicType(ty) then
4003 411 outExp := Expression.makePureBuiltinCall("pre", {exp}, Types.simplifyType(ty));
4004 else
4005 ✗ exp_str := ExpressionBasics.printExpStr(exp);
4006 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
4007 ✗ Error.addSourceMessageAndFail(Error.OPERAND_BUILTIN_TYPE,
4008 {"pre", pre_str, exp_str}, inInfo);
4009 end if;
4010 end if;
4011
4012 424 outProperties := DAE.PROP(ty, c);
4013 end elabBuiltinPre;
4014
4015 protected function elabBuiltinPre2
4016 "Help function for elabBuiltinPre, when type is array, send it here."
4017 input DAE.Exp inExp;
4018 input DAE.Type inType;
4019 output list<DAE.Exp> outExp;
4020 output Boolean outScalar;
4021 algorithm
4022 (outExp, outScalar) := matchcontinue inExp
4023 local
4024 Boolean sc;
4025 list<DAE.Exp> expl;
4026 Integer i;
4027 list<list<DAE.Exp>> mexpl;
4028 DAE.Type ty;
4029
4030 case DAE.CALL(expLst = {DAE.ARRAY(scalar = sc, array = expl)})
4031 13 then (makePreLst(expl, inType), sc);
4032
4033 case DAE.CALL(expLst = {DAE.MATRIX(ty = ty, integer = i, matrix = mexpl)})
4034 algorithm
4035 ✗ mexpl := list(makePreLst(e, inType) for e in mexpl);
4036 ✗ then
4037 ({DAE.MATRIX(ty, i, mexpl)}, false);
4038
4039 else ({inExp}, false);
4040 end matchcontinue;
4041 end elabBuiltinPre2;
4042
4043 protected function elabBuiltinInStream "This function elaborates the builtin operator inStream.
4044 Input is the arguments to the inStream operator and the environment, FCore.Graph."
4045 input FCore.Cache inCache;
4046 input FCore.Graph inEnv;
4047 input list<Absyn.Exp> inArgs;
4048 input list<Absyn.NamedArg> inNamedArgs;
4049 input Boolean inImpl;
4050 input DAE.Prefix inPrefix;
4051 input SourceInfo inInfo;
4052 output FCore.Cache outCache;
4053 output DAE.Exp outExp;
4054 output DAE.Properties outProperties;
4055 protected
4056 Absyn.Exp e;
4057 DAE.Exp exp;
4058 DAE.Type ty;
4059 algorithm
4060
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 228 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 228 times.
228 {e} := inArgs;
4061 228 (outCache, exp, outProperties) := elabExpInExpression(inCache, inEnv, e,
4062 inImpl, true, inPrefix, inInfo);
4063 228 ty := Types.getPropType(outProperties);
4064 228 outExp := elabBuiltinStreamOperator(outCache, inEnv, "inStream", exp, ty, inInfo);
4065
4066 // Use elabCallArgs to also try vectorized calls
4067
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 227 times.
227 if Types.dimensionsKnown(ty) then
4068 227 (outCache, outExp, outProperties) := elabCallArgs(outCache, inEnv,
4069 Absyn.IDENT("inStream"), {e}, {}, {}, inImpl, inPrefix, inInfo);
4070 end if;
4071 end elabBuiltinInStream;
4072
4073 protected function elabBuiltinActualStream "This function elaborates the builtin operator actualStream.
4074 Input is the arguments to the actualStream operator and the environment, FCore.Graph."
4075 input FCore.Cache inCache;
4076 input FCore.Graph inEnv;
4077 input list<Absyn.Exp> inArgs;
4078 input list<Absyn.NamedArg> inNamedArgs;
4079 input Boolean inImpl;
4080 input DAE.Prefix inPrefix;
4081 input SourceInfo inInfo;
4082 output FCore.Cache outCache;
4083 output DAE.Exp outExp;
4084 output DAE.Properties outProperties;
4085 protected
4086 Absyn.Exp e;
4087 DAE.Exp exp;
4088 DAE.Type ty;
4089 algorithm
4090
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 51 times.
51 {e} := inArgs;
4091 51 (outCache, exp, outProperties) := elabExpInExpression(inCache, inEnv, e,
4092 inImpl, true, inPrefix, inInfo);
4093 51 ty := Types.getPropType(outProperties);
4094 51 outExp := elabBuiltinStreamOperator(outCache, inEnv, "actualStream", exp, ty, inInfo);
4095
4096 // Use elabCallArgs to also try vectorized calls
4097
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51 times.
51 if Types.dimensionsKnown(ty) then
4098 51 (outCache, outExp, outProperties) := elabCallArgs(outCache, inEnv,
4099 Absyn.IDENT("actualStream"), {e}, {}, {}, inImpl, inPrefix, inInfo);
4100 end if;
4101 end elabBuiltinActualStream;
4102
4103 protected function elabBuiltinStreamOperator
4104 input FCore.Cache inCache;
4105 input FCore.Graph inEnv;
4106 input String inOperator;
4107 input DAE.Exp inExp;
4108 input DAE.Type inType;
4109 input SourceInfo inInfo;
4110 output DAE.Exp outExp;
4111 algorithm
4112 outExp := match inExp
4113 local
4114 DAE.Type et;
4115 DAE.Exp exp;
4116
4117 case DAE.ARRAY(array = {}) then inExp;
4118
4119 else
4120 algorithm
4121
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 161 times.
161 exp :: _ := Expression.flattenArrayExpToList(inExp);
4122 161 validateBuiltinStreamOperator(inCache, inEnv, exp, inType, inOperator, inInfo);
4123 160 et := Types.simplifyType(inType);
4124 160 exp := Expression.makePureBuiltinCall(inOperator, {exp}, et);
4125 then
4126 exp;
4127
4128 end match;
4129 end elabBuiltinStreamOperator;
4130
4131 protected function validateBuiltinStreamOperator
4132 input FCore.Cache inCache;
4133 input FCore.Graph inEnv;
4134 input DAE.Exp inOperand;
4135 input DAE.Type inType;
4136 input String inOperator;
4137 input SourceInfo inInfo;
4138 algorithm
4139 () := matchcontinue inOperand
4140 local
4141 DAE.ComponentRef cr;
4142 DAE.Attributes attr;
4143 String op_str;
4144
4145 // Operand is a stream variable, ok!
4146 case DAE.CREF(componentRef = cr)
4147 algorithm
4148 161 (_, attr) := Lookup.lookupVar(inCache, inEnv, cr);
4149
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 160 times.
161 DAE.ATTR(connectorType = DAE.STREAM()) := attr;
4150 then
4151 ();
4152
4153 // Operand is not a stream variable, error!
4154 else
4155 algorithm
4156 1 op_str := ExpressionBasics.printExpStr(inOperand);
4157 1 Error.addSourceMessage(Error.NON_STREAM_OPERAND_IN_STREAM_OPERATOR,
4158 {op_str, inOperator}, inInfo);
4159 1 then
4160 fail();
4161 end matchcontinue;
4162 end validateBuiltinStreamOperator;
4163
4164 protected function makePreLst
4165 "Takes a list of expressions and makes a list of pre - expressions"
4166 input list<DAE.Exp> inExpl;
4167 input DAE.Type inType;
4168 output list<DAE.Exp> outExpl;
4169 protected
4170 DAE.Type ty;
4171 algorithm
4172 13 ty := Types.simplifyType(inType);
4173
4/4
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 13 times.
✓ Branch 2 taken 35 times.
✓ Branch 3 taken 13 times.
83 outExpl := list(Expression.makePureBuiltinCall("pre", {e}, ty) for e in inExpl);
4174 end makePreLst;
4175
4176 protected function elabBuiltinPreMatrix
4177 "Help function for elabBuiltinPreMatrix, when type is matrix, send it here."
4178 input DAE.Exp inExp;
4179 input DAE.Type inType;
4180 output DAE.Exp outExp;
4181 algorithm
4182 outExp := match inExp
4183 local
4184 DAE.Exp exp;
4185
4186 case DAE.CALL(expLst = {exp as DAE.MATRIX()})
4187 algorithm
4188 ✗ exp.matrix := list(makePreLst(row, inType) for row in exp.matrix);
4189 then
4190 exp;
4191
4192 else inExp;
4193 end match;
4194 end elabBuiltinPreMatrix;
4195
4196 protected function elabBuiltinArray "
4197 This function elaborates the builtin operator \'array\'. For instance,
4198 array(1,4,6) which is the same as {1,4,6}.
4199 Input is the list of arguments to the operator, as Absyn.Exp list.
4200 "
4201 input FCore.Cache inCache;
4202 input FCore.Graph inEnv;
4203 input list<Absyn.Exp> inPosArgs;
4204 input list<Absyn.NamedArg> inNamedArgs;
4205 input Boolean inImplicit;
4206 input DAE.Prefix inPrefix;
4207 input SourceInfo inInfo;
4208 output FCore.Cache outCache;
4209 output DAE.Exp outExp;
4210 output DAE.Properties outProperties;
4211 protected
4212 list<DAE.Exp> expl;
4213 list<DAE.Properties> props;
4214 DAE.Type ty, arr_ty;
4215 DAE.Const c;
4216 Integer len;
4217 algorithm
4218 21 (outCache, expl, props) := elabExpList(inCache, inEnv, inPosArgs, inImplicit,
4219 true, inPrefix, inInfo);
4220
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
21 (_, DAE.PROP(ty, c)) := elabBuiltinArray2(expl, props, inPrefix, inInfo);
4221 20 len := listLength(expl);
4222 40 arr_ty := DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(len)});
4223 20 outProperties := DAE.PROP(arr_ty, c);
4224 20 arr_ty := Types.simplifyType(arr_ty);
4225
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
40 outExp := DAE.ARRAY(arr_ty, Types.isArray(ty), expl);
4226 end elabBuiltinArray;
4227
4228 protected function elabBuiltinArray2
4229 "Helper function to elabBuiltinArray.
4230 Asserts that all types are of same dimensionality and of same builtin types."
4231 input list<DAE.Exp> inExpl;
4232 input list<DAE.Properties> inProperties;
4233 input DAE.Prefix inPrefix;
4234 input SourceInfo inInfo;
4235 output list<DAE.Exp> outExpl;
4236 output DAE.Properties outProperties;
4237 protected
4238 String pre_str;
4239 DAE.Properties prop;
4240 algorithm
4241
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 20 times.
21 if not sameDimensions(inProperties) then
4242 1 pre_str := PrefixUtil.printPrefixStr3(inPrefix);
4243 1 Error.addSourceMessageAndFail(Error.DIFFERENT_DIM_SIZE_IN_ARGUMENTS,
4244 {"array", pre_str}, inInfo);
4245 end if;
4246
4247
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 prop := if Types.propsContainReal(inProperties) then
4248 DAE.PROP(DAE.T_REAL_DEFAULT, DAE.C_VAR()) else listHead(inProperties);
4249 20 (outExpl, outProperties) := elabBuiltinArray3(inExpl, inProperties, prop);
4250 end elabBuiltinArray2;
4251
4252 protected function elabBuiltinArray3
4253 "Helper function to elab_builtin_array."
4254 input list<DAE.Exp> inExpl;
4255 input list<DAE.Properties> inPropertiesLst;
4256 input DAE.Properties inProperties;
4257 output list<DAE.Exp> outExpl = {};
4258 output DAE.Properties outProperties = listHead(inPropertiesLst);
4259 protected
4260 DAE.Properties prop;
4261 list<DAE.Properties> rest_props = inPropertiesLst;
4262 algorithm
4263
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 20 times.
262 for e in inExpl loop
4264
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
242 prop :: rest_props := rest_props;
4265 242 e := Types.matchProp(e, prop, inProperties, true);
4266 outExpl := e :: outExpl;
4267 end for;
4268
4269 20 outExpl := listReverse(outExpl);
4270 end elabBuiltinArray3;
4271
4272 protected function elabBuiltinZeros "This function elaborates the builtin operator zeros(n)."
4273 input FCore.Cache inCache;
4274 input FCore.Graph inEnv;
4275 input list<Absyn.Exp> inPosArgs;
4276 input list<Absyn.NamedArg> inNamedArgs;
4277 input Boolean inImplicit;
4278 input DAE.Prefix inPrefix;
4279 input SourceInfo inInfo;
4280 output FCore.Cache outCache;
4281 output DAE.Exp outExp;
4282 output DAE.Properties outProperties;
4283 algorithm
4284 1894 (outCache, outExp, outProperties) := elabBuiltinFill(inCache, inEnv,
4285 Absyn.INTEGER(0) :: inPosArgs, {}, inImplicit, inPrefix, inInfo);
4286 end elabBuiltinZeros;
4287
4288 protected function sameDimensions
4289 "This function returns true if all properties, containing types, have the same
4290 dimensions, otherwise false."
4291 input list<DAE.Properties> inProps;
4292 output Boolean res;
4293 protected
4294 list<DAE.Type> types;
4295 list<DAE.Dimensions> dims;
4296 algorithm
4297 21 types := List.map(inProps, Types.getPropType);
4298 21 dims := List.map(types, TypesDump.getDimensions);
4299 21 res := sameDimensions2(dims);
4300 end sameDimensions;
4301
4302 protected function sameDimensionsExceptionDimX
4303 "This function returns true if all properties, containing types, have the same
4304 dimensions (except for dimension X), otherwise false."
4305 input list<DAE.Properties> inProps;
4306 input Integer dimException;
4307 output Boolean res;
4308 protected
4309 list<DAE.Type> types;
4310 list<DAE.Dimensions> dims;
4311 algorithm
4312 ✗ types := List.map(inProps, Types.getPropType);
4313 ✗ dims := List.map(types, TypesDump.getDimensions);
4314 ✗ dims := List.map1(dims, listDelete, dimException);
4315 ✗ res := sameDimensions2(dims);
4316 end sameDimensionsExceptionDimX;
4317
4318 protected function sameDimensions2
4319 "Helper function to sameDimensions. Checks that each list of dimensions has
4320 the same dimensions as the other lists."
4321 input list<DAE.Dimensions> inDimensions;
4322 output Boolean outSame = true;
4323 protected
4324 DAE.Dimensions dims;
4325 list<DAE.Dimensions> rest_dims = inDimensions;
4326 algorithm
4327
1/2
✓ Branch 0 taken 21 times.
✗ Branch 1 not taken.
21 if listEmpty(inDimensions) then
4328 ✗ return;
4329 end if;
4330
4331
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 1 time.
21 while not listEmpty(listHead(rest_dims)) loop
4332
4/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 time.
3 dims := list(listHead(d) for d in rest_dims);
4333
4334
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if not sameDimensions3(dims) then
4335 outSame := false;
4336 1 return;
4337 end if;
4338
4339 ✗ rest_dims := list(listRest(d) for d in rest_dims);
4340 end while;
4341
4342 // Make sure the lists were the same length.
4343
2/2
✓ Branch 0 taken 242 times.
✓ Branch 1 taken 20 times.
262 for d in rest_dims loop
4344
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 242 times.
242 true := listEmpty(d);
4345 end for;
4346 end sameDimensions2;
4347
4348 protected function sameDimensions3
4349 "Helper function to sameDimensions2. Check that all dimensions in a list are equal."
4350 input DAE.Dimensions inDims;
4351 output Boolean outSame = true;
4352 protected
4353 DAE.Dimension dim1;
4354 algorithm
4355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if listEmpty(inDims) then
4356 ✗ return;
4357 end if;
4358
4359 1 dim1 := listHead(inDims);
4360
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 for dim2 in listRest(inDims) loop
4361
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if not Expression.dimensionsEqual(dim1, dim2) then
4362 outSame := false;
4363 1 return;
4364 end if;
4365 end for;
4366 end sameDimensions3;
4367
4368 protected function elabBuiltinOnes "This function elaborates on the builtin opeator ones(n)."
4369 input FCore.Cache inCache;
4370 input FCore.Graph inEnv;
4371 input list<Absyn.Exp> inPosArgs;
4372 input list<Absyn.NamedArg> inNamedArg;
4373 input Boolean inImplicit;
4374 input DAE.Prefix inPrefix;
4375 input SourceInfo inInfo;
4376 output FCore.Cache outCache;
4377 output DAE.Exp outExp;
4378 output DAE.Properties outProperties;
4379 algorithm
4380 231 (outCache, outExp, outProperties) := elabBuiltinFill(inCache, inEnv,
4381 Absyn.INTEGER(1) :: inPosArgs, {}, inImplicit, inPrefix, inInfo);
4382 end elabBuiltinOnes;
4383
4384 protected function elabBuiltinMax
4385 "This function elaborates on the builtin operator max(a, b)."
4386 input FCore.Cache inCache;
4387 input FCore.Graph inEnv;
4388 input list<Absyn.Exp> inFnArgs;
4389 input list<Absyn.NamedArg> inNamedArg;
4390 input Boolean inImpl;
4391 input DAE.Prefix inPrefix;
4392 input SourceInfo info;
4393 output FCore.Cache outCache;
4394 output DAE.Exp outExp;
4395 output DAE.Properties outProperties;
4396 algorithm
4397 804 (outCache, outExp, outProperties) :=
4398 elabBuiltinMinMaxCommon(inCache, inEnv, "max", inFnArgs, inImpl, inPrefix, info);
4399 end elabBuiltinMax;
4400
4401 protected function elabBuiltinMin
4402 "This function elaborates the builtin operator min(a, b)"
4403 input FCore.Cache inCache;
4404 input FCore.Graph inEnv;
4405 input list<Absyn.Exp> inFnArgs;
4406 input list<Absyn.NamedArg> inNamedArg;
4407 input Boolean inImpl;
4408 input DAE.Prefix inPrefix;
4409 input SourceInfo info;
4410 output FCore.Cache outCache;
4411 output DAE.Exp outExp;
4412 output DAE.Properties outProperties;
4413 algorithm
4414 330 (outCache, outExp, outProperties) :=
4415 elabBuiltinMinMaxCommon(inCache, inEnv, "min", inFnArgs, inImpl, inPrefix, info);
4416 end elabBuiltinMin;
4417
4418 protected function elabBuiltinMinMaxCommon
4419 "Helper function to elabBuiltinMin and elabBuiltinMax, containing common
4420 functionality."
4421 input output FCore.Cache cache;
4422 input FCore.Graph env;
4423 input String inFnName;
4424 input list<Absyn.Exp> inFnArgs;
4425 input Boolean impl;
4426 input DAE.Prefix prefix;
4427 input SourceInfo info;
4428 output DAE.Exp outExp;
4429 output DAE.Properties outProperties;
4430 algorithm
4431 (outExp, outProperties) := match inFnArgs
4432 local
4433 DAE.Exp arrexp_1,s1_1,s2_1, call;
4434 DAE.Type tp;
4435 DAE.Type ty,ty1,ty2,elt_ty;
4436 DAE.Const c,c1,c2;
4437 Absyn.Exp arrexp,s1,s2;
4438
4439 // min|max(vector)
4440 case {arrexp}
4441 algorithm
4442
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
111 (cache, arrexp_1, DAE.PROP(ty, c)) :=
4443 elabExpInExpression(cache, env, arrexp, impl, true, prefix, info);
4444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
111 true := Types.isArray(ty);
4445 111 arrexp_1 := Expression.matrixToArray(arrexp_1);
4446 111 elt_ty := Types.arrayElementType(ty);
4447 111 tp := Types.simplifyType(elt_ty);
4448
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 111 times.
111 false := Types.isString(tp);
4449 111 call := Expression.makePureBuiltinCall(inFnName, {arrexp_1}, tp);
4450 111 then
4451 (call, DAE.PROP(elt_ty,c));
4452
4453 // min|max(x,y) where x & y are scalars.
4454 case {s1, s2}
4455 algorithm
4456
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
1023 (cache, s1_1, DAE.PROP(ty1, c1)) :=
4457 elabExpInExpression(cache, env, s1, impl, true, prefix, info);
4458
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
1023 (cache, s2_1, DAE.PROP(ty2, c2)) :=
4459 elabExpInExpression(cache, env, s2, impl, true, prefix, info);
4460
4461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
1023 (s1_1, s2_1, ty, true) := Types.checkTypeCompat(s1_1, ty1, s2_1, ty2);
4462 1023 c := Types.constAnd(c1, c2);
4463 1023 tp := Types.simplifyType(ty);
4464
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1023 times.
1023 false := Types.isString(tp);
4465 1023 call := Expression.makePureBuiltinCall(inFnName, {s1_1, s2_1}, tp);
4466 1023 then
4467 (call, DAE.PROP(ty,c));
4468
4469 end match;
4470 end elabBuiltinMinMaxCommon;
4471
4472 protected function elabBuiltinClock
4473 "Author: BTH
4474 This function elaborates the builtin Clock constructor Clock(..)."
4475 input FCore.Cache inCache;
4476 input FCore.Graph inEnv;
4477 input list<Absyn.Exp> args;
4478 input list<Absyn.NamedArg> nargs;
4479 input Boolean inBoolean;
4480 input DAE.Prefix inPrefix;
4481 input SourceInfo info;
4482 output FCore.Cache outCache;
4483 output DAE.Exp outExp;
4484 output DAE.Properties outProperties;
4485 algorithm
4486 (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4487 local
4488 DAE.Exp call,interval,intervalCounter,resolution,condition,startInterval,c,solverMethod;
4489 DAE.Type ty1,ty2;
4490 Boolean impl;
4491 FCore.Graph env;
4492 FCore.Cache cache;
4493 DAE.Prefix pre;
4494 DAE.Properties prop1,prop2, prop = DAE.PROP(DAE.T_CLOCK_DEFAULT, DAE.C_VAR());
4495 Absyn.Exp ainterval, aintervalCounter, aresolution, acondition, astartInterval, ac, asolverMethod;
4496 Values.Value val;
4497
4498 // Inferred clock "Clock()"
4499 case (cache, _, {}, {}, _, _)
4500 algorithm
4501 call := DAE.CLKCONST(DAE.INFERRED_CLOCK());
4502 then (cache, call, DAE.PROP(DAE.T_CLOCK_DEFAULT, DAE.C_VAR()));
4503
4504 // clock with rational interval "Clock(intervalCounter)"
4505 case (cache, env, {aintervalCounter}, {}, impl, pre)
4506 algorithm
4507 39 (cache, intervalCounter, prop1) := elabExpInExpression(cache,env,aintervalCounter,impl,true,pre,info);
4508 39 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4509 39 (intervalCounter,_) := Types.matchType(intervalCounter,ty1,DAE.T_INTEGER_DEFAULT,true);
4510 ✗ call := DAE.CLKCONST(DAE.RATIONAL_CLOCK(intervalCounter, DAE.ICONST(1)));
4511 ✗ then (cache, call, prop);
4512
4513 // clock with rational interval "Clock(intervalCounter, resolution)"
4514 case (cache, env, {aintervalCounter, aresolution}, {}, impl, pre)
4515 algorithm
4516 8 (cache, intervalCounter, prop1) := elabExpInExpression(cache,env,aintervalCounter,impl,true,pre,info);
4517 8 (cache, resolution, prop2) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info);
4518 8 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4519 8 ty2 := Types.arrayElementType(Types.getPropType(prop2));
4520 8 (intervalCounter,_) := Types.matchType(intervalCounter,ty1,DAE.T_INTEGER_DEFAULT,true);
4521 7 (resolution,_) := Types.matchType(resolution,ty2,DAE.T_INTEGER_DEFAULT,true);
4522 // evaluate and check if resolution >= 1 (rfranke)
4523 7 (cache, val) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0);
4524 14 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 1,
4525 Error.WRONG_VALUE_OF_ARG, {"Clock", "resolution", ValuesDump.valString(val), ">= 1"}, info);
4526 7 resolution := ValuesUtil.valueExp(val, SOME(resolution));
4527 7 call := DAE.CLKCONST(DAE.RATIONAL_CLOCK(intervalCounter, resolution));
4528 7 then (cache, call, prop);
4529
4530 // clock with Real interval "Clock(interval)"
4531 case (cache, env, {ainterval}, {}, impl, pre)
4532 algorithm
4533 39 (cache, interval, prop1) := elabExpInExpression(cache,env,ainterval,impl,true,pre,info);
4534 39 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4535 39 (interval,_) := Types.matchType(interval,ty1,DAE.T_REAL_DEFAULT,true);
4536 37 call := DAE.CLKCONST(DAE.REAL_CLOCK(interval));
4537 37 then (cache, call, prop);
4538
4539 // Event Clock (clock triggered by zero-crossing events) "Clock(condition)"
4540 case (cache, env, {acondition}, {}, impl, pre)
4541 algorithm
4542 2 (cache, condition, prop1) := elabExpInExpression(cache,env,acondition,impl,true,pre,info);
4543 2 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4544 2 (condition,_) := Types.matchType(condition,ty1,DAE.T_BOOL_DEFAULT,true);
4545 2 call := DAE.CLKCONST(DAE.EVENT_CLOCK(condition, DAE.RCONST(0.0)));
4546 2 then (cache, call, prop);
4547
4548 // Event Clock (clock triggered by zero-crossing events) "Clock(condition, startInterval)"
4549 case (cache, env, {acondition, astartInterval}, {}, impl, pre)
4550 algorithm
4551 1 (cache, condition, prop1) := elabExpInExpression(cache,env,acondition,impl,true,pre,info);
4552 1 (cache, startInterval, prop2) := elabExpInExpression(cache,env,astartInterval,impl,true,pre,info);
4553 1 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4554 1 ty2 := Types.arrayElementType(Types.getPropType(prop2));
4555 1 (condition,_) := Types.matchType(condition,ty1,DAE.T_BOOL_DEFAULT,true);
4556 1 (startInterval,_) := Types.matchType(startInterval,ty2,DAE.T_REAL_DEFAULT,true);
4557 // TODO! check if expression startInterval is >= 0.0
4558 // rStartInterval = Expression.toReal(startInterval);
4559 // true = rStartInterval >= 0.0;
4560 1 call := DAE.CLKCONST(DAE.EVENT_CLOCK(condition, startInterval));
4561 1 then (cache, call, prop);
4562
4563 // Solver Clock "Clock(c, solverMethod)"
4564 case (cache, env, {ac, asolverMethod}, {}, impl, pre)
4565 algorithm
4566 ✗ (cache, c, prop1) := elabExpInExpression(cache,env,ac,impl,true,pre,info);
4567 ✗ (cache, solverMethod, prop2) := elabExpInExpression(cache,env,asolverMethod,impl,true,pre,info);
4568 ✗ ty1 := Types.arrayElementType(Types.getPropType(prop1));
4569 ✗ ty2 := Types.arrayElementType(Types.getPropType(prop2));
4570 ✗ (c,_) := Types.matchType(c,ty1,DAE.T_CLOCK_DEFAULT,true);
4571 ✗ (solverMethod,_) := Types.matchType(solverMethod,ty2,DAE.T_STRING_DEFAULT,true);
4572 // evaluate structural solverMethod (rfranke)
4573 ✗ (cache, val) := Ceval.ceval(cache, env, solverMethod, false, Absyn.MSG(info), 0);
4574 ✗ solverMethod := ValuesUtil.valueExp(val, SOME(solverMethod));
4575 ✗ call := DAE.CLKCONST(DAE.SOLVER_CLOCK(c, solverMethod));
4576 ✗ then (cache, call, prop);
4577
4578 // Solver Clock "Clock(c, solverMethod=solverMethod)" with named arguments
4579 case (cache, env, {ac}, {Absyn.NAMEDARG(argName="solverMethod", argValue=asolverMethod)}, impl, pre)
4580 algorithm
4581 3 (cache, c, prop1) := elabExpInExpression(cache,env,ac,impl,true,pre,info);
4582 3 (cache, solverMethod, prop2) := elabExpInExpression(cache,env,asolverMethod,impl,true,pre,info);
4583 3 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4584 3 ty2 := Types.arrayElementType(Types.getPropType(prop2));
4585 3 (c,_) := Types.matchType(c,ty1,DAE.T_CLOCK_DEFAULT,true);
4586 3 (solverMethod,_) := Types.matchType(solverMethod,ty2,DAE.T_STRING_DEFAULT,true);
4587 // evaluate structural solverMethod (rfranke)
4588 3 (cache, val) := Ceval.ceval(cache, env, solverMethod, false, Absyn.MSG(info), 0);
4589 3 solverMethod := ValuesUtil.valueExp(val, SOME(solverMethod));
4590 3 call := DAE.CLKCONST(DAE.SOLVER_CLOCK(c, solverMethod));
4591 3 then (cache, call, prop);
4592
4593 end matchcontinue;
4594 end elabBuiltinClock;
4595
4596 protected function elabBuiltinHold "
4597 Author: BTH
4598 This function elaborates the builtin operator hold(u)."
4599 input FCore.Cache inCache;
4600 input FCore.Graph inEnv;
4601 input list<Absyn.Exp> args;
4602 input list<Absyn.NamedArg> nargs;
4603 input Boolean inBoolean;
4604 input DAE.Prefix inPrefix;
4605 input SourceInfo info;
4606 output FCore.Cache outCache;
4607 output DAE.Exp outExp;
4608 output DAE.Properties outProperties;
4609 algorithm
4610 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4611 local
4612 DAE.Exp call;
4613 DAE.Type ty1,ty;
4614 Boolean impl;
4615 FCore.Graph env;
4616 FCore.Cache cache;
4617 DAE.Prefix pre;
4618 DAE.Properties prop1, prop;
4619 Absyn.Exp au;
4620
4621 case (cache, env, {au}, {}, impl, pre)
4622 algorithm
4623 13 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4624 13 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4625 26 ty := DAE.T_FUNCTION(
4626 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
4627 ty1,
4628 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4629 Absyn.IDENT("hold"));
4630
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
✓ Branch 5 taken 13 times.
✗ Branch 6 not taken.
13 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("hold"), args, nargs, {}, impl, pre, info);
4631 then (cache, call, prop);
4632 end match;
4633 end elabBuiltinHold;
4634
4635 protected function elabBuiltinSample "
4636 Author: BTH
4637 This function elaborates the builtin operator sample(..) variants."
4638 input FCore.Cache inCache;
4639 input FCore.Graph inEnv;
4640 input list<Absyn.Exp> args;
4641 input list<Absyn.NamedArg> nargs;
4642 input Boolean inBoolean;
4643 input DAE.Prefix inPrefix;
4644 input SourceInfo info;
4645 output FCore.Cache outCache;
4646 output DAE.Exp outExp;
4647 output DAE.Properties outProperties;
4648 algorithm
4649 (outCache,outExp,outProperties) := matchcontinue (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4650 local
4651 DAE.Exp call,c,start,interval;
4652 DAE.Type ty1,ty2,ty;
4653 Boolean impl;
4654 FCore.Graph env;
4655 FCore.Cache cache;
4656 DAE.Prefix pre;
4657 DAE.Properties prop1,prop2,prop;
4658 DAE.Const variability;
4659 Absyn.Exp au,ac,astart,ainterval;
4660
4661 // The time event triggering sample(start, interval)
4662 case (cache, env, {astart,ainterval}, {}, impl, pre)
4663 algorithm
4664 81 (cache, start, prop1) := elabExpInExpression(cache,env,astart,impl,true,pre,info);
4665 81 (cache, interval, prop2) := elabExpInExpression(cache,env,ainterval,impl,true,pre,info);
4666 81 ty1 := Types.getPropType(prop1);
4667 81 ty2 := Types.getPropType(prop2);
4668 81 (start,_) := Types.matchType(start,ty1,DAE.T_REAL_DEFAULT,true);
4669 81 (interval,_) := Types.matchType(interval,ty2,DAE.T_REAL_DEFAULT,true);
4670 ty := DAE.T_FUNCTION(
4671 {DAE.FUNCARG("start",DAE.T_REAL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()),
4672 DAE.FUNCARG("interval",DAE.T_REAL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())},
4673 DAE.T_BOOL_DEFAULT,
4674 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4675 Absyn.IDENT("sample"));
4676
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 67 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 67 times.
68 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"), args, nargs, {}, impl, pre, info);
4677 then (cache, call, prop);
4678
4679 // The sample from the Synchronous Language Elements chapter (Modelica 3.3)
4680 case (cache, env, {au,ac}, {}, impl, pre)
4681 algorithm
4682 14 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4683 14 (cache, c, prop2) := elabExpInExpression(cache,env,ac,impl,true,pre,info);
4684 14 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4685 14 ty2 := Types.arrayElementType(Types.getPropType(prop2));
4686 14 variability := Types.getPropConst(prop1);
4687 14 (c,_) := Types.matchType(c,ty2,DAE.T_CLOCK_DEFAULT,true);
4688
4689 26 ty := DAE.T_FUNCTION(
4690 {DAE.FUNCARG("u",ty1,variability,DAE.NON_PARALLEL(),NONE()),
4691 DAE.FUNCARG("c",ty2,DAE.C_VAR(),DAE.NON_PARALLEL(),SOME(DAE.CLKCONST(DAE.INFERRED_CLOCK())))},
4692 ty1,
4693 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4694 Absyn.IDENT("sample"));
4695
4696
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
13 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"),
4697 args, nargs, {}, impl, pre, info);
4698 then (cache, call, prop);
4699
4700 case (cache, env, {au}, {}, impl, pre)
4701 algorithm
4702 20 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4703 20 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4704 20 variability := Types.getPropConst(prop1);
4705
4706 40 ty := DAE.T_FUNCTION(
4707 {DAE.FUNCARG("u",ty1,variability,DAE.NON_PARALLEL(),NONE()),
4708 DAE.FUNCARG("c",DAE.T_CLOCK_DEFAULT,DAE.C_VAR(),DAE.NON_PARALLEL(),SOME(DAE.CLKCONST(DAE.INFERRED_CLOCK())))},
4709 ty1,
4710 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4711 Absyn.IDENT("sample"));
4712
4713
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 20 times.
20 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("sample"),
4714 args, nargs, {}, impl, pre, info);
4715 then (cache, call, prop);
4716
4717
4718 end matchcontinue;
4719 end elabBuiltinSample;
4720
4721 protected function elabBuiltinShiftSample "
4722 Author: BTH
4723 This function elaborates the builtin operator shiftSample(u,shiftCounter,resolution)."
4724 input FCore.Cache inCache;
4725 input FCore.Graph inEnv;
4726 input list<Absyn.Exp> args;
4727 input list<Absyn.NamedArg> nargs;
4728 input Boolean inBoolean;
4729 input DAE.Prefix inPrefix;
4730 input SourceInfo info;
4731 output FCore.Cache outCache;
4732 output DAE.Exp outExp;
4733 output DAE.Properties outProperties;
4734 algorithm
4735 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4736 local
4737 DAE.Exp call,shiftCounter,resolution;
4738 DAE.Type ty1,ty;
4739 Boolean impl;
4740 FCore.Graph env;
4741 FCore.Cache cache;
4742 DAE.Prefix pre;
4743 DAE.Properties prop1,prop2,prop3,prop;
4744 Absyn.Exp au,ashiftCounter,aresolution;
4745 Values.Value val, rval;
4746
4747 case (cache, env, {au,ashiftCounter}, {}, impl, pre)
4748 algorithm
4749 4 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4750 4 (cache, shiftCounter, prop2) := elabExpInExpression(cache,env,ashiftCounter,impl,true,pre,info);
4751 4 (shiftCounter,_) := Types.matchType(shiftCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true);
4752 // evaluate and check if shiftCounter >= 0 (rfranke)
4753 4 (cache, val) := Ceval.ceval(cache, env, shiftCounter, false, Absyn.MSG(info), 0);
4754 8 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0,
4755 Error.WRONG_VALUE_OF_ARG, {"shiftSample", "shiftCounter", ValuesDump.valString(val), ">= 0"}, info);
4756 4 ashiftCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val));
4757 aresolution := Absyn.INTEGER(1);
4758 4 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4759 8 ty := DAE.T_FUNCTION(
4760 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
4761 DAE.FUNCARG("shiftCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()),
4762 DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())},
4763 ty1,
4764 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4765 Absyn.IDENT("shiftSample"));
4766 // Pretend that shiftSample(u,shiftCounter) was shiftSample(u,shiftCounter,1) (resolution=1 is default value)
4767
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("shiftSample"), {au, ashiftCounter, aresolution}, nargs, {}, impl, pre, info);
4768 then (cache, call, prop);
4769
4770 case (cache, env, {au,ashiftCounter,aresolution}, {}, impl, pre)
4771 algorithm
4772 6 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4773 6 (cache, shiftCounter, prop2) := elabExpInExpression(cache,env,ashiftCounter,impl,true,pre,info);
4774 6 (shiftCounter,_) := Types.matchType(shiftCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true);
4775 // evaluate and check if shiftCounter >= 0 (rfranke)
4776 6 (cache, val) := Ceval.ceval(cache, env, shiftCounter, false, Absyn.MSG(info), 0);
4777 12 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0,
4778 Error.WRONG_VALUE_OF_ARG, {"shiftSample", "shiftCounter", ValuesDump.valString(val), ">= 0"}, info);
4779 6 ashiftCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val));
4780 6 (cache, resolution, prop3) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info);
4781 6 (resolution,_) := Types.matchType(resolution,Types.getPropType(prop3),DAE.T_INTEGER_DEFAULT,true);
4782 // evaluate and check if resolution >= 1 (rfranke)
4783 6 (cache, rval) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0);
4784 12 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(rval) >= 1,
4785 Error.WRONG_VALUE_OF_ARG, {"shiftSample", "resolution", ValuesDump.valString(rval), ">= 1"}, info);
4786 6 aresolution := Absyn.INTEGER(ValuesUtil.valueInteger(rval));
4787 6 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4788 12 ty := DAE.T_FUNCTION(
4789 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
4790 DAE.FUNCARG("shiftCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()),
4791 DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())},
4792 ty1,
4793 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4794 Absyn.IDENT("shiftSample"));
4795
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
6 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("shiftSample"), {au, ashiftCounter, aresolution}, nargs, {}, impl, pre, info);
4796 then (cache, call, prop);
4797 end match;
4798 end elabBuiltinShiftSample;
4799
4800 protected function elabBuiltinBackSample "
4801 Author: BTH
4802 This function elaborates the builtin operator backSample(u,backCounter,resolution)."
4803 input FCore.Cache inCache;
4804 input FCore.Graph inEnv;
4805 input list<Absyn.Exp> args;
4806 input list<Absyn.NamedArg> nargs;
4807 input Boolean inBoolean;
4808 input DAE.Prefix inPrefix;
4809 input SourceInfo info;
4810 output FCore.Cache outCache;
4811 output DAE.Exp outExp;
4812 output DAE.Properties outProperties;
4813 algorithm
4814 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4815 local
4816 DAE.Exp call,backCounter,resolution;
4817 DAE.Type ty1,ty;
4818 Boolean impl;
4819 FCore.Graph env;
4820 FCore.Cache cache;
4821 DAE.Prefix pre;
4822 DAE.Properties prop1,prop2,prop3,prop;
4823 Absyn.Exp au,abackCounter,aresolution;
4824 Values.Value val, rval;
4825
4826 case (cache, env, {au,abackCounter}, {}, impl, pre)
4827 algorithm
4828 4 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4829 4 (cache, backCounter, prop2) := elabExpInExpression(cache,env,abackCounter,impl,true,pre,info);
4830 4 (backCounter,_) := Types.matchType(backCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true);
4831 // evaluate and check if backCounter >= 0 (rfranke)
4832 4 (cache, val) := Ceval.ceval(cache, env, backCounter, false, Absyn.MSG(info), 0);
4833 8 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0,
4834 Error.WRONG_VALUE_OF_ARG, {"backSample", "backCounter", ValuesDump.valString(val), ">= 0"}, info);
4835 4 abackCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val));
4836 aresolution := Absyn.INTEGER(1);
4837 4 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4838 8 ty := DAE.T_FUNCTION(
4839 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
4840 DAE.FUNCARG("backCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()),
4841 DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())},
4842 ty1,
4843 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4844 Absyn.IDENT("backSample"));
4845 // Pretend that backSample(u,backCounter) was backSample(u,backCounter,1) (resolution=1 is default value)
4846
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("backSample"), {au, abackCounter, aresolution}, nargs, {}, impl, pre, info);
4847 then (cache, call, prop);
4848
4849 case (cache, env, {au,abackCounter,aresolution}, {}, impl, pre)
4850 algorithm
4851 2 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4852 2 (cache, backCounter, prop2) := elabExpInExpression(cache,env,abackCounter,impl,true,pre,info);
4853 2 (backCounter,_) := Types.matchType(backCounter,Types.getPropType(prop2),DAE.T_INTEGER_DEFAULT,true);
4854 // evaluate and check if backCounter >= 0 (rfranke)
4855 2 (cache, val) := Ceval.ceval(cache, env, backCounter, false, Absyn.MSG(info), 0);
4856 4 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(val) >= 0,
4857 Error.WRONG_VALUE_OF_ARG, {"backSample", "backCounter", ValuesDump.valString(val), ">= 0"}, info);
4858 2 abackCounter := Absyn.INTEGER(ValuesUtil.valueInteger(val));
4859 2 (cache, resolution, prop3) := elabExpInExpression(cache,env,aresolution,impl,true,pre,info);
4860 2 (resolution,_) := Types.matchType(resolution,Types.getPropType(prop3),DAE.T_INTEGER_DEFAULT,true);
4861 // evaluate and check if resolution >= 1 (rfranke)
4862 2 (cache, rval) := Ceval.ceval(cache, env, resolution, false, Absyn.MSG(info), 0);
4863 4 Error.assertionOrAddSourceMessage(ValuesUtil.valueInteger(rval) >= 1,
4864 Error.WRONG_VALUE_OF_ARG, {"backSample", "resolution", ValuesDump.valString(rval), ">= 1"}, info);
4865 2 aresolution := Absyn.INTEGER(ValuesUtil.valueInteger(rval));
4866 2 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4867 4 ty := DAE.T_FUNCTION(
4868 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
4869 DAE.FUNCARG("backCounter",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE()),
4870 DAE.FUNCARG("resolution",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),NONE())},
4871 ty1,
4872 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4873 Absyn.IDENT("backSample"));
4874
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("backSample"), {au, abackCounter, aresolution}, nargs, {}, impl, pre, info);
4875 then (cache, call, prop);
4876 end match;
4877 end elabBuiltinBackSample;
4878
4879 protected function elabBuiltinNoClock "
4880 Author: BTH
4881 This function elaborates the builtin operator noClock(u)."
4882 input FCore.Cache inCache;
4883 input FCore.Graph inEnv;
4884 input list<Absyn.Exp> args;
4885 input list<Absyn.NamedArg> nargs;
4886 input Boolean inBoolean;
4887 input DAE.Prefix inPrefix;
4888 input SourceInfo info;
4889 output FCore.Cache outCache;
4890 output DAE.Exp outExp;
4891 output DAE.Properties outProperties;
4892 algorithm
4893 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4894 local
4895 DAE.Exp call;
4896 DAE.Type ty1,ty;
4897 Boolean impl;
4898 FCore.Graph env;
4899 FCore.Cache cache;
4900 DAE.Prefix pre;
4901 DAE.Properties prop1, prop;
4902 Absyn.Exp au;
4903
4904 case (cache, env, {au}, {}, impl, pre)
4905 algorithm
4906 5 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4907 5 ty1 := Types.arrayElementType(Types.getPropType(prop1));
4908 10 ty := DAE.T_FUNCTION(
4909 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
4910 ty1,
4911 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4912 Absyn.IDENT("noClock"));
4913
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
5 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("noClock"), args, nargs, {}, impl, pre, info);
4914 then (cache, call, prop);
4915 end match;
4916 end elabBuiltinNoClock;
4917
4918 protected function elabBuiltinFirstTick "
4919 This function elaborates the builtin operator firstTick(u)."
4920 input FCore.Cache inCache;
4921 input FCore.Graph inEnv;
4922 input list<Absyn.Exp> args;
4923 input list<Absyn.NamedArg> nargs;
4924 input Boolean inBoolean;
4925 input DAE.Prefix inPrefix;
4926 input SourceInfo info;
4927 output FCore.Cache outCache;
4928 output DAE.Exp outExp;
4929 output DAE.Properties outProperties;
4930 algorithm
4931 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4932 local
4933 DAE.Exp call;
4934 DAE.Type ty1,ty;
4935 Boolean impl;
4936 FCore.Graph env;
4937 FCore.Cache cache;
4938 DAE.Prefix pre;
4939 DAE.Properties prop1, prop;
4940 Absyn.Exp au;
4941
4942 case (cache, env, {}, {}, impl, pre)
4943 algorithm
4944 ty := DAE.T_FUNCTION(
4945 {},
4946 DAE.T_BOOL_DEFAULT,
4947 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4948 Absyn.IDENT("firstTick"));
4949 ✗ (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("firstTick"), args, nargs, {}, impl, pre, info);
4950 then (cache, call, prop);
4951
4952 case (cache, env, {au}, {}, impl, pre)
4953 algorithm
4954 ✗ (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
4955 ✗ ty1 := Types.arrayElementType(Types.getPropType(prop1));
4956 ✗ ty := DAE.T_FUNCTION(
4957 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
4958 DAE.T_BOOL_DEFAULT,
4959 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4960 Absyn.IDENT("firstTick"));
4961 ✗ (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("firstTick"), args, nargs, {}, impl, pre, info);
4962 then (cache, call, prop);
4963 end match;
4964 end elabBuiltinFirstTick;
4965
4966 protected function elabBuiltinInterval "
4967 Author: BTH
4968 This function elaborates the builtin operator interval(u)."
4969 input FCore.Cache inCache;
4970 input FCore.Graph inEnv;
4971 input list<Absyn.Exp> args;
4972 input list<Absyn.NamedArg> nargs;
4973 input Boolean inBoolean;
4974 input DAE.Prefix inPrefix;
4975 input SourceInfo info;
4976 output FCore.Cache outCache;
4977 output DAE.Exp outExp;
4978 output DAE.Properties outProperties;
4979 algorithm
4980 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
4981 local
4982 DAE.Exp call;
4983 DAE.Type ty1,ty;
4984 Boolean impl;
4985 FCore.Graph env;
4986 FCore.Cache cache;
4987 DAE.Prefix pre;
4988 DAE.Properties prop1, prop;
4989 Absyn.Exp au;
4990
4991 case (cache, env, {}, {}, impl, pre)
4992 algorithm
4993 ty := DAE.T_FUNCTION(
4994 {},
4995 DAE.T_REAL_DEFAULT,
4996 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
4997 Absyn.IDENT("interval"));
4998
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("interval"), args, nargs, {}, impl, pre, info);
4999 then (cache, call, prop);
5000
5001 case (cache, env, {au}, {}, impl, pre)
5002 algorithm
5003 4 (cache,_, prop1) := elabExpInExpression(cache,env,au,impl,true,pre,info);
5004 4 ty1 := Types.arrayElementType(Types.getPropType(prop1));
5005 8 ty := DAE.T_FUNCTION(
5006 {DAE.FUNCARG("u",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
5007 DAE.T_REAL_DEFAULT,
5008 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5009 Absyn.IDENT("interval"));
5010
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("interval"), args, nargs, {}, impl, pre, info);
5011 then (cache, call, prop);
5012 end match;
5013 end elabBuiltinInterval;
5014
5015 protected function isBlockTypeWorkaround "
5016 Author: BTH
5017 Helper function to elabBuiltinTransition.
5018 This function checks whether a type is complex.
5019 It is used as a workaround to check for block instances in elabBuiltinTransition, elabBultinActiveState and elabBuiltinInitalState.
5020 This is not perfect since there are also other instances that are 'complex' types which are not block instances.
5021 But allowing more might not be so bad anyway, since the MLS 3.3 restriction to block seems more restrictive than necessary,
5022 e.g., one can be more lenient and allow models as states, too..."
5023 input DAE.Type ity;
5024 output Boolean b;
5025 algorithm
5026 b := match ity
5027 ✗ case DAE.T_SUBTYPE_BASIC() then isBlockTypeWorkaround(ity.complexType);
5028 case DAE.T_COMPLEX() then true;
5029 else false;
5030 end match;
5031 end isBlockTypeWorkaround;
5032
5033 protected function elabBuiltinTransition "
5034 Author: BTH
5035 This function elaborates the builtin operator
5036 transition(from, to, condition, immediate=true, reset=true, synchronize=false, priority=1)."
5037 input FCore.Cache inCache;
5038 input FCore.Graph inEnv;
5039 input list<Absyn.Exp> args;
5040 input list<Absyn.NamedArg> nargs;
5041 input Boolean inBoolean;
5042 input DAE.Prefix inPrefix;
5043 input SourceInfo info;
5044 output FCore.Cache outCache;
5045 output DAE.Exp outExp;
5046 output DAE.Properties outProperties;
5047 algorithm
5048 (outCache,outExp,outProperties) := match (inCache, inEnv, inBoolean, inPrefix)
5049 local
5050 DAE.Exp call;
5051 DAE.Type ty1,ty2,ty;
5052 Boolean impl;
5053 FCore.Graph env;
5054 FCore.Cache cache;
5055 DAE.Prefix pre;
5056 DAE.Properties prop;
5057 Integer n;
5058 String strMsg0,strPre,s1,s2;
5059 list<String> slist;
5060
5061 case (cache, env, impl, pre)
5062 algorithm
5063 16 slist := List.map(nargs,Dump.printNamedArgStr);
5064 16 s1 := Dump.printExpLstStr(args);
5065 16 s2 := stringDelimitList(s1 :: slist, ", ");
5066 16 strMsg0 := "transition(" + s2 + ")";
5067 16 strPre := PrefixUtil.printPrefixStr3(pre);
5068 16 n := listLength(args);
5069
5070 // Check if "from" and "to" arguments are of complex type and return their type
5071 16 ty1 := elabBuiltinTransition2(cache, env, args, nargs, impl, pre, info, "from", n, strMsg0, strPre);
5072 16 ty2 := elabBuiltinTransition2(cache, env, args, nargs, impl, pre, info, "to", n, strMsg0, strPre);
5073
5074 // Alternatively, ty1 and ty2 could be replaced by DAE.T_CODE(DAE.C_VARIABLENAME,{}), not sure if that would be a better solution
5075 32 ty := DAE.T_FUNCTION(
5076 {DAE.FUNCARG("from",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
5077 DAE.FUNCARG("to",ty2,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
5078 DAE.FUNCARG("condition",DAE.T_BOOL_DEFAULT,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE()),
5079 DAE.FUNCARG("immediate",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(true))),
5080 DAE.FUNCARG("reset",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(true))),
5081 DAE.FUNCARG("synchronize",DAE.T_BOOL_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.BCONST(false))),
5082 DAE.FUNCARG("priority",DAE.T_INTEGER_DEFAULT,DAE.C_PARAM(),DAE.NON_PARALLEL(),SOME(DAE.ICONST(1)))},
5083 DAE.T_NORETCALL_DEFAULT,
5084 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5085 Absyn.IDENT("transition"));
5086
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
✓ Branch 5 taken 16 times.
✗ Branch 6 not taken.
16 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("transition"), args, nargs, {}, impl, pre, info);
5087 then (cache, call, prop);
5088 end match;
5089 end elabBuiltinTransition;
5090
5091 protected function elabBuiltinTransition2 "
5092 Author: BTH
5093 Helper function to elabBuiltinTransition.
5094 Check if the \"from\" argument or the \"to\" argument is of complex type."
5095 input FCore.Cache inCache;
5096 input FCore.Graph inEnv;
5097 input list<Absyn.Exp> args;
5098 input list<Absyn.NamedArg> nargs;
5099 input Boolean inBoolean;
5100 input DAE.Prefix inPrefix;
5101 input SourceInfo info;
5102 input Absyn.Ident argName;
5103 input Integer n;
5104 input String strMsg0;
5105 input String strPre;
5106 output DAE.Type ty;
5107 protected
5108 Absyn.Exp arg1;
5109 DAE.Properties prop1;
5110 Integer nPos;
5111 String s1,s2,strPos,strMsg1;
5112 Boolean b1;
5113 algorithm
5114
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
32 strPos := if argName == "from" then "first" else "second";
5115
3/4
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 16 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 16 times.
32 nPos := if argName == "from" then 1 else 2;
5116 32 b1 := List.isMemberOnTrue(argName, nargs, elabBuiltinTransition3);
5117
5118 32 s1 := strMsg0 + ", named argument \"" + argName + "\" already has a value.";
5119 32 Error.assertionOrAddSourceMessage(not (b1 and n >= nPos),Error.WRONG_TYPE_OR_NO_OF_ARGS,
5120 {s1, strPre}, info);
5121
5122 32 s2 := strMsg0 + ", missing value for " + strPos + " argument \"" + argName + "\".";
5123 32 Error.assertionOrAddSourceMessage(b1 or n >= nPos, Error.WRONG_TYPE_OR_NO_OF_ARGS,
5124 {s2, strPre}, info);
5125
5126 32 arg1 := elabBuiltinTransition5(argName, b1, args, nargs);
5127 32 (_, _, prop1) := elabExpInExpression(inCache,inEnv,arg1,inBoolean,true,inPrefix,info);
5128 32 ty := Types.getPropType(prop1);
5129 32 strMsg1 := strMsg0 + ", " + strPos + "argument needs to be a block instance.";
5130 32 Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty),Error.WRONG_TYPE_OR_NO_OF_ARGS,
5131 {strMsg1, strPre}, info);
5132
5133 end elabBuiltinTransition2;
5134
5135
5136 protected function elabBuiltinTransition3 "
5137 Author: BTH
5138 Helper function to elabBuiltinTransition.
5139 Checks if namedArg.argName == name"
5140 input Absyn.Ident name;
5141 input Absyn.NamedArg namedArg;
5142 output Boolean outIsEqual;
5143 algorithm
5144 outIsEqual := match namedArg
5145 local
5146 Absyn.Ident argName;
5147
5148 case Absyn.NAMEDARG()
5149
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
70 then stringEq(name, namedArg.argName);
5150
5151 else false;
5152 end match;
5153 end elabBuiltinTransition3;
5154
5155 protected function elabBuiltinTransition4 "
5156 Author: BTH
5157 Helper function to elabBuiltinTransition.
5158 Extract element argValue."
5159 input Absyn.NamedArg inElement;
5160 output Absyn.Exp argValue;
5161 algorithm
5162 ✗ Absyn.NAMEDARG(argValue = argValue) := inElement;
5163 end elabBuiltinTransition4;
5164
5165 protected function elabBuiltinTransition5 "
5166 Author: BTH
5167 Helper function to elabBuiltinTransition."
5168 input String argName;
5169 input Boolean getAsNamedArg;
5170 input list<Absyn.Exp> args;
5171 input list<Absyn.NamedArg> nargs;
5172 output Absyn.Exp argValue;
5173 algorithm
5174 argValue := match (argName, getAsNamedArg)
5175 local
5176 Absyn.NamedArg namedArg;
5177
5178 case ("from", true)
5179 algorithm
5180 ✗ namedArg := List.getMemberOnTrue("from", nargs, elabBuiltinTransition3);
5181 then elabBuiltinTransition4(namedArg);
5182 case ("from", false)
5183 16 then listHead(args);
5184 case ("to", true)
5185 algorithm
5186 ✗ namedArg := List.getMemberOnTrue("to", nargs, elabBuiltinTransition3);
5187 then elabBuiltinTransition4(namedArg);
5188 case ("to", false)
5189 16 then listGet(args, 2);
5190 end match;
5191 end elabBuiltinTransition5;
5192
5193 protected function elabBuiltinInitialState "
5194 Author: BTH
5195 This function elaborates the builtin operator
5196 initialState(state)."
5197 input FCore.Cache inCache;
5198 input FCore.Graph inEnv;
5199 input list<Absyn.Exp> args;
5200 input list<Absyn.NamedArg> nargs;
5201 input Boolean inBoolean;
5202 input DAE.Prefix inPrefix;
5203 input SourceInfo info;
5204 output FCore.Cache outCache;
5205 output DAE.Exp outExp;
5206 output DAE.Properties outProperties;
5207 algorithm
5208 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
5209 local
5210 DAE.Exp call;
5211 DAE.Type ty1,ty;
5212 Boolean impl;
5213 FCore.Graph env;
5214 FCore.Cache cache;
5215 DAE.Prefix pre;
5216 DAE.Properties prop1,prop;
5217 Absyn.Exp astate;
5218 String strMsg, strPre;
5219
5220 case (cache, env, {astate}, {}, impl, pre)
5221 algorithm
5222 8 (cache,_, prop1) := elabExpInExpression(cache,env,astate,impl,true,pre,info);
5223 8 ty1 := Types.getPropType(prop1);
5224 8 strMsg := "initialState(" + Dump.printExpLstStr(args) + "), Argument needs to be a block instance.";
5225 8 strPre := PrefixUtil.printPrefixStr3(pre);
5226 8 Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty1),Error.WRONG_TYPE_OR_NO_OF_ARGS,
5227 {strMsg, strPre}, info);
5228
5229 16 ty := DAE.T_FUNCTION(
5230 {DAE.FUNCARG("state",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
5231 DAE.T_NORETCALL_DEFAULT,
5232 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5233 Absyn.IDENT("initialState"));
5234
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
8 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("initialState"), args, nargs, {}, impl, pre, info);
5235 then (cache, call, prop);
5236 end match;
5237 end elabBuiltinInitialState;
5238
5239 protected function elabBuiltinActiveState "
5240 Author: BTH
5241 This function elaborates the builtin operator
5242 activeState(state)."
5243 input FCore.Cache inCache;
5244 input FCore.Graph inEnv;
5245 input list<Absyn.Exp> args;
5246 input list<Absyn.NamedArg> nargs;
5247 input Boolean inBoolean;
5248 input DAE.Prefix inPrefix;
5249 input SourceInfo info;
5250 output FCore.Cache outCache;
5251 output DAE.Exp outExp;
5252 output DAE.Properties outProperties;
5253 algorithm
5254 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
5255 local
5256 DAE.Exp call;
5257 DAE.Type ty1,ty;
5258 Boolean impl;
5259 FCore.Graph env;
5260 FCore.Cache cache;
5261 DAE.Prefix pre;
5262 DAE.Properties prop1,prop;
5263 Absyn.Exp astate;
5264 String strMsg, strPre;
5265
5266 case (cache, env, {astate}, {}, impl, pre)
5267 algorithm
5268 4 (cache,_, prop1) := elabExpInExpression(cache,env,astate,impl,true,pre,info);
5269 4 ty1 := Types.getPropType(prop1);
5270 4 strMsg := "activeState(" + Dump.printExpLstStr(args) + "), Argument needs to be a block instance.";
5271 4 strPre := PrefixUtil.printPrefixStr3(pre);
5272 4 Error.assertionOrAddSourceMessage(isBlockTypeWorkaround(ty1), Error.WRONG_TYPE_OR_NO_OF_ARGS,
5273 {strMsg, strPre}, info);
5274
5275 8 ty := DAE.T_FUNCTION(
5276 {DAE.FUNCARG("state",ty1,DAE.C_VAR(),DAE.NON_PARALLEL(),NONE())},
5277 DAE.T_BOOL_DEFAULT,
5278 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5279 Absyn.IDENT("activeState"));
5280
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 4 times.
✗ Branch 6 not taken.
4 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("activeState"), args, nargs, {}, impl, pre, info);
5281 then (cache, call, prop);
5282 end match;
5283 end elabBuiltinActiveState;
5284
5285 protected function elabBuiltinTicksInState "
5286 Author: BTH
5287 This function elaborates the builtin operator
5288 ticksInState()."
5289 input FCore.Cache inCache;
5290 input FCore.Graph inEnv;
5291 input list<Absyn.Exp> args;
5292 input list<Absyn.NamedArg> nargs;
5293 input Boolean inBoolean;
5294 input DAE.Prefix inPrefix;
5295 input SourceInfo info;
5296 output FCore.Cache outCache;
5297 output DAE.Exp outExp;
5298 output DAE.Properties outProperties;
5299 algorithm
5300 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
5301 local
5302 DAE.Exp call;
5303 DAE.Type ty;
5304 Boolean impl;
5305 FCore.Graph env;
5306 FCore.Cache cache;
5307 DAE.Prefix pre;
5308 DAE.Properties prop;
5309
5310 case (cache, env, {}, {}, impl, pre)
5311 algorithm
5312 ty := DAE.T_FUNCTION(
5313 {},
5314 DAE.T_INTEGER_DEFAULT,
5315 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5316 Absyn.IDENT("ticksInState"));
5317
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
1 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("ticksInState"), args, nargs, {}, impl, pre, info);
5318 then (cache, call, prop);
5319 end match;
5320 end elabBuiltinTicksInState;
5321
5322 protected function elabBuiltinTimeInState "
5323 Author: BTH
5324 This function elaborates the builtin operator
5325 timeInState()."
5326 input FCore.Cache inCache;
5327 input FCore.Graph inEnv;
5328 input list<Absyn.Exp> args;
5329 input list<Absyn.NamedArg> nargs;
5330 input Boolean inBoolean;
5331 input DAE.Prefix inPrefix;
5332 input SourceInfo info;
5333 output FCore.Cache outCache;
5334 output DAE.Exp outExp;
5335 output DAE.Properties outProperties;
5336 algorithm
5337 (outCache,outExp,outProperties) := match (inCache, inEnv, args, nargs, inBoolean, inPrefix)
5338 local
5339 DAE.Exp call;
5340 DAE.Type ty;
5341 Boolean impl;
5342 FCore.Graph env;
5343 FCore.Cache cache;
5344 DAE.Prefix pre;
5345 DAE.Properties prop;
5346
5347 case (cache, env, {}, {}, impl, pre)
5348 algorithm
5349 ty := DAE.T_FUNCTION(
5350 {},
5351 DAE.T_REAL_DEFAULT,
5352 DAE.FUNCTION_ATTRIBUTES_BUILTIN_IMPURE,
5353 Absyn.IDENT("timeInState"));
5354
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
1 (cache,SOME((call,prop))) := elabCallArgs3(cache, env, {ty}, Absyn.IDENT("timeInState"), args, nargs, {}, impl, pre, info);
5355 then (cache, call, prop);
5356 end match;
5357 end elabBuiltinTimeInState;
5358
5359 protected function elabBuiltinBoolean
5360 "This function elaborates on the builtin operator boolean, which extracts
5361 the boolean value of a Real, Integer or Boolean value."
5362 input FCore.Cache inCache;
5363 input FCore.Graph inEnv;
5364 input list<Absyn.Exp> inPosArgs;
5365 input list<Absyn.NamedArg> inNamedArgs;
5366 input Boolean inImplicit;
5367 input DAE.Prefix inPrefix;
5368 input SourceInfo inInfo;
5369 output FCore.Cache outCache;
5370 output DAE.Exp outExp;
5371 output DAE.Properties outProperties;
5372 algorithm
5373 ✗ (outCache, outExp, outProperties) := verifyBuiltInHandlerType(inCache, inEnv,
5374 inPosArgs, inImplicit, Types.isIntegerOrRealOrBooleanOrSubTypeOfEither,
5375 "boolean", inPrefix, inInfo);
5376 end elabBuiltinBoolean;
5377
5378 protected function elabBuiltinIntegerEnum
5379 "This function elaborates on the builtin operator Integer for Enumerations, which extracts
5380 the Integer value of a Enumeration element."
5381 input FCore.Cache inCache;
5382 input FCore.Graph inEnv;
5383 input list<Absyn.Exp> inPosArgs;
5384 input list<Absyn.NamedArg> inNamedArg;
5385 input Boolean inImplicit;
5386 input DAE.Prefix inPrefix;
5387 input SourceInfo inInfo;
5388 output FCore.Cache outCache;
5389 output DAE.Exp outExp;
5390 output DAE.Properties outProperties;
5391 algorithm
5392 2 (outCache, outExp, outProperties) := verifyBuiltInHandlerType(inCache, inEnv,
5393 inPosArgs, inImplicit, Types.isEnumeration, "Integer", inPrefix, inInfo);
5394 end elabBuiltinIntegerEnum;
5395
5396 protected function elabBuiltinNoevent
5397 "The builtin operator noEvent makes sure that events are not generated for the
5398 expression."
5399 input FCore.Cache inCache;
5400 input FCore.Graph inEnv;
5401 input list<Absyn.Exp> inPosArgs;
5402 input list<Absyn.NamedArg> inNamedArgs;
5403 input Boolean inImplicit;
5404 input DAE.Prefix inPrefix;
5405 input SourceInfo inInfo;
5406 output FCore.Cache outCache;
5407 output DAE.Exp outExp;
5408 output DAE.Properties outProperties;
5409 protected
5410 Absyn.Exp e;
5411 algorithm
5412 132 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "noEvent", inInfo);
5413
5414 132 e := listHead(inPosArgs);
5415 132 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e,
5416 inImplicit, true, inPrefix, inInfo);
5417 132 outExp := Expression.makePureBuiltinCall("noEvent", {outExp}, DAE.T_BOOL_DEFAULT);
5418 end elabBuiltinNoevent;
5419
5420 protected function elabBuiltinEdge
5421 "This function handles the built in edge operator."
5422 input FCore.Cache inCache;
5423 input FCore.Graph inEnv;
5424 input list<Absyn.Exp> inPosArgs;
5425 input list<Absyn.NamedArg> inNamedArgs;
5426 input Boolean inImplicit;
5427 input DAE.Prefix inPrefix;
5428 input SourceInfo inInfo;
5429 output FCore.Cache outCache;
5430 output DAE.Exp outExp;
5431 output DAE.Properties outProperties;
5432 protected
5433 DAE.Type ty;
5434 DAE.Const c;
5435 String msg;
5436 algorithm
5437 9 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "edge", inInfo);
5438
5439 9 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv,
5440 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
5441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
9 DAE.PROP(ty, c) := outProperties;
5442
5443 // Print an error if the argument is not a Boolean.
5444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
9 if not Types.isScalarBoolean(ty) then
5445 ✗ msg := "edge(" + ExpressionBasics.printExpStr(outExp) + ")";
5446 ✗ Error.addSourceMessageAndFail(Error.TYPE_ERROR, {msg}, inInfo);
5447 end if;
5448
5449 // If the argument is a variable, make a call to edge. Otherwise the
5450 // expression is false.
5451
1/2
✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
9 if Types.isVar(c) then
5452 9 outExp := Expression.makePureBuiltinCall("edge", {outExp}, DAE.T_BOOL_DEFAULT);
5453 else
5454 ✗ outExp := DAE.BCONST(false);
5455 end if;
5456 end elabBuiltinEdge;
5457
5458 protected function elabBuiltinDer
5459 "This function handles the built in der operator."
5460 input FCore.Cache inCache;
5461 input FCore.Graph inEnv;
5462 input list<Absyn.Exp> inPosArgs;
5463 input list<Absyn.NamedArg> inNamedArgs;
5464 input Boolean inImplicit;
5465 input DAE.Prefix inPrefix;
5466 input SourceInfo inInfo;
5467 output FCore.Cache outCache;
5468 output DAE.Exp outExp;
5469 output DAE.Properties outProperties;
5470 protected
5471 DAE.Type ty;
5472 DAE.Const c;
5473 list<DAE.Dimension> dims;
5474 String exp_str, ty_str;
5475 algorithm
5476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4068 times.
4068 if FGraph.inFunctionScope(inEnv) then
5477 ✗ Error.addSourceMessageAndFail(Error.DERIVATIVE_FUNCTION_CONTEXT, {}, inInfo);
5478 end if;
5479
5480 4068 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "der", inInfo);
5481
5482 4068 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv,
5483 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
5484
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4050 times.
4050 DAE.PROP(ty, c) := outProperties;
5485
5486 // Make sure the argument's type is a subtype of Real.
5487
2/2
✓ Branch 2 taken 1 time.
✓ Branch 3 taken 4049 times.
4050 if not Types.isRealOrSubTypeReal(Types.arrayElementType(ty)) then
5488 1 exp_str := Dump.printExpStr(listHead(inPosArgs));
5489 1 ty_str := TypesDump.unparseTypeNoAttr(ty);
5490 1 Error.addSourceMessageAndFail(Error.DERIVATIVE_NON_REAL,
5491 {exp_str, ty_str}, inInfo);
5492 end if;
5493
5494
2/2
✓ Branch 1 taken 4045 times.
✓ Branch 2 taken 4 times.
4049 if Types.isVar(c) then
5495
1/2
✓ Branch 1 taken 4045 times.
✗ Branch 2 not taken.
4045 if Types.dimensionsKnown(ty) then
5496 // Use elabCallArgs to handle vectorization if possible.
5497 4045 (outCache, outExp, outProperties) := elabCallArgs(inCache, inEnv,
5498 Absyn.IDENT("der"), inPosArgs, {}, {}, inImplicit, inPrefix, inInfo);
5499 else
5500 // Otherwise just create a call to der.
5501 ✗ outExp := Expression.makePureBuiltinCall("der", {outExp},
5502 Types.simplifyType(ty));
5503 end if;
5504 else
5505 // der(constant) = 0.
5506 4 dims := TypesDump.getDimensions(ty);
5507 4 (outExp, ty) := Expression.makeZeroExpression(dims);
5508 4 outProperties := DAE.PROP(ty, DAE.C_CONST());
5509 end if;
5510 end elabBuiltinDer;
5511
5512 protected function elabBuiltinChange
5513 "This function handles the built in change operator."
5514 input FCore.Cache inCache;
5515 input FCore.Graph inEnv;
5516 input list<Absyn.Exp> inPosArgs;
5517 input list<Absyn.NamedArg> inNamedArgs;
5518 input Boolean inImplicit;
5519 input DAE.Prefix inPrefix;
5520 input SourceInfo inInfo;
5521 output FCore.Cache outCache;
5522 output DAE.Exp outExp;
5523 output DAE.Properties outProperties;
5524 protected
5525 Absyn.Exp e;
5526 String pre_str;
5527 DAE.Type ty;
5528 DAE.Const c;
5529 DAE.Attributes attr;
5530 DAE.ComponentRef cref;
5531 SCode.Variability var;
5532 algorithm
5533 44 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "change", inInfo);
5534
5535 44 e := listHead(inPosArgs);
5536
5537 // Check that the argument is a variable (i.e. a component reference).
5538
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if not AbsynUtil.isCref(e) then
5539 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5540 ✗ Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_VARIABLE,
5541 {"First", "change", pre_str}, inInfo);
5542 end if;
5543
5544 44 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv, e,
5545 inImplicit, true, inPrefix, inInfo);
5546
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 44 times.
44 DAE.PROP(ty, c) := outProperties;
5547
5548
1/2
✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
44 if Types.isSimpleType(ty) then
5549
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 44 times.
44 if Types.isParameterOrConstant(c) then
5550 // change(constant) = false
5551 ✗ outExp := DAE.BCONST(false);
5552 ✗ outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_CONST());
5553 elseif Types.isDiscreteType(ty) then
5554 // If the argument is discrete, make a call to change.
5555 44 outExp := Expression.makePureBuiltinCall("change", {outExp}, DAE.T_BOOL_DEFAULT);
5556 44 outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR());
5557 else
5558 // Workaround for discrete Reals. Does not handle Reals that become
5559 // discrete due to when-section.
5560 ✗ cref := Expression.getCrefFromCrefOrAsub(outExp);
5561 // Look up the component's variability.
5562 ✗ (outCache, attr) := Lookup.lookupVar(outCache, inEnv, cref);
5563 ✗ DAE.ATTR(variability = var) := attr;
5564
5565 ✗ if valueEq(var, SCode.DISCRETE()) then
5566 // If it's discrete, make a call to change.
5567 ✗ outExp := Expression.makePureBuiltinCall("change", {outExp}, DAE.T_BOOL_DEFAULT);
5568 ✗ outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR());
5569 else
5570 // Otherwise, print an error and fail.
5571 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5572 ✗ Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_DISCRETE_VAR,
5573 {"First", "change", pre_str}, inInfo);
5574 end if;
5575 end if;
5576 else
5577 // If the argument does not have a simple type, print an error and fail.
5578 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5579 ✗ Error.addSourceMessageAndFail(Error.TYPE_MUST_BE_SIMPLE,
5580 {"operand to change", pre_str}, inInfo);
5581 end if;
5582 end elabBuiltinChange;
5583
5584 protected function elabBuiltinCat
5585 "This function handles the built in cat operator."
5586 input FCore.Cache inCache;
5587 input FCore.Graph inEnv;
5588 input list<Absyn.Exp> inPosArgs;
5589 input list<Absyn.NamedArg> inNamedArgs;
5590 input Boolean inImplicit;
5591 input DAE.Prefix inPrefix;
5592 input SourceInfo inInfo;
5593 output FCore.Cache outCache;
5594 output DAE.Exp outExp;
5595 output DAE.Properties outProperties;
5596 protected
5597 DAE.Exp dim_exp;
5598 DAE.Properties dim_props;
5599 DAE.Type dim_ty, ty, result_ty;
5600 DAE.Const dim_c, arr_c, c;
5601 String pre_str, exp_str;
5602 Integer dim_int;
5603 list<DAE.Exp> arr_expl;
5604 list<DAE.Properties> arr_props;
5605 list<DAE.Type> arr_tys, tys;
5606 list<DAE.Dimension> dims;
5607 DAE.Dimension dim;
5608 algorithm
5609
2/4
✓ Branch 1 taken 69 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 69 times.
69 if listLength(inPosArgs) < 2 or not listEmpty(inNamedArgs) then
5610 ✗ Error.addSourceMessageAndFail(Error.WRONG_NO_OF_ARGS, {"cat"}, inInfo);
5611 end if;
5612
5613 // Elaborate the first argument, the dimension to concatenate along.
5614 69 (outCache, dim_exp, dim_props) := elabExpInExpression(inCache, inEnv,
5615 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
5616
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 69 times.
69 DAE.PROP(dim_ty, dim_c) := dim_props;
5617
5618 // The first argument must be an integer.
5619
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 69 times.
69 if not Types.isScalarInteger(dim_ty) then
5620 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5621 ✗ Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_INTEGER,
5622 {"First", "cat", pre_str}, inInfo);
5623 end if;
5624
5625 // Evaluate the first argument.
5626
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 69 times.
69 (outCache, Values.INTEGER(dim_int)) :=
5627 Ceval.ceval(inCache, inEnv, dim_exp, false, Absyn.MSG(inInfo));
5628
5629 // Elaborate the rest of the arguments, the arrays to concatenate.
5630 69 (outCache, arr_expl, arr_props) := elabExpList(outCache, inEnv,
5631 listRest(inPosArgs), inImplicit, true, inPrefix, inInfo);
5632
5633 // Type check the arguments and check that all dimensions except the one we
5634 // will concatenate along is equal.
5635
4/4
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
225 arr_tys := list(Types.getPropType(p) for p in arr_props);
5636
5/6
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 69 times.
225 ty :: tys := list(Types.makeNthDimUnknown(t, dim_int) for t in arr_tys);
5637 69 result_ty := List.fold1(tys, Types.arraySuperType, inInfo, ty);
5638
5639 try
5640 69 (arr_expl, arr_tys) := Types.matchTypes(arr_expl, arr_tys, result_ty, false);
5641 else
5642 // Mismatched types, print an error and fail.
5643 ✗ exp_str := stringDelimitList(list(Dump.printExpStr(e) for e in inPosArgs), ", ");
5644 ✗ exp_str := "cat(" + exp_str + ")";
5645 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5646 ✗ Error.addSourceMessageAndFail(Error.DIFFERENT_DIM_SIZE_IN_ARGUMENTS,
5647 {exp_str, pre_str}, inInfo);
5648 end try;
5649
5650 // Calculate the size of the concatenated dimension, and insert it in the
5651 // result type.
5652
4/4
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
225 dims := list(Types.getDimensionNth(t, dim_int) for t in arr_tys);
5653
7/8
✓ Branch 0 taken 156 times.
✓ Branch 1 taken 69 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 69 times.
✓ Branch 4 taken 69 times.
✓ Branch 5 taken 87 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 69 times.
225 dim := Expression.dimensionsAdd(d for d in dims);
5654 69 result_ty := Types.setDimensionNth(result_ty, dim, dim_int);
5655
5656 // Construct a call to cat.
5657 69 arr_c := elabArrayConst(arr_props);
5658 69 c := Types.constAnd(dim_c, arr_c);
5659 69 ty := Types.simplifyType(result_ty);
5660 69 outExp := Expression.makePureBuiltinCall("cat", dim_exp :: arr_expl, ty);
5661 69 outProperties := DAE.PROP(result_ty, c);
5662 end elabBuiltinCat;
5663
5664 protected function elabBuiltinIdentity
5665 "This function handles the built in identity operator."
5666 input FCore.Cache inCache;
5667 input FCore.Graph inEnv;
5668 input list<Absyn.Exp> inPosArgs;
5669 input list<Absyn.NamedArg> inNamedArgs;
5670 input Boolean inImplicit;
5671 input DAE.Prefix inPrefix;
5672 input SourceInfo inInfo;
5673 output FCore.Cache outCache;
5674 output DAE.Exp outExp;
5675 output DAE.Properties outProperties;
5676 protected
5677 DAE.Type ty, exp_ty;
5678 DAE.Const c;
5679 String pre_str;
5680 Absyn.Msg msg;
5681 Integer sz;
5682 DAE.Dimension dim_size;
5683 DAE.Exp dim_exp;
5684 Boolean check_model;
5685 algorithm
5686 84 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "identity", inInfo);
5687
5688 84 (outCache, dim_exp, outProperties) := elabExpInExpression(inCache, inEnv,
5689 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
5690
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
84 DAE.PROP(ty, c) := outProperties;
5691
5692 // Check that the argument is an Integer.
5693
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 83 times.
84 if not Types.isScalarInteger(ty) then
5694 1 pre_str := PrefixUtil.printPrefixStr3(inPrefix);
5695 1 Error.addSourceMessageAndFail(Error.ARGUMENT_MUST_BE_INTEGER,
5696 {"First", "identity", pre_str}, inInfo);
5697 end if;
5698
5699
2/2
✓ Branch 1 taken 80 times.
✓ Branch 2 taken 3 times.
83 if Types.isParameterOrConstant(c) then
5700 // If the argument is a parameter or constant, evaluate it.
5701 80 check_model := Flags.getConfigBool(Flags.CHECK_MODEL);
5702
2/2
✓ Branch 0 taken 77 times.
✓ Branch 1 taken 3 times.
80 msg := if check_model then Absyn.NO_MSG() else Absyn.MSG(inInfo);
5703
5704 try
5705
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 (outCache, Values.INTEGER(sz)) :=
5706 Ceval.ceval(outCache, inEnv, dim_exp, false, msg);
5707 80 dim_size := DAE.DIM_INTEGER(sz);
5708 80 dim_exp := DAE.ICONST(sz);
5709 else
5710 // Allow evaluation to fail if checkModel is used.
5711 ✗ if check_model then dim_size := DAE.DIM_UNKNOWN(); else fail(); end if;
5712 end try;
5713 else
5714 dim_size := DAE.DIM_UNKNOWN();
5715 end if;
5716
5717 83 ty := Types.liftArrayListDims(DAE.T_INTEGER_DEFAULT, {dim_size, dim_size});
5718 83 exp_ty := Types.simplifyType(ty);
5719 83 outExp := Expression.makePureBuiltinCall("identity", {dim_exp}, exp_ty);
5720 83 outProperties := DAE.PROP(ty, c);
5721 end elabBuiltinIdentity;
5722
5723 protected function zeroSizeOverconstrainedOperator
5724 input DAE.Exp inExp;
5725 input DAE.Exp inFExp;
5726 input SourceInfo inInfo;
5727 algorithm
5728 () := match inExp
5729 local String s;
5730
5731 case DAE.ARRAY(array = {})
5732 algorithm
5733 ✗ s := ExpressionBasics.printExpStr(inFExp);
5734 ✗ Error.addSourceMessage(Error.OVERCONSTRAINED_OPERATOR_SIZE_ZERO_RETURN_FALSE, {s}, inInfo);
5735 then
5736 ();
5737
5738 else ();
5739
5740 end match;
5741 end zeroSizeOverconstrainedOperator;
5742
5743 protected function elabBuiltinIsRoot
5744 "This function elaborates on the builtin operator Connections.isRoot."
5745 input FCore.Cache inCache;
5746 input FCore.Graph inEnv;
5747 input list<Absyn.Exp> inPosArgs;
5748 input list<Absyn.NamedArg> inNamedArgs;
5749 input Boolean inImplicit;
5750 input DAE.Prefix inPrefix;
5751 input SourceInfo inInfo;
5752 output FCore.Cache outCache;
5753 output DAE.Exp outExp;
5754 output DAE.Properties outProperties;
5755 protected
5756 DAE.Exp exp;
5757 algorithm
5758 151 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "Connections.isRoot", inInfo);
5759
5760 151 (outCache, exp) := elabExpInExpression(inCache, inEnv, listHead(inPosArgs),
5761 false, false, inPrefix, inInfo);
5762 151 outExp := DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("isRoot")),
5763 {exp}, DAE.callAttrBuiltinBool);
5764 outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR());
5765
5766 151 zeroSizeOverconstrainedOperator(exp, outExp, inInfo);
5767 end elabBuiltinIsRoot;
5768
5769 protected function elabBuiltinRooted
5770 "author: adrpo
5771 This function handles the built-in rooted operator. (MultiBody).
5772 See more here: http://trac.modelica.org/Modelica/ticket/95"
5773 input FCore.Cache inCache;
5774 input FCore.Graph inEnv;
5775 input list<Absyn.Exp> inPosArgs;
5776 input list<Absyn.NamedArg> inNamedArgs;
5777 input Boolean inImplicit;
5778 input DAE.Prefix inPrefix;
5779 input SourceInfo inInfo;
5780 output FCore.Cache outCache;
5781 output DAE.Exp outExp;
5782 output DAE.Properties outProperties;
5783 protected
5784 DAE.Exp exp;
5785 algorithm
5786 // this operator is not even specified in the specification!
5787 // see: http://trac.modelica.org/Modelica/ticket/95
5788 128 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "rooted", inInfo);
5789
5790 128 (outCache, exp) := elabExpInExpression(inCache, inEnv, listHead(inPosArgs),
5791 false, false, inPrefix, inInfo);
5792 128 outExp := DAE.CALL(Absyn.IDENT("rooted"), {exp}, DAE.callAttrBuiltinBool);
5793 outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR());
5794
5795 128 zeroSizeOverconstrainedOperator(exp, outExp, inInfo);
5796 end elabBuiltinRooted;
5797
5798 protected function elabBuiltinUniqueRootIndices
5799 "This function elaborates on the builtin operator Connections.uniqueRootIndices.
5800 TODO: assert size(second arg) <= size(first arg)
5801 See Modelica_StateGraph2:
5802 https://github.com/modelica/Modelica_StateGraph2
5803 and
5804 https://trac.modelica.org/Modelica/ticket/984
5805 and
5806 http://www.ep.liu.se/ecp/043/041/ecp09430108.pdf
5807 for a specification of this operator"
5808 input FCore.Cache inCache;
5809 input FCore.Graph inEnv;
5810 input list<Absyn.Exp> inAbsynExpLst;
5811 input list<Absyn.NamedArg> inNamedArg;
5812 input Boolean inBoolean;
5813 input DAE.Prefix inPrefix;
5814 input SourceInfo info;
5815 output FCore.Cache outCache;
5816 output DAE.Exp outExp;
5817 output DAE.Properties outProperties;
5818 algorithm
5819 (outCache,outExp,outProperties):=
5820 match (inCache, inEnv, inAbsynExpLst, inNamedArg, inPrefix)
5821 local
5822 FCore.Graph env;
5823 FCore.Cache cache;
5824 Absyn.Exp aexp1, aexp2;
5825 DAE.Exp exp1, exp2, exp3;
5826 DAE.Prefix pre;
5827 list<DAE.Exp> lst;
5828 Integer dim;
5829 DAE.Type ty;
5830
5831 case (cache, env, {aexp1,aexp2}, {}, pre)
5832 algorithm
5833 ✗ (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info);
5834 ✗ dim := listLength(lst);
5835 ✗ (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info);
5836 ✗ exp3 := DAE.SCONST("");
5837 ✗ ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)});
5838 ✗ then
5839 (cache,
5840 DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3},
5841 DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),
5842 DAE.PROP(ty, DAE.C_VAR()));
5843
5844 case (cache, env, {aexp1,aexp2,_}, {}, pre)
5845 algorithm
5846 ✗ (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info);
5847 ✗ dim := listLength(lst);
5848 ✗ (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info);
5849 ✗ (cache,exp3,_) := elabExpInExpression(cache, env, aexp2, false, false, pre, info);
5850 ✗ ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)});
5851 ✗ then
5852 (cache,
5853 DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3},
5854 DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),
5855 DAE.PROP(ty, DAE.C_VAR()));
5856
5857 case (cache, env, {aexp1,aexp2}, {Absyn.NAMEDARG("message", _)}, pre)
5858 algorithm
5859 ✗ (cache,exp1 as DAE.ARRAY(array = lst),_) := elabExpInExpression(cache, env, aexp1, false, false, pre, info);
5860 ✗ dim := listLength(lst);
5861 ✗ (cache,exp2,_) := elabExpInExpression(cache, env, aexp2, false,false,pre,info);
5862 ✗ (cache,exp3,_) := elabExpInExpression(cache, env, aexp2, false,false,pre,info);
5863 ✗ ty := DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_INTEGER(dim)});
5864 ✗ then
5865 (cache,
5866 DAE.CALL(Absyn.QUALIFIED("Connections", Absyn.IDENT("uniqueRootIndices")), {exp1, exp2, exp3},
5867 DAE.CALL_ATTR(ty,false,true,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),
5868 DAE.PROP(ty, DAE.C_VAR()));
5869
5870 end match;
5871 end elabBuiltinUniqueRootIndices;
5872
5873 protected function elabBuiltinScalar
5874 "This function handles the built in scalar operator.
5875 For example, scalar({1}) => 1 or scalar({a}) => a"
5876 input FCore.Cache inCache;
5877 input FCore.Graph inEnv;
5878 input list<Absyn.Exp> inPosArgs;
5879 input list<Absyn.NamedArg> inNamedArgs;
5880 input Boolean inImplicit;
5881 input DAE.Prefix inPrefix;
5882 input SourceInfo inInfo;
5883 output FCore.Cache outCache;
5884 output DAE.Exp outExp;
5885 output DAE.Properties outProperties;
5886 protected
5887 DAE.Type ty, scalar_ty;
5888 DAE.Const c;
5889 list<DAE.Dimension> dims;
5890 String ty_str;
5891 algorithm
5892 1 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "scalar", inInfo);
5893
5894
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 (outCache, outExp, DAE.PROP(ty, c)) := elabExpInExpression(inCache, inEnv,
5895 listHead(inPosArgs), inImplicit, true, inPrefix, inInfo);
5896
5897 1 (scalar_ty, dims) := TypesDump.flattenArrayType(ty);
5898
5899 // Check that any known dimensions have size 1.
5900
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 1 time.
2 for dim in dims loop
5901
1/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 if Expression.dimensionKnown(dim) and Expression.dimensionSize(dim) <> 1 then
5902 ✗ ty_str := TypesDump.unparseTypeNoAttr(ty);
5903 ✗ Error.addSourceMessageAndFail(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP,
5904 {ty_str}, inInfo);
5905 end if;
5906 end for;
5907
5908 // If the argument is an array, make a call to scalar. Otherwise the
5909 // expression is already a scalar, so return it as it is.
5910
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 if not listEmpty(dims) then
5911 1 outExp := Expression.makePureBuiltinCall("scalar", {outExp}, scalar_ty);
5912 end if;
5913
5914 1 outExp := ExpressionSimplify.simplify1(outExp);
5915 1 outProperties := DAE.PROP(scalar_ty, c);
5916 end elabBuiltinScalar;
5917
5918 constant Slot STRING_ARG_MINLENGTH = SLOT(DAE.FUNCARG("minimumLength",
5919 DAE.T_INTEGER_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false,
5920 SOME(DAE.ICONST(0)), {}, 2, SLOT_NOT_EVALUATED);
5921
5922 constant Slot STRING_ARG_LEFTJUSTIFIED = SLOT(DAE.FUNCARG("leftJustified",
5923 DAE.T_BOOL_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false,
5924 SOME(DAE.BCONST(true)), {}, 3, SLOT_NOT_EVALUATED);
5925
5926 constant Slot STRING_ARG_SIGNIFICANT_DIGITS = SLOT(DAE.FUNCARG("significantDigits",
5927 DAE.T_INTEGER_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE()), false,
5928 SOME(DAE.ICONST(6)), {}, 4, SLOT_NOT_EVALUATED);
5929
5930 protected function elabBuiltinString "
5931 author: PA
5932 This function handles the built-in String operator."
5933 input FCore.Cache inCache;
5934 input FCore.Graph inEnv;
5935 input list<Absyn.Exp> inPosArgs;
5936 input list<Absyn.NamedArg> inNamedArgs;
5937 input Boolean inImplicit;
5938 input DAE.Prefix inPrefix;
5939 input SourceInfo inInfo;
5940 output FCore.Cache outCache;
5941 output DAE.Exp outExp;
5942 output DAE.Properties outProperties;
5943 protected
5944 Absyn.Exp e;
5945 DAE.Exp exp;
5946 DAE.Type ty;
5947 DAE.Const c;
5948 list<DAE.Exp> args;
5949 list<DAE.Const> consts;
5950 Slot val_slot;
5951 Option<DAE.Exp> format_arg = NONE();
5952 list<Slot> slots;
5953 algorithm
5954 try
5955 // Check if 'String' is overloaded.
5956 1486 e := Absyn.CALL(Absyn.CREF_IDENT("String", {}),
5957 Absyn.FUNCTIONARGS(inPosArgs, inNamedArgs), {});
5958 1486 (outCache, outExp, outProperties) := OperatorOverloading.string(inCache,
5959 inEnv, e, inImplicit, true, inPrefix, inInfo);
5960 else
5961 // Elaborate the first argument so we know what type we're dealing with.
5962 1485 e := listHead(inPosArgs);
5963
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1485 times.
1485 (outCache, exp, DAE.PROP(ty, c)) :=
5964 elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo);
5965
5966
2/2
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 1481 times.
1485 if Types.isMetaBoxedType(ty) then
5967 4 ty := Types.unboxedType(ty);
5968 4 exp := DAE.UNBOX(exp, ty);
5969 end if;
5970
5971 1485 val_slot := SLOT(DAE.FUNCARG("x", ty, DAE.C_VAR(), DAE.NON_PARALLEL(),
5972 NONE()), false, NONE(), {}, 1, SLOT_NOT_EVALUATED);
5973
5974 try // Try the String(val, <option>) format.
5975 slots := {STRING_ARG_MINLENGTH, STRING_ARG_LEFTJUSTIFIED};
5976
5977 // Only String(Real) has the significantDigits option.
5978
2/2
✓ Branch 1 taken 893 times.
✓ Branch 2 taken 592 times.
1485 if Types.isRealOrSubTypeReal(ty) then
5979 slots := STRING_ARG_SIGNIFICANT_DIGITS :: slots;
5980 end if;
5981
5982 slots := val_slot :: slots;
5983
5984 1485 (outCache, args, _, consts) := elabInputArgs(outCache, inEnv, inPosArgs, inNamedArgs,
5985 slots, false, true, inImplicit,
5986 inPrefix, inInfo, DAE.T_UNKNOWN_DEFAULT, Absyn.IDENT("String"));
5987 else
5988 // Try the String(val, format = s) format.
5989
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if Types.isRealOrSubTypeReal(ty) then
5990 format_arg := SOME(DAE.SCONST("f"));
5991 elseif Types.isIntegerOrSubTypeInteger(ty) then
5992 format_arg := SOME(DAE.SCONST("d"));
5993 elseif Types.isString(ty) then
5994 format_arg := SOME(DAE.SCONST("s"));
5995 else
5996 format_arg := NONE();
5997 end if;
5998
5999
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
1 if isSome(format_arg) then
6000 1 slots := {val_slot, SLOT(DAE.FUNCARG("format", DAE.T_STRING_DEFAULT, DAE.C_VAR(),
6001 DAE.NON_PARALLEL(), NONE()), false, format_arg, {}, 2,
6002 SLOT_NOT_EVALUATED)};
6003 else
6004 slots := {val_slot};
6005 end if;
6006
6007 1 (outCache, args, _, consts) := elabInputArgs(outCache, inEnv, inPosArgs, inNamedArgs,
6008 slots, false, true, inImplicit,
6009 inPrefix, inInfo, DAE.T_UNKNOWN_DEFAULT, Absyn.IDENT("String"));
6010 end try;
6011
6012 1485 c := List.fold(consts, Types.constAnd, DAE.C_CONST());
6013 1485 outExp := Expression.makePureBuiltinCall("String", args, DAE.T_STRING_DEFAULT);
6014 1485 outProperties := DAE.PROP(DAE.T_STRING_DEFAULT, c);
6015 end try;
6016 end elabBuiltinString;
6017
6018 protected function elabBuiltinGetInstanceName
6019 input FCore.Cache inCache;
6020 input FCore.Graph inEnv;
6021 input list<Absyn.Exp> inPosArgs;
6022 input list<Absyn.NamedArg> inNamedArgs;
6023 input Boolean inImplicit;
6024 input DAE.Prefix inPrefix;
6025 input SourceInfo inInfo;
6026 output FCore.Cache outCache = inCache;
6027 output DAE.Exp outExp;
6028 output DAE.Properties outProperties;
6029 protected
6030 String str;
6031 Absyn.Path name, envName;
6032 algorithm
6033 5 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 0, "getInstanceName", inInfo);
6034
6035
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 FCore.CACHE(modelName = name) := inCache;
6036
6037
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 if PrefixUtil.isNoPrefix(inPrefix) then
6038 5 envName := FGraph.getGraphNameNoImplicitScopes(inEnv);
6039
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 str := if AbsynUtil.pathEqual(envName, name) then
6040 AbsynUtil.pathLastIdent(name) else AbsynUtil.pathString(envName);
6041 else
6042 ✗ str := AbsynUtil.pathLastIdent(name) + "." + PrefixUtil.printPrefixStr(inPrefix);
6043 end if;
6044
6045 5 outExp := DAE.SCONST(str);
6046 outProperties := DAE.PROP(DAE.T_STRING_DEFAULT, DAE.C_CONST());
6047 end elabBuiltinGetInstanceName;
6048
6049 protected function elabBuiltinIsPresent
6050 input FCore.Cache inCache;
6051 input FCore.Graph inEnv;
6052 input list<Absyn.Exp> inPosArgs;
6053 input list<Absyn.NamedArg> inNamedArgs;
6054 input Boolean inImplicit;
6055 input DAE.Prefix inPrefix;
6056 input SourceInfo info;
6057 output FCore.Cache outCache = inCache;
6058 output DAE.Exp outExp;
6059 output DAE.Properties outProperties;
6060 protected
6061 String str;
6062 Absyn.Direction direction;
6063 Absyn.Exp exp;
6064 algorithm
6065 2 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "isPresent", info);
6066
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 if not FGraph.inFunctionScope(inEnv) then
6067 ✗ Error.addSourceMessage(Error.IS_PRESENT_WRONG_SCOPE, {SCodeDump.restrString(FGraph.getScopeRestriction(FGraph.currentScope(inEnv)))}, info);
6068 end if;
6069 outExp := match listGet(inPosArgs, 1)
6070 case Absyn.CREF(Absyn.CREF_IDENT(name=str))
6071 algorithm
6072 2 (outCache, DAE.TYPES_VAR(attributes=DAE.ATTR(direction=direction)), _, _, _, _) := Lookup.lookupIdentLocal(outCache, inEnv, str);
6073 () := match direction
6074 case Absyn.BIDIR()
6075 algorithm
6076 ✗ Error.addSourceMessage(Error.IS_PRESENT_WRONG_DIRECTION, {}, info);
6077 ✗ then fail();
6078 else ();
6079 end match;
6080 4 then Expression.makeImpureBuiltinCall("isPresent", DAE.CREF(DAE.CREF_IDENT(str, DAE.T_BOOL_DEFAULT, {}), DAE.T_BOOL_DEFAULT)::{}, DAE.T_BOOL_DEFAULT);
6081 case exp
6082 algorithm
6083 ✗ Error.addSourceMessage(Error.IS_PRESENT_INVALID_EXP, {Dump.printExpStr(exp)}, info);
6084 ✗ then fail();
6085 end match;
6086
6087 outProperties := DAE.PROP(DAE.T_BOOL_DEFAULT, DAE.C_VAR());
6088 end elabBuiltinIsPresent;
6089
6090 protected function elabBuiltinVector
6091 "This function handles the built in vector operator."
6092 input FCore.Cache inCache;
6093 input FCore.Graph inEnv;
6094 input list<Absyn.Exp> inPosArgs;
6095 input list<Absyn.NamedArg> inNamedArgs;
6096 input Boolean inImplicit;
6097 input DAE.Prefix inPrefix;
6098 input SourceInfo inInfo;
6099 output FCore.Cache outCache;
6100 output DAE.Exp outExp;
6101 output DAE.Properties outProperties;
6102 protected
6103 Absyn.Exp e;
6104 DAE.Type ty, arr_ty, exp_ty, el_ty;
6105 DAE.Const c;
6106 list<DAE.Exp> expl;
6107 algorithm
6108 107 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "vector", inInfo);
6109
6110 107 e := listHead(inPosArgs);
6111
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 (outCache, outExp, outProperties as DAE.PROP(ty, c)) :=
6112 elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo);
6113
6114 // Scalar
6115
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 107 times.
107 if Types.isSimpleType(ty) then
6116 // vector(scalar) = {scalar}
6117 ✗ arr_ty := Types.liftArray(ty, DAE.DIM_INTEGER(1));
6118 ✗ exp_ty := Types.simplifyType(arr_ty);
6119 ✗ outExp := DAE.ARRAY(exp_ty, true, {outExp});
6120 ✗ outProperties := DAE.PROP(arr_ty, c);
6121 // Array or Matrix
6122 elseif Expression.isArray(outExp) or Expression.isMatrix(outExp) then
6123 // If the array/matrix has more than one dimension, flatten it into a one-
6124 // dimensional array. Otherwise, do nothing and return the expression as is.
6125
2/2
✓ Branch 1 taken 105 times.
✓ Branch 2 taken 2 times.
107 if Types.numberOfDimensions(ty) <> 1 then
6126 105 checkBuiltinVectorDims(e, inEnv, ty, inPrefix, inInfo);
6127 105 expl := Expression.getArrayOrMatrixContents(outExp);
6128 105 expl := flattenArray(expl);
6129
6130 105 el_ty := Types.arrayElementType(ty);
6131 105 arr_ty := Types.liftArray(el_ty, DAE.DIM_INTEGER(listLength(expl)));
6132
6133 105 outExp := DAE.ARRAY(Types.simplifyType(arr_ty), false, expl);
6134 105 outProperties := DAE.PROP(arr_ty, c);
6135 end if;
6136 // Anything else
6137 else
6138 // For any other type of expression, make a call to vector.
6139 ✗ ty := Types.liftArray(Types.arrayElementType(ty), DAE.DIM_UNKNOWN());
6140 ✗ exp_ty := Types.simplifyType(ty);
6141 ✗ outExp := Expression.makePureBuiltinCall("vector", {outExp}, exp_ty);
6142 ✗ outProperties := DAE.PROP(ty, c);
6143 end if;
6144 end elabBuiltinVector;
6145
6146 protected function checkBuiltinVectorDims
6147 "Checks that the argument to vector has at most one dimension which is larger
6148 than one, otherwise prints an error and fails."
6149 input Absyn.Exp inExp;
6150 input FCore.Graph inEnv;
6151 input DAE.Type inType;
6152 input DAE.Prefix inPrefix;
6153 input SourceInfo inInfo;
6154 protected
6155 Boolean found_dim_sz_one = false;
6156 list<Integer> dims;
6157 String arg_str, scope_str, dim_str, pre_str;
6158 algorithm
6159 105 dims := Types.getDimensionSizes(inType);
6160
6161
2/2
✓ Branch 0 taken 211 times.
✓ Branch 1 taken 105 times.
316 for dim in dims loop
6162
2/2
✓ Branch 0 taken 105 times.
✓ Branch 1 taken 106 times.
211 if dim > 1 then
6163
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 105 times.
105 if found_dim_sz_one then
6164 ✗ scope_str := FGraph.printGraphPathStr(inEnv);
6165 ✗ arg_str := "vector(" + Dump.printExpStr(inExp) + ")";
6166 ✗ dim_str := "[" + stringDelimitList(list(intString(d) for d in dims), ", ") + "]";
6167 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
6168 ✗ Error.addSourceMessageAndFail(Error.BUILTIN_VECTOR_INVALID_DIMENSIONS,
6169 {scope_str, pre_str, dim_str, arg_str}, inInfo);
6170 else
6171 found_dim_sz_one := true;
6172 end if;
6173 end if;
6174 end for;
6175 end checkBuiltinVectorDims;
6176
6177 protected function flattenArray
6178 input list<DAE.Exp> arr;
6179 output list<DAE.Exp> flattenedExpl;
6180 algorithm
6181 flattenedExpl := match arr
6182 local
6183 DAE.Exp e;
6184 list<DAE.Exp> expl, expl2, rest_expl;
6185
6186 case {} then {};
6187
6188 case DAE.ARRAY(array = expl) :: rest_expl
6189 algorithm
6190 308 expl := flattenArray(expl);
6191 308 expl2 := flattenArray(rest_expl);
6192 308 expl2 := listAppend(expl, expl2);
6193 then expl2;
6194
6195 case DAE.MATRIX(matrix = {{e}}) :: rest_expl
6196 algorithm
6197 4 expl := flattenArray(rest_expl);
6198 then
6199 (e :: expl);
6200
6201 case e :: expl
6202 algorithm
6203 308 expl := flattenArray(expl);
6204 then
6205 (e :: expl);
6206 end match;
6207 end flattenArray;
6208
6209 public function elabBuiltinMatrix
6210 "Elaborates the builtin matrix function."
6211 input FCore.Cache inCache;
6212 input FCore.Graph inEnv;
6213 input list<Absyn.Exp> inPosArgs;
6214 input list<Absyn.NamedArg> inNamedArgs;
6215 input Boolean inImpl;
6216 input DAE.Prefix inPrefix;
6217 input SourceInfo inInfo;
6218 output FCore.Cache outCache;
6219 output DAE.Exp outExp;
6220 output DAE.Properties outProperties;
6221 protected
6222 DAE.Type ty;
6223 algorithm
6224 39 checkBuiltinCallArgs(inPosArgs, inNamedArgs, 1, "matrix", inInfo);
6225
6226 39 (outCache, outExp, outProperties) := elabExpInExpression(inCache, inEnv,
6227 listHead(inPosArgs), inImpl, true, inPrefix, inInfo);
6228 39 ty := Types.getPropType(outProperties);
6229 39 (outExp, outProperties) := elabBuiltinMatrix2(inCache, inEnv, outExp,
6230 outProperties, ty, inInfo);
6231 end elabBuiltinMatrix;
6232
6233 protected function elabBuiltinMatrix2
6234 "Helper function to elabBuiltinMatrix, evaluates the matrix function given the
6235 elaborated argument."
6236 input FCore.Cache inCache;
6237 input FCore.Graph inEnv;
6238 input DAE.Exp inArg;
6239 input DAE.Properties inProperties;
6240 input DAE.Type inType;
6241 input SourceInfo inInfo;
6242 output DAE.Exp outExp;
6243 output DAE.Properties outProperties;
6244 algorithm
6245 (outExp, outProperties) := match inArg
6246 local
6247 DAE.Type ty;
6248 DAE.Exp exp;
6249 DAE.Properties props;
6250 list<DAE.Exp> expl;
6251 DAE.Type ety;
6252 DAE.Dimension dim1, dim2;
6253 Boolean scalar;
6254
6255 // Scalar
6256 case _ guard(Types.isSimpleType(inType))
6257 algorithm
6258 1 (exp, props) := promoteExp(inArg, inProperties, 2);
6259 then
6260 (exp, props);
6261
6262 // 1-dimensional array
6263 case _ guard(Types.numberOfDimensions(inType) == 1)
6264 algorithm
6265 38 (exp, props) := promoteExp(inArg, inProperties, 2);
6266 then
6267 (exp, props);
6268
6269 // Matrix
6270 case DAE.MATRIX()
6271 ✗ then (inArg, inProperties);
6272
6273 // n-dimensional array
6274 case DAE.ARRAY(ty = DAE.T_ARRAY(ety, dim1 :: dim2 :: _), scalar = scalar, array = expl)
6275 algorithm
6276 ✗ expl := List.map1(expl, elabBuiltinMatrix3, inInfo);
6277 ✗ ty := Types.arrayElementType(inType);
6278 ✗ ty := Types.liftArrayListDims(ty, {dim1, dim2});
6279 ✗ props := Types.setPropType(inProperties, ty);
6280 ✗ then
6281 (DAE.ARRAY(DAE.T_ARRAY(ety, {dim1, dim2}), scalar, expl), props);
6282
6283 end match;
6284 end elabBuiltinMatrix2;
6285
6286 protected function elabBuiltinMatrix3
6287 "Helper function to elabBuiltinMatrix2."
6288 input DAE.Exp inExp;
6289 input SourceInfo inInfo;
6290 output DAE.Exp outExp;
6291 algorithm
6292 outExp := match inExp
6293 local
6294 DAE.Type ety, ety2;
6295 Boolean scalar;
6296 list<DAE.Exp> expl;
6297 DAE.Dimension dim;
6298 DAE.Dimensions dims;
6299 list<list<DAE.Exp>> matrix_expl;
6300
6301 case DAE.ARRAY(ty = DAE.T_ARRAY(ety, dim :: _),scalar = scalar, array = expl)
6302 algorithm
6303 ✗ expl := list(arrayScalar(e, 3, "matrix", inInfo) for e in expl);
6304 ✗ then
6305 DAE.ARRAY(DAE.T_ARRAY(ety, {dim}), scalar, expl);
6306
6307 case DAE.MATRIX(ty = DAE.T_ARRAY(ety, dim :: dims), matrix = matrix_expl)
6308 algorithm
6309 ✗ ety2 := DAE.T_ARRAY(ety, dims);
6310 ✗ expl := list(Expression.makeArray(e, ety2, true) for e in matrix_expl);
6311 ✗ expl := list(arrayScalar(e, 3, "matrix", inInfo) for e in expl);
6312 ✗ then
6313 DAE.ARRAY(DAE.T_ARRAY(ety, {dim}), true, expl);
6314
6315 end match;
6316 end elabBuiltinMatrix3;
6317
6318 protected function arrayScalar
6319 "Returns the scalar value of an array, or prints an error message and fails if
6320 any dimension of the array isn't of size 1."
6321 input DAE.Exp inExp;
6322 input Integer inDim "The current dimension, used for error message.";
6323 input String inOperator "The current operator name, used for error message.";
6324 input SourceInfo inInfo;
6325 output DAE.Exp outExp;
6326 algorithm
6327 outExp := match inExp
6328 local
6329 DAE.Exp exp;
6330 DAE.Type ty;
6331 list<DAE.Exp> expl;
6332 list<list<DAE.Exp>> mexpl;
6333 String dim_str, size_str;
6334
6335 // An array with one element.
6336 case DAE.ARRAY(array = {exp})
6337 ✗ then arrayScalar(exp, inDim + 1, inOperator, inInfo);
6338
6339 // Any other array.
6340 case DAE.ARRAY(array = expl)
6341 algorithm
6342 ✗ dim_str := intString(inDim);
6343 ✗ size_str := intString(listLength(expl));
6344 ✗ Error.addSourceMessage(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP,
6345 {dim_str, inOperator, "1", size_str}, inInfo);
6346 ✗ then
6347 fail();
6348
6349 // A matrix where the first dimension is 1.
6350 case DAE.MATRIX(ty = ty, matrix = {expl})
6351 ✗ then arrayScalar(DAE.ARRAY(ty, true, expl), inDim + 1, inOperator, inInfo);
6352
6353 // Any other matrix.
6354 case DAE.MATRIX(matrix = mexpl)
6355 algorithm
6356 ✗ dim_str := intString(inDim);
6357 ✗ size_str := intString(listLength(mexpl));
6358 ✗ Error.addSourceMessage(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP,
6359 {dim_str, inOperator, "1", size_str}, inInfo);
6360 ✗ then
6361 fail();
6362
6363 // Anything else is assumed to be a scalar.
6364 else inExp;
6365 end match;
6366 end arrayScalar;
6367
6368 public function elabBuiltinHandler
6369 "This function dispatches the elaboration of builtin operators by returning
6370 the appropriate function. When a new builtin operator is added, a new rule
6371 has to be added to this function."
6372 input String inIdent;
6373 output HandlerFunc outHandler;
6374
6375 partial function HandlerFunc
6376 input FCore.Cache inCache;
6377 input FCore.Graph inEnv;
6378 input list<Absyn.Exp> inAbsynExpLst;
6379 input list<Absyn.NamedArg> inNamedArg;
6380 input Boolean inBoolean;
6381 input DAE.Prefix inPrefix;
6382 input SourceInfo info;
6383 output FCore.Cache outCache;
6384 output DAE.Exp outExp;
6385 output DAE.Properties outProperties;
6386 end HandlerFunc;
6387 algorithm
6388 outHandler := match inIdent
6389 case "smooth" then elabBuiltinSmooth;
6390 case "size" then elabBuiltinSize;
6391 case "ndims" then elabBuiltinNDims;
6392 case "zeros" then elabBuiltinZeros;
6393 case "ones" then elabBuiltinOnes;
6394 case "fill" then elabBuiltinFill;
6395 case "max" then elabBuiltinMax;
6396 case "min" then elabBuiltinMin;
6397 case "transpose" then elabBuiltinTranspose;
6398 case "symmetric" then elabBuiltinSymmetric;
6399 case "array" then elabBuiltinArray;
6400 case "sum" then elabBuiltinSum;
6401 case "product" then elabBuiltinProduct;
6402 case "pre" then elabBuiltinPre;
6403 case "firstTick" then elabBuiltinFirstTick;
6404 case "interval" then elabBuiltinInterval;
6405 case "boolean" then elabBuiltinBoolean;
6406 case "noEvent" then elabBuiltinNoevent;
6407 case "edge" then elabBuiltinEdge;
6408 case "der" then elabBuiltinDer;
6409 case "change" then elabBuiltinChange;
6410 case "cat" then elabBuiltinCat;
6411 case "identity" then elabBuiltinIdentity;
6412 case "vector" then elabBuiltinVector;
6413 case "matrix" then elabBuiltinMatrix;
6414 case "scalar" then elabBuiltinScalar;
6415 case "String" then elabBuiltinString;
6416 case "rooted" then elabBuiltinRooted;
6417 case "Integer" then elabBuiltinIntegerEnum;
6418 case "EnumToInteger" then elabBuiltinIntegerEnum;
6419 case "inStream" then elabBuiltinInStream;
6420 case "actualStream" then elabBuiltinActualStream;
6421 case "getInstanceName" then elabBuiltinGetInstanceName;
6422 case "classDirectory" then elabBuiltinClassDirectory;
6423 case "sample" then elabBuiltinSample;
6424 case "cardinality" then elabBuiltinCardinality;
6425 case "homotopy" then elabBuiltinHomotopy;
6426 case "DynamicSelect" then elabBuiltinDynamicSelect;
6427 case "Clock"
6428 algorithm
6429
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
108 true := Config.synchronousFeaturesAllowed();
6430 then elabBuiltinClock;
6431 case "hold"
6432 algorithm
6433
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
26 true := Config.synchronousFeaturesAllowed();
6434 then elabBuiltinHold;
6435 case "shiftSample"
6436 algorithm
6437
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 true := Config.synchronousFeaturesAllowed();
6438 then elabBuiltinShiftSample;
6439 case "backSample"
6440 algorithm
6441
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
12 true := Config.synchronousFeaturesAllowed();
6442 then elabBuiltinBackSample;
6443 case "noClock"
6444 algorithm
6445
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 true := Config.synchronousFeaturesAllowed();
6446 then elabBuiltinNoClock;
6447 case "transition"
6448 algorithm
6449
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32 times.
32 true := Config.synchronousFeaturesAllowed();
6450 then elabBuiltinTransition;
6451 case "initialState"
6452 algorithm
6453
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
16 true := Config.synchronousFeaturesAllowed();
6454 then elabBuiltinInitialState;
6455 case "activeState"
6456 algorithm
6457
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8 times.
8 true := Config.synchronousFeaturesAllowed();
6458 then elabBuiltinActiveState;
6459 case "ticksInState"
6460 algorithm
6461
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := Config.synchronousFeaturesAllowed();
6462 then elabBuiltinTicksInState;
6463 case "timeInState"
6464 algorithm
6465
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := Config.synchronousFeaturesAllowed();
6466 then elabBuiltinTimeInState;
6467 case "sourceInfo"
6468 algorithm
6469
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 38 times.
38 true := Config.acceptMetaModelicaGrammar();
6470 then elabBuiltinSourceInfo;
6471 case "SOME"
6472 algorithm
6473
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 748 times.
748 true := Config.acceptMetaModelicaGrammar();
6474 then elabBuiltinSome;
6475 case "NONE"
6476 algorithm
6477
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6783 times.
6783 true := Config.acceptMetaModelicaGrammar();
6478 then elabBuiltinNone;
6479 case "isPresent"
6480 algorithm
6481
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 true := Config.acceptMetaModelicaGrammar();
6482 then elabBuiltinIsPresent;
6483 end match;
6484 end elabBuiltinHandler;
6485
6486 public function isBuiltinFunc "Returns true if the function name given as argument
6487 is a builtin function, which either has a elabBuiltinHandler function
6488 or can be found in the builtin environment."
6489 input Absyn.Path inPath "the path of the found function";
6490 input DAE.Type ty;
6491 output DAE.FunctionBuiltin isBuiltin;
6492 output Boolean b;
6493 output Absyn.Path outPath "make the path non-FQ";
6494 algorithm
6495 (isBuiltin,b,outPath) := matchcontinue (inPath,ty)
6496 local
6497 String id;
6498 Absyn.Path path;
6499
6500 case (path,DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=isBuiltin as DAE.FUNCTION_BUILTIN(_))))
6501 algorithm
6502 29124 path := AbsynUtil.makeNotFullyQualified(path);
6503 then (isBuiltin, true, path);
6504
6505 case (path,DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(isBuiltin=isBuiltin as DAE.FUNCTION_BUILTIN_PTR())))
6506 algorithm
6507 316 path := AbsynUtil.makeNotFullyQualified(path);
6508 then (isBuiltin, false, path);
6509
6510 case (Absyn.IDENT(name = id),_)
6511 algorithm
6512 751 elabBuiltinHandler(id);
6513 ✗ then (DAE.FUNCTION_BUILTIN(SOME(id), false), true, inPath);
6514
6515 case (Absyn.FULLYQUALIFIED(path), _)
6516 algorithm
6517
1/2
✓ Branch 1 taken 26348 times.
✗ Branch 2 not taken.
26348 (isBuiltin as DAE.FUNCTION_BUILTIN(),_,path) := isBuiltinFunc(path,ty);
6518 then
6519 (isBuiltin, true, path);
6520
6521 case (Absyn.QUALIFIED("Connections", Absyn.IDENT("isRoot")), _)
6522 then (DAE.FUNCTION_BUILTIN(NONE(), false), true, inPath);
6523
6524 else (DAE.FUNCTION_NOT_BUILTIN(), false, inPath);
6525 end matchcontinue;
6526 end isBuiltinFunc;
6527
6528 protected function elabCallBuiltin
6529 "This function elaborates on builtin operators (such as \"pre\", \"der\" etc.),
6530 by calling the builtin handler to retrieve the correct function to call."
6531 input FCore.Cache inCache;
6532 input FCore.Graph inEnv;
6533 input Absyn.ComponentRef inFnName;
6534 input list<Absyn.Exp> inPosArgs;
6535 input list<Absyn.NamedArg> inNamedArgs;
6536 input Boolean inImplicit;
6537 input DAE.Prefix inPrefix;
6538 input SourceInfo inInfo;
6539 output FCore.Cache outCache;
6540 output DAE.Exp outExp;
6541 output DAE.Properties outProperties;
6542
6543 partial function HandlerFunc
6544 input FCore.Cache inCache;
6545 input FCore.Graph inEnv;
6546 input list<Absyn.Exp> inPosArgs;
6547 input list<Absyn.NamedArg> inNamedArgs;
6548 input Boolean inImplicit;
6549 input DAE.Prefix inPrefix;
6550 input SourceInfo inInfo;
6551 output FCore.Cache outCache;
6552 output DAE.Exp outExp;
6553 output DAE.Properties outProperties;
6554 end HandlerFunc;
6555 algorithm
6556 (outCache, outExp, outProperties) := match inFnName
6557 local
6558 HandlerFunc handler;
6559 Absyn.ComponentRef cr;
6560
6561 case Absyn.CREF_IDENT(subscripts = {})
6562 algorithm
6563 20425 handler := elabBuiltinHandler(inFnName.name);
6564
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 20425 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 5 taken 11923 times.
✓ Branch 6 taken 8502 times.
32348 then
6565 handler(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo);
6566
6567 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "isRoot"))
6568 151 then elabBuiltinIsRoot(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo);
6569
6570 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "uniqueRootIndices"))
6571 algorithm
6572 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRootIndices"}, inInfo);
6573 ✗ then elabBuiltinUniqueRootIndices(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo);
6574
6575 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "rooted"))
6576 128 then elabBuiltinRooted(inCache, inEnv, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo);
6577
6578 case Absyn.CREF_FULLYQUALIFIED(cr)
6579 ✗ then elabCallBuiltin(inCache, inEnv, cr, inPosArgs, inNamedArgs, inImplicit, inPrefix, inInfo);
6580
6581 end match;
6582 end elabCallBuiltin;
6583
6584 protected function elabCall
6585 "This function elaborates on a function call. It converts the name to a
6586 Absyn.Path, and used the Static.elabCallArgs to do the rest of the work."
6587 input output FCore.Cache cache;
6588 input FCore.Graph env;
6589 input Absyn.ComponentRef fn;
6590 input list<Absyn.Exp> args;
6591 input list<Absyn.NamedArg> nargs;
6592 input list<Absyn.Path> typeVars;
6593 input Boolean impl;
6594 input DAE.Prefix pre;
6595 input SourceInfo info;
6596 output DAE.Exp e;
6597 output DAE.Properties prop;
6598 protected
6599 Integer numErrorMessages = Error.getNumErrorMessages();
6600 list<Integer> handles;
6601 String name, s, s1, s2;
6602 Absyn.Path fn_1;
6603 String fnstr,argstr,prestr;
6604 list<String> argstrs;
6605 algorithm
6606
2/2
✓ Branch 1 taken 20704 times.
✓ Branch 2 taken 75163 times.
95867 if hasBuiltInHandler(fn) then
6607 try
6608 20704 (cache,e,prop) := elabCallBuiltin(cache, env, fn, args, nargs, impl,pre,info) "Built in functions (e.g. \"pre\", \"der\"), have only possitional arguments" ;
6609 20588 return;
6610 else
6611
1/2
✓ Branch 1 taken 116 times.
✗ Branch 2 not taken.
116 true := numErrorMessages == Error.getNumErrorMessages();
6612 ✗ name := Dump.printComponentRefStr(fn);
6613 ✗ s1 := stringDelimitList(List.map(args, Dump.printExpStr), ", ");
6614 ✗ s2 := stringDelimitList(List.map(nargs, Dump.printNamedArgStr), ", ");
6615 ✗ s := if s2 == "" then s1 else s1 + ", " + s2;
6616 ✗ s := stringAppendList({name,"(",s,").\n"});
6617 ✗ Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {s,PrefixUtil.printPrefixStr3(pre)}, info);
6618 ✗ fail();
6619 end try;
6620 end if;
6621 handles := {};
6622 try
6623 // Interactive mode
6624 75163 ErrorExt.setCheckpoint("elabCall_InteractiveFunction");
6625 75163 fn_1 := AbsynUtil.crefToPath(fn);
6626 75163 (cache,e,prop) := elabCallArgs(cache,env, fn_1, args, nargs, typeVars, impl,pre,info);
6627 // If elabCallArgs fails, BackendCevalInterface.elabCallInteractive handles the checkpoint
6628 72503 ErrorExt.delCheckpoint("elabCall_InteractiveFunction");
6629 else
6630 // Best-effort failure trace before trying the scripting interface.
6631
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 2659 times.
2660 if Flags.isSet(Flags.FAILTRACE) then
6632 1 Debug.traceln("- Static.elabCall failed\n");
6633 1 Debug.trace(" function: ");
6634 1 fnstr := Dump.printComponentRefStr(fn);
6635 1 Debug.trace(fnstr);
6636 1 Debug.trace(" posargs: ");
6637 1 argstrs := List.map(args, Dump.printExpStr);
6638 1 argstr := stringDelimitList(argstrs, ", ");
6639 1 Debug.traceln(argstr);
6640 1 Debug.trace(" prefix: ");
6641 1 prestr := PrefixUtil.printPrefixStr(pre);
6642 1 Debug.traceln(prestr);
6643 end if;
6644 // Handle the scripting interface: simulate(), plot() etc.
6645 2660 (cache,e,prop) := BackendCevalInterface.elabCallInteractive(cache, env, fn, args, nargs, impl, pre, info);
6646 end try;
6647 end elabCall;
6648
6649 protected function hasBuiltInHandler "Determine if a function has a builtin handler or not."
6650 input Absyn.ComponentRef fn;
6651 output Boolean b;
6652 algorithm
6653 b := matchcontinue fn
6654 local
6655 Absyn.ComponentRef cr;
6656 String name;
6657 case Absyn.CREF_IDENT(name = name,subscripts = {})
6658 algorithm
6659 43091 elabBuiltinHandler(name);
6660 then true;
6661 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "isRoot"))
6662 then true;
6663
6664 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "uniqueRootIndices"))
6665 then true;
6666
6667 case Absyn.CREF_QUAL(name = "Connections", componentRef = Absyn.CREF_IDENT(name = "rooted"))
6668 then true;
6669
6670 4193 case Absyn.CREF_FULLYQUALIFIED(cr) then hasBuiltInHandler(cr);
6671 else false;
6672 end matchcontinue;
6673 end hasBuiltInHandler;
6674
6675 protected function isValidDerVariableName
6676 "Used to check if a der() expression is a valid VariableName.
6677 Valid forms are der(x), der(der(x)), etc."
6678 input Absyn.Exp exp;
6679 input Boolean nested = false;
6680 output Boolean isValid;
6681 protected
6682 Absyn.Exp arg;
6683 algorithm
6684 isValid := match exp
6685 case Absyn.CREF() then nested;
6686 case Absyn.CALL(function_ = Absyn.CREF_IDENT(name = "der"), functionArgs = Absyn.FUNCTIONARGS({arg}, {}))
6687 18 then isValidDerVariableName(arg, true);
6688 else false;
6689 end match;
6690 end isValidDerVariableName;
6691
6692 public function elabVariablenames "This function elaborates variablenames to DAE.Expression. A variablename can
6693 be used in e.g. plot(model,{v1{3},v2.t}) It should only be used in interactive
6694 functions that uses variablenames as componentreferences.
6695 "
6696 input list<Absyn.Exp> inExpl;
6697 output list<DAE.Exp> outExpl = {};
6698 protected
6699 algorithm
6700 ✗ outExpl := list(match e
6701 ✗ case Absyn.CREF() then DAE.CODE(Absyn.C_VARIABLENAME(e.componentRef), DAE.T_UNKNOWN_DEFAULT);
6702 ✗ case Absyn.CALL() guard isValidDerVariableName(e) then DAE.CODE(Absyn.C_EXPRESSION(e), DAE.T_UNKNOWN_DEFAULT);
6703 end match for e in inExpl);
6704 end elabVariablenames;
6705
6706 public function getOptionalNamedArgExpList
6707 input String name;
6708 input list<Absyn.NamedArg> nargs;
6709 output list<DAE.Exp> out;
6710 algorithm
6711 out := matchcontinue nargs
6712 local
6713 list<Absyn.Exp> absynExpList;
6714 String argName;
6715 list<Absyn.NamedArg> rest;
6716
6717 case {} then {};
6718
6719 case Absyn.NAMEDARG(argName = argName, argValue = Absyn.ARRAY(arrayExp = absynExpList)) :: _
6720 algorithm
6721 ✗ true := stringEq(name, argName);
6722 ✗ then
6723 absynExpListToDaeExpList(absynExpList);
6724
6725 case _ :: rest
6726 ✗ then getOptionalNamedArgExpList(name, rest);
6727
6728 end matchcontinue;
6729 end getOptionalNamedArgExpList;
6730
6731 protected function absynExpListToDaeExpList
6732 input list<Absyn.Exp> absynExpList;
6733 output list<DAE.Exp> out;
6734 algorithm
6735 out := match absynExpList
6736 local
6737 list<DAE.Exp> daeExpList;
6738 list<Absyn.Exp> absynRest;
6739 Absyn.ComponentRef absynCr;
6740 Absyn.Path absynPath;
6741 DAE.ComponentRef daeCr;
6742 DAE.Exp crefExp;
6743
6744 case {} then {};
6745
6746 case Absyn.CREF(componentRef = absynCr) :: absynRest
6747 algorithm
6748 ✗ absynPath := AbsynUtil.crefToPath(absynCr);
6749 ✗ daeCr := ComponentReference.pathToCref(absynPath);
6750 ✗ crefExp := Expression.crefExp(daeCr);
6751 ✗ daeExpList := absynExpListToDaeExpList(absynRest);
6752 then
6753 crefExp :: daeExpList;
6754
6755 case _ :: absynRest
6756 ✗ then absynExpListToDaeExpList(absynRest);
6757 end match;
6758 end absynExpListToDaeExpList;
6759
6760 public function getOptionalNamedArg
6761 "This function is used to 'elaborate' interactive functions' optional parameters,
6762 e.g. simulate(A.b, startTime=1), startTime is an optional parameter."
6763 input FCore.Cache inCache;
6764 input FCore.Graph inEnv;
6765 input Boolean inImplicit;
6766 input String inArgName;
6767 input DAE.Type inType;
6768 input list<Absyn.NamedArg> inArgs;
6769 input DAE.Exp inDefaultExp;
6770 input DAE.Prefix inPrefix;
6771 input SourceInfo inInfo;
6772 output FCore.Cache outCache = inCache;
6773 output DAE.Exp outExp = inDefaultExp;
6774 protected
6775 String name;
6776 DAE.Type ty;
6777 Absyn.Exp e;
6778 algorithm
6779
2/2
✓ Branch 0 taken 22348 times.
✓ Branch 1 taken 15023 times.
37371 for arg in inArgs loop
6780 22348 Absyn.NAMEDARG(argName = name) := arg;
6781
6782
4/4
✓ Branch 0 taken 3904 times.
✓ Branch 1 taken 18444 times.
✓ Branch 3 taken 1840 times.
✓ Branch 4 taken 2064 times.
22348 if name == inArgName then
6783 // Found the argument, try to evaluate it.
6784 try
6785 1840 Absyn.NAMEDARG(argValue = e) := arg;
6786
6787
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1840 times.
1840 (outCache, outExp, DAE.PROP(type_ = ty)) :=
6788 elabExpInExpression(inCache, inEnv, e, inImplicit, true, inPrefix, inInfo);
6789 1840 outExp := Types.matchType(outExp, ty, inType, true);
6790 else
6791 // The argument couldn't be evaluated, possibly due to having the wrong
6792 // type. We should print an error for this, but some API functions like
6793 // simulate depend on the default arguments having the wrong type.
6794 end try;
6795
6796 break;
6797 end if;
6798 end for;
6799 end getOptionalNamedArg;
6800
6801 public function elabUntypedCref
6802 "This function elaborates a ComponentRef without adding type information.
6803 Environment is passed along, such that constant subscripts can be elabed
6804 using existing functions."
6805 input FCore.Cache inCache;
6806 input FCore.Graph inEnv;
6807 input Absyn.ComponentRef inCref;
6808 input Boolean inImplicit;
6809 input DAE.Prefix inPrefix;
6810 input SourceInfo inInfo;
6811 output FCore.Cache outCache;
6812 output DAE.ComponentRef outCref;
6813 algorithm
6814 outCref := match inCref
6815 local
6816 list<DAE.Subscript> subs;
6817 DAE.ComponentRef cr;
6818
6819 case Absyn.CREF_IDENT()
6820 algorithm
6821 14 (outCache, subs) := elabSubscripts(inCache, inEnv, inCref.subscripts, inImplicit, inPrefix, inInfo);
6822 14 then
6823 ComponentReferenceBasics.makeCrefIdent(inCref.name, DAE.T_UNKNOWN_DEFAULT, subs);
6824
6825 case Absyn.CREF_QUAL()
6826 algorithm
6827 14 (outCache, subs) := elabSubscripts(inCache, inEnv, inCref.subscripts,
6828 inImplicit, inPrefix, inInfo);
6829 14 (outCache, cr) := elabUntypedCref(outCache, inEnv, inCref.componentRef,
6830 inImplicit, inPrefix, inInfo);
6831 14 then
6832 ComponentReferenceBasics.makeCrefQual(inCref.name, DAE.T_UNKNOWN_DEFAULT, subs, cr);
6833
6834 end match;
6835 end elabUntypedCref;
6836
6837 public function needToRebuild
6838 input String newFile;
6839 input String oldFile;
6840 input Real buildTime;
6841 output Boolean buildNeeded;
6842 algorithm
6843 buildNeeded := matchcontinue(newFile, oldFile)
6844 local String newf,oldf; Real nfmt;
6845 case ("", "") then true; // rebuild all the time if the function has no file!
6846 case (newf, oldf)
6847 algorithm
6848 ✗ true := stringEq(newf, oldf); // the files should be the same!
6849 // the new file nf should have an older modification time than the last build
6850 ✗ SOME(nfmt) := System.getFileModificationTime(newf);
6851 ✗ true := realGt(buildTime, nfmt); // the file was not modified since last build
6852 then false;
6853 else true;
6854 end matchcontinue;
6855 end needToRebuild;
6856
6857 protected function createDummyFarg
6858 input String name;
6859 output DAE.FuncArg farg;
6860 algorithm
6861 128 farg := DAE.FUNCARG(name, DAE.T_UNKNOWN_DEFAULT, DAE.C_VAR(), DAE.NON_PARALLEL(), NONE());
6862 end createDummyFarg;
6863
6864 public function elabCallArgs "
6865 function: elabCallArgs
6866 Given the name of a function and two lists of expression and
6867 NamedArg respectively to be used
6868 as actual arguments in a function call to that function, this
6869 function finds the function definition and matches the actual
6870 arguments to the formal parameters."
6871 input FCore.Cache inCache;
6872 input FCore.Graph inEnv;
6873 input Absyn.Path inPath;
6874 input list<Absyn.Exp> inAbsynExpLst;
6875 input list<Absyn.NamedArg> inAbsynNamedArgLst;
6876 input list<Absyn.Path> typeVars;
6877 input Boolean inBoolean;
6878 input DAE.Prefix inPrefix;
6879 input SourceInfo info;
6880 output FCore.Cache outCache;
6881 output DAE.Exp outExp;
6882 output DAE.Properties outProperties;
6883 algorithm
6884
3/4
✗ Branch 3 not taken.
✓ Branch 4 taken 79526 times.
✓ Branch 5 taken 2655 times.
✓ Branch 6 taken 76871 times.
79531 (outCache,SOME((outExp,outProperties))) :=
6885 elabCallArgs2(inCache,inEnv,inPath,inAbsynExpLst,inAbsynNamedArgLst,typeVars,inBoolean,Mutable.create(false),inPrefix,info,Error.getNumErrorMessages());
6886 76871 (outCache,outProperties) := elabCallArgsEvaluateArrayLength(outCache,inEnv,outProperties,inPrefix,info);
6887 end elabCallArgs;
6888
6889 protected function elabCallArgsEvaluateArrayLength
6890 "Evaluate array dimensions in the returned type. For a call f(n) we might get
6891 Integer[n] back, where n is a parameter expression. We consider any such
6892 parameter structural since it decides the dimension of an array. We fall
6893 back to not evaluating the parameter if we fail since the dimension may not
6894 be structural (used in another call or reduction, etc)."
6895 input FCore.Cache inCache;
6896 input FCore.Graph env;
6897 input DAE.Properties inProperties;
6898 input DAE.Prefix inPrefix;
6899 input SourceInfo info;
6900 output FCore.Cache outCache;
6901 output DAE.Properties outProperties;
6902 protected
6903 DAE.Type ty;
6904 algorithm
6905 try
6906 // Unsure if we want to evaluate dimensions inside function scope.
6907 // Last scope ref in env is a class scope.
6908
2/2
✓ Branch 2 taken 43452 times.
✓ Branch 3 taken 33419 times.
153742 true := FGraph.checkScopeType({FGraph.lastScopeRef(env)}, SOME(FCore.CLASS_SCOPE()));
6909 33419 ty := Types.getPropType(inProperties);
6910 33419 (ty, (outCache, _)) := Types.traverseType(ty, (inCache, env), elabCallArgsEvaluateArrayLength2);
6911 33419 outProperties := Types.setPropType(inProperties, ty);
6912 else
6913 outCache := inCache;
6914 outProperties := inProperties;
6915 end try;
6916 end elabCallArgsEvaluateArrayLength;
6917
6918 protected function elabCallArgsEvaluateArrayLength2
6919 input DAE.Type ty;
6920 input tuple<FCore.Cache,FCore.Graph> inTpl;
6921 output DAE.Type oty = ty;
6922 output tuple<FCore.Cache,FCore.Graph> outTpl;
6923 algorithm
6924 (oty,outTpl) := matchcontinue (oty,inTpl)
6925 local
6926 tuple<FCore.Cache,FCore.Graph> tpl;
6927 DAE.Dimensions dims;
6928 case (DAE.T_ARRAY(),tpl)
6929 algorithm
6930 16571 (dims,tpl) := List.mapFold(oty.dims,elabCallArgsEvaluateArrayLength3,tpl);
6931 16571 oty.dims := dims;
6932 16571 then (oty,tpl);
6933 90748 else (oty,inTpl);
6934 end matchcontinue;
6935 end elabCallArgsEvaluateArrayLength2;
6936
6937 protected function elabCallArgsEvaluateArrayLength3
6938 input DAE.Dimension inDim;
6939 input tuple<FCore.Cache,FCore.Graph> inTpl;
6940 output DAE.Dimension outDim;
6941 output tuple<FCore.Cache,FCore.Graph> outTpl;
6942 algorithm
6943 (outDim,outTpl) := matchcontinue (inDim,inTpl)
6944 local
6945 Integer i;
6946 DAE.Exp exp;
6947 FCore.Cache cache;
6948 FCore.Graph env;
6949 case (DAE.DIM_EXP(exp),(cache,env))
6950 algorithm
6951
0/2
✗ Branch 1 not taken.
✗ Branch 2 not taken.
3 (cache,Values.INTEGER(i)) := Ceval.ceval(cache,env,exp,false,Absyn.NO_MSG(),0);
6952 ✗ then (DAE.DIM_INTEGER(i),(cache,env));
6953 else (inDim,inTpl);
6954 end matchcontinue;
6955 end elabCallArgsEvaluateArrayLength3;
6956
6957 protected function createInputVariableReplacements
6958 "@author: adrpo
6959 This function will add the binding expressions for inputs
6960 to the variable replacement structure. This is needed to
6961 be able to replace input variables in default values.
6962 Example: ... "
6963 input list<Slot> inSlotLst;
6964 input VarTransform.VariableReplacements inVarsRepl;
6965 output VarTransform.VariableReplacements outVarsRepl;
6966 algorithm
6967 outVarsRepl := matchcontinue inSlotLst
6968 local
6969 VarTransform.VariableReplacements o;
6970 String id;
6971 DAE.Exp e;
6972 list<Slot> rest;
6973
6974 // handle empty
6975 case {} then inVarsRepl;
6976
6977 // only interested in filled slots that have a optional expression
6978 case SLOT(defaultArg = DAE.FUNCARG(name=id), slotFilled = true, arg = SOME(e)) :: rest
6979 algorithm
6980 ✗ o := VarTransform.addReplacement(inVarsRepl, ComponentReferenceBasics.makeCrefIdent(id, DAE.T_UNKNOWN_DEFAULT, {}), e);
6981 ✗ then
6982 createInputVariableReplacements(rest, o);
6983
6984 // try the next.
6985 ✗ else createInputVariableReplacements(listRest(inSlotLst), inVarsRepl);
6986 end matchcontinue;
6987 end createInputVariableReplacements;
6988
6989 protected function elabCallArgs2 "
6990 function: elabCallArgs
6991 Given the name of a function and two lists of expression and
6992 NamedArg respectively to be used
6993 as actual arguments in a function call to that function, this
6994 function finds the function definition and matches the actual
6995 arguments to the formal parameters."
6996 input FCore.Cache inCache;
6997 input FCore.Graph inEnv;
6998 input Absyn.Path inPath;
6999 input list<Absyn.Exp> inAbsynExpLst;
7000 input list<Absyn.NamedArg> inAbsynNamedArgLst;
7001 input list<Absyn.Path> typeVars;
7002 input Boolean inBoolean;
7003 input Mutable<Boolean> stopElab;
7004 input DAE.Prefix inPrefix;
7005 input SourceInfo info;
7006 input Integer numErrors;
7007 output FCore.Cache outCache;
7008 output Option<tuple<DAE.Exp,DAE.Properties>> expProps;
7009 algorithm
7010 (outCache,expProps) :=
7011 matchcontinue (inCache,inEnv,inPath,inAbsynExpLst,inAbsynNamedArgLst,inBoolean,inPrefix)
7012 local
7013 DAE.Type t,outtype,functype,tp1;
7014 list<DAE.FuncArg> fargs;
7015 FCore.Graph env_1,env_2,env,recordEnv;
7016 list<Slot> slots,newslots,newslots2;
7017 list<DAE.Exp> args_1,args_2;
7018 list<DAE.Const> constlist, constInputArgs;
7019 DAE.Const const;
7020 DAE.TupleConst tyconst;
7021 DAE.Properties prop,prop_1;
7022 SCode.Element cl,recordCl;
7023 Absyn.Path fn,fn_1,path;
7024 list<Absyn.Exp> args;
7025 list<Absyn.NamedArg> nargs;
7026 Boolean impl;
7027 list<DAE.Type> typelist;
7028 DAE.Dimensions vect_dims;
7029 DAE.Exp call_exp,callExp,daeexp;
7030 list<String> t_lst,names;
7031 String fn_str,types_str,scope,pre_str;
7032 String s,name,argStr;
7033 FCore.Cache cache;
7034 DAE.Type tp;
7035 DAE.Prefix pre;
7036 SCode.Restriction re;
7037 list<Absyn.Path> operNames;
7038 Absyn.ComponentRef cref;
7039 DAE.ComponentRef daecref;
7040 DAE.Function func;
7041
7042 /* Record constructors that might have come from Graphical expressions with unknown array sizes */
7043 /*
7044 * adrpo: HACK! HACK! TODO! remove this case if records with unknown sizes can be instantiated
7045 * this could be also fixed by transforming the function call arguments into modifications and
7046 * send the modifications as an option in Lookup.lookup* functions!
7047 */
7048 case (cache,env,fn,args,nargs,impl,pre)
7049 algorithm
7050
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 26 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 26 times.
79531 (cache,cl as SCode.CLASS(restriction = SCode.R_PACKAGE()),_) :=
7051 Lookup.lookupClassIdent(cache, env, "GraphicalAnnotationsProgram____");
7052
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 13 times.
26 (cache,cl as SCode.CLASS( restriction = SCode.R_RECORD(_)),env_1) := Lookup.lookupClass(cache, env, fn);
7053 13 (cache,cl,env_2) := Lookup.lookupRecordConstructorClass(cache, env_1 /* env */, fn);
7054
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 13 times.
13 (_,_::names) := SCodeUtil.getClassComponents(cl); // remove the first one as it is the result!
7055 /*
7056 (cache,(t as (DAE.T_FUNCTION(fargs,(outtype as (DAE.T_COMPLEX(complexClassType as ClassInf.RECORD(name),_,_,_),_))),_)),env_1)
7057 = Lookup.lookupType(cache, env, fn, SOME(info));
7058 */
7059 13 fargs := List.map(names, createDummyFarg);
7060 13 slots := makeEmptySlots(fargs);
7061 13 (cache,_,newslots,_,_) := elabInputArgs(cache, env, args, nargs, slots, true, false /*checkTypes*/ ,impl, pre,info,DAE.T_UNKNOWN_DEFAULT,fn,true);
7062 13 (cache,newslots2,_,_) := fillGraphicsDefaultSlots(cache, newslots, cl, env_2, impl, pre, info);
7063 13 args_2 := slotListArgs(newslots2);
7064
7065 13 tp := complexTypeFromSlots(newslots2,ClassInf.UNKNOWN(Absyn.IDENT("")));
7066 13 then
7067 (cache,SOME((DAE.CALL(fn,args_2,DAE.CALL_ATTR(tp,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS)),DAE.PROP(DAE.T_UNKNOWN_DEFAULT,DAE.C_CONST()))));
7068
7069 // Record constructors, user defined or implicit, try the hard stuff first
7070 case (cache,env,fn,args,nargs,impl,pre)
7071 algorithm
7072 // For unrolling errors if an overloaded 'constructor' matches later.
7073 79518 ErrorExt.setCheckpoint("RecordConstructor");
7074
7075 79518 (cache,func) := InstFunction.getRecordConstructorFunction(cache,env,fn);
7076
7077
2/2
✓ Branch 0 taken 22757 times.
✓ Branch 1 taken 482 times.
23239 DAE.RECORD_CONSTRUCTOR(path,tp1,_) := func;
7078
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 482 times.
482 DAE.T_FUNCTION(fargs, outtype, _, path) := tp1;
7079
7080
7081 482 slots := makeEmptySlots(fargs);
7082 482 (cache,_,newslots,constInputArgs,_) := elabInputArgs(cache,env, args, nargs, slots,true,true,impl,pre,info,tp1,path);
7083
7084 482 (args_2, newslots2) := addDefaultArgs(newslots, info);
7085 403 vect_dims := slotsVectorizable(newslots2, info);
7086
7087 403 constlist := constInputArgs;
7088 403 const := List.fold(constlist, Types.constAnd, DAE.C_CONST());
7089
7090 403 tyconst := elabConsts(outtype, const);
7091 403 prop := getProperties(outtype, tyconst);
7092
7093 403 callExp := DAE.CALL(path,args_2,DAE.CALL_ATTR(outtype,false,false,false,false,DAE.NO_INLINE(),DAE.NO_TAIL(),DAE.NoReturn.RETURNS));
7094
7095 403 (call_exp,prop_1) := vectorizeCall(callExp, vect_dims, newslots2, prop, info);
7096 403 expProps := SOME((call_exp,prop_1));
7097
7098 403 Mutable.update(stopElab,true);
7099 403 ErrorExt.rollBack("RecordConstructor");
7100
7101 403 then
7102 (cache,expProps);
7103
7104 /* If the default constructor failed and we have an operator record
7105 look for overloaded Record constructors (operators), user defined.
7106 mahge:TODO move this to a function and call it from above.
7107 avoids uneccesary lookup since we already have a record.*/
7108 case (cache,env,fn,args,nargs,impl,pre)
7109 algorithm
7110
7111
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79115 times.
154361 false := Mutable.access(stopElab);
7112
7113 79115 (cache,recordCl,recordEnv) := Lookup.lookupClass(cache,env,fn);
7114
2/2
✓ Branch 1 taken 75246 times.
✓ Branch 2 taken 79 times.
75325 true := SCodeUtil.isOperatorRecord(recordCl);
7115
7116 79 fn_1 := AbsynUtil.joinPaths(fn,Absyn.IDENT("'constructor'"));
7117 79 (cache,recordCl,recordEnv) := Lookup.lookupClass(cache,recordEnv,fn_1);
7118
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
79 true := SCodeUtil.isOperator(recordCl);
7119
7120 79 operNames := AbsynToSCode.getListofQualOperatorFuncsfromOperator(recordCl);
7121
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
79 (cache,typelist as _::_) := Lookup.lookupFunctionsListInEnv(cache, recordEnv, operNames, info, {});
7122
7123 79 Mutable.update(stopElab,true);
7124 79 (cache,expProps) := elabCallArgs3(cache,env,typelist,fn_1,args,nargs,typeVars,impl,pre,info);
7125
7126 79 ErrorExt.rollBack("RecordConstructor");
7127
7128 79 then
7129 (cache,expProps);
7130
7131 /* ------ */
7132 case (cache,env,fn,args,nargs,impl,pre) /* Metamodelica extension, added by simbj */
7133 algorithm
7134
7135 79036 ErrorExt.delCheckpoint("RecordConstructor");
7136
7137
2/2
✓ Branch 1 taken 46562 times.
✓ Branch 2 taken 32474 times.
90460 true := Config.acceptMetaModelicaGrammar();
7138
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 32474 times.
32474 false := Mutable.access(stopElab);
7139
2/2
✓ Branch 1 taken 11424 times.
✓ Branch 2 taken 20762 times.
32474 (cache,t as DAE.T_METARECORD(),_) := Lookup.lookupType(cache, env, fn, NONE());
7140 20762 Mutable.update(stopElab,true);
7141 20762 (cache,expProps) := elabCallArgsMetarecord(cache,env,t,args,nargs,impl,stopElab,pre,info);
7142 then
7143 (cache,expProps);
7144
7145 /* ..Other functions */
7146 case (cache,env,fn,args,nargs,impl,pre)
7147 algorithm
7148
7149 58274 ErrorExt.setCheckpoint("elabCallArgs2FunctionLookup");
7150
7151
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 58274 times.
60731 false := Mutable.access(stopElab);
7152
2/2
✓ Branch 1 taken 2457 times.
✓ Branch 2 taken 55817 times.
58274 (cache,typelist as _::_) := Lookup.lookupFunctionsInEnv(cache, env, fn, info)
7153 "PR. A function can have several types. Taking an array with
7154 different dimensions as parameter for example. Because of this we
7155 cannot just lookup the function name and trust that it
7156 returns the correct function. It returns just one
7157 functiontype of several possibilites. The solution is to send
7158 in the function type of the user function and check both the
7159 function name and the function\'s type." ;
7160 55817 Mutable.update(stopElab,true);
7161 55817 (cache,expProps) := elabCallArgs3(cache,env,typelist,fn,args,nargs,typeVars,impl,pre,info);
7162
7163 55633 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7164
7165 55633 then
7166 (cache,expProps);
7167
7168 case (cache,env,fn,args,nargs,impl,pre) /* no matching type found, with -one- candidate */
7169 algorithm
7170
4/4
✓ Branch 1 taken 2457 times.
✓ Branch 2 taken 184 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 181 times.
2641 (cache,typelist as {tp1}) := Lookup.lookupFunctionsInEnv(cache, env, fn, info);
7171 181 (cache,args_1,_,_,functype,_,_) :=
7172 elabTypes(cache, env, args, nargs, {}, typelist, true, false/* Do not check types*/,impl,pre,info);
7173 37 argStr := ExpressionDump.printExpListStr(args_1);
7174 37 pre_str := PrefixUtil.printPrefixStr3(pre);
7175 37 fn_str := AbsynUtil.pathString(fn) + "(" + argStr + ")\nof type\n " + TypesDump.unparseType(functype);
7176 37 types_str := "\n " + TypesDump.unparseType(tp1);
7177 37 Error.assertionOrAddSourceMessage(Error.getNumErrorMessages()<>numErrors,Error.NO_MATCHING_FUNCTION_FOUND, {fn_str,pre_str,types_str}, info);
7178
7179 37 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7180 37 then
7181 (cache,NONE());
7182
7183 case (cache,env,fn,_,_,_,_) /* class found; not function */
7184 algorithm
7185
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1328 times.
3910 (cache,SCode.CLASS(restriction = re),_) := Lookup.lookupClass(cache,env,fn);
7186
2/2
✓ Branch 1 taken 1306 times.
✓ Branch 2 taken 22 times.
1328 false := SCodeUtil.isFunctionRestriction(re);
7187 22 fn_str := AbsynUtil.pathString(fn);
7188 22 s := SCodeDump.restrString(re);
7189 22 Error.addSourceMessage(Error.LOOKUP_FUNCTION_GOT_CLASS, {fn_str,s}, info);
7190
7191 22 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7192 22 then
7193 (cache,NONE());
7194
7195 case (cache,env,fn,_,_,_,pre) /* no matching type found, with candidates */
7196 algorithm
7197
4/4
✓ Branch 1 taken 2435 times.
✓ Branch 2 taken 147 times.
✓ Branch 3 taken 144 times.
✓ Branch 4 taken 3 times.
2582 (cache,typelist as _::_::_) := Lookup.lookupFunctionsInEnv(cache,env, fn, info);
7198 3 t_lst := List.map(typelist, TypesDump.unparseType);
7199 3 fn_str := AbsynUtil.pathString(fn);
7200 3 pre_str := PrefixUtil.printPrefixStr3(pre);
7201 3 types_str := stringDelimitList(t_lst, "\n -");
7202 //fn_str = fn_str + " in component " + pre_str;
7203 3 Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND, {fn_str,pre_str,types_str}, info);
7204
7205 3 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7206 3 then
7207 (cache,NONE());
7208
7209 // In Optimica there is an odd syntax like for eg., x(finalTime) + y(finalTime); where both x and y are normal variables
7210 // not functions. So it is not really a call Exp but the compiler treats it as if it is up until this point.
7211 // This is a kind of trick to handle that.
7212 case (cache,env,fn,{Absyn.CREF(Absyn.CREF_IDENT(name,_))},_,impl,pre)
7213 guard Config.acceptOptimicaGrammar()
7214 algorithm
7215 21 cref := AbsynUtil.pathToCref(fn);
7216
7217
2/6
✗ Branch 1 not taken.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
21 (cache,SOME((daeexp as DAE.CREF(daecref,tp),prop,_))) := elabCref(cache,env, cref, impl,true,pre,info);
7218 ✗ ErrorExt.rollBack("elabCallArgs2FunctionLookup");
7219
7220 ✗ daeexp := DAE.CREF(DAE.OPTIMICA_ATTR_INST_CREF(daecref,name), tp);
7221 ✗ expProps := SOME((daeexp,prop));
7222 ✗ then
7223 (cache,expProps);
7224
7225 case (cache,env,fn,_,_,_,_)
7226 algorithm
7227
2/2
✓ Branch 0 taken 2579 times.
✓ Branch 1 taken 2574 times.
5153 failure(Lookup.lookupType(cache,env, fn, NONE())) "msg" ;
7228 2574 scope := FGraph.printGraphPathStr(env) + " (looking for a function or record)";
7229 2574 fn_str := AbsynUtil.pathString(fn);
7230 2574 Error.addSourceMessage(Error.LOOKUP_ERROR, {fn_str,scope}, info); // No need to add prefix because only depends on scope?
7231
7232 2574 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7233 2574 then
7234 (cache,NONE());
7235
7236 case (cache,env,fn,_,_,_,pre) /* no matching type found, no candidates. */
7237 algorithm
7238
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 (cache,{}) := Lookup.lookupFunctionsInEnv(cache,env,fn,info);
7239 ✗ fn_str := AbsynUtil.pathString(fn);
7240 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
7241 ✗ fn_str := fn_str + " in component " + pre_str;
7242 ✗ Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NO_CANDIDATE, {fn_str}, info);
7243
7244 ✗ ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7245 ✗ then
7246 (cache,NONE());
7247
7248 case (_,env,fn,_,_,_,_)
7249 algorithm
7250 5 ErrorExt.delCheckpoint("elabCallArgs2FunctionLookup");
7251
1/2
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
5 true := Flags.isSet(Flags.FAILTRACE);
7252 ✗ Debug.traceln("- Static.elabCallArgs failed on: " + AbsynUtil.pathString(fn) + " in env: " + FGraph.printGraphPathStr(env));
7253 ✗ then
7254 fail();
7255 end matchcontinue;
7256 end elabCallArgs2;
7257
7258 public function elabCallArgs3
7259 "Elaborates the input given a set of viable function candidates, and vectorizes the arguments+performs type checking"
7260 input FCore.Cache inCache;
7261 input FCore.Graph inEnv;
7262 input list<DAE.Type> typelist;
7263 input Absyn.Path fn;
7264 input list<Absyn.Exp> args;
7265 input list<Absyn.NamedArg> nargs;
7266 input list<Absyn.Path> typeVars;
7267 input Boolean impl;
7268 input DAE.Prefix pre;
7269 input SourceInfo info;
7270 output FCore.Cache outCache;
7271 output Option<tuple<DAE.Exp,DAE.Properties>> expProps;
7272 protected
7273 DAE.Exp callExp,call_exp;
7274 list<DAE.Exp> args_1,args_2;
7275 list<DAE.Const> constlist;
7276 DAE.Const const;
7277 DAE.Type restype,functype;
7278 DAE.FunctionBuiltin isBuiltin;
7279 DAE.FunctionParallelism funcParal;
7280 Boolean tuple_,builtin,isImpure;
7281 DAE.NoReturn noReturn;
7282 DAE.InlineType inlineType;
7283 Absyn.Path fn_1;
7284 DAE.Properties prop,prop_1;
7285 DAE.Type tp;
7286 DAE.TupleConst tyconst;
7287 DAE.Dimensions vect_dims;
7288 list<Slot> slots,slots2;
7289 AvlTreePathFunction.Tree functionTree;
7290 Util.Status status;
7291 FCore.Cache cache;
7292 Boolean didInline;
7293 Boolean onlyOneFunction,isFunctionPointer;
7294 DAE.Purity purity;
7295 algorithm
7296 56070 onlyOneFunction := listLength(typelist) == 1;
7297
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55889 times.
56070 (cache,
7298 args_1,
7299 constlist,
7300 restype,
7301 functype as DAE.T_FUNCTION(functionAttributes=DAE.FUNCTION_ATTRIBUTES(purity=purity,
7302 inline=inlineType,
7303 isFunctionPointer=isFunctionPointer,
7304 functionParallelism=funcParal,
7305 noReturn=noReturn)),
7306 vect_dims,
7307 slots) := elabTypes(inCache, inEnv, args, nargs, typeVars, typelist, onlyOneFunction, true/* Check types*/, impl,pre,info)
7308 "The constness of a function depends on the inputs. If all inputs are constant the call itself is constant.";
7309
7310 55889 isImpure := purity == DAE.Purity.IMPURE;
7311 55889 (fn_1,functype) := deoverloadFuncname(fn, functype, inEnv);
7312 55889 tuple_ := Types.isTuple(restype);
7313 55889 (isBuiltin,builtin,fn_1) := isBuiltinFunc(fn_1,functype);
7314 55889 inlineType := inlineBuiltin(isBuiltin,inlineType);
7315 //check the env to see if a call to a parallel or kernel function is a valid one.
7316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55889 times.
55889 true := isValidWRTParallelScope(fn,builtin,funcParal,inEnv,info);
7317
7318 55889 const := List.fold(constlist, Types.constAnd, DAE.C_CONST());
7319
6/6
✓ Branch 1 taken 10666 times.
✓ Branch 2 taken 45223 times.
✓ Branch 3 taken 1823 times.
✓ Branch 4 taken 8843 times.
✓ Branch 5 taken 46870 times.
✓ Branch 6 taken 176 times.
55889 const := if (Flags.isSet(Flags.RML) and not builtin) or purity == DAE.Purity.OM_IMPURE then DAE.C_VAR() else const "in RML no function needs to be ceval'ed; this speeds up compilation significantly when bootstrapping";
7320 55889 (cache,const) := determineConstSpecialFunc(cache,inEnv,const,fn_1);
7321 55889 tyconst := elabConsts(restype, const);
7322 55889 prop := getProperties(restype, tyconst);
7323 55889 tp := Types.simplifyType(restype);
7324 // adrpo: 2011-09-30 NOTE THAT THIS WILL NOT ADD DEFAULT ARGS
7325 // FROM extends (THE BASE CLASS)
7326 55889 (args_2, slots2) := addDefaultArgs(slots, info);
7327 // DO NOT CHECK IF ALL SLOTS ARE FILLED!
7328
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 55885 times.
55885 true := List.fold(slots2, slotAnd, true);
7329
8/8
✓ Branch 0 taken 55705 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 46382 times.
✓ Branch 3 taken 9503 times.
✓ Branch 4 taken 26796 times.
✓ Branch 5 taken 29089 times.
✓ Branch 6 taken 54319 times.
✓ Branch 7 taken 1566 times.
239087 callExp := DAE.CALL(fn_1,args_2,DAE.CALL_ATTR(tp,tuple_,builtin,isImpure or purity == DAE.Purity.OM_IMPURE,isFunctionPointer,inlineType,DAE.NO_TAIL(),noReturn));
7330 // ExpressionDump.dumpExpWithTitle("function elabCallArgs3: ", callExp);
7331
7332 // create a replacement for input variables -> their binding
7333 //inputVarsRepl = createInputVariableReplacements(slots2, VarTransform.emptyReplacements());
7334 //print("Repls: " + VarTransform.dumpReplacementsStr(inputVarsRepl) + "\n");
7335 // replace references to inputs in the arguments
7336 //callExp = VarTransform.replaceExp(callExp, inputVarsRepl, NONE());
7337
7338 //debugPrintString = if_(Util.isEqual(DAE.NORM_INLINE,inline)," Inline: " + AbsynUtil.pathString(fn_1) + "\n", "");print(debugPrintString);
7339 55885 (call_exp,prop_1) := vectorizeCall(callExp, vect_dims, slots2, prop, info);
7340 // print("3 Prefix: " + PrefixUtil.printPrefixStr(pre) + " path: " + AbsynUtil.pathString(fn_1) + "\n");
7341 // Instantiate the function and add to dae function tree
7342
2/2
✓ Branch 1 taken 55583 times.
✓ Branch 2 taken 302 times.
55885 (cache,status) := instantiateDaeFunction(cache,inEnv,
7343 if Lookup.isFunctionCallViaComponent(cache, inEnv, fn) then fn else fn_1, // don't use the fully qualified name for calling component functions
7344 builtin,NONE(),true);
7345 // Instantiate any implicit record constructors needed and add them to the dae function tree
7346 55885 cache := instantiateImplicitRecordConstructors(cache, inEnv, args_1);
7347 55885 functionTree := FCore.getFunctionTree(cache);
7348 55885 (call_exp,_,didInline,_) := Inline.inlineExp(call_exp,(SOME(functionTree),{DAE.BUILTIN_EARLY_INLINE(),DAE.EARLY_INLINE()}),DAE.emptyElementSource);
7349 55885 (call_exp,_) := ExpressionSimplify.condsimplify(didInline,call_exp);
7350
4/4
✓ Branch 0 taken 656 times.
✓ Branch 1 taken 55229 times.
✓ Branch 3 taken 370 times.
✓ Branch 4 taken 286 times.
55885 didInline := didInline and (not Config.acceptMetaModelicaGrammar() /* Some weird errors when inlining. Becomes boxed even if it shouldn't... */);
7351
2/2
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 55599 times.
55885 prop_1 := if didInline then Types.setPropType(prop_1, restype) else prop_1;
7352
2/2
✓ Branch 0 taken 46558 times.
✓ Branch 1 taken 9327 times.
55885 if not isImpure then
7353 46558 (cache, call_exp, prop_1) := Ceval.cevalIfConstant(cache, inEnv, call_exp, prop_1, impl, info);
7354 end if;
7355
2/2
✓ Branch 1 taken 55866 times.
✓ Branch 2 taken 19 times.
55885 expProps := if Util.isSuccess(status) then SOME((call_exp,prop_1)) else NONE();
7356 outCache := cache;
7357 end elabCallArgs3;
7358
7359 public function inlineBuiltin
7360 input DAE.FunctionBuiltin isBuiltin;
7361 input DAE.InlineType inlineType;
7362 output DAE.InlineType outInlineType;
7363 algorithm
7364 outInlineType := match isBuiltin
7365 case DAE.FUNCTION_BUILTIN_PTR() then DAE.BUILTIN_EARLY_INLINE();
7366 else inlineType;
7367 end match;
7368 end inlineBuiltin;
7369
7370 protected function isValidWRTParallelScope
7371 input Absyn.Path inFn;
7372 input Boolean isBuiltin;
7373 input DAE.FunctionParallelism inFuncParallelism;
7374 input FCore.Graph inEnv;
7375 input SourceInfo inInfo;
7376 output Boolean isValid;
7377 algorithm
7378 55889 isValid := isValidWRTParallelScope_dispatch(inFn, isBuiltin, inFuncParallelism, FGraph.currentScope(inEnv), inInfo);
7379 end isValidWRTParallelScope;
7380
7381 protected function isValidWRTParallelScope_dispatch
7382 input Absyn.Path inFn;
7383 input Boolean isBuiltin;
7384 input DAE.FunctionParallelism inFuncParallelism;
7385 input FCore.Scope inScope;
7386 input SourceInfo inInfo;
7387 output Boolean isValid;
7388 algorithm
7389 isValid := matchcontinue(isBuiltin, inFuncParallelism, inScope)
7390 local
7391 String scopeName, errorString;
7392 FCore.Scope restScope;
7393 FCore.Ref ref;
7394
7395
7396 // non-parallel builtin function call is OK everywhere.
7397 case(true, DAE.FP_NON_PARALLEL(), _)
7398 then true;
7399
7400 // If we have a function call in an implicit scope type, then go
7401 // up recursively to find the actuall scope and then check.
7402 // But parfor scope is a parallel type so is handled differently.
7403 case(_, _, ref::restScope)
7404 algorithm
7405
2/2
✓ Branch 1 taken 534 times.
✓ Branch 2 taken 42665 times.
43199 false := FNode.isRefTop(ref);
7406 42665 scopeName := FNode.refName(ref);
7407
2/2
✓ Branch 1 taken 26262 times.
✓ Branch 2 taken 16403 times.
42665 true := listMember(scopeName, FCore.implicitScopeNames);
7408
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 16403 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
16403 false := stringEq(scopeName, FCore.parForScopeName);
7409 16403 then isValidWRTParallelScope_dispatch(inFn,isBuiltin,inFuncParallelism,restScope,inInfo);
7410
7411 // This two are common cases so keep them at the top.
7412 // normal(non parallel) function call in a normal scope (function and class scopes) is OK.
7413 case(_, DAE.FP_NON_PARALLEL(), ref::_)
7414 algorithm
7415
2/2
✓ Branch 1 taken 16014 times.
✓ Branch 2 taken 10782 times.
26796 true := FGraph.checkScopeType({ref}, SOME(FCore.CLASS_SCOPE()));
7416 then
7417 true;
7418
7419 case(_, DAE.FP_NON_PARALLEL(), ref::_)
7420 algorithm
7421
2/2
✓ Branch 1 taken 534 times.
✓ Branch 2 taken 15480 times.
16014 true := FGraph.checkScopeType({ref}, SOME(FCore.FUNCTION_SCOPE()));
7422 then
7423 true;
7424
7425 // Normal function call in a prallel scope is error, if it is not a built-in function.
7426 case(_, DAE.FP_NON_PARALLEL(), ref::_)
7427 algorithm
7428
1/2
✓ Branch 1 taken 534 times.
✗ Branch 2 not taken.
534 false := FNode.isRefTop(ref);
7429 ✗ scopeName := FNode.refName(ref);
7430 ✗ true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE()));
7431
7432 ✗ errorString := "\n" +
7433 "- Non-Parallel function '" + AbsynUtil.pathString(inFn) +
7434 "' can not be called from a parallel scope." + "\n" +
7435 "- Here called from :" + scopeName + "\n" +
7436 "- Please declare the function as parallel function.";
7437 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7438 {errorString}, inInfo);
7439 then
7440 false;
7441
7442
7443 // parallel function call in a parallel scope (kernel function, parallel function) is OK.
7444 // Except when it is calling itself, recurssion
7445 case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_)
7446 algorithm
7447 ✗ false := FNode.isRefTop(ref);
7448 ✗ scopeName := FNode.refName(ref);
7449 ✗ true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE()));
7450 // make sure the function is not calling itself
7451 // recurrsion is not allowed.
7452 ✗ false := stringEqual(scopeName,AbsynUtil.pathString(inFn));
7453 then
7454 true;
7455
7456 // If the above case failed (parallel function recurssion) this will print the error message
7457 case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_)
7458 algorithm
7459 ✗ false := FNode.isRefTop(ref);
7460 ✗ scopeName := FNode.refName(ref);
7461 ✗ true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE()));
7462
7463 // make sure the function is not calling itself
7464 // recurrsion is not allowed.
7465 ✗ true := stringEqual(scopeName,AbsynUtil.pathString(inFn));
7466 ✗ errorString := "\n" +
7467 "- Parallel function '" + AbsynUtil.pathString(inFn) +
7468 "' can not call itself. Recurrsion is not allowed for parallel functions currently." + "\n" +
7469 "- Parallel functions can only be called from: 'kernel' functions," +
7470 " OTHER 'parallel' functions (no recurrsion) or from a body of a" +
7471 " 'parfor' loop";
7472 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7473 {errorString}, inInfo);
7474 then
7475 false;
7476
7477 // parallel function call in a parfor scope is OK.
7478 case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_)
7479 algorithm
7480 ✗ false := FNode.isRefTop(ref);
7481 ✗ scopeName := FNode.refName(ref);
7482 ✗ true := stringEqual(scopeName, FCore.parForScopeName);
7483 then
7484 true;
7485
7486 //parallel function call in non parallel scope types is error.
7487 case(_, DAE.FP_PARALLEL_FUNCTION(), ref::_)
7488 algorithm
7489 ✗ false := FNode.isRefTop(ref);
7490 ✗ scopeName := FNode.refName(ref);
7491
7492 ✗ errorString := "\n" +
7493 "- Parallel function '" + AbsynUtil.pathString(inFn) +
7494 "' can not be called from a non parallel scope '" + scopeName + "'.\n" +
7495 "- Parallel functions can only be called from: 'kernel' functions," +
7496 " other 'parallel' functions (no recurrsion) or from a body of a" +
7497 " 'parfor' loop";
7498 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7499 {errorString}, inInfo);
7500 then false;
7501
7502 // Kernel functions should not call themselves.
7503 case(_, DAE.FP_KERNEL_FUNCTION(), ref::_)
7504 algorithm
7505 ✗ false := FNode.isRefTop(ref);
7506 ✗ scopeName := FNode.refName(ref);
7507
7508 // make sure the function is not calling itself
7509 // recurrsion is not allowed.
7510 ✗ true := stringEqual(scopeName,AbsynUtil.pathString(inFn));
7511 ✗ errorString := "\n" +
7512 "- Kernel function '" + AbsynUtil.pathString(inFn) +
7513 "' can not call itself. " + "\n" +
7514 "- Recurrsion is not allowed for Kernel functions. ";
7515 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7516 {errorString}, inInfo);
7517 then
7518 false;
7519
7520 //kernel function call in a parallel scope (kernel function, parallel function) is Error.
7521 case(_, DAE.FP_KERNEL_FUNCTION(), ref::_)
7522 algorithm
7523 ✗ false := FNode.isRefTop(ref);
7524 ✗ scopeName := FNode.refName(ref);
7525 ✗ true := FGraph.checkScopeType({ref}, SOME(FCore.PARALLEL_SCOPE()));
7526
7527 ✗ errorString := "\n" +
7528 "- Kernel function '" + AbsynUtil.pathString(inFn) +
7529 "' can not be called from a parallel scope '" + scopeName + "'.\n" +
7530 "- Kernel functions CAN NOT be called from: 'kernel' functions," +
7531 " 'parallel' functions or from a body of a" +
7532 " 'parfor' loop";
7533 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7534 {errorString}, inInfo);
7535 then
7536 false;
7537
7538 //kernel function call in a parfor loop is Error too (similar to above). just different error message.
7539 case(_, DAE.FP_KERNEL_FUNCTION(), ref::_)
7540 algorithm
7541 ✗ false := FNode.isRefTop(ref);
7542 ✗ scopeName := FNode.refName(ref);
7543
7544 ✗ true := stringEqual(scopeName, FCore.parForScopeName);
7545 ✗ errorString := "\n" +
7546 "- Kernel function '" + AbsynUtil.pathString(inFn) +
7547 "' can not be called from inside parallel for (parfor) loop body." + "'.\n" +
7548 "- Kernel functions CAN NOT be called from: 'kernel' functions," +
7549 " 'parallel' functions or from a body of a" +
7550 " 'parfor' loop";
7551 ✗ Error.addSourceMessage(Error.PARMODELICA_ERROR,
7552 {errorString}, inInfo);
7553 then false;
7554
7555 // Kernel function call in a non-parallel scope is OK.
7556 // Except when it is calling itself, recurssion
7557 case(_, DAE.FP_KERNEL_FUNCTION(), ref::_)
7558 algorithm
7559 ✗ false := FNode.isRefTop(ref);
7560 ✗ scopeName := FNode.refName(ref);
7561 // make sure the function is not calling itself
7562 // recurrsion is not allowed.
7563 ✗ false := stringEqual(scopeName,AbsynUtil.pathString(inFn));
7564 then
7565 true;
7566
7567 else true;
7568
7569 /*
7570 //Normal (non parallel) function call in a normal function scope is OK.
7571 case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then();
7572 //Normal (non parallel) function call in a normal class scope is OK.
7573 case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.CLASS_SCOPE())) then();
7574 //Normal (non parallel) function call in a normal function scope is OK.
7575 case(DAE.FP_NON_PARALLEL(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then();
7576 //Normal (non parallel) function call in a normal class scope is OK.
7577 case(DAE.FP_KERNEL_FUNCTION(), FCore.N(scopeType = FCore.CLASS_SCOPE())) then();
7578 //Normal (non parallel) function call in a normal function scope is OK.
7579 case(DAE.FP_KERNEL_FUNCTION(), FCore.N(scopeType = FCore.FUNCTION_SCOPE())) then();
7580 */
7581
7582 end matchcontinue;
7583 end isValidWRTParallelScope_dispatch;
7584
7585 protected function elabCallArgsMetarecord
7586 input FCore.Cache inCache;
7587 input FCore.Graph inEnv;
7588 input DAE.Type inType;
7589 input list<Absyn.Exp> inPosArgs;
7590 input list<Absyn.NamedArg> inNamedArgs;
7591 input Boolean inImplicit;
7592 input Mutable<Boolean> stopElab;
7593 input DAE.Prefix inPrefix;
7594 input SourceInfo inInfo;
7595 output FCore.Cache outCache;
7596 output Option<tuple<DAE.Exp,DAE.Properties>> expProps;
7597 algorithm
7598 (outCache, expProps) := matchcontinue ty as inType
7599 local
7600 Absyn.Path fq_path;
7601 String str, fn_str;
7602 list<String> field_names;
7603 list<DAE.Type> tys, typeVars;
7604 list<DAE.FuncArg> fargs;
7605 list<Slot> slots;
7606 list<DAE.Const> const_lst;
7607 DAE.Const const;
7608 DAE.TupleConst ty_const;
7609 DAE.Properties prop;
7610 list<DAE.Exp> args;
7611 InstTypes.PolymorphicBindings bindings;
7612
7613 case DAE.T_METARECORD(path=fq_path)
7614 algorithm
7615 20762 DAE.TYPES_VAR(name = str) := List.find(inType.fields, Types.varHasMetaRecordType);
7616 ✗ fn_str := AbsynUtil.pathString(fq_path);
7617 ✗ Error.addSourceMessage(Error.METARECORD_CONTAINS_METARECORD_MEMBER,
7618 {fn_str, str}, inInfo);
7619 then
7620 (inCache, NONE());
7621
7622 case DAE.T_METARECORD()
7623 algorithm
7624
1/2
✓ Branch 3 taken 20762 times.
✗ Branch 4 not taken.
20762 false := listLength(inType.fields) == listLength(inPosArgs) + listLength(inNamedArgs);
7625 ✗ fn_str := TypesDump.unparseType(inType);
7626 ✗ Error.addSourceMessage(Error.WRONG_NO_OF_ARGS, {fn_str}, inInfo);
7627 then
7628 (inCache, NONE());
7629
7630 case DAE.T_METARECORD(path = fq_path)
7631 algorithm
7632
4/4
✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
59604 field_names := list(TypesDump.getVarName(var) for var in inType.fields);
7633
4/4
✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
59604 tys := list(Types.getVarType(var) for var in inType.fields);
7634
7/8
✓ Branch 0 taken 38842 times.
✓ Branch 1 taken 20762 times.
✓ Branch 2 taken 38842 times.
✓ Branch 3 taken 20762 times.
✓ Branch 4 taken 38842 times.
✓ Branch 5 taken 20762 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 20762 times.
59604 fargs := list(Types.makeDefaultFuncArg(n, t) threaded for n in field_names, t in tys);
7635 20762 slots := makeEmptySlots(fargs);
7636 20762 (outCache, _, slots, const_lst, bindings) := elabInputArgs(inCache, inEnv, inPosArgs,
7637 inNamedArgs, slots, true, true, inImplicit,
7638 inPrefix, inInfo, inType, inType.utPath);
7639 20762 const := List.fold(const_lst, Types.constAnd, DAE.C_CONST());
7640 20762 ty_const := elabConsts(inType, const);
7641
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20762 times.
20762 true := List.fold(slots, slotAnd, true);
7642 20762 args := slotListArgs(slots);
7643
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 20755 times.
20762 if not listEmpty(bindings) then
7644 7 bindings := Types.solvePolymorphicBindings(bindings, inInfo, inType.path);
7645
4/4
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 7 times.
15 typeVars := list(Types.fixPolymorphicRestype(tv, bindings, inInfo) for tv in inType.typeVars);
7646 7 ty.typeVars := typeVars;
7647 7 prop := getProperties(ty, ty_const);
7648 else
7649 20755 prop := getProperties(ty, ty_const);
7650 end if;
7651 20762 then
7652 (outCache, SOME((DAE.METARECORDCALL(fq_path, args, field_names, inType.index, inType.typeVars), prop)));
7653
7654 // MetaRecord failure.
7655 case DAE.T_METARECORD(path = fq_path)
7656 algorithm
7657 ✗ (outCache, _, prop) := elabExpInExpression(inCache, inEnv,
7658 Absyn.TUPLE(inPosArgs), false, false, inPrefix, inInfo);
7659 ✗ tys := list(Types.getVarType(var) for var in inType.fields);
7660 ✗ str := "Failed to match types:\n actual: " +
7661 TypesDump.unparseType(Types.getPropType(prop)) +
7662 "\n expected: " +
7663 TypesDump.unparseType(DAE.T_TUPLE(tys, NONE()));
7664 ✗ fn_str := AbsynUtil.pathString(fq_path);
7665 ✗ Error.addSourceMessage(Error.META_RECORD_FOUND_FAILURE, {fn_str, str}, inInfo);
7666 then
7667 (outCache, NONE());
7668
7669 // MetaRecord failure (args).
7670 case DAE.T_METARECORD(path = fq_path)
7671 algorithm
7672 ✗ str := "Failed to elaborate arguments " + Dump.printExpStr(Absyn.TUPLE(inPosArgs));
7673 ✗ fn_str := AbsynUtil.pathString(fq_path);
7674 ✗ Error.addSourceMessage(Error.META_RECORD_FOUND_FAILURE, {fn_str, str}, inInfo);
7675 then
7676 (inCache, NONE());
7677
7678 end matchcontinue;
7679 end elabCallArgsMetarecord;
7680
7681 protected uniontype ForceFunctionInst
7682 record FORCE_FUNCTION_INST "Used when blocking function instantiation to instantiate the function anyway" end FORCE_FUNCTION_INST;
7683 record NORMAL_FUNCTION_INST "Used when blocking function instantiation to instantiate the function anyway" end NORMAL_FUNCTION_INST;
7684 end ForceFunctionInst;
7685
7686 public function instantiateDaeFunction
7687 "Help function to elabCallArgs. Instantiates the function as a DAE and adds it
7688 to the functiontree of a newly created DAE."
7689 input FCore.Cache inCache;
7690 input FCore.Graph env;
7691 input Absyn.Path name;
7692 input Boolean builtin "builtin functions create empty dae";
7693 input Option<SCode.Element> clOpt "if not present, looked up by name in environment";
7694 input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated";
7695 output FCore.Cache outCache;
7696 output Util.Status status;
7697 algorithm
7698 60997 (outCache,status) := instantiateDaeFunction2(inCache, env, name, builtin,
7699 clOpt, printErrorMsg, NORMAL_FUNCTION_INST());
7700 end instantiateDaeFunction;
7701
7702 public function instantiateDaeFunctionFromTypes
7703 "Help function to elabCallArgs. Instantiates the function as a DAE and adds it
7704 to the functiontree of a newly created DAE."
7705 input FCore.Cache inCache;
7706 input FCore.Graph env;
7707 input list<DAE.Type> tys;
7708 input Boolean builtin "builtin functions create empty dae";
7709 input Option<SCode.Element> clOpt "if not present, looked up by name in environment";
7710 input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated";
7711 input Util.Status acc;
7712 output FCore.Cache outCache;
7713 output Util.Status status;
7714 algorithm
7715 (outCache,status) := match (tys, acc)
7716 local
7717 Absyn.Path name;
7718 list<DAE.Type> rest;
7719
7720 case (DAE.T_FUNCTION(path = name) :: rest, Util.SUCCESS())
7721 algorithm
7722 500 (outCache,status) := instantiateDaeFunction(inCache, env, name, builtin, clOpt, printErrorMsg);
7723 500 then
7724 instantiateDaeFunctionFromTypes(inCache, env, rest, builtin, clOpt, printErrorMsg, status);
7725
7726 else (inCache, acc);
7727 end match;
7728 end instantiateDaeFunctionFromTypes;
7729
7730 public function instantiateDaeFunctionForceInst
7731 "Help function to elabCallArgs. Instantiates the function as a DAE and adds it
7732 to the functiontree of a newly created DAE."
7733 input FCore.Cache inCache;
7734 input FCore.Graph env;
7735 input Absyn.Path name;
7736 input Boolean builtin "builtin functions create empty dae";
7737 input Option<SCode.Element> clOpt "if not present, looked up by name in environment";
7738 input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated";
7739 output FCore.Cache outCache;
7740 output Util.Status status;
7741 algorithm
7742 ✗ (outCache,status) := instantiateDaeFunction2(inCache, env, name, builtin,
7743 clOpt, printErrorMsg, FORCE_FUNCTION_INST());
7744 end instantiateDaeFunctionForceInst;
7745
7746 protected function instantiateDaeFunction2
7747 "Help function to elabCallArgs. Instantiates the function as a DAE and adds it
7748 to the functiontree of a newly created DAE."
7749 input FCore.Cache inCache;
7750 input FCore.Graph inEnv;
7751 input Absyn.Path inName;
7752 input Boolean builtin "builtin functions create empty dae";
7753 input Option<SCode.Element> clOpt "if not present, looked up by name in environment";
7754 input Boolean printErrorMsg "if true, prints an error message if the function could not be instantiated";
7755 input ForceFunctionInst forceFunctionInst;
7756 output FCore.Cache outCache;
7757 output Util.Status status;
7758 protected
7759 Integer numError = Error.getNumErrorMessages();
7760 Boolean instOnlyForcedFunctions = isSome(getGlobalRoot(Global.instOnlyForcedFunctions));
7761 algorithm
7762 (outCache,status) := matchcontinue(builtin, clOpt, instOnlyForcedFunctions, forceFunctionInst)
7763 local
7764 FCore.Graph env;
7765 SCode.Element cl;
7766 String pathStr,envStr;
7767 DAE.ComponentRef cref;
7768 Absyn.Path name;
7769 DAE.Type ty;
7770
7771 // Skip function instantiation if we set those flags
7772 case (_, _, true, NORMAL_FUNCTION_INST())
7773 algorithm
7774 // Don't skip builtin functions or functions in the same package; they are useful to inline
7775 ✗ false := AbsynUtil.pathIsIdent(inName);
7776 // print("Skipping: " + AbsynUtil.pathString(name) + "\n");
7777 then
7778 (inCache, Util.SUCCESS());
7779
7780 // Builtin functions skipped
7781 case (true, _, _, _) then (inCache, Util.SUCCESS());
7782
7783 // External object functions skipped
7784 case (_, _, _, NORMAL_FUNCTION_INST())
7785 algorithm
7786
2/2
✓ Branch 1 taken 31832 times.
✓ Branch 2 taken 45 times.
31877 (_, true) := isExternalObjectFunction(inCache, inEnv, inName);
7787 then
7788 (inCache, Util.SUCCESS());
7789
7790 // Recursive calls (by looking at environment) skipped
7791 case (_, NONE(), _, _)
7792 algorithm
7793
2/2
✓ Branch 1 taken 409 times.
✓ Branch 2 taken 31423 times.
31832 false := FGraph.isTopScope(inEnv);
7794
2/2
✓ Branch 2 taken 31408 times.
✓ Branch 3 taken 15 times.
31423 true := AbsynUtil.pathSuffixOf(inName, FGraph.getGraphName(inEnv));
7795 then
7796 (inCache, Util.SUCCESS());
7797
7798 // Recursive calls (by looking in cache) skipped
7799 case (_, _, _, _)
7800 algorithm
7801 31817 (outCache, _, _, name) := lookupAndFullyQualify(inCache, inEnv, inName);
7802 31649 FCore.checkCachedInstFuncGuard(outCache, name);
7803 then
7804 (outCache, Util.SUCCESS());
7805
7806 // class must be looked up
7807 case (_, NONE(), _, _)
7808 algorithm
7809 5928 (outCache, env, cl, name) := lookupAndFullyQualify(inCache, inEnv, inName);
7810 5760 outCache := FCore.addCachedInstFuncGuard(outCache, name);
7811 5760 outCache := InstFunction.implicitFunctionInstantiation(outCache, env,
7812 InnerOuter.emptyInstHierarchy, DAE.NOMOD(), DAE.NOPRE(), cl, {});
7813 then
7814 (outCache, Util.SUCCESS());
7815
7816 // class already available
7817 case (_, SOME(cl), _, _)
7818 algorithm
7819 ✗ (outCache,_) := Inst.makeFullyQualified(inCache, inEnv, inName);
7820 ✗ outCache := InstFunction.implicitFunctionInstantiation(outCache, inEnv,
7821 InnerOuter.emptyInstHierarchy, DAE.NOMOD(), DAE.NOPRE(), cl, {});
7822 then
7823 (outCache, Util.SUCCESS());
7824
7825 // call to function reference variable
7826 case (_, NONE(), _, _)
7827 algorithm
7828 187 cref := ComponentReference.pathToCref(inName);
7829 187 (outCache, _, ty) := Lookup.lookupVar(inCache, inEnv, cref);
7830
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 168 times.
168 DAE.T_FUNCTION() := ty;
7831 then
7832 (outCache, Util.SUCCESS());
7833
7834 case (_, _, true, _)
7835 algorithm
7836 ✗ true := Error.getNumErrorMessages() == numError;
7837 ✗ envStr := FGraph.printGraphPathStr(inEnv);
7838 ✗ pathStr := AbsynUtil.pathString(inName);
7839 ✗ Error.addMessage(Error.GENERIC_INST_FUNCTION, {pathStr, envStr});
7840 ✗ then
7841 fail();
7842
7843 else (inCache, Util.FAILURE());
7844 end matchcontinue;
7845 end instantiateDaeFunction2;
7846
7847 protected function lookupAndFullyQualify
7848 input FCore.Cache inCache;
7849 input FCore.Graph inEnv;
7850 input Absyn.Path inFunctionName;
7851 output FCore.Cache outCache;
7852 output FCore.Graph outEnv;
7853 output SCode.Element outClass;
7854 output Absyn.Path outFunctionName;
7855 algorithm
7856
2/2
✓ Branch 1 taken 320 times.
✓ Branch 2 taken 37425 times.
37745 if Lookup.isFunctionCallViaComponent(inCache, inEnv, inFunctionName) then
7857 // do NOT qualify function calls via component instance!
7858 320 (_, outClass, outEnv) := Lookup.lookupClass(inCache, inEnv, inFunctionName);
7859 320 outFunctionName := FGraph.joinScopePath(outEnv, AbsynUtil.makeIdentPathFromString(SCodeUtil.elementName(outClass)));
7860 outCache := inCache;
7861 else
7862 // qualify everything else
7863 37425 (outCache, outClass, outEnv) := Lookup.lookupClass(inCache, inEnv, inFunctionName);
7864 37089 outFunctionName := AbsynUtil.makeFullyQualified(
7865 FGraph.joinScopePath(outEnv, AbsynUtil.makeIdentPathFromString(SCodeUtil.elementName(outClass))));
7866 end if;
7867 end lookupAndFullyQualify;
7868
7869 protected function instantiateImplicitRecordConstructors
7870 "Given a list of arguments to a function, this function checks if any of the
7871 arguments are component references to a record instance, and instantiates the
7872 record constructors for those components. These are implicit record
7873 constructors, because they are not explicitly called, but are needed when code
7874 is generated for record instances as function input arguments."
7875 input FCore.Cache inCache;
7876 input FCore.Graph inEnv;
7877 input list<DAE.Exp> args;
7878 output FCore.Cache outCache;
7879 algorithm
7880 outCache := matchcontinue args
7881 local
7882 list<DAE.Exp> rest_args;
7883 Absyn.Path record_name;
7884 FCore.Cache cache;
7885
7886 // case (_, SOME(_)) then inCache; // TODO: Should this just return now? We always have symbol table!
7887 case {} then inCache;
7888
7889 case DAE.CREF(ty = DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(path = record_name))) :: rest_args
7890 algorithm
7891
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4197 times.
4197 (cache, Util.SUCCESS()) := instantiateDaeFunction(inCache, inEnv, record_name, false, NONE(), false);
7892 4197 then
7893 instantiateImplicitRecordConstructors(cache, inEnv, rest_args);
7894
7895 case _ :: rest_args
7896 76435 then instantiateImplicitRecordConstructors(inCache, inEnv, rest_args);
7897
7898 end matchcontinue;
7899 end instantiateImplicitRecordConstructors;
7900
7901 protected function addDefaultArgs
7902 "Adds default values to a list of function slots."
7903 input list<Slot> inSlots;
7904 input SourceInfo inInfo;
7905 output list<DAE.Exp> outArgs;
7906 output list<Slot> outSlots;
7907 algorithm
7908 56371 (outArgs, outSlots) := List.map2_2(inSlots, fillDefaultSlot, listArray(inSlots), inInfo);
7909 end addDefaultArgs;
7910
7911 protected function fillDefaultSlot
7912 "Fills a function slot with it's default value if it hasn't already been filled."
7913 input Slot inSlot;
7914 input array<Slot> inSlotArray;
7915 input SourceInfo inInfo;
7916 output DAE.Exp outArg;
7917 output Slot outSlot;
7918 algorithm
7919 (outArg, outSlot) := match inSlot
7920 local
7921 DAE.Exp arg;
7922 String id;
7923 Integer idx;
7924
7925 // Slot already filled by function argument.
7926 81868 case SLOT(slotFilled = true, arg = SOME(arg)) then (arg, inSlot);
7927
7928 // Slot not filled by function argument, but has default value.
7929 case SLOT(slotFilled = false, defaultArg = DAE.FUNCARG(defaultBinding=SOME(_)), idx = idx)
7930 21872 then fillDefaultSlot2(inSlotArray[idx], inSlotArray, inInfo);
7931
7932 // Slot not filled, and has no default value => error.
7933 case SLOT(defaultArg = DAE.FUNCARG(name = id))
7934 algorithm
7935 83 Error.addSourceMessage(Error.UNFILLED_SLOT, {id}, inInfo);
7936 83 then
7937 fail();
7938
7939 end match;
7940 end fillDefaultSlot;
7941
7942 protected function fillDefaultSlot2
7943 input Slot inSlot;
7944 input array<Slot> inSlotArray;
7945 input SourceInfo inInfo;
7946 output DAE.Exp outArg;
7947 output Slot outSlot = inSlot;
7948 algorithm
7949 (outArg, outSlot) := match outSlot
7950 local
7951 DAE.Exp exp;
7952 String id;
7953 Integer idx;
7954
7955 // An already evaluated slot, return its binding.
7956 case SLOT(arg = SOME(exp), evalStatus = 2)
7957 then (exp, inSlot);
7958
7959 // A slot in the process of being evaluated => cyclic bindings.
7960 case SLOT(defaultArg = DAE.FUNCARG(name=id),
7961 evalStatus = 1)
7962 algorithm
7963 ✗ Error.addSourceMessage(Error.CYCLIC_DEFAULT_VALUE,
7964 {id}, inInfo);
7965 ✗ then
7966 fail();
7967
7968 // A slot with an unevaluated binding, evaluate the binding and return it.
7969 case SLOT(defaultArg = DAE.FUNCARG(defaultBinding=SOME(exp)),
7970 idx = idx, evalStatus = 0)
7971 algorithm
7972 21872 outSlot.evalStatus := SLOT_EVALUATING;
7973 21872 arrayUpdate(inSlotArray, idx, outSlot);
7974
7975 21872 exp := evaluateSlotExp(exp, inSlotArray, inInfo);
7976 21872 outSlot.arg := SOME(exp);
7977 21872 outSlot.slotFilled := true;
7978
7979 21872 outSlot.evalStatus := SLOT_EVALUATED;
7980 21872 arrayUpdate(inSlotArray, idx, outSlot);
7981 then
7982 (exp, outSlot);
7983
7984 end match;
7985 end fillDefaultSlot2;
7986
7987 protected function evaluateSlotExp
7988 "Evaluates a slot's binding by recursively replacing references to other slots
7989 with their bindings."
7990 input DAE.Exp inExp;
7991 input array<Slot> inSlotArray;
7992 input SourceInfo inInfo;
7993 output DAE.Exp outExp;
7994 algorithm
7995 21872 outExp := Expression.traverseExpBottomUp(inExp, evaluateSlotExp_traverser, (inSlotArray, inInfo));
7996 end evaluateSlotExp;
7997
7998 protected function evaluateSlotExp_traverser
7999 input DAE.Exp inExp;
8000 input tuple<array<Slot>, SourceInfo> inTuple;
8001 output DAE.Exp outExp;
8002 output tuple<array<Slot>, SourceInfo> outTuple;
8003 algorithm
8004 (outExp,outTuple) := match (inExp, inTuple)
8005 local
8006 String id;
8007 array<Slot> slots;
8008 Option<Slot> slot;
8009 DAE.Exp exp, orig_exp;
8010 SourceInfo info;
8011
8012 // Only simple identifiers can be slot names.
8013 case (orig_exp as DAE.CREF(componentRef = DAE.CREF_IDENT(ident = id)), (slots, info))
8014 algorithm
8015 6 slot := lookupSlotInArray(id, slots);
8016 6 exp := getOptSlotDefaultExp(slot, slots, info, orig_exp);
8017 6 then
8018 (exp, (slots, info));
8019
8020 else (inExp, inTuple);
8021 end match;
8022 end evaluateSlotExp_traverser;
8023
8024 protected function lookupSlotInArray
8025 "Looks up the given name in an array of slots, and returns either SOME(slot)
8026 if a slot with that name was found, or NONE() if a slot couldn't be found."
8027 input String inSlotName;
8028 input array<Slot> inSlots;
8029 output Option<Slot> outSlot;
8030 protected
8031 Slot slot;
8032 algorithm
8033 try
8034 6 slot := Array.getMemberOnTrue(inSlotName, inSlots, isSlotNamed);
8035 outSlot := SOME(slot);
8036 else
8037 outSlot := NONE();
8038 end try;
8039 end lookupSlotInArray;
8040
8041 protected function isSlotNamed
8042 input String inName;
8043 input Slot inSlot;
8044 output Boolean outIsNamed;
8045 protected
8046 String id;
8047 algorithm
8048 8 SLOT(defaultArg = DAE.FUNCARG(name=id)) := inSlot;
8049
3/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 5 times.
8 outIsNamed := stringEq(id, inName);
8050 end isSlotNamed;
8051
8052 protected function getOptSlotDefaultExp
8053 "Takes an optional slot and tries to evaluate the slot's binding if it's SOME,
8054 otherwise returns the original expression if it's NONE."
8055 input Option<Slot> inSlot;
8056 input array<Slot> inSlots;
8057 input SourceInfo inInfo;
8058 input DAE.Exp inOrigExp;
8059 output DAE.Exp outExp;
8060 algorithm
8061 outExp := match inSlot
8062 local
8063 Slot slot;
8064 DAE.Exp exp;
8065
8066 // Got a slot, evaluate its binding and return it.
8067 case SOME(slot)
8068 algorithm
8069 5 exp := fillDefaultSlot(slot, inSlots, inInfo);
8070 then
8071 exp;
8072
8073 // No slot, return the original expression.
8074 case NONE() then inOrigExp;
8075 end match;
8076 end getOptSlotDefaultExp;
8077
8078 protected function determineConstSpecialFunc
8079 "For the special functions constructor and destructor, in external object, the
8080 constantness is always variable, even if arguments are constant, because they
8081 should be called during runtime and not during compiletime."
8082 input FCore.Cache inCache;
8083 input FCore.Graph inEnv;
8084 input DAE.Const inConst;
8085 input Absyn.Path inFuncName;
8086 output FCore.Cache outCache;
8087 output DAE.Const outConst;
8088 protected
8089 Boolean is_ext;
8090 algorithm
8091 55889 (outCache, is_ext) := isExternalObjectFunction(inCache, inEnv, inFuncName);
8092
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 55844 times.
55889 outConst := if is_ext then DAE.C_VAR() else inConst;
8093 end determineConstSpecialFunc;
8094
8095 public function isExternalObjectFunction
8096 input FCore.Cache inCache;
8097 input FCore.Graph inEnv;
8098 input Absyn.Path inPath;
8099 output FCore.Cache outCache;
8100 output Boolean outIsExt;
8101 protected
8102 list<SCode.Element> els;
8103 String last_id;
8104 algorithm
8105 try
8106
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 71543 times.
✓ Branch 3 taken 1591 times.
✓ Branch 4 taken 69952 times.
157718 (outCache, SCode.CLASS(classDef = SCode.PARTS(elementLst = els)), _) :=
8107 Lookup.lookupClass(inCache, inEnv, inPath);
8108
1/2
✓ Branch 1 taken 69952 times.
✗ Branch 2 not taken.
69952 true := SCodeUtil.isExternalObject(els);
8109 outIsExt := true;
8110 else
8111 87766 last_id := AbsynUtil.pathLastIdent(inPath);
8112 outCache := inCache;
8113
7/8
✓ Branch 0 taken 5928 times.
✓ Branch 1 taken 81838 times.
✓ Branch 3 taken 5838 times.
✓ Branch 4 taken 90 times.
✓ Branch 5 taken 3530 times.
✓ Branch 6 taken 84146 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 3530 times.
87766 outIsExt := last_id == "constructor" or last_id == "destructor";
8114 end try;
8115 end isExternalObjectFunction;
8116
8117 protected constant String vectorizeArg = "$vectorizeArg";
8118
8119 protected function vectorizeCall "author: PA
8120 Takes an expression and a list of array dimensions and the Slot list.
8121 It will vectorize the expression over the dimension given as array dim
8122 for the slots which have that dimension.
8123 For example foo:(Real,Real[:])=> Real
8124 foo(1:2,{1,2;3,4}) vectorizes with arraydim [2] to
8125 {foo(1,{1,2}),foo(2,{3,4})}"
8126 input DAE.Exp inExp;
8127 input DAE.Dimensions inDims;
8128 input list<Slot> inSlots;
8129 input DAE.Properties inProperties;
8130 input SourceInfo info;
8131 output DAE.Exp outExp;
8132 output DAE.Properties outProperties;
8133 algorithm
8134 (outExp, outProperties) := matchcontinue (inExp, inDims, inProperties)
8135 local
8136 DAE.Exp e,vect_exp;
8137 DAE.Type tp;
8138 DAE.Properties prop;
8139 DAE.Type exp_type;
8140 DAE.Const c;
8141 Absyn.Path fn;
8142 list<DAE.Exp> es;
8143 Integer int_dim;
8144 DAE.Dimension dim;
8145 DAE.Dimensions ad;
8146 String str;
8147 DAE.CallAttributes attr;
8148 DAE.ReductionInfo rinfo;
8149 String foldName,resultName;
8150 list<DAE.ReductionIterator> riters;
8151 Absyn.ReductionIterType iterType;
8152
8153 56288 case (e, {}, prop) then (e,prop);
8154
8155 // If the dimension is not defined we can't vectorize the call. If we are running
8156 // checkModel this should succeed anyway, since we might be checking a function
8157 // that takes a vector of unknown size. So pretend that the dimension is 1.
8158 case (e, (DAE.DIM_UNKNOWN() :: ad), prop)
8159 guard Flags.getConfigBool(Flags.CHECK_MODEL)
8160 ✗ then vectorizeCall(e, DAE.DIM_INTEGER(1) :: ad, inSlots, prop, info);
8161
8162 /* Scalar expression, i.e function call */
8163 case (e as DAE.CALL(),(dim :: ad),DAE.PROP(tp,c))
8164 algorithm
8165 2414 int_dim := Expression.dimensionSize(dim);
8166 2409 exp_type := Types.simplifyType(Types.liftArray(tp, dim)) "pass type of vectorized result expr";
8167 2409 vect_exp := vectorizeCallScalar(e, exp_type, int_dim, inSlots);
8168 2409 tp := Types.liftArray(tp, dim);
8169 2409 then vectorizeCall(vect_exp, ad, inSlots, DAE.PROP(tp,c),info);
8170
8171 /* array expression of function calls */
8172 case (DAE.ARRAY(),(dim :: ad),DAE.PROP(tp,c))
8173 algorithm
8174 ✗ int_dim := Expression.dimensionSize(dim);
8175 // _ = Types.simplifyType(Types.liftArray(tp, dim));
8176 ✗ vect_exp := vectorizeCallArray(inExp, int_dim, inSlots);
8177 ✗ tp := Types.liftArrayRight(tp, dim);
8178 ✗ then vectorizeCall(vect_exp, ad, inSlots, DAE.PROP(tp,c),info);
8179
8180 /* Multiple dimensions are possible to change to a reduction, like:
8181 * f(arr1,arr2) => array(f(x,y) thread for x in arr1, y in arr2)
8182 * f(mat1,mat2) => array(array(f(x,y) thread for x in arr1, y in arr2) thread for arr1 in mat1, arr2 in mat2
8183 */
8184 case (DAE.CALL(fn,es,attr),dim::ad,prop as DAE.PROP(tp,c))
8185 algorithm
8186 5 (es, riters) := vectorizeCallUnknownDimension(es,inSlots,info);
8187 5 tp := Types.liftArrayRight(tp, dim);
8188 5 prop := DAE.PROP(tp,c);
8189 5 e := DAE.CALL(fn,es,attr);
8190 5 (e, prop) := vectorizeCall(e,ad,inSlots,prop,info); // Recurse...
8191 5 foldName := Util.getTempVariableIndex();
8192 5 resultName := Util.getTempVariableIndex();
8193
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
5 iterType := if listLength(riters)>1 then Absyn.THREAD() else Absyn.COMBINE();
8194 5 rinfo := DAE.REDUCTIONINFO(Absyn.IDENT("array"),iterType,tp,SOME(Values.ARRAY({},{0})),foldName,resultName,NONE());
8195 5 then
8196 (DAE.REDUCTION(rinfo, e, riters), prop);
8197
8198 /* Scalar expression, non-constant but known dimensions */
8199 case (DAE.CALL(),(DAE.DIM_EXP() :: _),DAE.PROP())
8200 algorithm
8201 ✗ str := "Cannot vectorize call with dimensions [" + ExpressionBasics.dimensionsString(inDims) + "]";
8202 ✗ Error.addSourceMessage(Error.INTERNAL_ERROR,{str},info);
8203 ✗ then
8204 fail();
8205
8206 else
8207 algorithm
8208 ✗ true := Flags.isSet(Flags.FAILTRACE);
8209 ✗ str := ExpressionBasics.dimensionString(listHead(inDims));
8210 ✗ Debug.traceln("- Static.vectorizeCall failed: " + str);
8211 ✗ then
8212 fail();
8213 end matchcontinue;
8214 end vectorizeCall;
8215
8216 protected function vectorizeCallUnknownDimension
8217 "Returns the new call arguments and a reduction iterator argument"
8218 input list<DAE.Exp> inEs;
8219 input list<Slot> inSlots;
8220 input SourceInfo info;
8221 output list<DAE.Exp> oes = {};
8222 output list<DAE.ReductionIterator> ofound = {};
8223 protected
8224 list<Slot> rest_slots = inSlots;
8225 list<DAE.Dimension> dims;
8226 DAE.Type ty, tp;
8227 String name;
8228 algorithm
8229
2/2
✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
12 for e in inEs loop
8230
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 SLOT(dims = dims, defaultArg = DAE.FUNCARG(ty = ty)) :: rest_slots := rest_slots;
8231
8232
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
7 if listEmpty(dims) then
8233 oes := e :: oes;
8234 else
8235 7 name := Util.getTempVariableIndex();
8236 7 tp := Types.expTypetoTypesType(Expression.typeof(e)); // Maybe raise the type from the SLOT instead?
8237 7 ofound := DAE.REDUCTIONITER(name, e, NONE(), tp) :: ofound;
8238 7 oes := DAE.CREF(DAE.CREF_IDENT(name, ty, {}), ty) :: oes;
8239 end if;
8240 end for;
8241
8242
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
5 if listEmpty(ofound) then
8243 ✗ Error.addSourceMessageAndFail(Error.INTERNAL_ERROR,
8244 {"Static.vectorizeCallUnknownDimension could not find any slot to vectorize"}, info);
8245 end if;
8246
8247 5 oes := listReverse(oes);
8248 5 ofound := listReverse(ofound);
8249 end vectorizeCallUnknownDimension;
8250
8251 protected function vectorizeCallArray
8252 "Helper function to vectorizeCall, vectorizes an ARRAY expression to an array
8253 of array expressions."
8254 input DAE.Exp inExp;
8255 input Integer inDim;
8256 input list<Slot> inSlots;
8257 output DAE.Exp outExp;
8258 protected
8259 DAE.Type ty;
8260 list<DAE.Exp> expl;
8261 Boolean sc;
8262 algorithm
8263 ✗ DAE.ARRAY(ty = ty, array = expl) := inExp;
8264 ✗ expl := vectorizeCallArray2(expl, ty, inDim, inSlots);
8265 ✗ sc := Expression.typeBuiltin(ty);
8266 ✗ ty := Expression.liftArrayRight(ty, DAE.DIM_INTEGER(inDim));
8267 ✗ outExp := DAE.ARRAY(ty, sc, expl);
8268 end vectorizeCallArray;
8269
8270 protected function vectorizeCallArray2
8271 "Helper function to vectorizeCallArray"
8272 input list<DAE.Exp> inExpl;
8273 input DAE.Type inType;
8274 input Integer inDim;
8275 input list<Slot> inSlots;
8276 output list<DAE.Exp> outExpl;
8277 algorithm
8278 ✗ outExpl := list(
8279 match e
8280 ✗ case DAE.CALL() then vectorizeCallScalar(e, inType, inDim, inSlots);
8281 ✗ case DAE.ARRAY() then vectorizeCallArray(e, inDim, inSlots);
8282 end match for e in inExpl);
8283 end vectorizeCallArray2;
8284
8285 protected function vectorizeCallScalar
8286 "author: PA
8287 Helper function to vectorizeCall, vectorizes CALL expressions to
8288 array expressions."
8289 input DAE.Exp exp "e.g. abs(v)";
8290 input DAE.Type ty " e.g. Real[3], result of vectorized call";
8291 input Integer dim;
8292 input list<Slot> slots;
8293 output DAE.Exp outExp;
8294 algorithm
8295 outExp := matchcontinue exp
8296 local
8297 list<DAE.Exp> expl;
8298 Boolean scalar;
8299 DAE.Exp new_exp;
8300 DAE.Type e_type,arr_type;
8301
8302 case DAE.CALL()
8303 algorithm
8304 2409 expl := vectorizeCallScalar2(exp.path, exp.expLst, exp.attr, slots, dim);
8305 2409 e_type := Expression.unliftArray(ty);
8306 2409 scalar := Expression.typeBuiltin(e_type) " unlift vectorized dimension to find element type";
8307 4818 arr_type := DAE.T_ARRAY(e_type, {DAE.DIM_INTEGER(dim)});
8308
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2409 times.
2409 new_exp := DAE.ARRAY(arr_type,scalar,expl);
8309 then
8310 new_exp;
8311
8312 else
8313 algorithm
8314 ✗ true := Flags.isSet(Flags.FAILTRACE);
8315 ✗ Debug.trace("-Static.vectorizeCallScalar failed\n");
8316 ✗ then
8317 fail();
8318 end matchcontinue;
8319 end vectorizeCallScalar;
8320
8321 protected function vectorizeCallScalar2
8322 "Iterates through vectorized dimension an creates argument list according to vectorized dimension in corresponding slot."
8323 input Absyn.Path fn;
8324 input list<DAE.Exp> exps;
8325 input DAE.CallAttributes attr;
8326 input list<Slot> slots;
8327 input Integer dim;
8328 output list<DAE.Exp> res = {};
8329 protected
8330 list<DAE.Exp> callargs;
8331 algorithm
8332
2/2
✓ Branch 0 taken 222 times.
✓ Branch 1 taken 2187 times.
8848 for cur_dim in dim:-1:1 loop
8333 6439 callargs := vectorizeCallScalar3(exps, slots, cur_dim);
8334 6439 res := DAE.CALL(fn,callargs,attr) :: res;
8335 end for;
8336 end vectorizeCallScalar2;
8337
8338 protected function vectorizeCallScalar3
8339 "author: PA
8340 Helper function to vectorizeCallScalar2"
8341 input list<DAE.Exp> inExpl;
8342 input list<Slot> inSlots;
8343 input Integer inIndex;
8344 output list<DAE.Exp> outExpl = {};
8345 protected
8346 list<Slot> rest_slots = inSlots;
8347 list<DAE.Dimension> dims;
8348 algorithm
8349
2/2
✓ Branch 0 taken 9682 times.
✓ Branch 1 taken 6439 times.
16121 for e in inExpl loop
8350
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9682 times.
9682 SLOT(dims = dims) :: rest_slots := rest_slots;
8351
8352
2/2
✓ Branch 0 taken 7775 times.
✓ Branch 1 taken 1907 times.
9682 if not listEmpty(dims) then
8353 // Foreach argument.
8354 15550 e := Expression.makeASUB(e, {DAE.ICONST(inIndex)});
8355 7775 e := ExpressionSimplify.simplify1(e);
8356 end if;
8357
8358 outExpl := e :: outExpl;
8359 end for;
8360
8361 6439 outExpl := listReverse(outExpl);
8362 end vectorizeCallScalar3;
8363
8364 protected function deoverloadFuncname
8365 "This function is used to deoverload function calls. It investigates the
8366 type of the function to see if it has the optional functionname set. If
8367 so this is returned. Otherwise return input."
8368 input Absyn.Path inPath;
8369 input DAE.Type inType;
8370 input FCore.Graph inEnv;
8371 output Absyn.Path outPath;
8372 output DAE.Type outType;
8373 algorithm
8374 (outPath,outType) := match inType
8375 local
8376 Absyn.Path fn;
8377 String name;
8378 DAE.Type tty;
8379
8380 case tty as DAE.T_FUNCTION(functionAttributes = DAE.FUNCTION_ATTRIBUTES(
8381 isBuiltin = DAE.FUNCTION_BUILTIN(SOME(name))))
8382 algorithm
8383 57278 tty.path := Absyn.IDENT(name);
8384 then (tty.path, tty);
8385
8386 case DAE.T_FUNCTION(path = fn) then (fn,inType);
8387 else (inPath, inType);
8388
8389 end match;
8390 end deoverloadFuncname;
8391
8392 protected function elabTypes
8393 "Elaborate input parameters to a function and select matching function type
8394 from a list of types."
8395 input FCore.Cache inCache;
8396 input FCore.Graph inEnv;
8397 input list<Absyn.Exp> inPosArgs;
8398 input list<Absyn.NamedArg> inNamedArgs;
8399 input list<Absyn.Path> typeVars;
8400 input list<DAE.Type> inTypes;
8401 input Boolean inOnlyOneFunction "if true, we can report errors as soon as possible";
8402 input Boolean inCheckTypes "if true, checks types";
8403 input Boolean inImplicit;
8404 input DAE.Prefix inPrefix;
8405 input SourceInfo inInfo;
8406 output FCore.Cache outCache = inCache;
8407 output list<DAE.Exp> outArgs = {};
8408 output list<DAE.Const> outConsts = {};
8409 output DAE.Type outResultType = DAE.T_UNKNOWN_DEFAULT;
8410 output DAE.Type outFunctionType = DAE.T_UNKNOWN_DEFAULT;
8411 output DAE.Dimensions outDimensions = {};
8412 output list<Slot> outSlots = {};
8413 protected
8414 list<DAE.FuncArg> params;
8415 DAE.Type res_ty, func_ty;
8416 DAE.FunctionAttributes func_attr;
8417 list<Slot> slots;
8418 InstTypes.PolymorphicBindings pb;
8419 Absyn.Path path;
8420 Boolean success = false;
8421 list<DAE.Type> rest_tys = inTypes, tys;
8422 DAE.Exp arg;
8423 Integer numArgs;
8424 DAE.FuncArg funcarg;
8425 constant Boolean debug=false;
8426 algorithm
8427
2/2
✓ Branch 1 taken 877 times.
✓ Branch 2 taken 55409 times.
56286 if listLength(rest_tys)>1 then
8428 // Filter out some interesting candidates first; this makes us not
8429 // look at overloaded functions with the wrong number of arguments (getting weird error-messages)
8430 877 numArgs := listLength(inPosArgs)+listLength(inNamedArgs);
8431
13/14
✓ Branch 0 taken 1968 times.
✓ Branch 1 taken 1755 times.
✓ Branch 2 taken 1968 times.
✓ Branch 3 taken 1755 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 1968 times.
✓ Branch 6 taken 26 times.
✓ Branch 7 taken 1942 times.
✓ Branch 9 taken 1753 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 1748 times.
✓ Branch 12 taken 5 times.
✓ Branch 13 taken 1755 times.
✓ Branch 14 taken 877 times.
6355 tys := list(ty for ty guard match ty case DAE.T_FUNCTION() then
8432 ((numArgs <= listLength(ty.funcArg)) and numArgs >= sum(if isNone(argument.defaultBinding) then 1 else 0 for argument in ty.funcArg));
8433 end match in rest_tys);
8434
1/2
✓ Branch 0 taken 877 times.
✗ Branch 1 not taken.
877 if not listEmpty(tys) then
8435 rest_tys := tys;
8436 end if;
8437 end if;
8438
2/2
✓ Branch 0 taken 57419 times.
✓ Branch 1 taken 55961 times.
113380 while not success loop
8439
2/2
✓ Branch 0 taken 325 times.
✓ Branch 1 taken 57094 times.
57419 func_ty :: rest_tys := rest_tys;
8440
8441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 57094 times.
57094 DAE.T_FUNCTION(funcArg = params, funcResultType = res_ty,
8442 functionAttributes = func_attr, path = path) := func_ty;
8443 if debug then
8444 print("elabTypes, try: " + TypesDump.unparseType(func_ty) + "\n");
8445 end if;
8446 try
8447 57094 slots := makeEmptySlots(params);
8448 57094 (outCache, outArgs, outSlots, outConsts, pb) := elabInputArgs(inCache, inEnv,
8449 inPosArgs, inNamedArgs, slots, inOnlyOneFunction, inCheckTypes, inImplicit,
8450 inPrefix, inInfo, func_ty, path);
8451 55978 (outCache, pb) := addPolymorphicTypeVars(outCache, inEnv, typeVars, func_ty, pb, path, inInfo);
8452 55964 pb := Types.solvePolymorphicBindings(pb, inInfo, path);
8453 55961 res_ty := Types.fixPolymorphicRestype(res_ty, pb, inInfo);
8454 (outArgs, outSlots, params, res_ty) := match func_attr.isBuiltin
8455 case DAE.FUNCTION_BUILTIN(unboxArgs=true)
8456
4/4
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 177 times.
✓ Branch 2 taken 186 times.
✓ Branch 3 taken 177 times.
363 then (
8457 List.map(outArgs, Expression.unboxExp),
8458 369 list(match slot case SLOT(arg=SOME(arg)) algorithm slot.arg := SOME(Expression.unboxExp(arg)); then slot; else slot; end match for slot in outSlots),
8459 186 list(match p case funcarg algorithm funcarg.ty := Types.unboxedType(Types.fixPolymorphicRestype(p.ty, pb, inInfo)); then funcarg; end match for p in params), // Fix the types of the inputs (needed for slots evaluation)
8460 Types.unboxedType(res_ty));
8461 55784 else (outArgs, outSlots, params, res_ty);
8462 end match;
8463
8464 // Check the sanity of function parameters whose types are dependent on other parameters.
8465 // e.g. input Integer i; input Integer a[i]; // type of 'a' depends on the value 'i'.
8466 55961 (params, res_ty) := applyArgTypesToFuncType(outSlots, params, res_ty, inEnv, inCheckTypes, inInfo);
8467
8468 55961 outDimensions := slotsVectorizable(outSlots, inInfo);
8469 55961 outResultType := res_ty;
8470 55961 outFunctionType := DAE.T_FUNCTION(params, outResultType, func_attr, path);
8471 55961 outFunctionType := Types.fixPolymorphicRestype(outFunctionType, pb, inInfo);
8472
8473 // Only created when not checking types for error msg.
8474 55961 outFunctionType := createActualFunctype(outFunctionType, outSlots, inCheckTypes);
8475 success := true;
8476 if debug then
8477 print("elabTypes success for " + TypesDump.unparseType(func_ty) + ": "+TypesDump.unparseType(outFunctionType)+"=>"+TypesDump.unparseType(outResultType)+"\n");
8478 end if;
8479 else
8480 // The type didn't match, try next function type.
8481 end try;
8482 end while;
8483 end elabTypes;
8484
8485 function addPolymorphicTypeVars
8486 input output FCore.Cache cache;
8487 input FCore.Graph env;
8488 input list<Absyn.Path> typeVars;
8489 input DAE.Type funcTy;
8490 input output InstTypes.PolymorphicBindings pb;
8491 input Absyn.Path fnPath;
8492 input SourceInfo info;
8493 protected
8494 DAE.Type ty;
8495 FCore.Graph scope;
8496 SCode.Element e;
8497 list<String> poly_types;
8498 String ty_name;
8499 algorithm
8500
2/2
✓ Branch 0 taken 55960 times.
✓ Branch 1 taken 18 times.
55978 if listEmpty(typeVars) then
8501 55960 return;
8502 end if;
8503
8504 18 (cache, e, _) := Lookup.lookupClass(cache, env, fnPath);
8505
8506
6/6
✓ Branch 2 taken 27 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 31 times.
✓ Branch 5 taken 18 times.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 18 times.
49 poly_types := list("$" + SCodeUtil.getElementName(c)
8507 for c guard SCodeUtil.isPolymorphicTypeVar(c) in SCodeUtil.getClassElements(e));
8508
8509
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 14 times.
18 if listLength(typeVars) > listLength(poly_types) then
8510 28 Error.addSourceMessage(Error.TOO_MANY_TYPE_VARS_IN_CALL,
8511 {AbsynUtil.pathString(fnPath)}, info);
8512 14 fail();
8513 end if;
8514
8515
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
8 for tv in typeVars loop
8516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
4 ty_name :: poly_types := poly_types;
8517 4 (cache, e, scope) := Lookup.lookupClass(cache, env, tv, SOME(info));
8518 4 (cache, _, ty) := Inst.instClassType(cache, scope, e);
8519 4 pb := Types.addPolymorphicBinding(ty_name, ty, pb);
8520 end for;
8521 end addPolymorphicTypeVars;
8522
8523 protected function applyArgTypesToFuncType
8524 "This function is yet another hack trying to handle function parameters with
8525 unknown dimensions. It uses the input arguments to try and figure out the
8526 actual dimensions of the dimensions."
8527 input list<Slot> inSlots;
8528 input list<DAE.FuncArg> inParameters;
8529 input DAE.Type inResultType;
8530 input FCore.Graph inEnv;
8531 input Boolean checkTypes; // If not checking types no need to do any of this. In and out.
8532 input SourceInfo inInfo;
8533 output list<DAE.FuncArg> outParameters;
8534 output DAE.Type outResultType;
8535 protected
8536 list<DAE.Type> tys;
8537 list<DAE.Dimension> dims;
8538 list<String> used_args;
8539 list<Slot> used_slots;
8540 FCore.Cache cache;
8541 FCore.Graph env;
8542 list<DAE.Var> vars;
8543 SCode.Element dummy_var;
8544 algorithm
8545 // If not checking types or no function parameters there is nothing to be done here.
8546 // Even if dims don't match we need the function as candidate for error messages.
8547
4/4
✓ Branch 0 taken 55924 times.
✓ Branch 1 taken 37 times.
✓ Branch 2 taken 2559 times.
✓ Branch 3 taken 53365 times.
55961 if not checkTypes or listEmpty(inParameters) then
8548 outParameters := inParameters;
8549 outResultType := inResultType;
8550 2596 return;
8551 end if;
8552
8553 // Get all the dims, bind the actual params to the formal params.
8554 // Build a new env frame with these bindings and evaluate dimensions.
8555
8556 // Extract all dimensions from the parameters.
8557
4/4
✓ Branch 0 taken 102593 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 102593 times.
✓ Branch 3 taken 53365 times.
155958 tys := list(Types.funcArgType(param) for param in inParameters);
8558 53365 dims := getAllOutputDimensions(inResultType);
8559 53365 dims := listAppend(List.mapFlat(tys, TypesDump.getDimensions), dims);
8560
8561 // Use the dimensions to figure out which parameters are referenced by other
8562 // parameters' dimensions. This is done to minimize the things we need to
8563 // constant evaluate, a.k.a. 'things that go wrong'.
8564 53365 used_args := extractNamesFromDims(dims);
8565
6/6
✓ Branch 1 taken 101596 times.
✓ Branch 2 taken 997 times.
✓ Branch 3 taken 102593 times.
✓ Branch 4 taken 53365 times.
✓ Branch 5 taken 997 times.
✓ Branch 6 taken 53365 times.
155958 used_slots := list(s for s guard(isSlotUsed(s, used_args)) in inSlots);
8566
8567 // Create DAE.Vars from the slots.
8568 53365 cache := FCore.noCache();
8569
4/4
✓ Branch 0 taken 997 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 997 times.
✓ Branch 3 taken 53365 times.
54362 vars := list(makeVarFromSlot(s, inEnv, cache) for s in used_slots);
8570
8571 // Use a dummy SCode.Element, because we're only interested in the DAE.Vars.
8572 dummy_var := SCode.COMPONENT("dummy", SCode.defaultPrefixes,
8573 SCode.defaultVarAttr, Absyn.TPATH(Absyn.IDENT(""), NONE()), SCode.NOMOD(),
8574 SCode.noComment, NONE(), Absyn.dummyInfo);
8575
8576 // Create a new implicit scope with the needed parameters on top of the
8577 // current env so we can find the bindings if needed. We need an implicit
8578 // scope so comp1.comp2 can be looked up without package constant restriction.
8579 53365 env := FGraph.openScope(inEnv, SCode.NOT_ENCAPSULATED(), FCore.forScopeName, NONE());
8580
8581 // Add variables to the environment.
8582 53365 env := makeDummyFuncEnv(env, vars, dummy_var);
8583 // Evaluate the dimensions in the types.
8584
7/8
✓ Branch 0 taken 102593 times.
✓ Branch 1 taken 53365 times.
✓ Branch 2 taken 102593 times.
✓ Branch 3 taken 53365 times.
✓ Branch 4 taken 102593 times.
✓ Branch 5 taken 53365 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 53365 times.
155958 outParameters := list(evaluateFuncParamDimAndMatchTypes(s, p, env, cache, inInfo)
8585 threaded for s in inSlots, p in inParameters);
8586 53365 outResultType := evaluateFuncArgTypeDims(inResultType, env, cache);
8587 end applyArgTypesToFuncType;
8588
8589 protected function getAllOutputDimensions
8590 "Return the dimensions of an output type."
8591 input DAE.Type inOutputType;
8592 output list<DAE.Dimension> outDimensions;
8593 algorithm
8594 outDimensions := match inOutputType
8595 local
8596 list<DAE.Type> tys;
8597
8598 // A tuple, get the dimensions of all the types.
8599 case DAE.T_TUPLE(types = tys)
8600 3123 then List.mapFlat(tys, TypesDump.getDimensions);
8601
8602 106702 else TypesDump.getDimensions(inOutputType);
8603 end match;
8604 end getAllOutputDimensions;
8605
8606 protected function extractNamesFromDims
8607 "Extracts a list of unique names referenced by the given list of dimensions."
8608 input list<DAE.Dimension> inDimensions;
8609 input list<String> inAccumNames = {};
8610 output list<String> outNames;
8611 algorithm
8612 outNames := match inDimensions
8613 local
8614 DAE.Exp exp;
8615 list<DAE.Dimension> rest_dims;
8616 list<DAE.ComponentRef> crefs;
8617 list<String> names;
8618
8619 case DAE.DIM_EXP(exp = exp) :: rest_dims
8620 algorithm
8621 2463 crefs := Expression.extractCrefsFromExp(exp);
8622 2463 names := List.fold(crefs, extractNamesFromDims2, inAccumNames);
8623 2463 then
8624 extractNamesFromDims(rest_dims, names);
8625
8626 44429 case _ :: rest_dims then extractNamesFromDims(rest_dims, inAccumNames);
8627 case {} then inAccumNames;
8628
8629 end match;
8630 end extractNamesFromDims;
8631
8632 protected function extractNamesFromDims2
8633 input DAE.ComponentRef inCref;
8634 input list<String> inAccumNames;
8635 output list<String> outNames;
8636 algorithm
8637 outNames := match inCref
8638 local
8639 String name;
8640
8641 // Only interested in simple identifier, since that's all we can handle
8642 // anyway.
8643 case DAE.CREF_IDENT(ident = name)
8644 algorithm
8645 // Make sure we haven't added this name yet.
8646
2/2
✓ Branch 1 taken 1995 times.
✓ Branch 2 taken 476 times.
2471 outNames := if List.isMemberOnTrue(name, inAccumNames, stringEq) then
8647 inAccumNames else name :: inAccumNames;
8648 then
8649 outNames;
8650
8651 else inAccumNames;
8652
8653 end match;
8654 end extractNamesFromDims2;
8655
8656 protected function isSlotUsed
8657 "Checks if a slot is used, in the sense that it's referenced by a function
8658 parameter dimension."
8659 input Slot inSlot;
8660 input list<String> inUsedNames;
8661 output Boolean outIsUsed;
8662 protected
8663 String slot_name;
8664 algorithm
8665 206556 SLOT(defaultArg = DAE.FUNCARG(name=slot_name)) := inSlot;
8666 206556 outIsUsed := List.isMemberOnTrue(slot_name, inUsedNames, stringEq);
8667 end isSlotUsed;
8668
8669 protected function makeVarFromSlot
8670 "Converts a Slot to a DAE.Var."
8671 input Slot inSlot;
8672 input FCore.Graph inEnv;
8673 input FCore.Cache inCache;
8674 output DAE.Var outVar;
8675 algorithm
8676 outVar := matchcontinue inSlot
8677 local
8678 DAE.Ident name;
8679 DAE.Type ty;
8680 DAE.Exp exp;
8681 DAE.Binding binding;
8682 Values.Value val;
8683 DAE.FuncArg defaultArg;
8684
8685 // If the argument expression already has known dimensions, no need to
8686 // constant evaluate it.
8687 case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp))
8688 algorithm
8689
2/2
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 975 times.
991 false := Expression.expHasCref(exp,ComponentReferenceBasics.makeCrefIdent(name,DAE.T_UNKNOWN_DEFAULT,{}));
8690 975 ty := Expression.typeof(exp);
8691
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 965 times.
975 true := Types.dimensionsKnown(ty);
8692 965 binding := DAE.EQBOUND(exp, NONE(), DAE.C_CONST(), DAE.BINDING_FROM_DEFAULT_VALUE());
8693 965 then (DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, binding, false, NONE()));
8694
8695 // Otherwise, try to constant evaluate the expression.
8696 case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp))
8697 algorithm
8698 // Constant evaluate the bound expression.
8699 26 (_, val) := Ceval.ceval(inCache, inEnv, exp, false, Absyn.NO_MSG(), 0);
8700 ✗ exp := ValuesUtil.valueExp(val, SOME(exp));
8701 ✗ ty := Expression.typeof(exp);
8702 // Create a binding from the evaluated expression.
8703 ✗ binding := DAE.EQBOUND(exp, SOME(val), DAE.C_CONST(), DAE.BINDING_FROM_DEFAULT_VALUE());
8704 ✗ then DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, binding, false, NONE());
8705
8706 case SLOT(defaultArg = DAE.FUNCARG(name=name, ty=ty))
8707 32 then (DAE.TYPES_VAR(name, DAE.dummyAttrParam, ty, DAE.UNBOUND(), false, NONE()));
8708
8709 end matchcontinue;
8710 end makeVarFromSlot;
8711
8712 protected function evaluateStructuralSlots2
8713 input FCore.Cache inCache;
8714 input FCore.Graph inEnv;
8715 input list<Slot> inSlots;
8716 input list<String> usedSlots;
8717 input list<Slot> acc;
8718 output FCore.Cache cache;
8719 output list<Slot> slots;
8720 algorithm
8721 (cache,slots) := matchcontinue inSlots
8722 local
8723 DAE.Exp exp;
8724 Slot slot;
8725 list<Slot> rest;
8726 DAE.FuncArg defaultArg;
8727 list<DAE.Dimension> dims;
8728 Integer idx;
8729 Values.Value val;
8730 Integer ses;
8731
8732 56460 case {} then (inCache,listReverse(acc));
8733
8734 case slot::rest
8735 algorithm
8736
2/2
✓ Branch 1 taken 998 times.
✓ Branch 2 taken 102965 times.
103963 false := isSlotUsed(slot, usedSlots);
8737 102965 (cache,slots) := evaluateStructuralSlots2(inCache,inEnv,rest,usedSlots,slot::acc);
8738 then (cache,slots);
8739
8740 // If we are suggested the argument is structural, evaluate it
8741 case SLOT(defaultArg as DAE.FUNCARG(), _, SOME(exp), dims, idx, ses)::rest
8742 algorithm
8743 // Constant evaluate the bound expression.
8744 992 (cache, val) := Ceval.ceval(inCache, inEnv, exp, false, Absyn.NO_MSG(), 0);
8745 717 exp := ValuesUtil.valueExp(val, SOME(exp));
8746 // Create a binding from the evaluated expression.
8747 717 slot := SLOT(defaultArg,true,SOME(exp),dims,idx,ses);
8748 717 (cache,slots) := evaluateStructuralSlots2(cache,inEnv,rest,usedSlots,slot::acc);
8749 then (cache,slots);
8750
8751 case slot::rest
8752 algorithm
8753 281 (cache,slots) := evaluateStructuralSlots2(inCache,inEnv,rest,usedSlots,slot::acc);
8754 then (cache,slots);
8755 end matchcontinue;
8756 end evaluateStructuralSlots2;
8757
8758 protected function evaluateStructuralSlots
8759 input FCore.Cache inCache;
8760 input FCore.Graph inEnv;
8761 input list<Slot> inSlots;
8762 input DAE.Type funcType;
8763 output FCore.Cache cache;
8764 output list<Slot> slots;
8765 algorithm
8766 (cache,slots) := match funcType
8767 local
8768 list<DAE.Type> tys;
8769 list<DAE.Dimension> dims;
8770 list<String> used_args;
8771 list<DAE.FuncArg> funcArg;
8772 DAE.Type funcResultType;
8773
8774 case DAE.T_FUNCTION(funcArg=funcArg,funcResultType=funcResultType)
8775 algorithm
8776
4/4
✓ Branch 0 taken 103963 times.
✓ Branch 1 taken 56460 times.
✓ Branch 2 taken 103963 times.
✓ Branch 3 taken 56460 times.
160423 tys := list(Types.funcArgType(arg) for arg in funcArg);
8777 56460 dims := getAllOutputDimensions(funcResultType);
8778 56460 dims := listAppend(List.mapFlat(tys, TypesDump.getDimensions), dims);
8779 // Use the dimensions to figure out which parameters are referenced by
8780 // other parameters' dimensions. This is done to minimize the things we
8781 // need to constant evaluate, a.k.a. 'things that go wrong'.
8782 56460 used_args := extractNamesFromDims(dims);
8783 56460 (cache, slots) := evaluateStructuralSlots2(inCache, inEnv, inSlots, used_args, {});
8784 then
8785 (cache,slots);
8786
8787 22260 else (inCache, inSlots); // T_METARECORD, T_NOTYPE etc for builtins
8788 end match;
8789 end evaluateStructuralSlots;
8790
8791 protected function makeDummyFuncEnv
8792 "Helper function to applyArgTypesToFuncType, creates a dummy function
8793 environment."
8794 input FCore.Graph inEnv;
8795 input list<DAE.Var> inVars;
8796 input SCode.Element inDummyVar;
8797 output FCore.Graph outEnv = inEnv;
8798 protected
8799 SCode.Element dummy_var;
8800 algorithm
8801
2/2
✓ Branch 0 taken 997 times.
✓ Branch 1 taken 53365 times.
54362 for var in inVars loop
8802 997 dummy_var := SCodeUtil.setComponentName(inDummyVar, DAEUtil.typeVarIdent(var));
8803 997 outEnv := FGraph.mkComponentNode(outEnv, var, dummy_var, DAE.NOMOD(),
8804 FCore.VAR_TYPED(), FGraph.empty());
8805 end for;
8806 end makeDummyFuncEnv;
8807
8808 protected function evaluateFuncParamDimAndMatchTypes
8809 "Constant evaluates the dimensions of a FuncArg and then makes
8810 sure the type matches with the expected type in the slot."
8811 input Slot inSlot;
8812 input DAE.FuncArg inParam;
8813 input FCore.Graph inEnv;
8814 input FCore.Cache inCache;
8815 input SourceInfo inInfo;
8816 output DAE.FuncArg outParam;
8817 algorithm
8818 outParam := match(inSlot, inParam)
8819 local
8820 DAE.Type pty, sty;
8821 DAE.Dimensions dims1, dims2;
8822 DAE.Dimensions vdims;
8823
8824
8825 // If we have a code exp argument we can't check dims...
8826 // There are all kinds of scripting function that complicate things.
8827 case (_, DAE.FUNCARG(ty=DAE.T_CODE()))
8828 then inParam;
8829
8830 // If we have an array constant-evaluate the dimensions and make sure
8831 // They add up
8832 case (SLOT(arg = SOME(DAE.ARRAY(ty = sty)), dims = vdims), _)
8833 algorithm
8834 14434 DAE.FUNCARG(ty = pty) := inParam;
8835 // evaluate the dimesions
8836 14434 pty := evaluateFuncArgTypeDims(pty, inEnv, inCache);
8837 // append the vectorization dim if argument is vectorized.
8838 14434 dims1 := TypesDump.getDimensions(pty);
8839 14434 dims1 := listAppend(vdims,dims1);
8840
8841 14434 dims2 := TypesDump.getDimensions(sty);
8842
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14434 times.
14434 true := Expression.dimsEqual(dims1, dims2);
8843
8844 14434 outParam := Types.setFuncArgType(inParam, pty);
8845 then
8846 outParam;
8847
8848 case (SLOT(arg = SOME(DAE.MATRIX(ty = sty)), dims = vdims), _)
8849 algorithm
8850 524 DAE.FUNCARG(ty=pty) := inParam;
8851 // evaluate the dimesions
8852 524 pty := evaluateFuncArgTypeDims(pty, inEnv, inCache);
8853 // append the vectorization dim if argument is vectorized.
8854 524 dims1 := TypesDump.getDimensions(pty);
8855 524 vdims := listAppend(dims1,vdims);
8856 524 dims2 := TypesDump.getDimensions(sty);
8857
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 524 times.
524 true := Expression.dimsEqual(vdims, dims2);
8858
8859 524 outParam := Types.setFuncArgType(inParam, pty);
8860 then
8861 outParam;
8862
8863 else
8864 algorithm
8865 83572 DAE.FUNCARG(ty=pty) := inParam;
8866 83572 pty := evaluateFuncArgTypeDims(pty, inEnv, inCache);
8867 83572 outParam := Types.setFuncArgType(inParam, pty);
8868 then
8869 outParam;
8870
8871 end match;
8872 end evaluateFuncParamDimAndMatchTypes;
8873
8874 protected function evaluateFuncArgTypeDims
8875 "Constant evaluates the dimensions of a type."
8876 input DAE.Type inType;
8877 input FCore.Graph inEnv;
8878 input FCore.Cache inCache;
8879 output DAE.Type outType;
8880 algorithm
8881 outType := matchcontinue inType
8882 local
8883 DAE.Type ty;
8884 Integer n;
8885 DAE.Dimension dim;
8886
8887 // Array type, evaluate the dimension.
8888 case DAE.T_ARRAY(ty, {dim})
8889 algorithm
8890
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19100 times.
23015 (_, Values.INTEGER(n)) := Ceval.cevalDimension(inCache, inEnv, dim, false, Absyn.NO_MSG(), 0);
8891 19100 ty := evaluateFuncArgTypeDims(ty, inEnv, inCache);
8892 38200 then
8893 DAE.T_ARRAY(ty, {DAE.DIM_INTEGER(n)});
8894
8895 // Previous case failed, keep the dimension but evaluate the rest of the type.
8896 case DAE.T_ARRAY(ty, {dim})
8897 algorithm
8898 3915 ty := evaluateFuncArgTypeDims(ty, inEnv, inCache);
8899 3915 then
8900 DAE.T_ARRAY(ty, {dim});
8901
8902 case ty as DAE.T_TUPLE()
8903 algorithm
8904 1556 ty.types := List.map2(ty.types, evaluateFuncArgTypeDims, inEnv, inCache);
8905 then ty;
8906
8907 else inType;
8908
8909 end matchcontinue;
8910 end evaluateFuncArgTypeDims;
8911
8912 protected function createActualFunctype
8913 "Creates the actual function type of a CALL expression, used for error messages.
8914 This type is only created if checkTypes is false."
8915 input DAE.Type tp;
8916 input list<Slot> slots;
8917 input Boolean checkTypes;
8918 output DAE.Type outTp = tp;
8919 algorithm
8920 outTp := match(outTp, checkTypes)
8921 local
8922
8923 case (_, true) then tp;
8924
8925 // When not checking types, create function type by looking at the filled slots
8926 case (DAE.T_FUNCTION(), _)
8927 algorithm
8928 37 outTp.funcArg := funcArgsFromSlots(slots);
8929 then
8930 outTp;
8931
8932 end match;
8933 end createActualFunctype;
8934
8935 protected function slotsVectorizable
8936 "author: PA
8937 This function checks all vectorized array dimensions in the slots and
8938 confirms that they all are of same dimension,or no dimension, i.e. not
8939 vectorized. The uniform vectorized array dimension is returned."
8940 input list<Slot> inSlots;
8941 input SourceInfo info;
8942 output DAE.Dimensions outDims;
8943 algorithm
8944 outDims := matchcontinue inSlots
8945 local
8946 DAE.Dimensions ad;
8947 list<Slot> rest;
8948 DAE.Exp exp;
8949 String name;
8950
8951 case {} then {};
8952
8953 case SLOT(defaultArg = DAE.FUNCARG(name=name), arg = SOME(exp), dims = (ad as (_ :: _))) :: rest
8954 algorithm
8955 2413 sameSlotsVectorizable(rest, ad, name, exp, info);
8956 then
8957 ad;
8958
8959 100595 case SLOT(dims = {}) :: rest then slotsVectorizable(rest, info);
8960
8961 else
8962 algorithm
8963 ✗ true := Flags.isSet(Flags.FAILTRACE);
8964 ✗ Debug.trace("-slots_vectorizable failed\n");
8965 ✗ then
8966 fail();
8967 end matchcontinue;
8968 end slotsVectorizable;
8969
8970 protected function sameSlotsVectorizable
8971 "author: PA
8972 This function succeds if all slots in the list either has the array
8973 dimension as given by the second argument or no array dimension at all.
8974 The array dimension must match both in dimension size and number of
8975 dimensions."
8976 input list<Slot> inSlots;
8977 input DAE.Dimensions inDims;
8978 input String name;
8979 input DAE.Exp exp;
8980 input SourceInfo info;
8981 algorithm
8982 () := match inSlots
8983 local
8984 DAE.Dimensions slot_ad;
8985 list<Slot> rest;
8986 DAE.Exp exp2;
8987 String name2;
8988
8989 // Array dims must match.
8990 case SLOT(defaultArg = DAE.FUNCARG(name=name2), arg = SOME(exp2), dims = (slot_ad as (_ :: _))) :: rest
8991 algorithm
8992 469 sameArraydimLst(inDims, name, exp, slot_ad, name2, exp2, info);
8993 469 sameSlotsVectorizable(rest, inDims, name, exp, info);
8994 then
8995 ();
8996
8997 // Empty array dims matches too.
8998 case SLOT(dims = {}) :: rest
8999 algorithm
9000 322 sameSlotsVectorizable(rest, inDims, name, exp, info);
9001 then
9002 ();
9003
9004 case {} then ();
9005 end match;
9006 end sameSlotsVectorizable;
9007
9008 protected function sameArraydimLst
9009 "author: PA
9010 Helper function to sameSlotsVectorizable. "
9011 input DAE.Dimensions inDims1;
9012 input String name1;
9013 input DAE.Exp exp1;
9014 input DAE.Dimensions inDims2;
9015 input String name2;
9016 input DAE.Exp exp2;
9017 input SourceInfo info;
9018 algorithm
9019 ():= matchcontinue (inDims2, inDims2)
9020 local
9021 Integer i1,i2;
9022 DAE.Dimensions ads1,ads2;
9023 DAE.Exp e1,e2;
9024 DAE.Dimension ad1,ad2;
9025 String str1,str2,str3,str4;
9026
9027 case (DAE.DIM_INTEGER(integer = i1) :: ads1,
9028 DAE.DIM_INTEGER(integer = i2) :: ads2)
9029 algorithm
9030
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 468 times.
468 true := intEq(i1, i2);
9031 468 sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info);
9032 then
9033 ();
9034
9035 case (DAE.DIM_UNKNOWN() :: ads1, DAE.DIM_UNKNOWN() :: ads2)
9036 algorithm
9037 ✗ sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info);
9038 then
9039 ();
9040
9041 case (DAE.DIM_EXP(e1) :: ads1, DAE.DIM_EXP(e2) :: ads2)
9042 algorithm
9043
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := ExpressionBasics.expEqual(e1,e2);
9044 2 sameArraydimLst(ads1, name1, exp1, ads2, name2, exp2, info);
9045 then
9046 ();
9047
9048 case ({}, {}) then ();
9049
9050 case (ad1 :: _, ad2 :: _)
9051 algorithm
9052 ✗ str1 := ExpressionBasics.printExpStr(exp1);
9053 ✗ str2 := ExpressionBasics.printExpStr(exp2);
9054 ✗ str3 := ExpressionBasics.dimensionString(ad1);
9055 ✗ str4 := ExpressionBasics.dimensionString(ad2);
9056 ✗ Error.addSourceMessage(Error.VECTORIZE_CALL_DIM_MISMATCH, {name1,str1,name2,str2,str3,str4}, info);
9057 ✗ then
9058 fail();
9059
9060 end matchcontinue;
9061 end sameArraydimLst;
9062
9063 protected function getProperties
9064 "This function creates a Properties object from a DAE.Type and a
9065 DAE.TupleConst value."
9066 input DAE.Type inType;
9067 input DAE.TupleConst inTupleConst;
9068 output DAE.Properties outProperties;
9069 algorithm
9070 outProperties := match(inType,inTupleConst)
9071 local
9072 DAE.Type tt,t,ty;
9073 DAE.TupleConst const;
9074 DAE.Const b;
9075 String tystr,conststr;
9076
9077 // At least two elements in the type list, this is a tuple. LS: Tuples are fixed before here
9078 1566 case (tt as DAE.T_TUPLE(),const) then DAE.PROP_TUPLE(tt,const);
9079
9080 // One type, this is a tuple with one element. The resulting properties is then identical to that of a single expression.
9081 75488 case (t,DAE.TUPLE_CONST(tupleConstLst = (DAE.SINGLE_CONST(const = b) :: {}))) then DAE.PROP(t,b);
9082 ✗ case (t,DAE.TUPLE_CONST(tupleConstLst = (DAE.SINGLE_CONST(const = b) :: {}))) then DAE.PROP(t,b);
9083 ✗ case (t,DAE.SINGLE_CONST(const = b)) then DAE.PROP(t,b);
9084
9085 // failure
9086 case (ty,const)
9087 algorithm
9088 ✗ true := Flags.isSet(Flags.FAILTRACE);
9089 ✗ Debug.trace("- Static.getProperties failed: ");
9090 ✗ tystr := TypesDump.unparseType(ty);
9091 ✗ conststr := TypesDump.printTupleConstStr(const);
9092 ✗ Debug.trace(tystr);
9093 ✗ Debug.trace(", ");
9094 ✗ Debug.traceln(conststr);
9095 ✗ then
9096 fail();
9097
9098 end match;
9099 end getProperties;
9100
9101 protected function elabConsts "author: PR
9102 This just splits the properties list into a type list and a const list.
9103 LS: Changed to take a Type, which is the functions return type.
9104 LS: Update: const is derived from the input arguments and sent here."
9105 input DAE.Type inType;
9106 input DAE.Const inConst;
9107 output DAE.TupleConst outTupleConst;
9108 algorithm
9109 outTupleConst := match(inType,inConst)
9110 local
9111 list<DAE.TupleConst> consts;
9112 list<DAE.Type> tys;
9113 DAE.Const c;
9114 DAE.Type ty;
9115
9116 case (DAE.T_TUPLE(types = tys), c)
9117 algorithm
9118 1566 consts := checkConsts(tys, c);
9119 1566 then
9120 DAE.TUPLE_CONST(consts);
9121
9122 // LS: If not a tuple then one normal type, T_INTEGER etc, but we make a list of types
9123 // with one element and call the same check_consts, so that we always have DAE.TUPLE_CONST as result
9124 case (ty, c)
9125 algorithm
9126 75488 consts := checkConsts({ty}, c);
9127 75488 then
9128 DAE.TUPLE_CONST(consts);
9129
9130 end match;
9131 end elabConsts;
9132
9133 protected function checkConsts
9134 "LS: Changed to take a Type list, which is the functions return type. Only
9135 for functions returning a tuple
9136 LS: Update: const is derived from the input arguments and sent here "
9137 input list<DAE.Type> inTypes;
9138 input DAE.Const inConst;
9139 output list<DAE.TupleConst> outTupleConsts;
9140 algorithm
9141
4/4
✓ Branch 0 taken 79362 times.
✓ Branch 1 taken 77054 times.
✓ Branch 2 taken 79362 times.
✓ Branch 3 taken 77054 times.
156416 outTupleConsts := list(checkConst(ty, inConst) for ty in inTypes);
9142 end checkConsts;
9143
9144 protected function checkConst "author: PR
9145 At the moment this make all outputs non cons.
9146 All ouputs should be checked in the function body for constness.
9147 LS: but it says true?
9148 LS: Adapted to check one type instead of funcarg, since it just checks
9149 return type
9150 LS: Update: const is derived from the input arguments and sent here"
9151 input DAE.Type inType;
9152 input DAE.Const c;
9153 output DAE.TupleConst outTupleConst;
9154 algorithm
9155 outTupleConst := match inType
9156 case DAE.T_TUPLE()
9157 algorithm
9158 ✗ Error.addInternalError("No support for tuples built by tuples", sourceInfo());
9159 ✗ then fail();
9160
9161 79362 else DAE.SINGLE_CONST(c);
9162 end match;
9163 end checkConst;
9164
9165 protected function splitProps
9166 "Splits the properties list into the separated types list and const list."
9167 input list<DAE.Properties> inProperties;
9168 output list<DAE.Type> outTypes = {};
9169 output list<DAE.TupleConst> outConsts = {};
9170 protected
9171 DAE.Type ty;
9172 DAE.Const c;
9173 DAE.TupleConst tc;
9174 algorithm
9175
2/2
✓ Branch 1 taken 6300 times.
✓ Branch 2 taken 3149 times.
9449 for prop in listReverse(inProperties) loop
9176 tc := match prop
9177 6300 case DAE.PROP(type_ = ty, constFlag = c) then DAE.SINGLE_CONST(c);
9178 case DAE.PROP_TUPLE(type_ = ty, tupleConst = tc) then tc;
9179 end match;
9180
9181 outTypes := ty :: outTypes;
9182 outConsts := tc :: outConsts;
9183 end for;
9184 end splitProps;
9185
9186 protected function getTypes
9187 "This function returns the types of a DAE.FuncArg list."
9188 input list<DAE.FuncArg> farg;
9189 output list<DAE.Type> outTypes;
9190 algorithm
9191 ✗ outTypes := list(Types.funcArgType(arg) for arg in farg);
9192 end getTypes;
9193
9194 protected function elabInputArgs
9195 "This function_ elaborates on a number of expressions and_ matches them to a
9196 number of `DAE.Var\' objects, applying type_ conversions on the expressions
9197 when necessary to match the type_ of the DAE.Var.
9198
9199 Positional arguments and named arguments are filled in the argument slots as:
9200 1. Positional arguments fill the first slots according to their position.
9201 2. Named arguments fill slots with the same name as the named argument.
9202 3. Unfilled slots are checked so that they have default values, otherwise error."
9203 input FCore.Cache inCache;
9204 input FCore.Graph inEnv;
9205 input list<Absyn.Exp> inPosArgs;
9206 input list<Absyn.NamedArg> inNamedArgs;
9207 input list<Slot> inSlots;
9208 input Boolean inOnlyOneFunction;
9209 input Boolean inCheckTypes "if true, check types";
9210 input Boolean inImplicit;
9211 input DAE.Prefix inPrefix;
9212 input SourceInfo inInfo;
9213 input DAE.Type inFuncType "Used to determine which arguments are structural. We will evaluate them later to figure if they are used in dimensions. So we evaluate them here to get a more optimised DAE";
9214 input Absyn.Path inPath;
9215 input Boolean isGraphicsExp = false;
9216 output FCore.Cache outCache = inCache;
9217 output list<DAE.Exp> outExps;
9218 output list<Slot> outSlots = inSlots;
9219 output list<DAE.Const> outConsts;
9220 output InstTypes.PolymorphicBindings outPolymorphicBindings = {};
9221 protected
9222 list<DAE.FuncArg> fargs;
9223 list<DAE.Const> consts1, consts2;
9224 algorithm
9225 // Empty function call, e.g. foo(), is always constant.
9226 // adrpo 2010-11-09: TODO! FIXME! This is not always true, RecordCall() can
9227 // contain DEFAULT bindings that are param.
9228
4/4
✓ Branch 0 taken 18281 times.
✓ Branch 1 taken 61556 times.
✓ Branch 2 taken 818 times.
✓ Branch 3 taken 17463 times.
79837 if listEmpty(inPosArgs) and listEmpty(inNamedArgs) then
9229 outConsts := {DAE.C_CONST()};
9230 else
9231 62374 fargs := funcArgsFromSlots(inSlots);
9232
9233 // Elaborate positional arguments.
9234 62374 (outCache, outSlots, consts1, outPolymorphicBindings) :=
9235 elabPositionalInputArgs(outCache, inEnv, inPosArgs, fargs, outSlots,
9236 inOnlyOneFunction, inCheckTypes, inImplicit,
9237 outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp);
9238
9239 // Elaborate named arguments.
9240 61282 (outCache, outSlots, consts2, outPolymorphicBindings) :=
9241 elabNamedInputArgs(outCache, inEnv, inNamedArgs, fargs, outSlots,
9242 inOnlyOneFunction, inCheckTypes, inImplicit,
9243 outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp);
9244
9245 61257 outConsts := listAppend(consts1, consts2);
9246 end if;
9247
9248 78720 (outCache, outSlots) := evaluateStructuralSlots(outCache, inEnv, outSlots, inFuncType);
9249 78720 outExps := slotListArgs(outSlots);
9250 end elabInputArgs;
9251
9252 protected function makeEmptySlots
9253 "Creates a list of empty slots given a list of function parameters."
9254 input list<DAE.FuncArg> inArgs;
9255 output list<Slot> outSlots;
9256 algorithm
9257 78351 outSlots := List.mapFold(inArgs, makeEmptySlot, 1);
9258 end makeEmptySlots;
9259
9260 protected function makeEmptySlot
9261 input DAE.FuncArg inArg;
9262 input Integer inIndex;
9263 output Slot outSlot;
9264 output Integer outIndex;
9265 algorithm
9266 143845 outSlot := SLOT(inArg, false, NONE(), {}, inIndex, SLOT_NOT_EVALUATED);
9267
1/2
✓ Branch 0 taken 143845 times.
✗ Branch 1 not taken.
143845 outIndex := inIndex + 1;
9268 end makeEmptySlot;
9269
9270 protected function funcArgsFromSlots
9271 "Converts a list of Slot to a list of FuncArg."
9272 input list<Slot> inSlots;
9273 output list<DAE.FuncArg> outFuncArgs;
9274 algorithm
9275
4/4
✓ Branch 0 taken 143695 times.
✓ Branch 1 taken 62411 times.
✓ Branch 2 taken 143695 times.
✓ Branch 3 taken 62411 times.
206106 outFuncArgs := list(funcArgFromSlot(slot) for slot in inSlots);
9276 end funcArgsFromSlots;
9277
9278 protected function funcArgFromSlot
9279 input Slot inSlot;
9280 output DAE.FuncArg outFuncArg;
9281 algorithm
9282 143695 SLOT(defaultArg = outFuncArg) := inSlot;
9283 end funcArgFromSlot;
9284
9285 protected function complexTypeFromSlots
9286 "Creates an DAE.T_COMPLEX type from a list of slots.
9287 Used to create type of record constructors "
9288 input list<Slot> inSlots;
9289 input ClassInf.State complexClassType;
9290 output DAE.Type outType;
9291 protected
9292 String id;
9293 DAE.Type ty;
9294 list<DAE.Var> vars = {};
9295 algorithm
9296
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 13 times.
141 for slot in inSlots loop
9297 128 SLOT(defaultArg = DAE.FUNCARG(name = id, ty = ty)) := slot;
9298 128 vars := Expression.makeVar(id, Types.simplifyType(ty)) :: vars;
9299 end for;
9300
9301 13 vars := listReverse(vars);
9302 13 outType := DAE.T_COMPLEX(complexClassType, vars, NONE(), false);
9303 end complexTypeFromSlots;
9304
9305 protected function slotListArgs
9306 "Gets the argument expressions from a list of slots."
9307 input list<Slot> inSlots;
9308 output list<DAE.Exp> outArgs;
9309 algorithm
9310 99495 outArgs := List.filterMap(inSlots, slotArg);
9311 end slotListArgs;
9312
9313 protected function slotArg
9314 "Gets the argument from a slot."
9315 input Slot inSlot;
9316 output DAE.Exp outArg;
9317 algorithm
9318
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 187249 times.
✓ Branch 2 taken 22076 times.
✓ Branch 3 taken 165173 times.
187249 SLOT(arg = SOME(outArg)) := inSlot;
9319 end slotArg;
9320
9321 protected function fillGraphicsDefaultSlots
9322 "This function takes a slot list and a class definition of a function
9323 and fills default values into slots which have not been filled.
9324
9325 Special case for graphics exps"
9326 input FCore.Cache inCache;
9327 input list<Slot> inSlots;
9328 input SCode.Element inClass;
9329 input FCore.Graph inEnv;
9330 input Boolean inImplicit;
9331 input DAE.Prefix inPrefix;
9332 input SourceInfo inInfo;
9333 output FCore.Cache outCache = inCache;
9334 output list<Slot> outSlots = {};
9335 output list<DAE.Const> outConsts = {};
9336 output InstTypes.PolymorphicBindings outPolymorphicBindings = {};
9337 protected
9338 Boolean filled;
9339 Absyn.Exp e;
9340 DAE.Exp exp;
9341 DAE.FuncArg defarg;
9342 DAE.Type ty;
9343 DAE.Const c;
9344 algorithm
9345
2/2
✓ Branch 0 taken 128 times.
✓ Branch 1 taken 13 times.
141 for slot in inSlots loop
9346 128 SLOT(slotFilled = filled) := slot;
9347
9348 // Try to fill the slot if it's not yet filled.
9349
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 46 times.
128 if not filled then
9350 slot := matchcontinue slot
9351 case SLOT(defaultArg = defarg as DAE.FUNCARG())
9352 algorithm
9353
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 82 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 82 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 82 times.
82 SCode.COMPONENT(modifications = SCode.MOD(binding = SOME(e))) :=
9354 SCodeUtil.getElementNamed(defarg.name, inClass);
9355
9356
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 (outCache, exp, DAE.PROP(ty, c)) :=
9357 elabExpInExpression(outCache, inEnv, e, inImplicit, true, inPrefix, inInfo);
9358
9359 82 (exp, _, outPolymorphicBindings) := Types.matchTypePolymorphic(exp,
9360 ty, defarg.ty, FGraph.getGraphPathNoImplicitScope(inEnv), outPolymorphicBindings, false);
9361
9362
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 82 times.
82 true := Types.constEqualOrHigher(c, defarg.const);
9363 82 outConsts := c :: outConsts;
9364
9365 82 slot.slotFilled := true;
9366 82 slot.arg := SOME(exp);
9367 then
9368 slot;
9369
9370 ✗ else slot;
9371 end matchcontinue;
9372 end if;
9373
9374 outSlots := slot :: outSlots;
9375 end for;
9376
9377 13 outSlots := listReverse(outSlots);
9378 13 outConsts := listReverse(outConsts);
9379 end fillGraphicsDefaultSlots;
9380
9381 protected function printSlotsStr
9382 "prints the slots to a string"
9383 input list<Slot> inSlots;
9384 output String outString;
9385 algorithm
9386 outString := match inSlots
9387 local
9388 Boolean filled;
9389 String farg_str,filledStr,str,s,s1,s2,res;
9390 list<String> str_lst;
9391 DAE.FuncArg farg;
9392 Option<DAE.Exp> exp;
9393 DAE.Dimensions ds;
9394 list<Slot> xs;
9395
9396 case SLOT(defaultArg = farg,slotFilled = filled,arg = exp,dims = ds) :: xs
9397 algorithm
9398 ✗ farg_str := TypesDump.printFargStr(farg);
9399 ✗ filledStr := if filled then "filled" else "not filled";
9400 ✗ str := Util.applyOptionOrDefault(exp, ExpressionBasics.printExpStr, "");
9401 ✗ str_lst := List.map(ds, ExpressionBasics.dimensionString);
9402 ✗ s := stringDelimitList(str_lst, ", ");
9403 ✗ s1 := stringAppendList({"SLOT(",farg_str,", ",filledStr,", ",str,", [",s,"])\n"});
9404 ✗ s2 := printSlotsStr(xs);
9405 ✗ res := stringAppend(s1, s2);
9406 then
9407 res;
9408
9409 case {} then "";
9410
9411 end match;
9412 end printSlotsStr;
9413
9414 protected function isFreeParameterExp
9415 "Checks if inExp is a an expression of free parameters."
9416 input DAE.Exp inExp;
9417 input FCore.Cache inCache;
9418 input FCore.Graph inEnv;
9419 output Boolean isFree;
9420 output FCore.Cache outCache;
9421 algorithm
9422 ✗ outCache := inCache;
9423 isFree := match inExp
9424 local
9425 DAE.ComponentRef cr;
9426 DAE.Binding binding;
9427 DAE.Exp exp1, exp2;
9428 list<DAE.Exp> exps;
9429 list<list<DAE.Exp>> mat;
9430 Boolean isFree2;
9431
9432 case DAE.ICONST() then true;
9433
9434 case DAE.RCONST() then true;
9435
9436 case DAE.SCONST() then true;
9437
9438 case DAE.BCONST() then true;
9439
9440 case DAE.CREF(componentRef = cr)
9441 algorithm
9442 ✗ (outCache, _, _, binding, _, _, _, _, _) := Lookup.lookupVar(inCache, inEnv, cr);
9443 then
9444 match binding
9445 case DAE.VALBOUND() then
9446 true;
9447 case DAE.EQBOUND(exp = exp1)
9448 guard
9449 Expression.isConst(exp1)
9450 then
9451 true;
9452 else
9453 false;
9454 end match;
9455
9456 case DAE.BINARY(exp1 = exp1, exp2 = exp2)
9457 algorithm
9458 ✗ (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv);
9459 ✗ (isFree2, outCache) := isFreeParameterExp(exp2, outCache, inEnv);
9460 ✗ then
9461 isFree and isFree2;
9462
9463 case DAE.UNARY(exp = exp1)
9464 algorithm
9465 ✗ (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv);
9466 then
9467 isFree;
9468
9469 case DAE.LBINARY(exp1 = exp1, exp2 = exp2)
9470 algorithm
9471 ✗ (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv);
9472 ✗ (isFree2, outCache) := isFreeParameterExp(exp2, outCache, inEnv);
9473 ✗ then
9474 isFree and isFree2;
9475
9476 case DAE.LUNARY(exp = exp1)
9477 algorithm
9478 ✗ (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv);
9479 then
9480 isFree;
9481
9482 case DAE.CALL(expLst = exps)
9483 algorithm
9484 outCache := inCache;
9485 isFree := true;
9486 ✗ for exp in exps loop
9487 ✗ (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv);
9488 ✗ isFree := isFree and isFree2;
9489 end for;
9490 then
9491 isFree;
9492
9493 case DAE.ARRAY(array = exps)
9494 algorithm
9495 outCache := inCache;
9496 isFree := true;
9497 ✗ for exp in exps loop
9498 ✗ (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv);
9499 ✗ isFree := isFree and isFree2;
9500 end for;
9501 then
9502 isFree;
9503
9504 case DAE.MATRIX(matrix = mat)
9505 algorithm
9506 outCache := inCache;
9507 isFree := true;
9508 ✗ for row in mat loop
9509 ✗ for exp in row loop
9510 ✗ (isFree2, outCache) := isFreeParameterExp(exp, outCache, inEnv);
9511 ✗ isFree := isFree and isFree2;
9512 end for;
9513 end for;
9514 then
9515 isFree;
9516
9517 case DAE.CAST(exp = exp1)
9518 algorithm
9519 ✗ (isFree, outCache) := isFreeParameterExp(exp1, inCache, inEnv);
9520 then
9521 isFree;
9522
9523 else
9524 false;
9525 end match;
9526 end isFreeParameterExp;
9527
9528 protected function elabPositionalInputArgs
9529 "This function elaborates the positional input arguments of a function.
9530 A list of slots is filled from the beginning with types of each
9531 positional argument."
9532 input FCore.Cache inCache;
9533 input FCore.Graph inEnv;
9534 input list<Absyn.Exp> inPosArgs;
9535 input list<DAE.FuncArg> inFuncArgs;
9536 input list<Slot> inSlots;
9537 input Boolean inOnlyOneFunction;
9538 input Boolean inCheckTypes "if true, check types";
9539 input Boolean inImplicit;
9540 input InstTypes.PolymorphicBindings inPolymorphicBindings;
9541 input DAE.Prefix inPrefix;
9542 input SourceInfo inInfo;
9543 input Absyn.Path inPath;
9544 input Boolean isGraphicsExp;
9545 output FCore.Cache outCache = inCache;
9546 output list<Slot> outSlots = inSlots;
9547 output list<DAE.Const> outConsts = {};
9548 output InstTypes.PolymorphicBindings outPolymorphicBindings = inPolymorphicBindings;
9549 protected
9550 DAE.FuncArg farg;
9551 list<DAE.FuncArg> farg_rest = inFuncArgs;
9552 DAE.Const c;
9553 Integer position = 1;
9554 algorithm
9555
2/2
✓ Branch 0 taken 120123 times.
✓ Branch 1 taken 61282 times.
181405 for arg in inPosArgs loop
9556
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 119859 times.
120123 farg :: farg_rest := farg_rest;
9557
9558 119859 (outCache, outSlots, c, outPolymorphicBindings) :=
9559 elabPositionalInputArg(outCache, inEnv, arg, farg, position, outSlots,
9560 inOnlyOneFunction, inCheckTypes, inImplicit,
9561 outPolymorphicBindings, inPrefix, inInfo, inPath, isGraphicsExp);
9562
9563 119031 position := position + 1;
9564 119031 outConsts := c :: outConsts;
9565 end for;
9566
9567 61282 outConsts := listReverse(outConsts);
9568 end elabPositionalInputArgs;
9569
9570 protected function elabPositionalInputArg
9571 "This function elaborates the positional input arguments of a function.
9572 A list of slots is filled from the beginning with types of each
9573 positional argument."
9574 input FCore.Cache inCache;
9575 input FCore.Graph inEnv;
9576 input Absyn.Exp inExp;
9577 input DAE.FuncArg farg;
9578 input Integer position;
9579 input list<Slot> inSlotLst;
9580 input Boolean onlyOneFunction;
9581 input Boolean checkTypes "if true, check types";
9582 input Boolean impl;
9583 input InstTypes.PolymorphicBindings inPolymorphicBindings;
9584 input DAE.Prefix inPrefix;
9585 input SourceInfo info;
9586 input Absyn.Path path;
9587 input Boolean isGraphicsExp;
9588 output FCore.Cache outCache;
9589 output list<Slot> outSlotLst;
9590 output DAE.Const outConst;
9591 output InstTypes.PolymorphicBindings outPolymorphicBindings;
9592 protected
9593 Integer numErrors = Error.getNumErrorMessages();
9594 algorithm
9595 (outCache,outSlotLst,outConst,outPolymorphicBindings):=
9596 matchcontinue (inCache, inEnv, inExp, farg, inSlotLst, onlyOneFunction, checkTypes, inPolymorphicBindings, inPrefix)
9597 local
9598 list<Slot> slots,slots_1;
9599 DAE.Exp e_1,e_2;
9600 DAE.Type t,vt;
9601 DAE.Const c1;
9602 DAE.VarParallelism pr;
9603 DAE.Properties prop;
9604 FCore.Graph env;
9605 Absyn.Exp e;
9606 DAE.Dimensions ds;
9607 FCore.Cache cache;
9608 String id;
9609 DAE.Properties props;
9610 DAE.Prefix pre;
9611 DAE.CodeType ct;
9612 InstTypes.PolymorphicBindings polymorphicBindings;
9613 String s1,s2,s3,s4,s5;
9614
9615 case (cache, env, e, DAE.FUNCARG(name=id,ty = vt as DAE.T_CODE(ct),par=pr), slots, _, true, polymorphicBindings, pre)
9616 algorithm
9617 3836 e_1 := elabCodeExp(e,cache,env,ct,info);
9618 3836 slots_1 := fillSlot(DAE.FUNCARG(id,vt,DAE.C_VAR(),pr,NONE()), e_1, {}, slots,pre,info, path);
9619 3836 then
9620 (cache,slots_1,DAE.C_VAR(),polymorphicBindings);
9621
9622 // exact match
9623 case (cache, env, e, DAE.FUNCARG(name=id,ty=vt,par=pr), slots, _, true, polymorphicBindings, pre)
9624 algorithm
9625 115977 (cache,e_1,props) := elabExpInExpression(cache,env, e, impl, true,pre,info);
9626 115977 t := Types.getPropType(props);
9627 115977 vt := Types.traverseType(vt, -1, Types.makeExpDimensionsUnknown);
9628 115977 c1 := Types.propAllConst(props);
9629 115977 (e_2,_,polymorphicBindings) := Types.matchTypePolymorphic(e_1,t,vt,FGraph.getGraphPathNoImplicitScope(env),polymorphicBindings,false);
9630 112303 slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, {}, slots,pre,info, path) "no vectorized dim" ;
9631 112300 then
9632 (cache,slots_1,c1,polymorphicBindings);
9633
9634 // check if vectorized argument
9635 case (cache, env, e, DAE.FUNCARG(name=id,ty=vt,par=pr), slots, _, true, polymorphicBindings, pre)
9636 algorithm
9637 3677 (cache,e_1,props) := elabExpInExpression(cache,env, e, impl,true,pre,info);
9638 3677 t := Types.getPropType(props);
9639 3677 vt := Types.traverseType(vt, -1, Types.makeExpDimensionsUnknown);
9640 3677 c1 := Types.propAllConst(props);
9641 3677 (e_2,_,ds,polymorphicBindings) := Types.vectorizableType(e_1, t, vt, FGraph.getGraphPathNoImplicitScope(env));
9642 2852 slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, ds, slots, pre,info, path);
9643 2849 then
9644 (cache,slots_1,c1,polymorphicBindings);
9645
9646 // not checking types
9647 case (cache, env, e, DAE.FUNCARG(name=id,par=pr), slots, _, false, polymorphicBindings, pre)
9648 algorithm
9649 46 (cache,e_1,props) := elabExpInExpression(cache,env, e, impl,true,pre,info);
9650 46 t := Types.getPropType(props);
9651 46 c1 := Types.propAllConst(props);
9652 /* fill slot with actual type for error message*/
9653 46 slots_1 := fillSlot(DAE.FUNCARG(id,t,c1,pr,NONE()), e_1, {}, slots, pre,info, path);
9654 46 then
9655 (cache,slots_1,c1,polymorphicBindings);
9656
9657 // check types and display error
9658 case (cache, env, e, DAE.FUNCARG(name=id,ty=vt), _, true, true, _, pre)
9659 algorithm
9660
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 16 times.
17 true := Error.getNumErrorMessages() == numErrors;
9661 16 (cache,e_1,prop) := elabExpInExpression(cache, env, e, impl, true,pre,info);
9662 16 s1 := intString(position);
9663 16 s2 := AbsynUtil.pathStringNoQual(path);
9664 16 s3 := ExpressionBasics.printExpStr(e_1);
9665 16 s4 := TypesDump.unparseTypeNoAttr(Types.getPropType(prop));
9666 16 s5 := TypesDump.unparseTypeNoAttr(vt);
9667 16 Error.addSourceMessage(Error.ARG_TYPE_MISMATCH, {s1,s2,id,s3,s4,s5}, info);
9668 16 then fail();
9669
9670 end matchcontinue;
9671 end elabPositionalInputArg;
9672
9673 protected function elabNamedInputArgs
9674 "This function takes an Env, a NamedArg list, a DAE.FuncArg list and a
9675 Slot list.
9676 It builds up a new slot list and a list of elaborated expressions.
9677 If a slot is filled twice the function fails. If a slot is not filled at
9678 all and the
9679 value is not a parameter or a constant the function also fails."
9680 input FCore.Cache inCache;
9681 input FCore.Graph inEnv;
9682 input list<Absyn.NamedArg> inAbsynNamedArgLst;
9683 input list<DAE.FuncArg> inTypesFuncArgLst;
9684 input list<Slot> inSlotLst;
9685 input Boolean onlyOneFunction;
9686 input Boolean checkTypes "if true, check types";
9687 input Boolean impl;
9688 input InstTypes.PolymorphicBindings inPolymorphicBindings;
9689 input DAE.Prefix inPrefix;
9690 input SourceInfo info;
9691 input Absyn.Path path;
9692 input Boolean isGraphicsExp;
9693 output FCore.Cache outCache;
9694 output list<Slot> outSlotLst;
9695 output list<DAE.Const> outTypesConstLst;
9696 output InstTypes.PolymorphicBindings outPolymorphicBindings;
9697 algorithm
9698 (outCache,outSlotLst,outTypesConstLst,outPolymorphicBindings) :=
9699 match (inCache,inEnv,inAbsynNamedArgLst,inTypesFuncArgLst,inSlotLst,inPolymorphicBindings)
9700 local
9701 DAE.Const c1;
9702 list<Slot> slots;
9703 list<DAE.Const> clist;
9704 FCore.Graph env;
9705 Absyn.NamedArg na;
9706 list<Absyn.NamedArg> nas;
9707 list<DAE.FuncArg> farg;
9708 FCore.Cache cache;
9709 InstTypes.PolymorphicBindings polymorphicBindings;
9710
9711 // the empty case
9712 case (cache,_,{},_,slots,_)
9713 then (cache,slots,{},inPolymorphicBindings);
9714
9715 case (cache, env, na :: nas, farg, slots, polymorphicBindings)
9716 algorithm
9717 3393 (cache,slots,c1,polymorphicBindings) :=
9718 elabNamedInputArg(cache, env, na, farg, slots, onlyOneFunction, checkTypes, impl, polymorphicBindings, inPrefix, info, path, Error.getNumErrorMessages(), isGraphicsExp);
9719 3368 (cache,slots,clist,polymorphicBindings) :=
9720 elabNamedInputArgs(cache, env, nas, farg, slots, onlyOneFunction, checkTypes, impl, polymorphicBindings, inPrefix, info, path, isGraphicsExp);
9721 3362 then
9722 (cache,slots,c1::clist,polymorphicBindings);
9723
9724 end match;
9725 end elabNamedInputArgs;
9726
9727 protected function elabNamedInputArg
9728 "This function takes an Env, a NamedArg list, a DAE.FuncArg list and a
9729 Slot list.
9730 It builds up a new slot list and a list of elaborated expressions.
9731 If a slot is filled twice the function fails. If a slot is not filled at
9732 all and the
9733 value is not a parameter or a constant the function also fails."
9734 input FCore.Cache inCache;
9735 input FCore.Graph inEnv;
9736 input Absyn.NamedArg inNamedArg;
9737 input list<DAE.FuncArg> inTypesFuncArgLst;
9738 input list<Slot> inSlotLst;
9739 input Boolean onlyOneFunction;
9740 input Boolean checkTypes "if true, check types";
9741 input Boolean impl;
9742 input InstTypes.PolymorphicBindings inPolymorphicBindings;
9743 input DAE.Prefix inPrefix;
9744 input SourceInfo info;
9745 input Absyn.Path path;
9746 input Integer numErrors;
9747 input Boolean isGraphicsExp;
9748 output FCore.Cache outCache;
9749 output list<Slot> outSlotLst;
9750 output DAE.Const outTypesConstLst;
9751 output InstTypes.PolymorphicBindings outPolymorphicBindings;
9752 algorithm
9753 (outCache,outSlotLst,outTypesConstLst,outPolymorphicBindings) :=
9754 matchcontinue (inCache, inEnv, inNamedArg, inTypesFuncArgLst, inSlotLst, onlyOneFunction, checkTypes, inPolymorphicBindings, inPrefix)
9755 local
9756 DAE.Exp e_1,e_2;
9757 DAE.Type t,vt;
9758 DAE.Const c1;
9759 DAE.VarParallelism pr;
9760 list<Slot> slots_1,slots;
9761 FCore.Graph env;
9762 String id;
9763 Absyn.Exp e;
9764 list<DAE.FuncArg> farg;
9765 DAE.CodeType ct;
9766 FCore.Cache cache;
9767 DAE.Dimensions ds;
9768 DAE.Prefix pre;
9769 InstTypes.PolymorphicBindings polymorphicBindings;
9770 DAE.Properties prop;
9771 String s1,s2,s3,s4;
9772
9773 case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre)
9774 algorithm
9775
2/2
✓ Branch 1 taken 3293 times.
✓ Branch 2 taken 26 times.
3332 vt as DAE.T_CODE(ty=ct) := findNamedArgType(id, farg);
9776 26 pr := findNamedArgParallelism(id,farg);
9777 26 e_1 := elabCodeExp(e,cache,env,ct,info);
9778 26 slots_1 := fillSlot(DAE.FUNCARG(id,vt,DAE.C_VAR(),pr,NONE()), e_1, {}, slots,pre,info, path);
9779 26 then (cache,slots_1,DAE.C_VAR(),polymorphicBindings);
9780
9781 // check types exact match
9782 case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre)
9783 algorithm
9784 3306 vt := findNamedArgType(id, farg);
9785 3293 pr := findNamedArgParallelism(id,farg);
9786
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3293 times.
3293 (cache,e_1,DAE.PROP(t,c1)) := elabExpInExpression(cache, env, e, impl, true,pre,info);
9787 3293 (e_2,_,polymorphicBindings) := Types.matchTypePolymorphic(e_1,t,vt,FGraph.getGraphPathNoImplicitScope(env),polymorphicBindings,false);
9788 3260 slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, {}, slots,pre,info, path);
9789 3260 then (cache,slots_1,c1,polymorphicBindings);
9790
9791 // check types vectorized argument
9792 case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, true, polymorphicBindings, pre)
9793 algorithm
9794 46 vt := findNamedArgType(id, farg);
9795 33 pr := findNamedArgParallelism(id,farg);
9796
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 33 times.
33 (cache,e_1,DAE.PROP(t,c1)) := elabExpInExpression(cache, env, e, impl, true,pre,info);
9797 33 (e_2,_,ds,polymorphicBindings) := Types.vectorizableType(e_1, t, vt, FGraph.getGraphPathNoImplicitScope(env));
9798 33 slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_2, ds, slots, pre,info, path);
9799 33 then (cache,slots_1,c1,polymorphicBindings);
9800
9801 // do not check types
9802 case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, slots, _, false, polymorphicBindings, pre)
9803 algorithm
9804 61 vt := findNamedArgType(id, farg);
9805 49 pr := findNamedArgParallelism(id,farg);
9806
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 49 times.
49 (cache,e_1,DAE.PROP(_,c1)) := elabExpInExpression(cache,env, e, impl,true,pre,info);
9807 49 slots_1 := fillSlot(DAE.FUNCARG(id,vt,c1,pr,NONE()), e_1, {}, slots,pre,info, path);
9808 49 then (cache,slots_1,c1,polymorphicBindings);
9809
9810 case (cache, _, Absyn.NAMEDARG(argName = id), farg, slots, true, _, polymorphicBindings, _)
9811 algorithm
9812
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
48 failure(findNamedArgType(id, farg));
9813 24 s1 := AbsynUtil.pathStringNoQual(path);
9814 24 Error.addSourceMessage(Error.NO_SUCH_PARAMETER, {s1,id}, info);
9815
1/2
✓ Branch 0 taken 24 times.
✗ Branch 1 not taken.
24 true := isGraphicsExp;
9816 ✗ then (cache,slots,DAE.C_CONST(),polymorphicBindings);
9817
9818 // failure
9819 case (cache, env, Absyn.NAMEDARG(argName = id,argValue = e), farg, _, true, true, _, pre)
9820 algorithm
9821
1/2
✓ Branch 1 taken 12 times.
✗ Branch 2 not taken.
12 true := Error.getNumErrorMessages() == numErrors;
9822 ✗ vt := findNamedArgType(id, farg);
9823 ✗ (cache,e_1,prop) := elabExpInExpression(cache, env, e, impl, true,pre,info);
9824 ✗ s1 := AbsynUtil.pathStringNoQual(path);
9825 ✗ s2 := ExpressionBasics.printExpStr(e_1);
9826 ✗ s3 := TypesDump.unparseTypeNoAttr(Types.getPropType(prop));
9827 ✗ s4 := TypesDump.unparseTypeNoAttr(vt);
9828 ✗ Error.addSourceMessage(Error.NAMED_ARG_TYPE_MISMATCH, {s1,id,s2,s3,s4}, info);
9829 ✗ then fail();
9830 end matchcontinue;
9831 end elabNamedInputArg;
9832
9833 protected function findNamedArg
9834 input String inIdent;
9835 input list<DAE.FuncArg> inArgs;
9836 output DAE.FuncArg outArg;
9837 protected
9838 String id;
9839 Boolean haveMM = Config.acceptMetaModelicaGrammar();
9840 String inIdent2 = if haveMM then "$in_"+inIdent else "";
9841 algorithm
9842
2/2
✓ Branch 0 taken 30573 times.
✓ Branch 1 taken 75 times.
30648 for arg in inArgs loop
9843 30573 DAE.FUNCARG(name = id) := arg;
9844
9845
7/10
✓ Branch 0 taken 14391 times.
✓ Branch 1 taken 16182 times.
✓ Branch 3 taken 4296 times.
✓ Branch 4 taken 10095 times.
✓ Branch 5 taken 534 times.
✓ Branch 6 taken 19944 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 534 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
30573 if id == inIdent or (haveMM and id == inIdent2) then
9846 outArg := arg;
9847 10095 return;
9848 end if;
9849 end for;
9850 75 fail();
9851 end findNamedArg;
9852
9853 protected function findNamedArgType
9854 "This function takes an Ident and a FuncArg list, and returns the FuncArg
9855 which has that identifier.
9856 Used for instance when looking up named arguments from the function type."
9857 input String inIdent;
9858 input list<DAE.FuncArg> inArgs;
9859 output DAE.Type outType;
9860 algorithm
9861 6769 DAE.FUNCARG(ty = outType) := findNamedArg(inIdent, inArgs);
9862 end findNamedArgType;
9863
9864 protected function findNamedArgParallelism
9865 "This function takes an Ident and a FuncArg list, and returns the
9866 parallelism of the FuncArg which has that identifier."
9867 input String inIdent;
9868 input list<DAE.FuncArg> inArgs;
9869 output DAE.VarParallelism outParallelism;
9870 algorithm
9871 3401 DAE.FUNCARG(par = outParallelism) := findNamedArg(inIdent, inArgs);
9872 end findNamedArgParallelism;
9873
9874 protected function fillSlot
9875 "This function takses a `FuncArg\' and an DAE.Exp and a Slot list and fills
9876 the slot holding the FuncArg, by setting the boolean value of the slot
9877 and setting the expression. The function fails if the slot is allready set."
9878 input DAE.FuncArg inFuncArg;
9879 input DAE.Exp inExp;
9880 input DAE.Dimensions inDims;
9881 input list<Slot> inSlotLst;
9882 input DAE.Prefix inPrefix;
9883 input SourceInfo inInfo;
9884 input Absyn.Path fn;
9885 output list<Slot> outSlotLst = {};
9886 protected
9887 String fa1, fa2, exp_str, c_str, pre_str;
9888 DAE.Type ty1;
9889 DAE.Const c1, c2;
9890 DAE.VarParallelism prl;
9891 Option<DAE.Exp> binding;
9892 Boolean filled;
9893 Integer idx, ses;
9894 Slot slot;
9895 list<Slot> rest_slots = inSlotLst;
9896 algorithm
9897 122405 DAE.FUNCARG(name = fa1, ty = ty1, const = c1) := inFuncArg;
9898
9899
1/2
✓ Branch 0 taken 264233 times.
✗ Branch 1 not taken.
264233 while not listEmpty(rest_slots) loop
9900 264233 slot :: rest_slots := rest_slots;
9901 264233 SLOT(defaultArg = DAE.FUNCARG(name = fa2)) := slot;
9902
9903 // Check if this slot has the same name as the one we're looking for.
9904
7/8
✓ Branch 1 taken 143354 times.
✓ Branch 2 taken 120879 times.
✓ Branch 4 taken 20949 times.
✓ Branch 5 taken 122405 times.
✓ Branch 6 taken 3707 times.
✓ Branch 7 taken 138121 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 3707 times.
264233 if stringEq(fa1, fa2) or stringEq("$in_"+fa1, fa2) /* OM extension input output arguments */ then
9905 122405 SLOT(defaultArg = DAE.FUNCARG(const = c2, par = prl, defaultBinding = binding),
9906 slotFilled = filled, idx = idx, evalStatus = ses) := slot;
9907
9908 // Fail if the slot is already filled.
9909
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 122405 times.
122405 if filled then
9910 ✗ pre_str := PrefixUtil.printPrefixStr3(inPrefix);
9911 ✗ Error.addSourceMessageAndFail(Error.FUNCTION_SLOT_ALREADY_FILLED,
9912 {fa2, pre_str}, inInfo);
9913 end if;
9914
9915 // Fail if the variability is wrong.
9916
2/2
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 122399 times.
122405 if not Types.constEqualOrHigher(c1, c2) then
9917 6 exp_str := ExpressionBasics.printExpStr(inExp);
9918 6 c_str := TypesDump.unparseConst(c2);
9919 18 Error.addSourceMessageAndFail(Error.FUNCTION_SLOT_VARIABILITY,
9920 {fa1, exp_str, AbsynUtil.pathStringNoQual(fn), TypesDump.unparseConst(c1), c_str}, inInfo);
9921 end if;
9922
9923 // Found a valid slot, fill it and reconstruct the slot list.
9924 244798 slot := SLOT(DAE.FUNCARG(fa2, ty1, c2, prl, binding), true, SOME(inExp), inDims, idx, ses);
9925 122399 outSlotLst := List.append_reverse(outSlotLst, slot :: rest_slots);
9926 122399 return;
9927 end if;
9928
9929 outSlotLst := slot :: outSlotLst;
9930 end while;
9931
9932 ✗ Error.addSourceMessageAndFail(Error.NO_SUCH_PARAMETER, {"", fa1}, inInfo);
9933 end fillSlot;
9934
9935 public function elabCref "
9936 function: elabCref
9937 Elaborate on a component reference. Check the type of the
9938 component referred to, and check if the environment contains
9939 either a constant binding for that variable, or if it contains an
9940 equation binding with a constant expression."
9941 input FCore.Cache inCache;
9942 input FCore.Graph inEnv;
9943 input Absyn.ComponentRef inComponentRef;
9944 input Boolean inImplicit "implicit instantiation";
9945 input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}";
9946 input DAE.Prefix inPrefix;
9947 input SourceInfo info;
9948 output FCore.Cache outCache;
9949 output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res;
9950 algorithm
9951 432315 (outCache,res) := elabCref1(inCache,inEnv,inComponentRef,inImplicit,performVectorization,inPrefix,true,info);
9952 end elabCref;
9953
9954 public function elabCrefNoEval "
9955 Some functions expect a DAE.ComponentRef back and use this instead of elabCref :)"
9956 input FCore.Cache inCache;
9957 input FCore.Graph inEnv;
9958 input Absyn.ComponentRef inComponentRef;
9959 input Boolean inImplicit "implicit instantiation";
9960 input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}";
9961 input DAE.Prefix inPrefix;
9962 input SourceInfo info;
9963 output FCore.Cache outCache;
9964 output DAE.Exp outExp;
9965 output DAE.Properties outProperties;
9966 output DAE.Attributes outAttributes;
9967 algorithm
9968
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 121041 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 121041 times.
✓ Branch 6 taken 121041 times.
✗ Branch 7 not taken.
121041 (outCache, SOME((outExp, outProperties, outAttributes))) :=
9969 elabCref1(inCache,inEnv,inComponentRef,inImplicit,performVectorization,inPrefix,false,info);
9970 end elabCrefNoEval;
9971
9972 protected function elabCref1 "
9973 function: elabCref
9974 Elaborate on a component reference. Check the type of the
9975 component referred to, and check if the environment contains
9976 either a constant binding for that variable, or if it contains an
9977 equation binding with a constant expression."
9978 input FCore.Cache inCache;
9979 input FCore.Graph inEnv;
9980 input Absyn.ComponentRef inComponentRef;
9981 input Boolean inImplicit "implicit instantiation";
9982 input Boolean performVectorization "true => generates vectorized expressions, {v[1],v[2],...}";
9983 input DAE.Prefix inPrefix;
9984 input Boolean evalCref;
9985 input SourceInfo info;
9986 output FCore.Cache outCache;
9987 output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res;
9988 algorithm
9989 (outCache,res) := matchcontinue (inCache,inEnv,inComponentRef,inImplicit,inPrefix)
9990 local
9991 DAE.ComponentRef c_1;
9992 DAE.Const const,constSubs;
9993 DAE.Type t,origt;
9994 DAE.Exp exp,crefExp;
9995 FCore.Graph env;
9996 Absyn.ComponentRef c;
9997 FCore.Cache cache;
9998 Boolean impl,isBuiltinFn,isBuiltinFnOrInlineBuiltin,hasZeroSizeDim;
9999 DAE.Type et;
10000 String s,scope;
10001 InstTypes.SplicedExpData splicedExpData;
10002 Absyn.Path path,fpath;
10003 list<String> enum_lit_strs;
10004 String typeStr,id;
10005 DAE.ComponentRef expCref;
10006 Option<DAE.Const> forIteratorConstOpt;
10007 DAE.Prefix pre;
10008 Absyn.Exp e;
10009 SCode.Element cl;
10010 DAE.FunctionBuiltin isBuiltin;
10011 DAE.Attributes attr;
10012 DAE.Binding binding "equation modification";
10013 list<Absyn.Subscript> subscripts;
10014 Absyn.ComponentRef stripped_cref;
10015
10016 // wildcard
10017 case (cache, _, Absyn.WILD(), _, _)
10018 algorithm
10019 6994 t := DAE.T_ANYTYPE_DEFAULT;
10020 6994 et := Types.simplifyType(t);
10021 6994 crefExp := Expression.makeCrefExp(DAE.WILD(),et);
10022 6994 then
10023 (cache,SOME((crefExp,DAE.PROP(t, DAE.C_VAR()),DAE.dummyAttrVar)));
10024
10025 // Boolean => {false, true}
10026 case (cache, _, Absyn.CREF_IDENT(name = "Boolean"), _, _)
10027 algorithm
10028 1 exp := Expression.makeScalarArray({DAE.BCONST(false), DAE.BCONST(true)}, DAE.T_BOOL_DEFAULT);
10029 1 t := DAE.T_ARRAY(DAE.T_BOOL_DEFAULT, {DAE.DIM_INTEGER(2)});
10030 1 then
10031 (cache, SOME((exp, DAE.PROP(t, DAE.C_CONST()), DAE.dummyAttrConst)));
10032
10033 case (_, _, Absyn.CREF_IDENT(name = "time"), _, _)
10034 algorithm
10035
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1028 times.
1028 res := if isValidTimeScope(inEnv, info) then BUILTIN_TIME else NONE();
10036 1028 then
10037 (inCache, res);
10038
10039 // qualified subscripted array
10040 case (cache, env, Absyn.CREF_QUAL(), impl, pre)
10041 algorithm
10042
2/2
✓ Branch 1 taken 117337 times.
✓ Branch 2 taken 3964 times.
121301 true := Config.acceptMetaModelicaGrammar();
10043
1/2
✓ Branch 1 taken 3964 times.
✗ Branch 2 not taken.
3964 true := AbsynUtil.crefHasSubscripts(inComponentRef);
10044
10045 // get the last subscripts and then strip them
10046 ✗ subscripts := AbsynUtil.crefGetLastSubs(inComponentRef);
10047 ✗ stripped_cref := AbsynUtil.crefStripLastSubs(inComponentRef);
10048
10049 // fail if there are still subscripts left or more than one have been extracted
10050 ✗ true := not AbsynUtil.crefHasSubscripts(stripped_cref) and listLength(subscripts) == 1;
10051
10052 // elaborate the subscript
10053 ✗ {Absyn.SUBSCRIPT(e)} := subscripts;
10054 ✗ (cache, res) := elabCrefArraySubscripts(
10055 cref = stripped_cref,
10056 e = e,
10057 cache = cache,
10058 env = env,
10059 pre = pre,
10060 evalCref = evalCref,
10061 impl = impl,
10062 info = info
10063 );
10064 then
10065 (cache, res);
10066
10067 // ident subscripted array
10068 case (cache, env, Absyn.CREF_IDENT(name = id, subscripts = {Absyn.SUBSCRIPT(e)}), impl, pre)
10069 algorithm
10070
2/2
✓ Branch 1 taken 74210 times.
✓ Branch 2 taken 134 times.
74344 true := Config.acceptMetaModelicaGrammar();
10071 // elaborate the subscript
10072 134 (cache, res) := elabCrefArraySubscripts(
10073 cref = Absyn.CREF_IDENT(id, {}),
10074 e = e,
10075 cache = cache,
10076 env = env,
10077 pre = pre,
10078 evalCref = evalCref,
10079 impl = impl,
10080 info = info
10081 );
10082 then
10083 (cache, res);
10084
10085 // a normal cref
10086 case (cache, env, c, impl, pre)
10087 algorithm
10088 545333 c := replaceEnd(c);
10089
2/2
✓ Branch 1 taken 2835 times.
✓ Branch 2 taken 542498 times.
545333 env := if AbsynUtil.crefIsFullyQualified(inComponentRef) then FGraph.topScope(inEnv) else inEnv;
10090 545333 (cache,c_1,constSubs,hasZeroSizeDim) := elabCrefSubs(cache, env, inEnv, c, pre, DAE.NOPRE(), impl, false, info);
10091 535354 (cache,attr,t,binding,forIteratorConstOpt,splicedExpData) := Lookup.lookupVar(cache, env, c_1);
10092 // get the binding if is a constant
10093 535354 (cache,exp,const,attr) := elabCref2(cache, env, c_1, attr, constSubs, forIteratorConstOpt, t, binding, performVectorization, splicedExpData, pre, evalCref, info);
10094 535354 t := fixEnumerationType(t);
10095
4/4
✓ Branch 0 taken 1803 times.
✓ Branch 1 taken 533551 times.
✓ Branch 2 taken 31 times.
✓ Branch 3 taken 1772 times.
1068936 (exp,const) := evaluateEmptyVariable(hasZeroSizeDim and evalCref,exp,t,const);
10096 535354 then
10097 (cache,SOME((exp,DAE.PROP(t, const),attr)));
10098
10099 // An enumeration type => array of enumeration literals.
10100 case (cache, env, c, _, _)
10101 algorithm
10102 9979 c := replaceEnd(c);
10103 9979 path := AbsynUtil.crefToPath(c);
10104
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 372 times.
✓ Branch 3 taken 367 times.
✓ Branch 4 taken 5 times.
9286 (cache, cl as SCode.CLASS(restriction = SCode.R_ENUMERATION()), env) :=
10105 Lookup.lookupClass(cache, env, path);
10106 5 typeStr := AbsynUtil.pathLastIdent(path);
10107 5 path := FGraph.joinScopePath(env, Absyn.IDENT(typeStr));
10108 5 enum_lit_strs := SCodeUtil.componentNames(cl);
10109 5 (exp, t) := makeEnumerationArray(path, enum_lit_strs);
10110 5 then
10111 (cache,SOME((exp,DAE.PROP(t, DAE.C_CONST()),DAE.dummyAttrConst /* RO */)));
10112
10113 // MetaModelica Partial Function
10114 case (cache, env, c, _, _)
10115 algorithm
10116 // true = Flags.isSet(Flags.FNPTR) or Config.acceptMetaModelicaGrammar();
10117 9974 path := AbsynUtil.crefToPath(c);
10118 // call the lookup function that removes errors when it fails!
10119
3/4
✓ Branch 1 taken 8938 times.
✓ Branch 2 taken 343 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 343 times.
9281 (cache, {t}) := lookupFunctionsInEnvNoError(cache, env, path, info);
10120 343 (isBuiltin,isBuiltinFn,path) := isBuiltinFunc(path,t);
10121 343 isBuiltinFnOrInlineBuiltin := not valueEq(DAE.FUNCTION_NOT_BUILTIN(),isBuiltin);
10122 // some builtin functions store {} there
10123 fpath := match t
10124 343 case DAE.T_FUNCTION() then t.path;
10125 end match;
10126 origt := t;
10127 343 t := Types.makeFunctionPolymorphicReference(t);
10128 343 c := AbsynUtil.pathToCref(fpath);
10129 343 expCref := ComponentReference.toExpCref(c);
10130
2/2
✓ Branch 0 taken 264 times.
✓ Branch 1 taken 79 times.
607 exp := Expression.makeCrefExp(expCref,DAE.T_FUNCTION_REFERENCE_FUNC(isBuiltinFnOrInlineBuiltin,origt));
10131 // This is not done by lookup - only elabCall. So we should do it here.
10132
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 343 times.
343 (cache,Util.SUCCESS()) := instantiateDaeFunction(cache,env,path,isBuiltinFn,NONE(),true);
10133 343 then
10134 (cache,SOME((exp,DAE.PROP(t,DAE.C_VAR()),DAE.dummyAttrConst /* RO */)));
10135
10136 // MetaModelica extension
10137 case (cache, _, Absyn.CREF_IDENT("NONE",{}), _, _)
10138 algorithm
10139
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := Config.acceptMetaModelicaGrammar();
10140 1 Error.addSourceMessage(Error.META_NONE_CREF, {}, info);
10141 1 then
10142 (cache,NONE());
10143
10144 case (_, env, c, _, _)
10145 algorithm
10146 // enabled with -d=failtrace
10147
2/2
✓ Branch 1 taken 9629 times.
✓ Branch 2 taken 1 time.
9630 true := Flags.isSet(Flags.FAILTRACE);
10148 1 Debug.traceln("- Static.elabCref failed: " +
10149 Dump.printComponentRefStr(c) + " in env: " +
10150 FGraph.printGraphPathStr(env));
10151 // Debug.traceln("ENVIRONMENT:\n" + FGraph.printGraphStr(env));
10152 1 then
10153 fail();
10154
10155 /*
10156 // maybe we do have it but without a binding, so maybe we can actually type it!
10157 case (cache,env,c,impl,doVect,pre,info)
10158 algorithm
10159 failure((_,_,_) = elabCrefSubs(cache,env, c, pre, DAE.NOPRE(),impl,info));
10160 id = AbsynUtil.crefFirstIdent(c);
10161 (cache,DAE.TYPES_VAR(name, attributes, visibility, ty, binding, constOfForIteratorRange),
10162 SOME((cl as SCode.COMPONENT(n, pref, SCode.ATTR(arrayDims = ad), Absyn.TPATH(tpath, _),m,comment,cond,info),cmod)),instStatus,_)
10163 = Lookup.lookupIdent(cache, env, id);
10164 print("Static: cref:" + Dump.printComponentRefStr(c) + " component first ident:\n" + SCodeDump.unparseElementStr(cl) + "\n");
10165 (cache, cl, env) = Lookup.lookupClass(cache, env, tpath);
10166 print("Static: cref:" + Dump.printComponentRefStr(c) + " class component first ident:\n" + SCodeDump.unparseElementStr(cl) + "\n");
10167 then
10168 (cache,NONE());*/
10169
10170 case (cache, env, c, impl, pre)
10171 algorithm
10172
2/2
✓ Branch 0 taken 9630 times.
✓ Branch 1 taken 9630 times.
19260 failure(elabCrefSubs(cache,env, env,c, pre, DAE.NOPRE(),impl,false,info));
10173 9630 s := Dump.printComponentRefStr(c);
10174 9630 scope := FGraph.printGraphPathStr(env);
10175 // No need to add prefix info since problem only depends on the scope?
10176 9630 Error.addSourceMessage(Error.LOOKUP_VARIABLE_ERROR, {s,scope}, info);
10177 9630 then
10178 (cache,NONE());
10179 end matchcontinue;
10180 end elabCref1;
10181
10182 protected function elabCrefArraySubscripts
10183 "function: elabCrefArraySubscripts
10184 Parse the subscripts of an array and unbox if necessary."
10185 input Absyn.ComponentRef cref "originally subscripted (now stripped) cref";
10186 input Absyn.Exp e "the subscript";
10187 input output FCore.Cache cache "cache";
10188 input FCore.Graph env "environment";
10189 input DAE.Prefix pre "cref prefixes";
10190 input Boolean evalCref "true if cref should be evaluated";
10191 input Boolean impl "implicit instantiation";
10192 input SourceInfo info "source information";
10193 output Option<tuple<DAE.Exp,DAE.Properties,DAE.Attributes>> res "elaborated expression with props and attr";
10194 protected
10195 DAE.Exp exp, exp1, exp2;
10196 DAE.Const const, const1, const2;
10197 DAE.Type t, sub_ty;
10198 DAE.Attributes attr;
10199 algorithm
10200 // Elaborate the cref without the subscript.
10201
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 134 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 134 times.
134 (cache, SOME((exp1, DAE.PROP(t, const1), attr))) :=
10202 elabCref1(cache, env, cref, false, false, pre, evalCref, info);
10203
10204 // Check that the type is a MetaModelica array, and get the element type.
10205 134 t := Types.metaArrayElementType(t);
10206
10207 // Elaborate the subscript.
10208
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
134 (cache,exp2,DAE.PROP(sub_ty, const2)) :=
10209 elabExpInExpression(cache,env,e,impl,false,pre,info);
10210
10211 // Unbox the subscript if it's boxed, since it will be converted to an
10212 // arrayGet/arrayUpdate in code generation.
10213
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 129 times.
134 if Types.isMetaBoxedType(sub_ty) then
10214 5 sub_ty := Types.unboxedType(sub_ty);
10215 5 exp2 := DAE.UNBOX(exp2, sub_ty);
10216 end if;
10217
10218
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 134 times.
134 true := Types.isScalarInteger(sub_ty);
10219 134 const := Types.constAnd(const1,const2);
10220 134 exp := Expression.makeASUB(exp1,{exp2});
10221 134 res := SOME((exp, DAE.PROP(t, const), attr));
10222 end elabCrefArraySubscripts;
10223
10224 protected function isValidTimeScope
10225 "Checks if time is allowed to be used in the current scope."
10226 input FCore.Graph inEnv;
10227 input SourceInfo inInfo;
10228 output Boolean outIsValid;
10229 protected
10230 SCode.Restriction res;
10231 algorithm
10232 try
10233 1028 res := FGraph.lastScopeRestriction(inEnv);
10234 else
10235 outIsValid := true;
10236 65 return;
10237 end try;
10238
10239 outIsValid := match res
10240 case SCode.R_CLASS() then true;
10241 case SCode.R_OPTIMIZATION() then true;
10242 case SCode.R_MODEL() then true;
10243 case SCode.R_BLOCK() then true;
10244 else
10245 algorithm
10246 ✗ Error.addSourceMessage(Error.INVALID_TIME_SCOPE, {}, inInfo);
10247 then
10248 false;
10249 end match;
10250 end isValidTimeScope;
10251
10252 protected function lookupFunctionsInEnvNoError
10253 input FCore.Cache inCache;
10254 input FCore.Graph inEnv;
10255 input Absyn.Path inPath;
10256 input SourceInfo inInfo;
10257 output FCore.Cache outCache;
10258 output list<DAE.Type> outTypesTypeLst;
10259 algorithm
10260 (outCache, outTypesTypeLst) := match inInfo
10261
10262 case _
10263 algorithm
10264 9281 ErrorExt.setCheckpoint("Static.lookupFunctionsInEnvNoError");
10265 9281 (outCache, outTypesTypeLst) := Lookup.lookupFunctionsInEnv(inCache, inEnv, inPath, inInfo);
10266 // rollback lookup errors!
10267 9281 ErrorExt.rollBack("Static.lookupFunctionsInEnvNoError");
10268
1/2
✓ Branch 0 taken 9281 times.
✗ Branch 1 not taken.
9281 then
10269 (outCache, outTypesTypeLst);
10270
10271 else
10272 algorithm
10273 // rollback lookup errors!
10274 ✗ ErrorExt.rollBack("Static.lookupFunctionsInEnvNoError");
10275 ✗ then
10276 fail();
10277 end match;
10278 end lookupFunctionsInEnvNoError;
10279
10280
10281 protected function evaluateEmptyVariable
10282 "A variable with a 0-length dimension can be evaluated.
10283 This is good to do because otherwise the C-code contains references to non-existing variables"
10284 input Boolean hasZeroSizeDim;
10285 input DAE.Exp inExp;
10286 input DAE.Type ty;
10287 input DAE.Const c;
10288 output DAE.Exp oexp;
10289 output DAE.Const oc;
10290 algorithm
10291 (oexp,oc) := matchcontinue (hasZeroSizeDim, inExp)
10292 local
10293 Boolean sc,a;
10294 DAE.Type et;
10295 list<DAE.Subscript> ss;
10296 DAE.ComponentRef cr;
10297 list<DAE.Exp> expl;
10298 DAE.Exp exp;
10299
10300 case (true, DAE.ASUB(sub=ss))
10301 algorithm
10302 ✗ expl := list(Expression.getSubscriptExp(sub) for sub in ss);
10303 // TODO: Use a DAE.ERROR() or something if this has subscripts?
10304 ✗ a := Types.isArray(ty);
10305 sc := boolNot(a);
10306 ✗ et := Types.simplifyType(ty);
10307 ✗ exp := DAE.ARRAY(et,sc,{});
10308 ✗ exp := Expression.makeASUB(exp,expl);
10309 then (exp,c);
10310
10311 case (true, DAE.CREF(componentRef=cr))
10312 algorithm
10313 19 a := Types.isArray(ty);
10314 sc := boolNot(a);
10315 19 et := Types.simplifyType(ty);
10316
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 17 times.
19 {} := ComponentReference.crefLastSubs(cr);
10317
1/2
✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
34 exp := DAE.ARRAY(et,sc,{});
10318 then (exp,c);
10319
10320 case (true, DAE.CREF(componentRef=cr))
10321 algorithm
10322 // TODO: Use a DAE.ERROR() or something if this has subscripts?
10323 2 a := Types.isArray(ty);
10324 sc := boolNot(a);
10325 2 et := Types.simplifyType(ty);
10326
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 ss as _::_ := ComponentReference.crefLastSubs(cr);
10327
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
4 exp := DAE.ARRAY(et,sc,{});
10328 2 exp := Expression.makeASUB(exp,List.map(ss,Expression.getSubscriptExp));
10329 then (exp,c);
10330
10331 else (inExp,c);
10332 end matchcontinue;
10333 end evaluateEmptyVariable;
10334
10335 public function fixEnumerationType
10336 "Removes the index from an enumeration type."
10337 input DAE.Type inType;
10338 output DAE.Type outType;
10339 algorithm
10340 outType := match inType
10341 local
10342 Absyn.Path p;
10343 list<String> n;
10344 list<DAE.Var> v, al;
10345
10346 case DAE.T_ENUMERATION(index = SOME(_), path = p, names = n, literalVarLst = v, attributeLst = al)
10347 15252 then DAE.T_ENUMERATION(NONE(), p, n, v, al);
10348
10349 else inType;
10350 end match;
10351 end fixEnumerationType;
10352
10353 public function applySubscriptsVariability
10354 "Takes the variability of a variable and the constness of it's subscripts and
10355 determines if the varibility of the variable should be raised. I.e.:
10356 parameter with variable subscripts => variable
10357 constant with variable subscripts => variable
10358 constant with parameter subscripts => parameter"
10359 input SCode.Variability inVariability;
10360 input DAE.Const inSubsConst;
10361 output SCode.Variability outVariability;
10362 algorithm
10363 outVariability := match(inVariability, inSubsConst)
10364 case (SCode.PARAM(), DAE.C_VAR()) then SCode.VAR();
10365 case (SCode.CONST(), DAE.C_VAR()) then SCode.VAR();
10366 case (SCode.CONST(), DAE.C_PARAM()) then SCode.PARAM();
10367 else inVariability;
10368 end match;
10369 end applySubscriptsVariability;
10370
10371 public function makeEnumerationArray
10372 "Expands an enumeration type to an array of it's enumeration literals."
10373 input Absyn.Path enumTypeName;
10374 input list<String> enumLiterals;
10375 output DAE.Exp enumArray;
10376 output DAE.Type enumArrayType;
10377
10378 protected
10379 list<DAE.Exp> enum_lit_expl;
10380 Integer sz;
10381 DAE.Type ety;
10382 algorithm
10383 5 enum_lit_expl := Expression.makeEnumLiterals(enumTypeName, enumLiterals);
10384 5 sz := listLength(enumLiterals);
10385 10 ety := DAE.T_ARRAY(DAE.T_ENUMERATION(NONE(), enumTypeName, enumLiterals, {}, {}),
10386 {DAE.DIM_ENUM(enumTypeName, enumLiterals, sz)});
10387 5 enumArray := DAE.ARRAY(ety, true, enum_lit_expl);
10388 enumArrayType := ety;
10389 end makeEnumerationArray;
10390
10391 protected function fillCrefSubscripts
10392 "This is a helper function to elab_cref2.
10393 It investigates a DAE.Type in order to fill the subscript lists of a
10394 component reference. For instance, the name a.b with the type array of
10395 one dimension will become a.b[:]."
10396 input DAE.ComponentRef inComponentRef;
10397 input DAE.Type inType;
10398 output DAE.ComponentRef outComponentRef;
10399 algorithm
10400 outComponentRef := match (inComponentRef,inType/*,slicedExp*/)
10401 local
10402 DAE.ComponentRef e,cref_1,cref;
10403 DAE.Type t;
10404 list<DAE.Subscript> subs_1,subs;
10405 String id;
10406 DAE.Type ty2;
10407 // no subscripts
10408 case ((e as DAE.CREF_IDENT(subscriptLst = {})),_) then e;
10409
10410 // simple ident with non-empty subscripts
10411 case ((DAE.CREF_IDENT(ident = id, identType = ty2, subscriptLst = subs)),t)
10412 algorithm
10413 77525 subs_1 := fillSubscripts(subs, t);
10414 77525 then
10415 ComponentReferenceBasics.makeCrefIdent(id,ty2,subs_1);
10416 // qualified ident with non-empty subscrips
10417 case ((DAE.CREF_QUAL(ident = id,subscriptLst = subs,componentRef = cref,identType = ty2 )),t)
10418 algorithm
10419 96021 subs := fillSubscripts(subs, ty2);
10420 96021 t := stripPrefixType(t, ty2);
10421 96021 cref_1 := fillCrefSubscripts(cref, t);
10422 96021 then
10423 ComponentReferenceBasics.makeCrefQual(id,ty2,subs,cref_1);
10424 end match;
10425 end fillCrefSubscripts;
10426
10427 protected function stripPrefixType
10428 input DAE.Type inType;
10429 input DAE.Type inPrefixType;
10430 output DAE.Type outType;
10431 algorithm
10432 outType := match(inType, inPrefixType)
10433 local
10434 DAE.Type t, pt;
10435
10436 735 case (DAE.T_ARRAY(ty = t), DAE.T_ARRAY(ty = pt)) then stripPrefixType(t, pt);
10437 else inType;
10438 end match;
10439 end stripPrefixType;
10440
10441 protected function fillSubscripts
10442 "Helper function to fillCrefSubscripts."
10443 input list<DAE.Subscript> inExpSubscriptLst;
10444 input DAE.Type inType;
10445 output list<DAE.Subscript> outExpSubscriptLst;
10446 algorithm
10447 outExpSubscriptLst := matchcontinue inType
10448 local
10449 list<DAE.Subscript> subs;
10450
10451 // an array
10452 case DAE.T_ARRAY()
10453 algorithm
10454 3597 subs := List.fill(DAE.WHOLEDIM(), listLength(TypesDump.getDimensions(inType)));
10455 3597 subs := List.stripN(subs, listLength(inExpSubscriptLst));
10456 2145 subs := listAppend(inExpSubscriptLst, subs);
10457 then
10458 subs;
10459
10460 // not an array type!
10461 else inExpSubscriptLst;
10462
10463 end matchcontinue;
10464 end fillSubscripts;
10465
10466 protected function elabCref2
10467 "This function does some more processing of crefs, like replacing a constant
10468 with its value and vectorizing a non-constant."
10469 input FCore.Cache inCache;
10470 input FCore.Graph inEnv;
10471 input DAE.ComponentRef inCref;
10472 input DAE.Attributes inAttributes;
10473 input DAE.Const constSubs;
10474 input Option<DAE.Const> inIteratorConst;
10475 input DAE.Type inType;
10476 input DAE.Binding inBinding;
10477 input Boolean inVectorize "true => vectorized expressions";
10478 input InstTypes.SplicedExpData splicedExpData;
10479 input DAE.Prefix inPrefix;
10480 input Boolean evalCref;
10481 input SourceInfo info;
10482 output FCore.Cache outCache = inCache;
10483 output DAE.Exp outExp;
10484 output DAE.Const outConst;
10485 output DAE.Attributes outAttributes;
10486 protected
10487 SCode.Variability var = DAEUtil.getAttrVariability(inAttributes);
10488 algorithm
10489 (outExp, outConst, outAttributes) := matchcontinue(var, inType, inBinding, splicedExpData)
10490 local
10491 DAE.Type expTy, idTy, expIdTy;
10492 DAE.ComponentRef cr, subCr1, subCr2;
10493 DAE.Exp e, index;
10494 Option<DAE.Exp> sexp;
10495 Values.Value v;
10496 DAE.Const const;
10497 String s, scope, pre_str;
10498 DAE.Binding binding;
10499 Integer i;
10500 Absyn.Path p;
10501 DAE.Attributes attr;
10502 list<DAE.Subscript> subsc;
10503
10504 // If type not yet determined, component must be referencing itself.
10505 // Use the variability as the constness.
10506 case (_, DAE.T_UNKNOWN(), _, _)
10507 algorithm
10508 80 expTy := Types.simplifyType(inType);
10509 80 const := Types.variabilityToConst(var);
10510 80 then
10511 (DAE.CREF(inCref, expTy), const, inAttributes);
10512
10513 // adrpo: report a warning if the binding came from a start value!
10514 // lochel: I moved the warning to the back end for now
10515 case (SCode.PARAM(), _, DAE.EQBOUND(source = DAE.BINDING_FROM_START_VALUE()), _)
10516 algorithm
10517
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80 times.
80 true := Types.getFixedVarAttributeParameterOrConstant(inType);
10518 // s := ComponentReferenceBasics.printComponentRefStr(inCref);
10519 // pre_str := PrefixUtil.printPrefixStr2(inPrefix);
10520 // s := pre_str + s;
10521 // str := DAEUtil.printBindingExpStr(inBinding);
10522 // Error.addSourceMessage(Error.UNBOUND_PARAMETER_WITH_START_VALUE_WARNING, {s,str}, info); // Don't add source info here... Many models give multiple errors that are not filtered out
10523 80 binding := DAEUtil.setBindingSource(inBinding, DAE.BINDING_FROM_DEFAULT_VALUE());
10524 80 (outCache, e, const, attr) := elabCref2(outCache, inEnv, inCref, inAttributes, constSubs,
10525 inIteratorConst, inType, binding, inVectorize, splicedExpData, inPrefix, evalCref, info);
10526 80 then
10527 (e, const, attr);
10528
10529 // an enumeration literal -> simplify to a literal expression
10530 case (SCode.CONST(), DAE.T_ENUMERATION(index = SOME(i), path = p), _, _) guard(evalCref)
10531 algorithm
10532 12593 p := AbsynUtil.joinPaths(p, ComponentReference.crefLastPath(inCref));
10533 12593 then
10534 (DAE.ENUM_LITERAL(p, i), DAE.C_CONST(), inAttributes);
10535
10536 // Don't evaluate constants if evalCref is false.
10537 case (SCode.CONST(), _, _, _) guard(not evalCref)
10538 algorithm
10539 ✗ expTy := Types.simplifyType(inType);
10540 ✗ then
10541 (Expression.makeCrefExp(inCref, expTy), DAE.C_CONST(), inAttributes);
10542
10543 // a constant with variable subscript
10544 case (SCode.CONST(), _, _, InstTypes.SPLICEDEXPDATA()) guard(Types.isVar(constSubs))
10545 algorithm
10546 237 cr := ComponentReferenceBasics.crefStripLastSubs(inCref);
10547 237 subsc := ComponentReference.crefLastSubs(inCref);
10548 237 (outCache, v) := Ceval.cevalCref(outCache, inEnv, cr, false, Absyn.MSG(info), 0);
10549 237 e := ValuesUtil.valueExp(v);
10550
4/4
✓ Branch 0 taken 290 times.
✓ Branch 1 taken 232 times.
✓ Branch 2 taken 290 times.
✓ Branch 3 taken 232 times.
522 e := Expression.makeASUB(e, list(Expression.getSubscriptExp(sub) for sub in subsc));
10551 then
10552 (e, DAE.C_VAR(), inAttributes);
10553
10554 // a constant -> evaluate binding
10555 case (SCode.CONST(), _, binding, InstTypes.SPLICEDEXPDATA(_, idTy))
10556 algorithm
10557
2/2
✓ Branch 1 taken 908 times.
✓ Branch 2 taken 56453 times.
57361 true := Types.equivtypes(inType, idTy);
10558
10559 try
10560 56453 (outCache, v) := Ceval.cevalCrefBinding(outCache, inEnv, inCref, binding, false, Absyn.MSG(info), 0);
10561 55167 e := ValuesUtil.valueExp(v);
10562 else
10563 // Couldn't evaluate binding, replace the cref with the unevaluated binding.
10564
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 1286 times.
✓ Branch 3 taken 1286 times.
✗ Branch 4 not taken.
1286 SOME(e) := DAEUtil.bindingExp(binding);
10565
10566 ✗ e := Expression.makeASUB(e,
10567 list(Expression.getSubscriptExp(sub) for sub in ComponentReference.crefLastSubs(inCref)));
10568 end try;
10569
10570 const := DAE.C_CONST(); //Types.constAnd(DAE.C_CONST(), constSubs);
10571 55167 then
10572 (e, const, inAttributes);
10573
10574 // a constant with some for iterator constness -> don't constant evaluate
10575 case (SCode.CONST(), _, _, _) guard(isSome(inIteratorConst))
10576 algorithm
10577 1279 expTy := Types.simplifyType(inType);
10578 1279 then
10579 (Expression.makeCrefExp(inCref, expTy), DAE.C_CONST(), inAttributes);
10580
10581 // a constant with a binding
10582 case (SCode.CONST(), _, DAE.EQBOUND(constant_ = DAE.C_CONST()),
10583 InstTypes.SPLICEDEXPDATA(sexp, idTy))
10584 algorithm
10585 908 expTy := Types.simplifyType(inType) "Constants with equal bindings should be constant, i.e. true
10586 but const is passed on, allowing constants to have wrong bindings
10587 This must be caught later on." ;
10588 908 expIdTy := Types.simplifyType(idTy);
10589 908 cr := fillCrefSubscripts(inCref, inType);
10590 908 e := Expression.makeCrefExp(cr, expTy);
10591 908 e := crefVectorize(inVectorize, e, inType, sexp, expIdTy);
10592 908 (outCache, v) := Ceval.ceval(outCache, inEnv, e, false, Absyn.MSG(info), 0);
10593 739 e := ValuesUtil.valueExp(v, SOME(e));
10594 then
10595 (e, DAE.C_CONST(), inAttributes);
10596
10597 // evaluate parameters only if "evalparam" or Config.getEvaluateParametersInAnnotations() is set
10598 // TODO! also ceval if annotation Evaluate := true.
10599 case (SCode.PARAM(), _, _, InstTypes.SPLICEDEXPDATA(sexp, idTy)) guard(DAEUtil.isBound(inBinding))
10600 algorithm
10601
3/4
✓ Branch 1 taken 53762 times.
✓ Branch 2 taken 571 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 53762 times.
54333 true := Flags.isSet(Flags.EVAL_PARAM) or Config.getEvaluateParametersInAnnotations();
10602 // make it a constant if evalparam is used
10603 571 attr := DAEUtil.setAttrVariability(inAttributes, SCode.CONST());
10604 571 expTy := Types.simplifyType(inType) "Constants with equal bindings should be constant, i.e. true
10605 but const is passed on, allowing constants to have wrong bindings
10606 This must be caught later on.";
10607 571 expIdTy := Types.simplifyType(idTy);
10608 571 cr := fillCrefSubscripts(inCref, inType);
10609 571 e := crefVectorize(inVectorize, Expression.makeCrefExp(cr, expTy), inType, sexp, expIdTy);
10610 571 (outCache, v) := Ceval.ceval(outCache, inEnv, e, false, Absyn.MSG(info), 0);
10611 558 e := ValuesUtil.valueExp(v, SOME(e));
10612 558 then
10613 (e, DAE.C_PARAM(), attr);
10614
10615 // a constant array indexed by a for iterator -> transform into an array of values. HACK! HACK! UGLY! TODO! FIXME!
10616 // handles things like fcall(data[i]) in 1:X where data is a package constant of the form:
10617 // data:={Common.SingleGasesData.N2,Common.SingleGasesData.H2,Common.SingleGasesData.CO,Common.SingleGasesData.O2,Common.SingleGasesData.H2O, Common.SingleGasesData.CO2}
10618 case (SCode.CONST(), _, DAE.EQBOUND(evaluatedExp = SOME(v), constant_ = DAE.C_CONST()),
10619 InstTypes.SPLICEDEXPDATA(SOME(DAE.CREF(componentRef = cr)), _))
10620 algorithm
10621
7/12
✗ Branch 1 not taken.
✓ Branch 2 taken 169 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 169 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 169 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 169 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 169 times.
✓ Branch 11 taken 5 times.
✓ Branch 12 taken 164 times.
169 {DAE.INDEX(DAE.CREF(componentRef = subCr2)), DAE.SLICE(exp = e)} := ComponentReference.crefLastSubs(cr);
10622
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 164 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 164 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 164 times.
164 {DAE.INDEX(index as DAE.CREF(componentRef = subCr1))} := ComponentReference.crefLastSubs(inCref);
10623
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 164 times.
164 true := ComponentReferenceBasics.crefEqual(subCr1, subCr2);
10624
2/4
✓ Branch 1 taken 164 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 164 times.
164 true := Expression.isArray(e) or Expression.isRange(e);
10625 164 e := ValuesUtil.valueExp(v, SOME(e));
10626 328 e := DAE.ASUB(e, {DAE.INDEX(index)});
10627 then
10628 (e, DAE.C_CONST(), inAttributes);
10629
10630 // constants without value should not produce error if they are not in a simulation model!
10631 case (SCode.CONST(), _, DAE.UNBOUND(), _) guard(isNone(inIteratorConst))
10632 algorithm
10633
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
7 if Flags.isSet(Flags.STATIC) then
10634 ✗ s := ComponentReferenceBasics.printComponentRefStr(inCref);
10635 ✗ scope := FGraph.printGraphPathStr(inEnv);
10636 ✗ pre_str := PrefixUtil.printPrefixStr2(inPrefix);
10637 ✗ s := pre_str + s;
10638
10639 ✗ Debug.traceln("- Static.elabCref2 failed on: " + pre_str + s +
10640 " with no constant binding in scope: " + scope);
10641 end if;
10642
10643 7 expTy := Types.simplifyType(inType);
10644 7 cr := fillCrefSubscripts(inCref, inType);
10645 7 e := Expression.makeCrefExp(cr, expTy);
10646 then
10647 (e, DAE.C_CONST(), inAttributes);
10648
10649 // Everything else, vectorize the cref.
10650 case (_, _, _, InstTypes.SPLICEDEXPDATA(sexp, idTy))
10651 algorithm
10652 464535 expTy := Types.simplifyType(inType);
10653 464535 expIdTy := Types.simplifyType(idTy);
10654 464535 cr := fillCrefSubscripts(inCref, inType);
10655 464535 e := crefVectorize(inVectorize, Expression.makeCrefExp(cr, expTy), inType, sexp, expIdTy);
10656 464535 const := Types.variabilityToConst(var);
10657 464535 then
10658 (e, const, inAttributes);
10659
10660 // failure!
10661 else
10662 algorithm
10663 ✗ true := Flags.isSet(Flags.FAILTRACE);
10664 ✗ pre_str := PrefixUtil.printPrefixStr2(inPrefix);
10665 ✗ Debug.traceln("- Static.elabCref2 failed for: " + pre_str +
10666 ComponentReferenceBasics.printComponentRefStr(inCref) +
10667 "\n env:" + FGraph.printGraphStr(inEnv));
10668 ✗ then
10669 fail();
10670
10671 end matchcontinue;
10672 end elabCref2;
10673
10674 public function crefVectorize
10675 "This function takes a DAE.Exp and a DAE.Type and if the expression
10676 is a ComponentRef and the type is an array it returns an array of
10677 component references with subscripts for each index.
10678 For instance, parameter Real x[3];
10679 gives cref_vectorize('x', <arraytype>) => '{x[1],x[2],x[3]}
10680 This is needed since the DAE does not know what the variable 'x' is,
10681 it only knows the variables 'x[1]', 'x[2]' and 'x[3]'.
10682 NOTE: Currently only works for one and two dimensions."
10683 input Boolean performVectorization "if false, return input";
10684 input DAE.Exp inExp;
10685 input DAE.Type inType;
10686 input Option<DAE.Exp> splicedExp;
10687 input DAE.Type crefIdType "the type of the last cref ident, without considering subscripts. picked up from splicedExpData and used for crefs in vectorized exp";
10688 output DAE.Exp outExp;
10689 algorithm
10690 outExp := matchcontinue (performVectorization, inExp, inType, splicedExp)
10691 local
10692 Boolean b1,b2;
10693 DAE.Type exptp;
10694 DAE.Exp e;
10695 DAE.ComponentRef cr;
10696 DAE.Type t;
10697 DAE.Dimension d1, d2;
10698 Integer ds, ds2;
10699
10700 // no vectorization
10701 case(false, e, _, _) then e;
10702
10703 // types extending basictype
10704 case (_, e, DAE.T_SUBTYPE_BASIC(complexType = t), _)
10705 algorithm
10706 948 e := crefVectorize(true,e,t,NONE(),crefIdType);
10707 then e;
10708
10709 // component reference and an array type with dimensions less than vectorization limit
10710 case (_, _, DAE.T_ARRAY(dims = {d1}, ty = DAE.T_ARRAY(dims = {d2})), SOME(DAE.CREF(componentRef = cr)))
10711 algorithm
10712 1168 b1 := (Expression.dimensionSize(d1) < Config.vectorizationLimit());
10713 1135 b2 := (Expression.dimensionSize(d2) < Config.vectorizationLimit());
10714
2/4
✓ Branch 0 taken 1135 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 1135 times.
✗ Branch 4 not taken.
1135 true := boolAnd(b1, b2) or Config.vectorizationLimit() == 0;
10715 1135 e := elabCrefSlice(cr,crefIdType);
10716 1135 e := elabMatrixToMatrixExp(e);
10717 then
10718 e;
10719
10720 case (_, _, DAE.T_ARRAY(dims = {d1}, ty = t), SOME(DAE.CREF(componentRef = cr)))
10721 algorithm
10722
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 32853 times.
32886 false := Types.isArray(t);
10723
2/4
✓ Branch 2 taken 32236 times.
✗ Branch 3 not taken.
✗ Branch 5 not taken.
✓ Branch 6 taken 32236 times.
32853 true := (Expression.dimensionSize(d1) < Config.vectorizationLimit()) or Config.vectorizationLimit() == 0;
10724 32236 e := elabCrefSlice(cr,crefIdType);
10725 then
10726 e;
10727
10728 // matrix sizes > vectorization limit is not vectorized
10729 case (_, DAE.CREF(componentRef = cr, ty = exptp), DAE.T_ARRAY(dims = {d1}, ty = t as DAE.T_ARRAY(dims = {d2})), _)
10730 algorithm
10731 33 ds := Expression.dimensionSize(d1);
10732 ✗ ds2 := Expression.dimensionSize(d2);
10733 ✗ b1 := (ds < Config.vectorizationLimit());
10734 ✗ b2 := (ds2 < Config.vectorizationLimit());
10735 ✗ true := boolAnd(b1, b2) or Config.vectorizationLimit() == 0;
10736 ✗ true := listEmpty(ComponentReference.crefLastSubs(cr));
10737 ✗ e := createCrefArray2d(cr, 1, ds, ds2, exptp, t,crefIdType);
10738 then
10739 e;
10740
10741 // vectorsizes > vectorization limit is not vectorized
10742 case (_, DAE.CREF(componentRef = cr,ty = exptp), DAE.T_ARRAY(dims = {d1},ty = t), _)
10743 algorithm
10744
2/2
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 907 times.
940 false := Types.isArray(t);
10745 907 ds := Expression.dimensionSize(d1);
10746
2/4
✓ Branch 1 taken 290 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 290 times.
290 true := ds < Config.vectorizationLimit() or Config.vectorizationLimit() == 0;
10747 290 e := createCrefArray(cr, 1, ds, exptp, t,crefIdType);
10748 then
10749 e;
10750 else inExp;
10751 end matchcontinue;
10752 end crefVectorize;
10753
10754 protected function extractDimensionOfChild
10755 "A function for extracting the type-dimension of the child to *me* to dimension *my* array-size.
10756 Also returns wheter the array is a scalar or not."
10757 input DAE.Exp inExp;
10758 output DAE.Dimensions outExp;
10759 output Boolean isScalar;
10760 algorithm
10761 (outExp,isScalar) := matchcontinue inExp
10762 local
10763 DAE.Exp exp2;
10764 list<DAE.Exp> expl1;
10765 DAE.Dimensions tl;
10766 Integer x;
10767 Boolean sc;
10768
10769 case DAE.ARRAY(ty = (DAE.T_ARRAY(dims=(tl))),scalar=sc)
10770 then (tl,sc);
10771
10772 case DAE.ARRAY(array=expl1 as ((exp2 as DAE.ARRAY(_,_,_)) :: _))
10773 algorithm
10774 1400 (tl,_) := extractDimensionOfChild(exp2);
10775 1400 x := listLength(expl1);
10776 1400 then
10777 (DAE.DIM_INTEGER(x)::tl, false );
10778
10779 case DAE.ARRAY(array=expl1)
10780 algorithm
10781 44089 x := listLength(expl1);
10782 44089 then ({DAE.DIM_INTEGER(x)},true);
10783
10784 case DAE.CREF(_ , _)
10785 then
10786 ({},true);
10787 end matchcontinue;
10788 end extractDimensionOfChild;
10789
10790 protected function elabCrefSlice
10791 "Bjozac, 2007-05-29 Main function from now for vectorizing output.
10792 the subscriptlist should contain either 'done slices' or numbers representing
10793 dimension entries.
10794 Example:
10795 1) a is a real[2,3] with no subscripts, the input here should be
10796 CREF_IDENT('a',{DAE.SLICE(DAE.ARRAY(_,_,{1,2})), DAE.SLICE(DAE.ARRAY(_,_,{1,2,3}))})>
10797 ==> {{a[1,1],a[1,2],a[1,3]},{a[2,1],a[2,2],a[2,3]}}
10798 2) a is a real[3,3] with subscripts {1,2},{1,3}, the input should be
10799 CREF_IDENT('a',{DAE.SLICE(DAE.ARRAY(_,_,{DAE.INDEX(1),DAE.INDEX(2)})),
10800 DAE.SLICE(DAE.ARRAY(_,_,{DAE.INDEX(1),DAE.INDEX(3)}))})
10801 ==> {{a[1,1],a[1,3]},{a[2,1],a[2,3]}}"
10802 input DAE.ComponentRef inCref;
10803 input DAE.Type inType;
10804 output DAE.Exp outCref;
10805 algorithm
10806 outCref := match(inCref, inType)
10807 local
10808 list<DAE.Subscript> ssl;
10809 String id;
10810 DAE.ComponentRef child;
10811 DAE.Exp exp1,childExp;
10812 DAE.Type ety, prety;
10813
10814 case( DAE.CREF_IDENT(ident = id,subscriptLst = ssl),ety)
10815 algorithm
10816 33371 exp1 := flattenSubscript(ssl,id,ety);
10817 then
10818 exp1;
10819 case( DAE.CREF_QUAL(ident = id, identType = prety, subscriptLst = ssl, componentRef = child),ety)
10820 algorithm
10821 7754 childExp := elabCrefSlice(child,ety);
10822 7736 exp1 := flattenSubscript(ssl,id,prety);
10823 7736 exp1 := mergeQualWithRest(exp1,childExp,ety);
10824 then
10825 exp1;
10826 end match;
10827 end elabCrefSlice;
10828
10829 protected function mergeQualWithRest
10830 "Incase we have a qual with child references, this function merges them.
10831 The input should be an array, or just one CREF_QUAL, of arrays...of arrays
10832 of CREF_QUALS and the same goes for 'rest'. Also the flat type as input."
10833 input DAE.Exp qual;
10834 input DAE.Exp rest;
10835 input DAE.Type inType;
10836 output DAE.Exp outExp;
10837 algorithm
10838 outExp := match(qual,rest,inType)
10839 local
10840 DAE.Exp exp1,exp2;
10841 list<DAE.Exp> expl1;
10842 DAE.Type ety;
10843 DAE.Dimensions iLst;
10844 Boolean scalar;
10845 // a component reference
10846 case(exp1 as DAE.CREF(_,_),exp2,_)
10847 8195 then mergeQualWithRest2(exp2,exp1);
10848 // an array
10849 case(DAE.ARRAY(_, _, expl1),exp2,ety)
10850 algorithm
10851 267 expl1 := List.map2(expl1,mergeQualWithRest,exp2,ety);
10852
10853 267 exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1);
10854 267 (iLst, scalar) := extractDimensionOfChild(exp2);
10855 267 ety := Expression.arrayEltType(ety);
10856
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 253 times.
281 exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1);
10857 then exp2;
10858 end match;
10859 end mergeQualWithRest;
10860
10861 protected function mergeQualWithRest2
10862 "Helper to mergeQualWithRest, handles the case
10863 when the child-qual is arrays of arrays."
10864 input DAE.Exp rest;
10865 input DAE.Exp qual;
10866 output DAE.Exp outExp;
10867 algorithm
10868 outExp := match(rest,qual)
10869 local
10870 DAE.Exp exp1,exp2;
10871 list<DAE.Exp> expl1;
10872 list<DAE.Subscript> ssl;
10873 DAE.ComponentRef cref,cref_2;
10874 String id;
10875 DAE.Type ety,ty2;
10876 Boolean scalar;
10877 // a component reference
10878 case(DAE.CREF(cref, ety),DAE.CREF(DAE.CREF_IDENT(id,ty2, ssl),_))
10879 algorithm
10880 21202 cref_2 := ComponentReferenceBasics.makeCrefQual(id,ty2, ssl,cref);
10881 21202 then Expression.makeCrefExp(cref_2,ety);
10882 // an array
10883 case(exp1 as DAE.ARRAY(ety, _, expl1), exp2 as DAE.CREF(DAE.CREF_IDENT(_,_, _),_))
10884 algorithm
10885 8240 expl1 := List.map1(expl1,mergeQualWithRest2,exp2);
10886 8240 exp1 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1);
10887 8240 (_, scalar) := extractDimensionOfChild(exp1);
10888
2/2
✓ Branch 0 taken 252 times.
✓ Branch 1 taken 7988 times.
8492 then DAE.ARRAY(ety, scalar, expl1);
10889 end match;
10890 end mergeQualWithRest2;
10891
10892 protected function flattenSubscript
10893 "to catch subscript free CREF's."
10894 input list<DAE.Subscript> inSubs;
10895 input String name;
10896 input DAE.Type inType;
10897 output DAE.Exp outExp;
10898 algorithm
10899 outExp := matchcontinue(inSubs,name, inType)
10900 local
10901 String id;
10902 list<DAE.Subscript> subs1;
10903 DAE.Exp exp1,exp2;
10904 DAE.Type ety;
10905 DAE.ComponentRef cref_;
10906 // empty list
10907 case({},id,ety)
10908 algorithm
10909 7311 cref_ := ComponentReferenceBasics.makeCrefIdent(id,ety,{});
10910 7311 exp1 := Expression.makeCrefExp(cref_,ety);
10911 then
10912 exp1;
10913 // some subscripts present
10914 case(subs1,id,ety) // {1,2,3}
10915 algorithm
10916 33796 exp2 := flattenSubscript2(subs1,id,ety);
10917 then
10918 exp2;
10919 end matchcontinue;
10920 end flattenSubscript;
10921
10922 // BZ(2010-01-29): Changed to public to be able to vectorize crefs from other places
10923 public function flattenSubscript2
10924 "This function takes the created 'invalid' subscripts
10925 and the name of the CREF and returning the CREFS
10926 Example: flattenSubscript2({SLICE({1,2}},SLICE({1}),\"a\",tp) ==> {{a[1,1]},{a[2,1]}}.
10927
10928 This is done in several function calls, this specific
10929 function extracts the numbers ( 1,2 and 1 ).
10930 "
10931 input list<DAE.Subscript> inSubs;
10932 input String name;
10933 input DAE.Type inType;
10934 output DAE.Exp outExp;
10935 algorithm
10936 outExp := matchcontinue(inSubs,name, inType)
10937 local
10938 String id;
10939 DAE.Subscript sub1;
10940 list<DAE.Subscript> subs1;
10941 list<DAE.Exp> expl1,expl2;
10942 DAE.Exp exp1,exp2,exp3;
10943 DAE.Type ety;
10944
10945 // empty subscript
10946 case({},_,_) then DAE.ARRAY(DAE.T_UNKNOWN_DEFAULT,false,{});
10947
10948 // first subscript integer, ety
10949 case( ( (DAE.INDEX(exp = exp1 as DAE.ICONST(_))) :: subs1),id,ety)
10950 algorithm
10951 1513 exp2 := flattenSubscript2(subs1,id,ety);
10952 //print("1. flattened rest into "+ExpressionDump.dumpExpStr(exp2,0)+"\n");
10953 1513 exp2 := applySubscript(exp1, exp2 ,id,Expression.unliftArray(ety));
10954 //print("1. applied this subscript into "+ExpressionDump.dumpExpStr(exp2,0)+"\n");
10955 then
10956 exp2;
10957 // special case for zero dimension...
10958 case( ((DAE.SLICE( DAE.ARRAY(_,_,(expl1 as DAE.ICONST(0)::{})) )):: subs1),id,ety) // {1,2,3}
10959 algorithm
10960 1327 exp2 := flattenSubscript2(subs1,id,ety);
10961 1327 expl2 := List.map3(expl1,applySubscript,exp2,id,ety);
10962 1327 exp3 := listHead(expl2);
10963 //exp3 = removeDoubleEmptyArrays(exp3);
10964 then
10965 exp3;
10966 // normal case;
10967 case( ((DAE.SLICE( DAE.ARRAY(_,_,expl1) )):: subs1),id,ety) // {1,2,3}
10968 algorithm
10969 940 exp2 := flattenSubscript2(subs1,id,ety);
10970 940 then
10971 flattenSubscript3(expl1, id, ety, exp2);
10972
10973 case ((sub1 as DAE.SLICE(exp = DAE.RANGE())) :: subs1, id, ety)
10974 algorithm
10975 31973 expl1 := Expression.expandRange(sub1.exp);
10976 31973 exp2 := flattenSubscript2(subs1, id, ety);
10977 31970 then
10978 flattenSubscript3(expl1, id, ety, exp2);
10979
10980 end matchcontinue;
10981 end flattenSubscript2;
10982
10983 protected function flattenSubscript3
10984 input list<DAE.Exp> inSubscripts;
10985 input String inName;
10986 input DAE.Type inType;
10987 input DAE.Exp inExp;
10988 output DAE.Exp outExp;
10989 protected
10990 list<DAE.Exp> expl;
10991 list<DAE.Dimension> dims;
10992 Boolean scalar;
10993 DAE.Type ty;
10994 algorithm
10995
4/4
✓ Branch 0 taken 102815 times.
✓ Branch 1 taken 32910 times.
✓ Branch 2 taken 102815 times.
✓ Branch 3 taken 32910 times.
135725 expl := list(applySubscript(e, inExp, inName, inType) for e in inSubscripts);
10996 32910 outExp := DAE.ARRAY(DAE.T_INTEGER_DEFAULT, false, expl);
10997 32910 (dims, scalar) := extractDimensionOfChild(outExp);
10998 32910 ty := Expression.arrayEltType(inType);
10999
2/2
✓ Branch 1 taken 1121 times.
✓ Branch 2 taken 31789 times.
34031 outExp := DAE.ARRAY(DAE.T_ARRAY(ty, dims), scalar, expl);
11000 end flattenSubscript3;
11001
11002 protected function removeDoubleEmptyArrays
11003 " A help function, to prevent the {{}} look of empty arrays."
11004 input DAE.Exp inArr;
11005 output DAE.Exp outArr;
11006 algorithm
11007 outArr := matchcontinue inArr
11008 local
11009 DAE.Exp exp1,exp2;
11010 list<DAE.Exp> expl1,expl3;
11011 DAE.Type ty1;
11012 Boolean sc;
11013 case DAE.ARRAY(array = ((exp2 as DAE.ARRAY(array={}))::{}) )
11014 then
11015 exp2;
11016 case DAE.ARRAY(ty = ty1,scalar=sc,array = expl1 as
11017 ((DAE.ARRAY())::expl3) )
11018 algorithm
11019 ✗ expl3 := List.map(expl1,removeDoubleEmptyArrays);
11020 ✗ exp1 := DAE.ARRAY(ty1, sc, (expl3));
11021 then
11022 exp1;
11023 case exp1 then exp1;
11024 case exp1
11025 algorithm
11026 ✗ print("- Static.removeDoubleEmptyArrays failure for: " + ExpressionBasics.printExpStr(exp1) + "\n");
11027 ✗ then
11028 fail();
11029 end matchcontinue;
11030 end removeDoubleEmptyArrays;
11031
11032 protected function applySubscript
11033 "here we apply the subscripts to the IDENTS of the CREF's.
11034 Special case for adressing INDEX[0], make an empty array.
11035 If we have an array of subscript, we call applySubscript2"
11036 input DAE.Exp inSub "dim n ";
11037 input DAE.Exp inSubs "dim >n";
11038 input String name;
11039 input DAE.Type inType;
11040 output DAE.Exp outExp;
11041 algorithm
11042 outExp := matchcontinue(inSub, inSubs ,name, inType)
11043 local
11044 String id;
11045 DAE.Exp exp1,exp2;
11046 DAE.Type ety,crty;
11047 DAE.Dimensions arrDim;
11048 DAE.ComponentRef cref_;
11049
11050 case(_,exp1 as DAE.ARRAY(DAE.T_ARRAY(dims = arrDim) ,_,{}),_ ,_)
11051 algorithm
11052
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 514 times.
514 true := Expression.arrayContainZeroDimension(arrDim);
11053 then exp1;
11054
11055 /* add dimensions */
11056 case(DAE.ICONST(integer=0),DAE.ARRAY(DAE.T_ARRAY(dims = arrDim) ,_,_),_ ,ety)
11057 algorithm
11058 3 ety := Expression.arrayEltType(ety);
11059 3 then DAE.ARRAY(DAE.T_ARRAY(ety, DAE.DIM_INTEGER(0)::arrDim),true,{});
11060
11061 case(DAE.ICONST(integer=0),_,_ ,ety)
11062 algorithm
11063 1322 ety := Expression.arrayEltType(ety);
11064 1322 then DAE.ARRAY(DAE.T_ARRAY(ety,{DAE.DIM_INTEGER(0)}),true,{});
11065
11066 case(exp1,DAE.ARRAY(_,_,{}),id ,ety)
11067 algorithm
11068
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 99404 times.
99404 true := Expression.isValidSubscript(exp1);
11069 99404 crty := Expression.unliftArray(ety) "only subscripting one dimension, unlifting once ";
11070 198808 cref_ := ComponentReferenceBasics.makeCrefIdent(id,ety,{DAE.INDEX(exp1)});
11071 99404 then Expression.makeCrefExp(cref_,crty);
11072
11073 case(exp1, exp2, _ ,ety)
11074 algorithm
11075
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4412 times.
4412 true := Expression.isValidSubscript(exp1);
11076 4412 then applySubscript2(exp1, exp2,ety);
11077 end matchcontinue;
11078 end applySubscript;
11079
11080 protected function applySubscript2
11081 "Handles multiple subscripts for the expression.
11082 If it is an array, we listmap applySubscript3"
11083 input DAE.Exp inSub "The subs to add";
11084 input DAE.Exp inSubs "The already created subs";
11085 input DAE.Type inType;
11086 output DAE.Exp outExp;
11087 algorithm
11088 outExp := match(inSub, inSubs, inType )
11089 local
11090 String id;
11091 DAE.Exp exp1,exp2;
11092 list<DAE.Exp> expl1;
11093 list<DAE.Subscript> subs;
11094 DAE.Type ety,ty2,crty;
11095 DAE.Dimensions iLst;
11096 Boolean scalar;
11097 DAE.ComponentRef cref_;
11098
11099 case(exp1, DAE.CREF(DAE.CREF_IDENT(id,ty2,subs),_ ),_ )
11100 algorithm
11101 724 crty := Expression.unliftArrayTypeWithSubs(DAE.INDEX(exp1)::subs,ty2);
11102 724 cref_ := ComponentReferenceBasics.makeCrefIdent(id,ty2,(DAE.INDEX(exp1)::subs));
11103 362 exp2 := Expression.makeCrefExp(cref_,crty);
11104 then exp2;
11105
11106 case(exp1, DAE.ARRAY(_,_,expl1),ety )
11107 algorithm
11108 4050 expl1 := List.map2(expl1,applySubscript3,exp1,ety);
11109 4050 exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1);
11110 4050 (iLst, scalar) := extractDimensionOfChild(exp2);
11111 4050 ety := Expression.arrayEltType(ety);
11112
2/2
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 4039 times.
4061 exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1);
11113 then exp2;
11114 end match;
11115 end applySubscript2;
11116
11117 protected function applySubscript3
11118 "Final applySubscript function, here we call ourself
11119 recursive until we have the CREFS we are looking for."
11120 input DAE.Exp inSubs "The already created subs";
11121 input DAE.Exp inSub "The subs to add";
11122 input DAE.Type inType;
11123 output DAE.Exp outExp;
11124 algorithm
11125 outExp := match(inSubs,inSub, inType )
11126 local
11127 String id;
11128 DAE.Exp exp1,exp2;
11129 list<DAE.Exp> expl1;
11130 list<DAE.Subscript> subs;
11131 DAE.Type ety,ty2,crty;
11132 DAE.Dimensions iLst;
11133 Boolean scalar;
11134 DAE.ComponentRef cref_;
11135
11136 case(DAE.CREF(DAE.CREF_IDENT(id,ty2,subs),_), exp1, _ )
11137 algorithm
11138 21448 crty := Expression.unliftArrayTypeWithSubs(DAE.INDEX(exp1)::subs,ty2);
11139 21448 cref_ := ComponentReferenceBasics.makeCrefIdent(id,ty2,(DAE.INDEX(exp1)::subs));
11140 10724 exp2 := Expression.makeCrefExp(cref_,crty);
11141 then exp2;
11142
11143 case(DAE.ARRAY(_,_,expl1), exp1, ety)
11144 algorithm
11145 22 expl1 := List.map2(expl1,applySubscript3,exp1,ety);
11146 22 exp2 := DAE.ARRAY(DAE.T_INTEGER_DEFAULT,false,expl1);
11147 22 (iLst, scalar) := extractDimensionOfChild(exp2);
11148 22 ety := Expression.arrayEltType(ety);
11149
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 20 times.
24 exp2 := DAE.ARRAY(DAE.T_ARRAY(ety, iLst), scalar, expl1);
11150 then exp2;
11151 end match;
11152 end applySubscript3;
11153
11154
11155 protected function callVectorize
11156 "author: PA
11157
11158 Takes an expression that is a function call and an expresion list
11159 and maps the call to each expression in the list.
11160 For instance, call_vectorize(DAE.CALL(XX(\"der\",),...),{1,2,3}))
11161 => {DAE.CALL(XX(\"der\"),{1}), DAE.CALL(XX(\"der\"),{2}),DAE.CALL(XX(\"der\",{3}))}
11162 NOTE: the vectorized expression is inserted first in the argument list
11163 of the call, so if extra arguments should be passed these can be given as
11164 input to the call expression."
11165 input DAE.Exp inExp;
11166 input list<DAE.Exp> inExpExpLst;
11167 output list<DAE.Exp> outExpExpLst;
11168 algorithm
11169 outExpExpLst := matchcontinue (inExp,inExpExpLst)
11170 local
11171 DAE.Exp e,callexp;
11172 list<DAE.Exp> es_1,args,es;
11173 Absyn.Path fn;
11174 DAE.CallAttributes attr;
11175 // empty list
11176 case (_,{}) then {};
11177 // vectorize call
11178 case ((callexp as DAE.CALL(fn,args,attr)),(e :: es))
11179 algorithm
11180 ✗ es_1 := callVectorize(callexp, es);
11181 ✗ then
11182 (DAE.CALL(fn,(e :: args),attr) :: es_1);
11183 else
11184 algorithm
11185 ✗ true := Flags.isSet(Flags.FAILTRACE);
11186 ✗ Debug.trace("- Static.callVectorize failed\n");
11187 ✗ then
11188 fail();
11189 end matchcontinue;
11190 end callVectorize;
11191
11192 protected function createCrefArray
11193 "helper function to crefVectorize, creates each individual cref,
11194 e.g. {x{1},x{2}, ...} from x."
11195 input DAE.ComponentRef inComponentRef1;
11196 input Integer inInteger2;
11197 input Integer inInteger3;
11198 input DAE.Type inType4;
11199 input DAE.Type inType5;
11200 input DAE.Type crefIdType;
11201 output DAE.Exp outExp;
11202 algorithm
11203 outExp := matchcontinue (inComponentRef1, inInteger2, inInteger3, inType4, inType5)
11204 local
11205 DAE.ComponentRef cr,cr_1;
11206 Integer indx,ds,indx_1;
11207 DAE.Type et,elt_tp;
11208 DAE.Type t;
11209 list<DAE.Exp> expl;
11210 DAE.Exp e_1;
11211 // index iterator dimension size
11212 case (_, indx, ds, et, _) guard indx > ds
11213 290 then
11214 DAE.ARRAY(et,true,{});
11215 // index
11216 /*
11217 case (cr,indx,ds,et,t,crefIdType)
11218 algorithm
11219 (DAE.INDEX(e_1) :: ss) = ComponentReference.crefLastSubs(cr);
11220 cr_1 = ComponentReferenceBasics.crefStripLastSubs(cr);
11221 cr_1 = ComponentReference.subscriptCref(cr_1,ss);
11222 DAE.ARRAY(_,_,expl) = createCrefArray(cr_1, indx, ds, et, t,crefIdType);
11223 expl = List.map1(expl,Expression.prependSubscriptExp,DAE.INDEX(e_1));
11224 then
11225 DAE.ARRAY(et,true,expl);
11226 */
11227 // for crefs with wholedim
11228 case (cr, indx, ds, et, t)
11229 algorithm
11230 628 indx_1 := indx + 1;
11231 628 cr_1 := ComponentReference.replaceWholeDimSubscript(cr,indx);
11232
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 593 times.
593 DAE.ARRAY(_,_,expl) := createCrefArray(cr, indx_1, ds, et, t,crefIdType);
11233 593 elt_tp := Expression.unliftArray(et);
11234 593 e_1 := crefVectorize(true,Expression.makeCrefExp(cr_1,elt_tp), t,NONE(),crefIdType);
11235 593 then
11236 DAE.ARRAY(et,true,(e_1 :: expl));
11237 // no subscript
11238 case (cr, indx, ds, et, t)
11239 algorithm
11240 35 indx_1 := indx + 1;
11241 // {} = ComponentReference.crefLastSubs(cr);
11242
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 35 times.
35 DAE.ARRAY(_,_,expl) := createCrefArray(cr, indx_1, ds, et, t,crefIdType);
11243 70 e_1 := Expression.makeASUB(Expression.makeCrefExp(cr,et),{DAE.ICONST(indx)});
11244 35 (e_1,_) := ExpressionSimplify.simplify(e_1);
11245 35 e_1 := crefVectorize(true,e_1, t,NONE(),crefIdType);
11246 35 then
11247 DAE.ARRAY(et,true,(e_1 :: expl));
11248 // failure
11249 case (cr, _, _, _, _)
11250 algorithm
11251 ✗ true := Flags.isSet(Flags.FAILTRACE);
11252 ✗ Debug.trace("createCrefArray failed on:" + ComponentReferenceBasics.printComponentRefStr(cr));
11253 ✗ then
11254 fail();
11255 end matchcontinue;
11256 end createCrefArray;
11257
11258 protected function createCrefArray2d
11259 "helper function to cref_vectorize, creates each
11260 individual cref, e.g. {x{1,1},x{2,1}, ...} from x."
11261 input DAE.ComponentRef inCref;
11262 input Integer inIndex;
11263 input Integer inDim1;
11264 input Integer inDim2;
11265 input DAE.Type inType5;
11266 input DAE.Type inType6;
11267 input DAE.Type crefIdType;
11268 output DAE.Exp outExp;
11269 algorithm
11270 outExp := matchcontinue (inCref, inIndex, inDim1, inDim2, inType5, inType6)
11271 local
11272 DAE.ComponentRef cr,cr_1;
11273 Integer indx,ds,ds2,indx_1;
11274 DAE.Type et,elt_tp;
11275 DAE.Type t;
11276 list<list<DAE.Exp>> ms;
11277 list<DAE.Exp> expl;
11278 // index iterator dimension size 1 dimension size 2
11279 case (_, indx, ds, _, et, _) guard indx > ds
11280 ✗ then
11281 DAE.MATRIX(et,0,{});
11282 // increase the index dimension
11283 case (cr, indx, ds, ds2, et, t)
11284 algorithm
11285 ✗ indx_1 := indx + 1;
11286 ✗ DAE.MATRIX(matrix = ms) := createCrefArray2d(cr, indx_1, ds, ds2, et, t,crefIdType);
11287 ✗ cr_1 := ComponentReference.subscriptCref(cr, {DAE.INDEX(DAE.ICONST(indx))});
11288 ✗ elt_tp := Expression.unliftArray(et);
11289 ✗ DAE.ARRAY(_,true,expl) := crefVectorize(true,Expression.makeCrefExp(cr_1,elt_tp), t,NONE(),crefIdType);
11290 ✗ then
11291 DAE.MATRIX(et,ds,(expl :: ms));
11292 //
11293 case (cr, _, _, _, _, _)
11294 algorithm
11295 ✗ true := Flags.isSet(Flags.FAILTRACE);
11296 ✗ Debug.traceln("- Static.createCrefArray2d failed on: " + ComponentReferenceBasics.printComponentRefStr(cr));
11297 ✗ then
11298 fail();
11299 end matchcontinue;
11300 end createCrefArray2d;
11301
11302 public function absynCrefToComponentReference "This function converts an absyn cref to a component reference"
11303 input Absyn.ComponentRef inComponentRef;
11304 output DAE.ComponentRef outComponentRef;
11305 algorithm
11306 outComponentRef := match inComponentRef
11307 local
11308 String i;
11309 Absyn.ComponentRef c;
11310 DAE.ComponentRef cref;
11311
11312 case Absyn.CREF_IDENT(name = i,subscripts = {})
11313 algorithm
11314 ✗ cref := ComponentReferenceBasics.makeCrefIdent(i, DAE.T_UNKNOWN_DEFAULT, {});
11315 then
11316 cref;
11317
11318 case Absyn.CREF_QUAL(name = i,subscripts = {},componentRef = c)
11319 algorithm
11320 ✗ cref := absynCrefToComponentReference(c);
11321 ✗ cref := ComponentReferenceBasics.makeCrefQual(i, DAE.T_UNKNOWN_DEFAULT, {}, cref);
11322 then
11323 cref;
11324
11325 case Absyn.CREF_FULLYQUALIFIED(componentRef = c)
11326 algorithm
11327 ✗ cref := absynCrefToComponentReference(c);
11328 then
11329 cref;
11330 end match;
11331 end absynCrefToComponentReference;
11332
11333 protected function elabCrefSubs
11334 "This function elaborates on all subscripts in a component reference."
11335 input FCore.Cache inCache;
11336 input FCore.Graph inCrefEnv "search for the cref in this environment";
11337 input FCore.Graph inSubsEnv;
11338 input Absyn.ComponentRef inComponentRef;
11339 input DAE.Prefix inTopPrefix "the top prefix, i.e. the one send down by elabCref1, needed to prefix expressions in subscript types!";
11340 input DAE.Prefix inCrefPrefix "the accumulated cref, required for lookup";
11341 input Boolean inBoolean;
11342 input Boolean inHasZeroSizeDim;
11343 input SourceInfo info;
11344 output FCore.Cache outCache;
11345 output DAE.ComponentRef outComponentRef;
11346 output DAE.Const outConst "The constness of the subscripts. Note: This is not the same as
11347 the constness of a cref with subscripts! (just becase x[1,2] has a constant subscript list does
11348 not mean that the variable x[1,2] is constant)";
11349 output Boolean outHasZeroSizeDim;
11350 algorithm
11351 (outCache,outComponentRef,outConst,outHasZeroSizeDim) := matchcontinue (inCache, inCrefEnv, inSubsEnv, inComponentRef, inTopPrefix, inCrefPrefix, inBoolean, inHasZeroSizeDim)
11352 local
11353 DAE.Type t;
11354 DAE.Dimensions sl;
11355 DAE.Const const,const1,const2;
11356 FCore.Graph crefEnv, crefSubs;
11357 String id;
11358 list<Absyn.Subscript> ss;
11359 Boolean impl, hasZeroSizeDim;
11360 DAE.ComponentRef cr;
11361 Absyn.ComponentRef absynCr;
11362 DAE.Type ty, id_ty;
11363 list<DAE.Subscript> ss_1;
11364 Absyn.ComponentRef restCref,absynCref;
11365 FCore.Cache cache;
11366 SCode.Variability vt;
11367 DAE.Prefix crefPrefix;
11368 DAE.Prefix topPrefix;
11369
11370 // IDENT
11371 case (cache, crefEnv, crefSubs, Absyn.CREF_IDENT(name = id,subscripts = ss), topPrefix, crefPrefix, impl, hasZeroSizeDim)
11372 algorithm
11373 // Debug.traceln("Try elabSucscriptsDims " + id);
11374 584823 (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix,
11375 ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{}));
11376 584823 (cache,_,_,_,_,InstTypes.SPLICEDEXPDATA(identType = id_ty),_,_,_) := Lookup.lookupVar(cache, crefEnv, cr);
11377 // false = Types.isUnknownType(t);
11378 // print("elabCrefSubs type of: " + id + " is " + TypesDump.printTypeStr(t) + "\n");
11379 // Debug.traceln(" elabSucscriptsDims " + id + " got var");
11380 // _ = Types.simplifyType(t);
11381 535356 id_ty := Types.simplifyType(id_ty);
11382 535356 hasZeroSizeDim := Types.isZeroLengthArray(id_ty);
11383 535356 sl := TypesDump.getDimensions(id_ty);
11384 // Constant evaluate subscripts on form x[1,p,q] where p,q are constants or parameters
11385 535356 (cache,ss_1,const) := elabSubscriptsDims(cache, crefSubs, ss, sl, impl, topPrefix, inComponentRef, info);
11386 535354 then
11387 (cache,ComponentReferenceBasics.makeCrefIdent(id,id_ty,ss_1),const,hasZeroSizeDim);
11388
11389 // QUAL,with no subscripts => looking for var in the top env!
11390 case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = {},componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim)
11391 algorithm
11392 187439 (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix,
11393 ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{}));
11394 //print("env:");print(FGraph.printGraphStr(env));print("\n");
11395 187439 (cache,_,t,_,_,_,_,_,_) := Lookup.lookupVar(cache, crefEnv, cr);
11396 127939 ty := Types.simplifyType(t);
11397 127939 sl := TypesDump.getDimensions(ty);
11398 127939 crefPrefix := PrefixUtil.prefixAdd(id,sl,{},crefPrefix,SCode.VAR(),ClassInf.UNKNOWN(Absyn.IDENT("")),info); // variability doesn't matter
11399 127939 (cache,cr,const,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info);
11400 98035 then
11401 (cache,ComponentReferenceBasics.makeCrefQual(id,ty,{},cr),const,hasZeroSizeDim);
11402
11403 // QUAL,with no subscripts second case => look for class
11404 case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = {},componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim)
11405 algorithm
11406 89404 crefPrefix := PrefixUtil.prefixAdd(id,{},{},crefPrefix,SCode.VAR(),ClassInf.UNKNOWN(Absyn.IDENT("")),info); // variability doesn't matter
11407 89404 (cache,cr,const,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info);
11408 58117 then
11409 (cache,ComponentReferenceBasics.makeCrefQual(id,DAE.T_COMPLEX_DEFAULT,{},cr),const,hasZeroSizeDim);
11410
11411 // QUAL,with constant subscripts
11412 case (cache, crefEnv, crefSubs, Absyn.CREF_QUAL(name = id,subscripts = ss as _::_,componentRef = restCref), topPrefix, crefPrefix, impl, hasZeroSizeDim)
11413 algorithm
11414 994 (cache,cr) := PrefixUtil.prefixCref(cache,crefEnv,InnerOuter.emptyInstHierarchy,crefPrefix,
11415 ComponentReferenceBasics.makeCrefIdent(id,DAE.T_UNKNOWN_DEFAULT,{}));
11416 994 (cache,DAE.ATTR(variability = vt),t,_,_,InstTypes.SPLICEDEXPDATA(identType = id_ty),_,_,_) := Lookup.lookupVar(cache, crefEnv, cr);
11417 950 ty := Types.simplifyType(t);
11418 950 id_ty := Types.simplifyType(id_ty);
11419 950 sl := TypesDump.getDimensions(id_ty);
11420 950 (cache,ss_1,const1) := elabSubscriptsDims(cache, crefSubs, ss, sl, impl, topPrefix, inComponentRef, info);
11421 950 crefPrefix := PrefixUtil.prefixAdd(id, sl, ss_1, crefPrefix, vt, ClassInf.UNKNOWN(Absyn.IDENT("")),info);
11422 950 (cache,cr,const2,hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, restCref, topPrefix, crefPrefix, impl, hasZeroSizeDim, info);
11423 950 const := Types.constAnd(const1, const2);
11424 950 then
11425 (cache,ComponentReferenceBasics.makeCrefQual(id,ty,ss_1,cr),const,hasZeroSizeDim);
11426
11427 case (cache, crefEnv, crefSubs, Absyn.CREF_FULLYQUALIFIED(componentRef = absynCr), topPrefix, crefPrefix, impl, hasZeroSizeDim)
11428 algorithm
11429 2835 crefEnv := FGraph.topScope(crefEnv);
11430 2835 (cache, cr, const1, hasZeroSizeDim) := elabCrefSubs(cache, crefEnv, crefSubs, absynCr, topPrefix, crefPrefix, impl, hasZeroSizeDim, info);
11431 then
11432 (cache, cr, const1, hasZeroSizeDim);
11433
11434 // failure
11435 case (_, crefEnv, _, absynCref, topPrefix, crefPrefix, _, _)
11436 algorithm
11437 // FAILTRACE REMOVE
11438
2/2
✓ Branch 1 taken 80798 times.
✓ Branch 2 taken 2 times.
80800 true := Flags.isSet(Flags.FAILTRACE);
11439 2 Debug.traceln("- Static.elabCrefSubs failed on: " +
11440 "[top:" + PrefixUtil.printPrefixStr(topPrefix) + "]." +
11441 PrefixUtil.printPrefixStr(crefPrefix) + "." +
11442 Dump.printComponentRefStr(absynCref) + " env: " +
11443 FGraph.printGraphPathStr(crefEnv));
11444 2 then
11445 fail();
11446 end matchcontinue;
11447 end elabCrefSubs;
11448
11449 public function elabSubscripts
11450 "This function converts a list of Absyn.Subscript to a list of
11451 DAE.Subscript, and checks if all subscripts are constant.
11452 HJ: not checking for constant, returning if constant or not"
11453 input FCore.Cache inCache;
11454 input FCore.Graph inEnv;
11455 input list<Absyn.Subscript> inAbsynSubscriptLst;
11456 input Boolean inBoolean;
11457 input DAE.Prefix inPrefix;
11458 input SourceInfo info;
11459 output FCore.Cache outCache;
11460 output list<DAE.Subscript> outExpSubscriptLst;
11461 output DAE.Const outConst;
11462 algorithm
11463 (outCache,outExpSubscriptLst,outConst) := match (inCache, inEnv, inAbsynSubscriptLst, inBoolean, inPrefix)
11464 local
11465 DAE.Subscript sub_1;
11466 DAE.Const const1,const2,const;
11467 list<DAE.Subscript> subs_1;
11468 FCore.Graph env;
11469 Absyn.Subscript sub;
11470 list<Absyn.Subscript> subs;
11471 Boolean impl;
11472 FCore.Cache cache;
11473 DAE.Prefix pre;
11474
11475 // empty list
11476 case (cache, _, {}, _, _) then (cache,{},DAE.C_CONST());
11477 // elab a subscript then recurse
11478 case (cache, env, (sub :: subs), impl, pre)
11479 algorithm
11480 13 (cache,sub_1,const1, _) := elabSubscript(cache,env, sub, impl,pre,info);
11481 13 (cache,subs_1,const2) := elabSubscripts(cache,env, subs, impl,pre,info);
11482 13 const := Types.constAnd(const1, const2);
11483 13 then
11484 (cache,(sub_1 :: subs_1),const);
11485 end match;
11486 end elabSubscripts;
11487
11488 protected function elabSubscriptsDims
11489 "Elaborates a list of subscripts and checks that they are valid for the given dimensions."
11490 input FCore.Cache inCache;
11491 input FCore.Graph inEnv;
11492 input list<Absyn.Subscript> inSubscripts;
11493 input list<DAE.Dimension> inDimensions;
11494 input Boolean inImpl;
11495 input DAE.Prefix inPrefix;
11496 input Absyn.ComponentRef inCref;
11497 input SourceInfo inInfo;
11498 output FCore.Cache outCache = inCache;
11499 output list<DAE.Subscript> outSubs = {};
11500 output DAE.Const outConst = DAE.C_CONST();
11501 protected
11502 list<DAE.Dimension> rest_dims = inDimensions;
11503 DAE.Dimension dim;
11504 DAE.Subscript dsub;
11505 DAE.Const const;
11506 Option<DAE.Properties> prop;
11507 String subl_str, diml_str, cref_str;
11508 Integer nrdims, nrsubs;
11509 algorithm
11510
2/2
✓ Branch 0 taken 82318 times.
✓ Branch 1 taken 536304 times.
618622 for asub in inSubscripts loop
11511
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 82318 times.
82318 if listEmpty(rest_dims) then
11512 // Check that we don't have more subscripts than there are dimensions.
11513 ✗ cref_str := Dump.printComponentRefStr(inCref);
11514 ✗ subl_str := intString(listLength(inSubscripts));
11515 ✗ diml_str := intString(listLength(inDimensions));
11516
11517 ✗ Error.addSourceMessageAndFail(Error.WRONG_NUMBER_OF_SUBSCRIPTS,
11518 {cref_str, subl_str, diml_str}, inInfo);
11519 else
11520 82318 dim :: rest_dims := rest_dims;
11521 end if;
11522
11523 82318 (outCache, dsub, const, prop) :=
11524 elabSubscript(outCache, inEnv, asub, inImpl, inPrefix, inInfo);
11525 82316 outConst := Types.constAnd(const, outConst);
11526 82316 (outCache, dsub) := elabSubscriptsDims2(outCache, inEnv, dsub, dim,
11527 outConst, prop, inImpl, inCref, inInfo);
11528
11529 82316 outSubs := dsub :: outSubs;
11530 end for;
11531
11532 536304 nrsubs := listLength(outSubs);
11533
11534 // If there are subs and the number of subs is less than dims
11535 // then fill in whole dims for the missing subs. i.e. We have a slice.
11536 // If there are no subs then it is a whole array so we do nothing.
11537
2/2
✓ Branch 0 taken 78703 times.
✓ Branch 1 taken 457601 times.
536304 if nrsubs > 0 then
11538 78703 nrdims := listLength(inDimensions);
11539
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 78703 times.
78703 while nrsubs < nrdims loop
11540 outSubs := DAE.WHOLEDIM()::outSubs;
11541 ✗ nrsubs := nrsubs + 1;
11542 end while;
11543 end if;
11544
11545 536304 outSubs := listReverse(outSubs);
11546 end elabSubscriptsDims;
11547
11548 protected function elabSubscriptsDims2
11549 "Helper function to elabSubscriptsDims."
11550 input FCore.Cache inCache;
11551 input FCore.Graph inEnv;
11552 input DAE.Subscript inSubscript;
11553 input DAE.Dimension inDimension;
11554 input DAE.Const inConst;
11555 input Option<DAE.Properties> inProperties;
11556 input Boolean inImpl;
11557 input Absyn.ComponentRef inCref;
11558 input SourceInfo inInfo;
11559 output FCore.Cache outCache;
11560 output DAE.Subscript outSubscript;
11561 algorithm
11562 (outCache, outSubscript) := matchcontinue(inDimension, inProperties)
11563 local
11564 FCore.Cache cache;
11565 DAE.Subscript sub;
11566 Integer int_dim;
11567 DAE.Properties prop;
11568 DAE.Type ty;
11569 DAE.Exp e;
11570 String sub_str, dim_str, cref_str;
11571
11572 // If in for iterator loop scope the subscript should never be evaluated to
11573 // a value (since the parameter/const value of iterator variables are not
11574 // available until expansion, which happens later on)
11575 // Note that for loops are expanded 'on the fly' and should therefore not be
11576 // treated in this way.
11577 case (_, _)
11578 algorithm
11579
2/2
✓ Branch 1 taken 81107 times.
✓ Branch 2 taken 1209 times.
82316 true := FGraph.inForOrParforIterLoopScope(inEnv);
11580
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1201 times.
1209 true := Expression.dimensionKnown(inDimension);
11581 1201 then
11582 (inCache, inSubscript);
11583
11584 // Keep non-fixed parameters.
11585 case (_, SOME(prop))
11586 algorithm
11587
2/2
✓ Branch 1 taken 78906 times.
✓ Branch 2 taken 963 times.
79869 true := Types.isParameter(inConst);
11588 963 ty := Types.getPropType(prop);
11589
1/2
✓ Branch 1 taken 963 times.
✗ Branch 2 not taken.
963 false := Types.getFixedVarAttributeParameterOrConstant(ty);
11590 ✗ then
11591 (inCache, inSubscript);
11592
11593 /*/ Keep parameters as they are:
11594 // adrpo 2012-12-02 this does not work as we need to evaluate final parameters!
11595 // and we have now way yet of knowing which ones those are
11596 case (_, _, _, _, _, _, _, _, _)
11597 algorithm
11598 true = Types.isParameter(inConst);
11599 then
11600 (inCache, inSubscript);*/
11601
11602 // If the subscript contains a const then it should be evaluated to
11603 // the value.
11604 case (_, _)
11605 algorithm
11606 81115 int_dim := Expression.dimensionSize(inDimension);
11607
2/2
✓ Branch 1 taken 903 times.
✓ Branch 2 taken 79321 times.
80224 true := Types.isParameterOrConstant(inConst);
11608 79321 (cache, sub) := Ceval.cevalSubscript(inCache, inEnv, inSubscript, int_dim, inImpl, Absyn.MSG(inInfo), 0);
11609 then
11610 (cache, sub);
11611
11612 case (DAE.DIM_EXP(exp=e), _)
11613 algorithm
11614
2/2
✓ Branch 1 taken 215 times.
✓ Branch 2 taken 41 times.
256 true := Types.isParameterOrConstant(inConst);
11615
0/2
✗ Branch 2 not taken.
✗ Branch 3 not taken.
41 (_, Values.INTEGER(integer=int_dim)) := Ceval.ceval(inCache,inEnv,e,true,Absyn.MSG(inInfo),0);
11616 ✗ (cache, sub) := Ceval.cevalSubscript(inCache, inEnv, inSubscript, int_dim, inImpl, Absyn.MSG(inInfo), 0);
11617 then
11618 (cache, sub);
11619
11620 // If the previous case failed and we're just checking the model, try again
11621 // but skip the constant evaluation.
11622 case (_, _)
11623 algorithm
11624
2/2
✓ Branch 1 taken 1769 times.
✓ Branch 2 taken 25 times.
1794 true := Flags.getConfigBool(Flags.CHECK_MODEL);
11625
2/2
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 5 times.
25 true := Types.isParameterOrConstant(inConst);
11626 5 then
11627 (inCache, inSubscript);
11628
11629 // Keep variables and parameters inside of for-loops as they are.
11630 case (_, _)
11631 algorithm
11632
2/2
✓ Branch 1 taken 886 times.
✓ Branch 2 taken 903 times.
1789 true := Expression.dimensionKnown(inDimension);
11633
2/6
✓ Branch 1 taken 903 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 903 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
903 false := Types.isConstant(inConst) or
11634 (Types.isParameter(inConst) and not FGraph.inForLoopScope(inEnv));
11635 903 then
11636 (inCache, inSubscript);
11637
11638 // For unknown dimensions, ':', keep as is.
11639 case (DAE.DIM_UNKNOWN(), _)
11640 630 then (inCache, inSubscript);
11641 case (DAE.DIM_EXP(_), _)
11642 256 then (inCache, inSubscript);
11643
11644 else
11645 algorithm
11646 ✗ sub_str := ExpressionBasics.printSubscriptStr(inSubscript);
11647 ✗ dim_str := ExpressionBasics.dimensionString(inDimension);
11648 ✗ cref_str := Dump.printComponentRefStr(inCref);
11649 ✗ Error.addSourceMessage(Error.ILLEGAL_SUBSCRIPT, {sub_str, dim_str, cref_str}, inInfo);
11650 ✗ then
11651 fail();
11652
11653 end matchcontinue;
11654 end elabSubscriptsDims2;
11655
11656 protected function elabSubscript "This function converts an Absyn.Subscript to an
11657 DAE.Subscript."
11658 input FCore.Cache inCache;
11659 input FCore.Graph inEnv;
11660 input Absyn.Subscript inSubscript;
11661 input Boolean inBoolean;
11662 input DAE.Prefix inPrefix;
11663 input SourceInfo info;
11664 output FCore.Cache outCache;
11665 output DAE.Subscript outSubscript;
11666 output DAE.Const outConst;
11667 output Option<DAE.Properties> outProperties;
11668 algorithm
11669 (outCache, outSubscript, outConst, outProperties) :=
11670 matchcontinue(inCache, inEnv, inSubscript, inBoolean, inPrefix)
11671 local
11672 Boolean impl;
11673 DAE.Exp sub_1;
11674 DAE.Type ty;
11675 DAE.Const const;
11676 DAE.Subscript sub_2;
11677 FCore.Graph env;
11678 Absyn.Exp sub;
11679 FCore.Cache cache;
11680 DAE.Properties prop;
11681 DAE.Prefix pre;
11682
11683 // no subscript
11684 case (cache, _, Absyn.NOSUB(), _, _)
11685 then (cache, DAE.WHOLEDIM(), DAE.C_CONST(), NONE());
11686
11687 // some subscript, try to elaborate it
11688 case (cache, env, Absyn.SUBSCRIPT(subscript = sub), impl, pre)
11689 algorithm
11690
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80837 times.
80839 (cache, sub_1, prop as DAE.PROP(constFlag = const)) :=
11691 elabExpInExpression(cache, env, sub, impl, true, pre, info);
11692
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 80837 times.
80837 (cache, sub_1, prop as DAE.PROP(type_ = ty)) :=
11693 Ceval.cevalIfConstant(cache, env, sub_1, prop, impl, info);
11694 80837 sub_2 := elabSubscriptType(ty, sub, sub_1, info);
11695 then
11696 (cache, sub_2, const, SOME(prop));
11697
11698 // failtrace
11699 else
11700 algorithm
11701
1/2
✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
2 true := Flags.isSet(Flags.FAILTRACE);
11702 ✗ Debug.traceln("- Static.elabSubscript failed on " +
11703 Dump.printSubscriptStr(inSubscript) + " in env: " +
11704 FGraph.printGraphPathStr(inEnv));
11705 ✗ then
11706 fail();
11707 end matchcontinue;
11708 end elabSubscript;
11709
11710 protected function elabSubscriptType
11711 "This function is used to find the correct constructor for DAE.Subscript to
11712 use for an indexing expression. If a scalar is given as index, DAE.INDEX()
11713 is used, and if an array is given, DAE.SLICE() is used."
11714 input DAE.Type inType;
11715 input Absyn.Exp inAbsynExp;
11716 input DAE.Exp inDaeExp;
11717 input SourceInfo inInfo;
11718 output DAE.Subscript outSubscript;
11719 algorithm
11720 outSubscript := match inType
11721 local
11722 String e_str,t_str;
11723
11724 79622 case DAE.T_INTEGER() then DAE.INDEX(inDaeExp);
11725 197 case DAE.T_ENUMERATION() then DAE.INDEX(inDaeExp);
11726 1 case DAE.T_BOOL() then DAE.INDEX(inDaeExp);
11727 1011 case DAE.T_ARRAY(ty = DAE.T_INTEGER()) then DAE.SLICE(inDaeExp);
11728 2 case DAE.T_ARRAY(ty = DAE.T_ENUMERATION()) then DAE.SLICE(inDaeExp);
11729 4 case DAE.T_ARRAY(ty = DAE.T_BOOL()) then DAE.SLICE(inDaeExp);
11730 case DAE.T_METABOXED()
11731 ✗ then elabSubscriptType(inType.ty, inAbsynExp, inDaeExp, inInfo);
11732
11733 else
11734 algorithm
11735 ✗ e_str := Dump.printExpStr(inAbsynExp);
11736 ✗ t_str := TypesDump.unparseType(inType);
11737 ✗ Error.addSourceMessage(Error.WRONG_DIMENSION_TYPE, {e_str, t_str}, inInfo);
11738 ✗ then
11739 fail();
11740 end match;
11741 end elabSubscriptType;
11742
11743 protected function subscriptCrefType
11744 "If a component of an array type is subscripted, the type of the
11745 component reference is of lower dimensionality than the
11746 component. This function shows the function between the component
11747 type and the component reference expression type.
11748
11749 This function might actually not be needed.
11750 "
11751 input DAE.Exp inExp;
11752 input DAE.Type inType;
11753 output DAE.Type outType;
11754 algorithm
11755 outType := matchcontinue (inExp,inType)
11756 local
11757 DAE.Type t_1,t;
11758 DAE.ComponentRef c;
11759
11760 case (DAE.CREF(componentRef = c),t)
11761 algorithm
11762 ✗ t_1 := subscriptCrefType2(c, t);
11763 then
11764 t_1;
11765
11766 else inType;
11767 end matchcontinue;
11768 end subscriptCrefType;
11769
11770 protected function subscriptCrefType2
11771 input DAE.ComponentRef inComponentRef;
11772 input DAE.Type inType;
11773 output DAE.Type outType;
11774 algorithm
11775 outType := match (inComponentRef,inType)
11776 local
11777 DAE.Type t,t_1;
11778 list<DAE.Subscript> subs;
11779 DAE.ComponentRef c;
11780
11781 case (DAE.CREF_IDENT(subscriptLst = {}),t) then t;
11782 case (DAE.CREF_IDENT(subscriptLst = subs),t)
11783 algorithm
11784 ✗ t_1 := subscriptType(t, subs);
11785 then
11786 t_1;
11787 case (DAE.CREF_QUAL(componentRef = c),t)
11788 algorithm
11789 ✗ t_1 := subscriptCrefType2(c, t);
11790 then
11791 t_1;
11792 end match;
11793 end subscriptCrefType2;
11794
11795 protected function subscriptType "Given an array dimensionality and a list of subscripts, this
11796 function reduces the dimensionality.
11797 This does not handle slices or check that subscripts are not out
11798 of bounds."
11799 input DAE.Type inType;
11800 input list<DAE.Subscript> inExpSubscriptLst;
11801 output DAE.Type outType;
11802 algorithm
11803 outType := matchcontinue (inType,inExpSubscriptLst)
11804 local
11805 DAE.Type t,t_1;
11806 list<DAE.Subscript> subs;
11807 DAE.Dimension dim;
11808
11809 case (t,{}) then t;
11810
11811 case (DAE.T_ARRAY(dims = {DAE.DIM_INTEGER()}, ty = t),(DAE.INDEX() :: subs))
11812 algorithm
11813 ✗ t_1 := subscriptType(t, subs);
11814 then
11815 t_1;
11816
11817 case (DAE.T_ARRAY(dims = {dim}, ty = t),(DAE.SLICE() :: subs))
11818 algorithm
11819 ✗ t_1 := subscriptType(t, subs);
11820 ✗ then
11821 DAE.T_ARRAY(t_1,{dim});
11822
11823 case (DAE.T_ARRAY(dims = {dim}, ty = t),(DAE.WHOLEDIM() :: subs))
11824 algorithm
11825 ✗ t_1 := subscriptType(t, subs);
11826 ✗ then
11827 DAE.T_ARRAY(t_1,{dim});
11828
11829 case (t,_)
11830 algorithm
11831 ✗ Print.printBuf("- subscript_type failed (");
11832 ✗ Print.printBuf(TypesDump.printTypeStr(t));
11833 ✗ Print.printBuf(" , [...])\n");
11834 ✗ then
11835 fail();
11836 end matchcontinue;
11837 end subscriptType;
11838
11839 protected function makeIfExp
11840 input FCore.Cache inCache;
11841 input FCore.Graph inEnv;
11842 input DAE.Exp inCondition;
11843 input DAE.Properties inCondProp;
11844 input DAE.Exp inTrueBranch;
11845 input DAE.Properties inTrueProp;
11846 input DAE.Exp inFalseBranch;
11847 input DAE.Properties inFalseProp;
11848 input Boolean inImplicit;
11849 input DAE.Prefix inPrefix;
11850 input SourceInfo inInfo;
11851 output FCore.Cache outCache = inCache;
11852 output DAE.Exp outExp;
11853 output DAE.Properties outProperties;
11854 protected
11855 Boolean ty_match, cond;
11856 DAE.Type cond_ty, true_ty, false_ty, exp_ty;
11857 DAE.Const cond_c, true_c, false_c, exp_c;
11858 String cond_str, cond_ty_str, e1_str, e2_str, ty1_str, ty2_str, pre_str;
11859 DAE.Exp cond_exp, true_exp, false_exp;
11860 algorithm
11861 // Check that the condition is a boolean expression.
11862
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
8298 DAE.PROP(type_ = cond_ty, constFlag = cond_c) := inCondProp;
11863 8298 (cond_exp, _, ty_match) := Types.matchTypeNoFail(inCondition, cond_ty, DAE.T_BOOL_DEFAULT);
11864
11865 // Print an error message and fail if the condition is not a boolean expression.
11866
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
8298 if not ty_match then
11867 ✗ cond_str := ExpressionBasics.printExpStr(inCondition);
11868 ✗ cond_ty_str := TypesDump.unparseTypeNoAttr(cond_ty);
11869 ✗ Error.addSourceMessageAndFail(Error.IF_CONDITION_TYPE_ERROR,
11870 {cond_str, cond_ty_str}, inInfo);
11871 end if;
11872
11873 // Check that both branches are type compatible.
11874
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
8298 DAE.PROP(type_ = true_ty, constFlag = true_c) := inTrueProp;
11875
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8298 times.
8298 DAE.PROP(type_ = false_ty, constFlag = false_c) := inFalseProp;
11876
11877 8298 (true_exp, false_exp, exp_ty, ty_match) :=
11878 Types.checkTypeCompat(inTrueBranch, true_ty, inFalseBranch, false_ty);
11879
11880 // If the compatible type is an array with some unknown dimensions, and we're
11881 // not in a function, then we need to choose one of the branches.
11882
4/4
✓ Branch 1 taken 27 times.
✓ Branch 2 taken 8271 times.
✓ Branch 4 taken 10 times.
✓ Branch 5 taken 17 times.
8298 if Types.arrayHasUnknownDims(exp_ty) and not FGraph.inFunctionScope(inEnv) then
11883 // Check if the condition is reasonably constant, so we can evaluate it.
11884
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
10 if Types.isParameterOrConstant(cond_c) then
11885 cond_c := DAE.C_CONST();
11886 else
11887 // Otherwise it's a type error.
11888 ✗ ty_match := false;
11889 end if;
11890 end if;
11891
11892 // If the types are not matching, print an error and fail.
11893
3/4
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8296 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
8298 if (not ty_match) and not Config.getGraphicsExpMode() then
11894 2 e1_str := ExpressionBasics.printExpStr(inTrueBranch);
11895 2 e2_str := ExpressionBasics.printExpStr(inFalseBranch);
11896 2 ty1_str := TypesDump.unparseTypeNoAttr(true_ty);
11897 2 ty2_str := TypesDump.unparseTypeNoAttr(false_ty);
11898 2 pre_str := PrefixUtil.printPrefixStr3(inPrefix);
11899 2 Error.addSourceMessageAndFail(Error.TYPE_MISMATCH_IF_EXP,
11900 {pre_str, e1_str, ty1_str, e2_str, ty2_str}, inInfo);
11901 end if;
11902
11903
2/2
✓ Branch 1 taken 758 times.
✓ Branch 2 taken 7538 times.
8296 if Types.isConstant(cond_c) then
11904 // If the condition is constant, try to evaluate it and choose a branch.
11905 try
11906
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 718 times.
758 (outCache, Values.BOOL(cond)) := Ceval.ceval(inCache, inEnv, cond_exp,
11907 inImplicit, Absyn.NO_MSG(), 0);
11908
11909
2/2
✓ Branch 0 taken 564 times.
✓ Branch 1 taken 154 times.
718 if cond then
11910 564 outExp := true_exp;
11911 outProperties := inTrueProp;
11912 else
11913 154 outExp := false_exp;
11914 outProperties := inFalseProp;
11915 end if;
11916
11917 // Evaluation succeeded, return the chosen branch.
11918 718 return;
11919 else
11920 end try;
11921 end if;
11922
11923 // If the condition is not constant or ceval failed, create an if-expression.
11924
7/8
✓ Branch 0 taken 22734 times.
✓ Branch 1 taken 7578 times.
✓ Branch 2 taken 22734 times.
✓ Branch 3 taken 7578 times.
✓ Branch 4 taken 7578 times.
✓ Branch 5 taken 15156 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 7578 times.
30312 exp_c := Types.constAnd(c for c in {cond_c, false_c, true_c});
11925 7578 outExp := DAE.IFEXP(cond_exp, true_exp, false_exp);
11926 7578 outProperties := DAE.PROP(exp_ty, exp_c);
11927 end makeIfExp;
11928
11929 protected function canonCref2 "This function relates a DAE.ComponentRef to its canonical form,
11930 which is when all subscripts are evaluated to constant values.
11931 If Such an evaluation is not possible, there is no canonical
11932 form and this function fails."
11933 input FCore.Cache inCache;
11934 input FCore.Graph inEnv;
11935 input DAE.ComponentRef inComponentRef;
11936 input DAE.ComponentRef inPrefixCref;
11937 input Boolean inBoolean;
11938 output FCore.Cache outCache;
11939 output DAE.ComponentRef outComponentRef;
11940 algorithm
11941 (outCache,outComponentRef) :=
11942 match (inCache,inEnv,inComponentRef,inPrefixCref,inBoolean)
11943 local
11944 list<DAE.Subscript> ss_1,ss;
11945 FCore.Graph env;
11946 String n;
11947 Boolean impl;
11948 FCore.Cache cache;
11949 DAE.ComponentRef prefixCr,cr;
11950 list<Integer> sl;
11951 DAE.Type t;
11952 DAE.Type ty2;
11953 case (cache,env,DAE.CREF_IDENT(ident = n,identType = ty2, subscriptLst = ss),prefixCr,impl) /* impl */
11954 algorithm
11955 ✗ cr := ComponentReference.crefPrependIdent(prefixCr,n,{},ty2);
11956 ✗ (cache,_,t) := Lookup.lookupVar(cache,env, cr);
11957 ✗ sl := Types.getDimensionSizes(t);
11958 ✗ (cache,ss_1) := Ceval.cevalSubscripts(cache,env, ss, sl, impl, Absyn.NO_MSG(),0);
11959 ✗ then
11960 (cache,ComponentReferenceBasics.makeCrefIdent(n,ty2,ss_1));
11961 end match;
11962 end canonCref2;
11963
11964 public function canonCref "Transform expression to canonical form
11965 by constant evaluating all subscripts."
11966 input FCore.Cache inCache;
11967 input FCore.Graph inEnv;
11968 input DAE.ComponentRef inComponentRef;
11969 input Boolean inBoolean;
11970 output FCore.Cache outCache;
11971 output DAE.ComponentRef outComponentRef;
11972 algorithm
11973 (outCache,outComponentRef) :=
11974 matchcontinue (inCache,inEnv,inComponentRef,inBoolean)
11975 local
11976 DAE.Type t;
11977 list<Integer> sl;
11978 list<DAE.Subscript> ss_1,ss;
11979 FCore.Graph env, componentEnv;
11980 String n;
11981 Boolean impl;
11982 DAE.ComponentRef c_1,c,cr;
11983 FCore.Cache cache;
11984 DAE.Type ty2;
11985
11986 // handle wild _
11987 case (cache,_,DAE.WILD(),_)
11988 algorithm
11989
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := Config.acceptMetaModelicaGrammar();
11990 then
11991 (cache,DAE.WILD());
11992
11993 // an unqualified component reference
11994 case (cache,env,DAE.CREF_IDENT(ident = n,subscriptLst = ss),impl) /* impl */
11995 algorithm
11996 61960 (cache,_,t,_,_,_,_,_,_) := Lookup.lookupVarIdent(cache, env, n);
11997 61931 sl := Types.getDimensionSizes(t);
11998 61931 (cache,ss_1) := Ceval.cevalSubscripts(cache, env, ss, sl, impl, Absyn.NO_MSG(),0);
11999 61931 ty2 := Types.simplifyType(t);
12000 61931 then
12001 (cache,ComponentReferenceBasics.makeCrefIdent(n,ty2,ss_1));
12002
12003 // a qualified component reference
12004 case (cache,env,DAE.CREF_QUAL(ident = n,subscriptLst = ss,componentRef = c),impl)
12005 algorithm
12006 39094 (cache,_,t,_,_,_,_,componentEnv,_) := Lookup.lookupVarIdent(cache, env, n);
12007 39094 ty2 := Types.simplifyType(t);
12008 39094 sl := Types.getDimensionSizes(t);
12009 39094 (cache,ss_1) := Ceval.cevalSubscripts(cache, env, ss, sl, impl, Absyn.NO_MSG(),0);
12010 //(cache,c_1) = canonCref2(cache, env, c, ComponentReferenceBasics.makeCrefIdent(n,ty2,ss), impl);
12011 39094 (cache, c_1) := canonCref(cache, componentEnv, c, impl);
12012 39065 then
12013 (cache,ComponentReferenceBasics.makeCrefQual(n,ty2, ss_1,c_1));
12014
12015 // failtrace
12016 case (_,_,cr,_)
12017 algorithm
12018
1/2
✓ Branch 1 taken 58 times.
✗ Branch 2 not taken.
58 true := Flags.isSet(Flags.FAILTRACE);
12019 ✗ Debug.trace("- Static.canonCref failed, cr: ");
12020 ✗ Debug.traceln(ComponentReferenceBasics.printComponentRefStr(cr));
12021 ✗ then
12022 fail();
12023 end matchcontinue;
12024 end canonCref;
12025
12026 protected function unevaluatedFunctionVariability
12027 "In a function we might have input arguments with unknown dimensions, and in
12028 that case we can't expand calls such as fill. A function call is therefore
12029 created with variable variability. This function checks that we're inside a
12030 function and returns DAE.C_VAR(), or fails if we're not inside a function.
12031
12032 The exception is if checkModel is used, in which case we don't know what the
12033 variability would have been had all parameters received a binding. We can't
12034 set the variability to variable or parameter because then we might get
12035 bindings with higher variability than the component, and we can't set it to
12036 constant because that would cause the compiler to try and constant evaluate
12037 the call. So we set it to DAE.C_UNKNOWN() instead."
12038 input FCore.Graph inEnv;
12039 output DAE.Const outConst;
12040 algorithm
12041
2/2
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 16 times.
18 if FGraph.inFunctionScope(inEnv) then
12042 outConst := DAE.C_VAR();
12043 elseif Flags.getConfigBool(Flags.CHECK_MODEL) or Config.splitArrays() then
12044 // bug #2113, seems that there is nothing in the specs
12045 // that requires that fill arguments are of parameter/constant
12046 // variability, so allow it.
12047 outConst := DAE.C_UNKNOWN();
12048 else
12049 ✗ fail();
12050 end if;
12051 end unevaluatedFunctionVariability;
12052
12053 protected function slotAnd
12054 "Use with listFold to check if all slots have been filled"
12055 input Slot s;
12056 input Boolean b;
12057 output Boolean res;
12058 algorithm
12059 141328 SLOT(slotFilled = res) := s;
12060 141328 res := b and res;
12061 end slotAnd;
12062
12063 public function elabCodeExp
12064 input Absyn.Exp exp;
12065 input FCore.Cache cache;
12066 input FCore.Graph env;
12067 input DAE.CodeType ct;
12068 input SourceInfo info;
12069 output DAE.Exp outExp;
12070 algorithm
12071 outExp := matchcontinue (exp,ct)
12072 local
12073 String s1,s2;
12074 Absyn.ComponentRef cr;
12075 Absyn.Path path;
12076 list<DAE.Exp> es_1;
12077 list<Absyn.Exp> es;
12078 DAE.Type et;
12079 Integer i;
12080 DAE.Exp dexp;
12081
12082 // first; try to elaborate the exp (maybe there is a binding in the environment that says v is a VariableName
12083 case (_,_)
12084 algorithm
12085 // adrpo: be very careful with this as it can take quite a long time, for example a call to:
12086 // getDerivedClassModifierValue(Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel.Medium.MassFlowRate,unit);
12087 // will instantiate Modelica.Fluid.Vessels.BaseClasses.PartialLumpedVessel.Medium.MassFlowRate
12088 // if we're not careful
12089 5337 dexp := elabCodeExp_dispatch(exp,cache,env,ct,info);
12090 then
12091 dexp;
12092
12093 case (Absyn.CODE(code=Absyn.C_MODIFICATION()),DAE.C_EXPRESSION_OR_MODIFICATION())
12094 ✗ then DAE.CODE(exp.code,DAE.T_UNKNOWN_DEFAULT);
12095 case (Absyn.CODE(code=Absyn.C_EXPRESSION()),DAE.C_EXPRESSION())
12096 ✗ then DAE.CODE(exp.code,DAE.T_UNKNOWN_DEFAULT);
12097
12098 // Expression
12099 case (_,DAE.C_EXPRESSION())
12100 14 then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT);
12101 case (_,DAE.C_EXPRESSION_OR_MODIFICATION())
12102 13 then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT);
12103
12104 // Type Name
12105 case (Absyn.CREF(componentRef=cr),DAE.C_TYPENAME())
12106 algorithm
12107 2503 path := AbsynUtil.crefToPath(cr);
12108 2503 then DAE.CODE(Absyn.C_TYPENAME(path),DAE.T_UNKNOWN_DEFAULT);
12109
12110 // Variable Names
12111 case (Absyn.ARRAY(es),DAE.C_VARIABLENAMES())
12112 algorithm
12113 52 es_1 := List.map4(es,elabCodeExp,cache,env,DAE.C_VARIABLENAME(),info);
12114 52 i := listLength(es);
12115 104 et := DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(i)});
12116 52 then DAE.ARRAY(et,false,es_1);
12117
12118 case (_,DAE.C_VARIABLENAMES())
12119 algorithm
12120 et := DAE.T_ARRAY(DAE.T_UNKNOWN_DEFAULT, {DAE.DIM_INTEGER(1)});
12121 ✗ dexp := elabCodeExp(exp,cache,env,DAE.C_VARIABLENAME(),info);
12122 ✗ then DAE.ARRAY(et,false,{dexp});
12123
12124 // Variable Name
12125 case (Absyn.CREF(componentRef=cr),DAE.C_VARIABLENAME())
12126 2265 then DAE.CODE(Absyn.C_VARIABLENAME(cr),DAE.T_UNKNOWN_DEFAULT);
12127
12128 // der() expression
12129 case (Absyn.CALL(), DAE.C_VARIABLENAME())
12130 guard isValidDerVariableName(exp)
12131 18 then DAE.CODE(Absyn.C_EXPRESSION(exp),DAE.T_UNKNOWN_DEFAULT);
12132
12133 // failure
12134 else
12135 algorithm
12136 ✗ failure(DAE.C_VARIABLENAMES() := ct);
12137 ✗ s1 := Dump.printExpStr(exp);
12138 ✗ s2 := TypesDump.printCodeTypeStr(ct);
12139 ✗ Error.addSourceMessage(Error.ELAB_CODE_EXP_FAILED, {s1,s2}, info);
12140 ✗ then fail();
12141 end matchcontinue;
12142 end elabCodeExp;
12143
12144 public function elabCodeExp_dispatch
12145 "@author: adrpo
12146 evaluate a code expression.
12147 be careful how much you lookup"
12148 input Absyn.Exp exp;
12149 input FCore.Cache cache;
12150 input FCore.Graph env;
12151 input DAE.CodeType ct;
12152 input Absyn.Info info;
12153 output DAE.Exp outExp;
12154 algorithm
12155 outExp := matchcontinue exp
12156 local
12157 Absyn.ComponentRef cr;
12158 DAE.Exp dexp;
12159 DAE.Properties prop;
12160 DAE.Type ty;
12161 DAE.CodeType ct2;
12162 Absyn.Ident id;
12163
12164 // for a component reference make sure the first ident is either "OpenModelica" or not a class
12165 case Absyn.CREF(componentRef=cr)
12166 algorithm
12167 5186 ErrorExt.setCheckpoint("elabCodeExp_dispatch1");
12168 5186 id := AbsynUtil.crefFirstIdent(cr);
12169 try
12170 // if the first one is OpenModelica, search
12171
4/4
✓ Branch 0 taken 142 times.
✓ Branch 1 taken 5044 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 140 times.
5186 true := id == "OpenModelica";
12172 2 (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12173 else
12174 // not a class or OpenModelica, continue; a class which is not
12175 // OpenModelica makes this fail (and the enclosing case rolls back).
12176
2/2
✓ Branch 0 taken 5186 times.
✓ Branch 1 taken 3092 times.
8278 failure(Lookup.lookupClassIdent(cache, env, id));
12177 3092 (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12178 end try;
12179
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 418 times.
454 DAE.T_CODE(ty=ct2) := Types.getPropType(prop);
12180
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 418 times.
418 true := valueEq(ct,ct2);
12181 418 ErrorExt.delCheckpoint("elabCodeExp_dispatch1");
12182 // print(ExpressionBasics.printExpStr(dexp) + " " + TypesDump.unparseType(ty) + "\n");
12183 418 then dexp;
12184
12185 case Absyn.CREF()
12186 algorithm
12187 4768 ErrorExt.rollBack("elabCodeExp_dispatch1");
12188 4768 then fail();
12189
12190 case _
12191 algorithm
12192
2/2
✓ Branch 1 taken 4768 times.
✓ Branch 2 taken 151 times.
4919 false := AbsynUtil.isCref(exp);
12193 151 ErrorExt.setCheckpoint("elabCodeExp_dispatch");
12194 151 (_,dexp,prop) := elabExpInExpression(cache,env,exp,false,false,DAE.NOPRE(),info);
12195
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 54 times.
64 DAE.T_CODE(ty=ct2) := Types.getPropType(prop);
12196
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
54 true := valueEq(ct,ct2);
12197 54 ErrorExt.delCheckpoint("elabCodeExp_dispatch");
12198 // print(ExpressionBasics.printExpStr(dexp) + " " + TypesDump.unparseType(ty) + "\n");
12199 54 then dexp;
12200
12201 else
12202 algorithm
12203
2/2
✓ Branch 1 taken 4768 times.
✓ Branch 2 taken 97 times.
4865 false := AbsynUtil.isCref(exp);
12204 97 ErrorExt.rollBack("elabCodeExp_dispatch");
12205 97 then fail();
12206
12207 end matchcontinue;
12208 end elabCodeExp_dispatch;
12209
12210 public function elabArrayDims
12211 "Elaborates a list of array dimensions."
12212 input FCore.Cache inCache;
12213 input FCore.Graph inEnv;
12214 input Absyn.ComponentRef inComponentRef;
12215 input list<Absyn.Subscript> inDimensions;
12216 input Boolean inImplicit;
12217 input Boolean inDoVect;
12218 input DAE.Prefix inPrefix;
12219 input SourceInfo inInfo;
12220 output FCore.Cache outCache;
12221 output DAE.Dimensions outDimensions;
12222 algorithm
12223 225155 (outCache, outDimensions) := elabArrayDims2(inCache, inEnv, inComponentRef,
12224 inDimensions, inImplicit, inDoVect, inPrefix, inInfo, {});
12225 end elabArrayDims;
12226
12227 protected function elabArrayDims2
12228 "Helper function to elabArrayDims. Needed because of tail recursion."
12229 input FCore.Cache inCache;
12230 input FCore.Graph inEnv;
12231 input Absyn.ComponentRef inCref;
12232 input list<Absyn.Subscript> inDimensions;
12233 input Boolean inImplicit;
12234 input Boolean inDoVect;
12235 input DAE.Prefix inPrefix;
12236 input SourceInfo inInfo;
12237 input DAE.Dimensions inElaboratedDims;
12238 output FCore.Cache outCache;
12239 output DAE.Dimensions outDimensions;
12240 algorithm
12241 (outCache, outDimensions) := match inDimensions
12242 local
12243 FCore.Cache cache;
12244 Absyn.Subscript dim;
12245 list<Absyn.Subscript> rest_dims;
12246 DAE.Dimension elab_dim;
12247 DAE.Dimensions elab_dims;
12248
12249 case {}
12250 225054 then (inCache, listReverse(inElaboratedDims));
12251
12252 case dim :: rest_dims
12253 algorithm
12254 69953 (cache, elab_dim) := elabArrayDim(inCache, inEnv, inCref, dim,
12255 inImplicit, inDoVect, inPrefix, inInfo);
12256 69852 elab_dims := elab_dim :: inElaboratedDims;
12257 69852 (cache, elab_dims) := elabArrayDims2(cache, inEnv, inCref, rest_dims,
12258 inImplicit, inDoVect, inPrefix, inInfo, elab_dims);
12259 then
12260 (cache, elab_dims);
12261 end match;
12262 end elabArrayDims2;
12263
12264 protected function elabArrayDim
12265 "Elaborates a single array dimension."
12266 input FCore.Cache inCache;
12267 input FCore.Graph inEnv;
12268 input Absyn.ComponentRef inCref;
12269 input Absyn.Subscript inDimension;
12270 input Boolean inImpl;
12271 input Boolean inDoVect;
12272 input DAE.Prefix inPrefix;
12273 input SourceInfo inInfo;
12274 output FCore.Cache outCache;
12275 output DAE.Dimension outDimension;
12276 algorithm
12277 (outCache, outDimension) := matchcontinue(inCache, inDimension)
12278 local
12279 Absyn.ComponentRef cr;
12280 DAE.Dimension dim;
12281 FCore.Cache cache;
12282 Absyn.Path type_path;
12283 String name;
12284 Absyn.Exp sub, cr_exp;
12285 DAE.Exp e, dim_exp;
12286 DAE.Properties prop;
12287 Absyn.Exp size_arg;
12288 DAE.Type t;
12289
12290 // The : operator results in an unknown dimension.
12291 case (_, Absyn.NOSUB())
12292 6641 then (inCache, DAE.DIM_UNKNOWN());
12293
12294 // Size expression that refers to the array itself, such as
12295 // Real x(:, size(x, 1)).
12296 case (_, Absyn.SUBSCRIPT(subscript = Absyn.CALL(function_ =
12297 Absyn.CREF_IDENT(name = "size"), functionArgs = Absyn.FUNCTIONARGS(args =
12298 {cr_exp as Absyn.CREF(componentRef = cr), size_arg}))))
12299 algorithm
12300
2/2
✓ Branch 1 taken 818 times.
✓ Branch 2 taken 115 times.
933 true := AbsynUtil.crefEqual(inCref, cr);
12301 115 (cache, e, _) := elabExpInExpression(inCache, inEnv, cr_exp, inImpl,
12302 inDoVect, inPrefix, inInfo);
12303 23 (cache, dim_exp, _) := elabExpInExpression(cache, inEnv, size_arg, inImpl,
12304 inDoVect, inPrefix, inInfo);
12305 23 dim := DAE.DIM_EXP(DAE.SIZE(e, SOME(dim_exp)));
12306 //dim = DAE.DIM_UNKNOWN();
12307 23 then
12308 (inCache, dim);
12309
12310 case (_, Absyn.SUBSCRIPT(subscript = Absyn.CREF(componentRef = Absyn.CREF_IDENT(name = "Boolean"))))
12311 5 then
12312 (inCache, DAE.DIM_BOOLEAN());
12313
12314 // Array dimension from a Boolean or enumeration.
12315 case (cache, Absyn.SUBSCRIPT(subscript = Absyn.CREF(cr)))
12316 algorithm
12317 4381 type_path := AbsynUtil.crefToPath(cr);
12318 4381 cache := Lookup.lookupClass(cache, inEnv, type_path);
12319 138 (cache, t) := Lookup.lookupType(cache, inEnv, type_path, NONE());
12320 dim := match t
12321 case DAE.T_ENUMERATION(index=NONE())
12322 122 then DAE.DIM_ENUM(t.path, t.names, listLength(t.names));
12323 case DAE.T_BOOL()
12324 then DAE.DIM_BOOLEAN();
12325 end match;
12326 122 then
12327 (cache, dim);
12328
12329 case (_, Absyn.SUBSCRIPT(subscript = Absyn.EXPRESSIONCOMMENT(exp=sub)))
12330 algorithm
12331 ✗ (cache, dim) := elabArrayDim(inCache, inEnv, inCref, Absyn.SUBSCRIPT(sub), inImpl, inDoVect, inPrefix, inInfo);
12332 then
12333 (cache, dim);
12334
12335 // For all other cases we need to elaborate the subscript expression, so the
12336 // expression is elaborated and passed on to elabArrayDim2 to avoid doing
12337 // the elaboration several times.
12338 case (_, Absyn.SUBSCRIPT(subscript = sub))
12339 algorithm
12340 63162 (cache, e, prop) := elabExpInExpression(inCache, inEnv, sub, inImpl,
12341 inDoVect, inPrefix, inInfo);
12342
3/4
✗ Branch 1 not taken.
✓ Branch 2 taken 63064 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 63061 times.
63064 (cache, SOME(dim)) := elabArrayDim2(cache, inEnv, inCref, e, prop, inImpl,
12343 inDoVect, inPrefix, inInfo);
12344 63061 then
12345 (cache, dim);
12346
12347 else
12348 algorithm
12349
1/2
✓ Branch 1 taken 101 times.
✗ Branch 2 not taken.
101 true := Flags.isSet(Flags.FAILTRACE);
12350 ✗ Debug.traceln("- Static.elabArrayDim failed on: " +
12351 Dump.printComponentRefStr(inCref) +
12352 Dump.printArraydimStr({inDimension}));
12353 ✗ then
12354 fail();
12355
12356 end matchcontinue;
12357 end elabArrayDim;
12358
12359 protected function elabArrayDim2
12360 "Helper function to elabArrayDim. Continues the work from the last case in
12361 elabArrayDim to avoid unnecessary elaboration."
12362 input FCore.Cache inCache;
12363 input FCore.Graph inEnv;
12364 input Absyn.ComponentRef inCref;
12365 input DAE.Exp inExp;
12366 input DAE.Properties inProperties;
12367 input Boolean inImpl;
12368 input Boolean inDoVect;
12369 input DAE.Prefix inPrefix;
12370 input SourceInfo inInfo;
12371 output FCore.Cache outCache;
12372 output Option<DAE.Dimension> outDimension;
12373 algorithm
12374 (outCache, outDimension) := matchcontinue(inProperties, inImpl)
12375 local
12376 DAE.Const cnst;
12377 FCore.Cache cache;
12378 DAE.Exp e;
12379 DAE.Type ty;
12380 String e_str, t_str, a_str;
12381 Integer i;
12382
12383 // Constant dimension creates DIM_INTEGER.
12384 case (DAE.PROP(DAE.T_INTEGER(), cnst), _)
12385 algorithm
12386
2/2
✓ Branch 1 taken 1055 times.
✓ Branch 2 taken 62009 times.
63067 true := Types.isParameterOrConstant(cnst);
12387
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 61999 times.
62009 (cache, Values.INTEGER(i)) := Ceval.ceval(inCache, inEnv, inExp, inImpl);
12388 61999 then
12389 (cache, SOME(DAE.DIM_INTEGER(i)));
12390
12391 // When arrays are non-expanded, non-constant parametric dimensions are allowed.
12392 case (DAE.PROP(DAE.T_INTEGER(), DAE.C_PARAM()), _)
12393 algorithm
12394
1/2
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
8 false := Config.splitArrays();
12395 ✗ then
12396 (inCache, SOME(DAE.DIM_EXP(inExp)));
12397
12398 // When not implicit instantiation, array dimension must be constant.
12399 case (DAE.PROP(DAE.T_INTEGER(), DAE.C_VAR()), false)
12400 algorithm
12401 ✗ e_str := ExpressionBasics.printExpStr(inExp);
12402 ✗ Error.addSourceMessage(Error.DIMENSION_NOT_KNOWN, {e_str}, inInfo);
12403 then
12404 (inCache, NONE());
12405
12406 // Non-constant dimension creates DIM_EXP.
12407 case (DAE.PROP(DAE.T_INTEGER(), _), true)
12408 algorithm
12409 1062 (cache, e, _) :=
12410 Ceval.cevalIfConstant(inCache, inEnv, inExp, inProperties, inImpl, inInfo);
12411 1062 then
12412 (cache, SOME(DAE.DIM_EXP(e)));
12413
12414 case (_, _)
12415 algorithm
12416
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 (cache, e as DAE.SIZE(_, _), _) :=
12417 Ceval.cevalIfConstant(inCache, inEnv, inExp, inProperties, inImpl, inInfo);
12418 ✗ then
12419 (cache, SOME(DAE.DIM_EXP(e)));
12420
12421 case (_, _)
12422 algorithm
12423
1/2
✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
3 true := Flags.getConfigBool(Flags.CHECK_MODEL);
12424 then
12425 (inCache, SOME(DAE.DIM_UNKNOWN()));
12426
12427 // an integer parameter with no binding
12428 case (DAE.PROP(DAE.T_INTEGER(), cnst), _)
12429 algorithm
12430
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 true := Types.isParameterOrConstant(cnst);
12431 3 e_str := ExpressionBasics.printExpStr(inExp);
12432 3 a_str := Dump.printComponentRefStr(inCref) + "[" + e_str + "]";
12433 3 Error.addSourceMessage(Error.STRUCTURAL_PARAMETER_OR_CONSTANT_WITH_NO_BINDING, {e_str, a_str}, inInfo);
12434 //(_, _) = elabArrayDim2(inCache, inEnv, inCref, inExp, inProperties, inImpl, inDoVect, inPrefix, inInfo);
12435 then
12436 (inCache, NONE());
12437
12438 case (DAE.PROP(ty, _), _)
12439 algorithm
12440 ✗ e_str := ExpressionBasics.printExpStr(inExp);
12441 ✗ t_str := TypesDump.unparseType(ty);
12442 ✗ Types.typeErrorSanityCheck(t_str, "Integer", inInfo);
12443 ✗ Error.addSourceMessage(Error.ARRAY_DIMENSION_INTEGER,
12444 {e_str, t_str}, inInfo);
12445 then
12446 (inCache, NONE());
12447
12448 end matchcontinue;
12449 end elabArrayDim2;
12450
12451 protected function consStrippedCref
12452 input Absyn.Exp e;
12453 input list<Absyn.Exp> es;
12454 output list<Absyn.Exp> oes;
12455 algorithm
12456 oes := match e
12457 local
12458 Absyn.ComponentRef cr;
12459 case Absyn.CREF(cr)
12460 algorithm
12461 ✗ cr := AbsynUtil.crefStripLastSubs(cr);
12462 ✗ then Absyn.CREF(cr)::es;
12463 else es;
12464 end match;
12465 end consStrippedCref;
12466
12467 protected function replaceEnd
12468 "Replaces end-expressions in a cref with the appropriate size-expressions."
12469 input Absyn.ComponentRef inCref;
12470 output Absyn.ComponentRef outCref;
12471 protected
12472 list<Absyn.ComponentRef> cr_parts;
12473 Absyn.ComponentRef cr, cr_no_subs;
12474 algorithm
12475 //print("Before replace: " + Dump.printComponentRefStr(inCref) + "\n");
12476
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 578833 times.
578833 outCref :: cr_parts := AbsynUtil.crefExplode(inCref);
12477
12478
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 578833 times.
578833 if not AbsynUtil.crefIsIdent(outCref) then
12479 outCref := inCref;
12480 ✗ return;
12481 end if;
12482
12483
2/2
✓ Branch 1 taken 2881 times.
✓ Branch 2 taken 575952 times.
578833 if AbsynUtil.crefIsFullyQualified(inCref) then
12484 2881 outCref := AbsynUtil.crefMakeFullyQualified(outCref);
12485 end if;
12486
12487 578833 outCref := replaceEndInSubs(AbsynUtil.crefStripLastSubs(outCref), AbsynUtil.crefLastSubs(outCref));
12488
12489
2/2
✓ Branch 0 taken 181309 times.
✓ Branch 1 taken 578833 times.
760142 for cr in cr_parts loop
12490 181309 cr_no_subs := AbsynUtil.crefStripLastSubs(cr);
12491 181309 outCref := AbsynUtil.joinCrefs(outCref, cr_no_subs);
12492 181309 outCref := replaceEndInSubs(outCref, AbsynUtil.crefLastSubs(cr));
12493 end for;
12494 //print("After replace: " + Dump.printComponentRefStr(outCref) + "\n");
12495 end replaceEnd;
12496
12497 protected function replaceEndInSubs
12498 input Absyn.ComponentRef inCref;
12499 input list<Absyn.Subscript> inSubscripts;
12500 output Absyn.ComponentRef outCref = inCref;
12501 protected
12502 list<Absyn.Subscript> subs = {};
12503 Absyn.Subscript new_sub;
12504 Integer i = 1;
12505 algorithm
12506
2/2
✓ Branch 0 taken 80126 times.
✓ Branch 1 taken 680016 times.
760142 if listEmpty(inSubscripts) then
12507 680016 return;
12508 end if;
12509
12510
2/2
✓ Branch 0 taken 84011 times.
✓ Branch 1 taken 80126 times.
164137 for sub in inSubscripts loop
12511 84011 new_sub := replaceEndInSub(sub, i, inCref);
12512 subs := new_sub :: subs;
12513 84011 i := i + 1;
12514 end for;
12515
12516 80126 outCref := AbsynUtil.crefSetLastSubs(outCref, listReverse(subs));
12517 end replaceEndInSubs;
12518
12519 protected function replaceEndInSub
12520 input Absyn.Subscript inSubscript;
12521 input Integer inDimIndex;
12522 input Absyn.ComponentRef inCref;
12523 output Absyn.Subscript outSubscript;
12524 algorithm
12525 outSubscript := match inSubscript
12526 case Absyn.SUBSCRIPT()
12527 82521 then Absyn.SUBSCRIPT(replaceEndTraverser(inSubscript.subscript, (inCref, inDimIndex)));
12528
12529 else inSubscript;
12530 end match;
12531 end replaceEndInSub;
12532
12533 protected function replaceEndTraverser
12534 input Absyn.Exp inExp;
12535 input tuple<Absyn.ComponentRef, Integer> inTuple;
12536 output Absyn.Exp outExp;
12537 algorithm
12538 outExp := match inExp
12539 local
12540 Absyn.ComponentRef cr;
12541 Integer i;
12542
12543 case Absyn.END()
12544 algorithm
12545 41 (cr, i) := inTuple;
12546 82 then
12547 Absyn.CALL(Absyn.CREF_IDENT("size", {}),
12548 Absyn.FUNCTIONARGS({Absyn.CREF(cr), Absyn.INTEGER(i)}, {}), {});
12549
12550 case Absyn.CREF()
12551 23521 then Absyn.CREF(replaceEnd(inExp.componentRef));
12552
12553 85539 else AbsynUtil.traverseExpShallow(inExp, inTuple, replaceEndTraverser);
12554
12555 end match;
12556 end replaceEndTraverser;
12557
12558 protected function fixTupleMetaModelica
12559 input list<DAE.Exp> exps;
12560 input list<DAE.Type> types;
12561 input list<DAE.TupleConst> consts;
12562 output DAE.Exp exp;
12563 output DAE.Properties prop;
12564 protected
12565 DAE.Const c;
12566 list<DAE.Type> tys2;
12567 list<DAE.Exp> exps2;
12568 algorithm
12569
2/2
✓ Branch 1 taken 3067 times.
✓ Branch 2 taken 82 times.
3149 if Config.acceptMetaModelicaGrammar() then
12570 3067 c := Types.tupleConstListToConst(consts);
12571
4/4
✓ Branch 0 taken 6097 times.
✓ Branch 1 taken 3067 times.
✓ Branch 2 taken 6097 times.
✓ Branch 3 taken 3067 times.
9164 tys2 := list(Types.boxIfUnboxedType(ty) for ty in types);
12572 3067 (exps2, tys2) := Types.matchTypeTuple(exps, types, tys2, false);
12573 3067 exp := DAE.META_TUPLE(exps2);
12574 3067 prop := DAE.PROP(DAE.T_METATUPLE(tys2), c);
12575 else
12576 82 exp := DAE.TUPLE(exps);
12577 82 prop := DAE.PROP_TUPLE(DAE.T_TUPLE(types, NONE()), DAE.TUPLE_CONST(consts));
12578 end if;
12579 end fixTupleMetaModelica;
12580
12581 protected function checkBuiltinCallArgs
12582 input list<Absyn.Exp> inPosArgs;
12583 input list<Absyn.NamedArg> inNamedArgs;
12584 input Integer inExpectedArgs;
12585 input String inFnName;
12586 input Absyn.Info inInfo;
12587 protected
12588 algorithm
12589
2/4
✓ Branch 1 taken 5956 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 5956 times.
✗ Branch 4 not taken.
5956 if listLength(inPosArgs) <> inExpectedArgs or not listEmpty(inNamedArgs) then
12590 ✗ Error.addSourceMessageAndFail(Error.WRONG_NO_OF_ARGS, {inFnName}, inInfo);
12591 end if;
12592 end checkBuiltinCallArgs;
12593
12594 annotation(__OpenModelica_Interface="frontend");
12595 end Static;
12596