Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 70.4% 448 / 0 / 636
Functions: -% 0 / 1 / 1
Branches: 48.8% 286 / 0 / 586

OMCompiler/Compiler/NFFrontEnd/NFBuiltinCall.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 NFBuiltinCall
37 import Absyn;
38 import AbsynUtil;
39 import Call = NFCall;
40 import Expression = NFExpression;
41 import NFInstNode.InstNode;
42 import NFInstNode;
43 import NFPrefixes.{Variability, Purity};
44 import Type = NFType;
45 import Subscript = NFSubscript;
46 import System;
47 import Global;
48
49 protected
50 import Ceval = NFCeval;
51 import ComponentRef = NFComponentRef;
52 import Dimension = NFDimension;
53 import List;
54 import MetaModelica.Dangerous.listReverseInPlace;
55 import Class = NFClass;
56 import NFFunction.Function;
57 import NFFunction.FunctionMatchKind;
58 import NFFunction.MatchedFunction;
59 import NFFunction.NamedArg;
60 import NFFunction.TypedArg;
61 import NFInstNode.CachedData;
62 import NFTyping.InstContext;
63 import Prefixes = NFPrefixes;
64 import TypeCheck = NFTypeCheck;
65 import Typing = NFTyping;
66 import Util;
67 import ExpandExp = NFExpandExp;
68 import Operator = NFOperator;
69 import Component = NFComponent;
70 import NFPrefixes.ConnectorType;
71 import ClockKind = NFClockKind;
72 import Structural = NFStructural;
73 import Array;
74
75 public
76 function needSpecialHandling
77 "Returns whether or not a call refers to a builtin function that doesn't
78 follow normal Modelica rules and instead needs special handling."
79 input Call call;
80 output Boolean special;
81 algorithm
82 () := match call
83 case Call.UNTYPED_CALL()
84 algorithm
85
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 101635 times.
101635 CachedData.FUNCTION(specialBuiltin = special) :=
86 InstNode.getFuncCache(InstNode.classScope(ComponentRef.node(call.ref)));
87 then
88 ();
89
90 // for retyping
91 case Call.TYPED_CALL()
92 algorithm
93 204 special := Function.isSpecialBuiltin(call.fn);
94 then
95 ();
96
97 else
98 algorithm
99 ✗ Error.terminate(getInstanceName() + " got unknown call: " +
100 Call.toString(call), sourceInfo());
101 ✗ then
102 fail();
103 end match;
104 end needSpecialHandling;
105
106 function typeSpecial
107 input Call call;
108 input InstContext.Type context;
109 input SourceInfo info;
110 output Expression callExp;
111 output Type ty;
112 output Variability variability;
113 output Purity purity;
114 protected
115 ComponentRef cref;
116 algorithm
117
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 30062 times.
30062 Call.UNTYPED_CALL(ref = cref) := call;
118
119 (callExp, ty, variability, purity) := match ComponentRef.firstName(cref)
120 //case "activeState" then typeActiveStateCall(call, context, info);
121 110 case "actualStream" then typeActualInStreamCall("actualStream", call, context, info);
122 2 case "backSample" then typeBackSampleCall(call, context, info);
123 602 case "branch" then typeBranchCall(call, context, info);
124 2355 case "cardinality" then typeCardinalityCall(call, context, info);
125 498 case "cat" then typeCatCall(call, context, info);
126 17 case "change" then typeChangeCall(call, context, info);
127 89 case "Clock" then typeClockCall(call, context, info);
128 6733 case "der" then typeDerCall(call, context, info);
129 ✗ case "DynamicSelect" then typeDynamicSelectCall("DynamicSelect", call, context, info);
130 30 case "edge" then typeEdgeCall(call, context, info);
131 2128 case "fill" then typeFillCall(call, context, info);
132 60 case "getInstanceName" then typeGetInstanceName(call, context, info);
133 //case "initialState" then typeInitialStateCall(call, context, info);
134 198 case "initial" then typeDiscreteCall(call, context, info);
135 847 case "inStream" then typeActualInStreamCall("inStream", call, context, info);
136 423 case "isRoot" then typeIsRootCall(call, context, info);
137 141 case "matrix" then typeMatrixCall(call, context, info);
138 1444 case "max" then typeMinMaxCall("max", call, context, info);
139 834 case "min" then typeMinMaxCall("min", call, context, info);
140 3 case "ndims" then typeNdimsCall(call, context, info);
141 814 case "noEvent" then typeNoEventCall(call, context, info);
142 6 case "nthRoot" then typeNthRootCall(call, context, info);
143 171 case "ones" then typeZerosOnesCall("ones", call, context, info);
144 226 case "potentialRoot" then typePotentialRootCall(call, context, info);
145 928 case "pre" then typePreCall(call, context, info);
146 1 case "promote" then typePromoteCall(call, context, info);
147 1 case "pure" then typePureCall(call, context, info);
148 141 case "rooted" then typeRootedCall(call, context, info);
149 413 case "root" then typeRootCall(call, context, info);
150 144 case "sample" then typeSampleCall(call, context, info);
151 6 case "scalar" then typeScalarCall(call, context, info);
152 2 case "shiftSample" then typeShiftSampleCall(call, context, info);
153 470 case "smooth" then typeSmoothCall(call, context, info);
154 13 case "spatialDistribution" then typeSpatialDistribution(call, context, info);
155 4244 case "String" then typeStringCall(call, context, info);
156 18 case "subSample" then typeSubSampleCall(call, context, info);
157 12 case "superSample" then typeSuperSampleCall(call, context, info);
158 1 case "symmetric" then typeSymmetricCall(call, context, info);
159 12 case "terminal" then typeDiscreteCall(call, context, info);
160 //case "ticksInState" then typeTicksInStateCall(call, context, info);
161 //case "timeInState" then typeTimeInStateCall(call, context, info);
162 //case "transition" then typeTransitionCall(call, context, info);
163 392 case "transpose" then typeTransposeCall(call, context, info);
164 ✗ case "uniqueRootIndices" then typeUniqueRootIndicesCall(call, context, info);
165 ✗ case "uniqueRoot" then typeUniqueRootCall(call, context, info);
166 396 case "vector" then typeVectorCall(call, context, info);
167 5137 case "zeros" then typeZerosOnesCall("zeros", call, context, info);
168 else
169 algorithm
170 ✗ Error.terminate(getInstanceName() + " got unhandled builtin function: " + Call.toString(call), sourceInfo());
171 ✗ then
172 fail();
173 end match;
174 end typeSpecial;
175
176 function makeSizeExp
177 input list<Expression> posArgs;
178 input list<NamedArg> namedArgs;
179 input SourceInfo info;
180 output Expression callExp;
181 protected
182 Expression arg1, arg2;
183 algorithm
184 2642 assertNoNamedParams("size", namedArgs, info);
185
186 callExp := match posArgs
187 6 case {arg1} then Expression.SIZE(arg1, NONE());
188 2635 case {arg1, arg2} then Expression.SIZE(arg1, SOME(arg2));
189 else
190 algorithm
191 2 Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
192 {"size" + List.toString(posArgs, Expression.toString, List.Style.FLAT_BRACKETS),
193 "size(Any[:, ...]) => Integer[:]\n size(Any[:, ...], Integer) => Integer"}, info);
194 1 then
195 fail();
196 end match;
197 end makeSizeExp;
198
199 function makeArrayExp
200 input list<Expression> posArgs;
201 input list<NamedArg> namedArgs;
202 input SourceInfo info;
203 output Expression arrayExp;
204 protected
205 algorithm
206 149 assertNoNamedParams("array", namedArgs, info);
207
208 // array can take any number of arguments, but needs at least one.
209
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 149 times.
149 if listEmpty(posArgs) then
210 ✗ Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
211 {"array" + List.toString(posArgs, Expression.toString, List.Style.FLAT_BRACKETS),
212 "array(Any, Any, ...) => Any[:]"}, info);
213 ✗ fail();
214 end if;
215
216 149 arrayExp := Expression.makeArray(Type.UNKNOWN(), listArray(posArgs));
217 end makeArrayExp;
218
219 function makeCatExp
220 input Integer n;
221 input list<Expression> args;
222 input list<Type> tys;
223 input Variability variability;
224 input Purity purity;
225 input SourceInfo info;
226 output Expression callExp;
227 output Type ty;
228 protected
229 Expression arg2;
230 list<Expression> args2 = {}, res = {};
231 list<Type> tys2 = tys, tys3;
232 list<list<Dimension>> dimsLst = {};
233 list<Dimension> dims;
234 Type resTy = Type.UNKNOWN(), ty1, ty2, resTyToMatch;
235 TypeCheck.MatchKind mk;
236 Integer maxn, pos;
237 Dimension sumDim;
238 algorithm
239
2/4
✓ Branch 2 taken 8315 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 8315 times.
8315 Error.assertion(listLength(args)==listLength(tys) and not listEmpty(args), getInstanceName() + " got wrong input sizes", sourceInfo());
240
241 // First: Get the number of dimensions and the element type
242
243
2/2
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
33559 for arg in args loop
244
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
25244 ty::tys2 := tys2;
245 25244 dimsLst := Type.arrayDims(ty) :: dimsLst;
246
2/2
✓ Branch 1 taken 8315 times.
✓ Branch 2 taken 16929 times.
25244 if Type.isEqual(resTy, Type.UNKNOWN()) then
247 8315 resTy := Type.arrayElementType(ty);
248 else
249 16929 (,, ty1, mk) := TypeCheck.matchExpressions(Expression.INTEGER(0), Type.arrayElementType(ty), Expression.INTEGER(0), resTy);
250
1/2
✓ Branch 1 taken 16929 times.
✗ Branch 2 not taken.
16929 if TypeCheck.isCompatibleMatch(mk) then
251 16929 resTy := ty1;
252 end if;
253 end if;
254 end for;
255
256
4/4
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
✓ Branch 2 taken 25244 times.
✓ Branch 3 taken 8315 times.
33559 maxn := max(listLength(d) for d in dimsLst);
257
5/6
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
✓ Branch 2 taken 25244 times.
✓ Branch 3 taken 8315 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 8315 times.
33559 if maxn <> min(listLength(d) for d in dimsLst) then
258 ✗ Error.addSourceMessageAndFail(Error.NF_DIFFERENT_NUM_DIM_IN_ARGUMENTS, {stringDelimitList(list(String(listLength(d)) for d in dimsLst), ", "), "cat"}, info);
259 end if;
260
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8315 times.
8315 if n < 1 or n > maxn then
261 ✗ Error.addSourceMessageAndFail(Error.NF_CAT_WRONG_DIMENSION, {String(maxn), String(n)}, info);
262 end if;
263
264 tys2 := tys;
265 tys3 := {};
266 args2 := {};
267 8315 pos := listLength(args)+2;
268
269 // Second: Try to match the element type of all the arguments
270
271
2/2
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
33559 for arg in args loop
272
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
25244 ty::tys2 := tys2;
273 25244 pos := pos-1;
274 25244 ty2 := Type.setArrayElementType(ty, resTy);
275 25244 (arg2, ty1, mk) := TypeCheck.matchTypes(ty, ty2, arg, NFTypeCheck.ALLOW_UNKNOWN);
276
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25244 times.
25244 if TypeCheck.isIncompatibleMatch(mk) then
277 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH, {String(pos), "cat", "arg", Expression.toString(arg), Type.toString(ty), Type.toString(ty2)}, info);
278 end if;
279 args2 := arg2 :: args2;
280 25244 tys3 := ty1 :: tys3;
281 end for;
282
283 // Third: We now have matched the element types of all arguments
284 // Try to match the dimensions as well
285
286 resTy := Type.UNKNOWN();
287 tys2 := tys3;
288
289
2/2
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
33559 for arg in args2 loop
290
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
25244 ty::tys2 := tys2;
291
292
2/2
✓ Branch 1 taken 16929 times.
✓ Branch 2 taken 8315 times.
25244 if Type.isEqual(resTy, Type.UNKNOWN()) then
293 resTy := ty;
294 else
295 16929 (,, ty1, mk) := TypeCheck.matchExpressions(Expression.INTEGER(0), ty, Expression.INTEGER(0), resTy);
296
2/2
✓ Branch 1 taken 16085 times.
✓ Branch 2 taken 844 times.
16929 if TypeCheck.isCompatibleMatch(mk) then
297 16085 resTy := ty1;
298 end if;
299 end if;
300 end for;
301
302 // Got the supertype of the dimensions; trying to match all arguments
303 // with the concatenated dimension set to unknown.
304
305 8315 dims := Type.arrayDims(resTy);
306 8315 resTyToMatch := Type.ARRAY(Type.arrayElementType(resTy), List.set(dims, n, Dimension.UNKNOWN()));
307
4/4
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
✓ Branch 2 taken 25244 times.
✓ Branch 3 taken 8315 times.
33559 dims := list(listGet(lst, n) for lst in dimsLst);
308 8315 sumDim := Dimension.fromInteger(0);
309
2/2
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
33559 for d in dims loop
310 // Create the concatenated dimension
311 25244 sumDim := Dimension.add(sumDim, d);
312 end for;
313 8315 resTy := Type.ARRAY(Type.arrayElementType(resTy), List.set(Type.arrayDims(resTy), n, sumDim));
314 tys2 := tys3;
315 tys3 := {};
316 res := {};
317 8315 pos := listLength(args)+2;
318
319
2/2
✓ Branch 0 taken 25244 times.
✓ Branch 1 taken 8315 times.
33559 for arg in args2 loop
320
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25244 times.
25244 ty::tys2 := tys2;
321 25244 pos := pos-1;
322 25244 (arg2, ty1, mk) := TypeCheck.matchTypes(ty, resTyToMatch, arg, NFTypeCheck.ALLOW_UNKNOWN);
323
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 25244 times.
25244 if TypeCheck.isIncompatibleMatch(mk) then
324 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH, {String(pos), "cat", "arg", Expression.toString(arg), Type.toString(ty), Type.toString(resTyToMatch)}, info);
325 end if;
326 res := arg2 :: res;
327 25244 tys3 := ty1 :: tys3;
328 end for;
329
330 // We have all except dimension n having equal sizes; with matching types
331
332 ty := resTy;
333 16630 callExp := Expression.CALL(Call.makeTypedCall(NFBuiltinFuncs.CAT,
334 Expression.INTEGER(n)::res, variability, purity, resTy));
335 end makeCatExp;
336
337 protected
338 function assertNoNamedParams
339 input String fnName;
340 input list<NamedArg> namedArgs;
341 input SourceInfo info;
342 algorithm
343
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 25441 times.
25441 if not listEmpty(namedArgs) then
344 ✗ Error.addSourceMessage(Error.NO_SUCH_INPUT_PARAMETER,
345 {fnName, Util.tuple21(listHead(namedArgs))}, info);
346 ✗ fail();
347 end if;
348 end assertNoNamedParams;
349
350 function typeStringCall
351 input Call call;
352 input InstContext.Type context;
353 input SourceInfo info;
354 output Expression callExp;
355 output Type outType;
356 output Variability var;
357 output Purity purity;
358 protected
359 Type arg_ty;
360 list<TypedArg> args;
361 list<TypedArg> named_args;
362 TypedArg arg;
363 Call ty_call;
364 algorithm
365
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4244 times.
4244 ty_call as Call.ARG_TYPED_CALL(_, args, named_args) := Call.typeNormalCall(call, context, info);
366 4244 arg := listHead(args);
367 4244 arg_ty := Type.arrayElementType(arg.ty);
368
369
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 4243 times.
4244 if Type.isComplex(arg_ty) then
370 1 (callExp, outType, var, purity) := typeOverloadedStringCall(arg_ty, args, named_args, ty_call, context, info);
371 else
372 4243 (callExp, outType, var, purity) := typeBuiltinStringCall(ty_call, context, info);
373 end if;
374 end typeStringCall;
375
376 function typeBuiltinStringCall
377 input Call call;
378 input InstContext.Type context;
379 input SourceInfo info;
380 output Expression callExp;
381 output Type ty;
382 output Variability var;
383 output Purity purity;
384 protected
385 Call ty_call;
386 algorithm
387 4244 ty_call := Call.matchTypedNormalCall(call, context, info);
388 4243 ty := Call.typeOf(ty_call);
389 4243 var := Call.variability(ty_call);
390 4243 purity := Call.purity(ty_call);
391 4243 callExp := Expression.CALL(ty_call);
392 end typeBuiltinStringCall;
393
394 function typeOverloadedStringCall
395 input Type overloadedType;
396 input list<TypedArg> args;
397 input list<TypedArg> namedArgs;
398 input Call call;
399 input InstContext.Type context;
400 input SourceInfo info;
401 output Expression callExp;
402 output Type outType;
403 output Variability var = Variability.CONSTANT;
404 output Purity purity = Purity.PURE;
405 protected
406 ComponentRef fn_ref;
407 list<Function> candidates;
408 InstNode recopnode;
409 MatchedFunction matchedFunc;
410 list<MatchedFunction> matchedFunctions, exactMatches;
411 algorithm
412 1 recopnode := Type.complexNode(overloadedType);
413
414 try
415 1 fn_ref := Function.lookupFunctionSimple("'String'", recopnode, context);
416 else
417 // If there's no 'String' overload, let the normal String handler print the error.
418 1 typeBuiltinStringCall(call, context, info);
419 ✗ fail();
420 end try;
421
422 ✗ fn_ref := Function.instFunctionRef(fn_ref, context, InstNode.info(recopnode));
423 ✗ candidates := Function.typeRefCache(fn_ref);
424 //for fn in candidates loop
425 // TypeCheck.checkValidOperatorOverload("'String'", fn, recopnode);
426 //end for;
427
428 ✗ matchedFunctions := Function.matchFunctionsSilent(candidates, args, namedArgs, context, info);
429 ✗ exactMatches := MatchedFunction.getExactMatches(matchedFunctions);
430 ✗ if listEmpty(exactMatches) then
431 ✗ Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
432 {Call.typedString(call), Function.candidateFuncListString(candidates)}, info);
433 ✗ fail();
434 end if;
435
436 ✗ if listLength(exactMatches) == 1 then
437 ✗ matchedFunc ::_ := exactMatches;
438 ✗ outType := Function.returnType(matchedFunc.func);
439
440 ✗ for arg in matchedFunc.args loop
441 ✗ var := Prefixes.variabilityMax(var, arg.var);
442 ✗ purity := Prefixes.purityMin(purity, arg.purity);
443 end for;
444
445 ✗ callExp := Expression.CALL(
446 Call.makeTypedCall(
447 matchedFunc.func,
448 list(a.value for a in matchedFunc.args),
449 var,
450 purity,
451 outType));
452 ✗ return;
453 else
454 ✗ Error.addSourceMessage(Error.AMBIGUOUS_MATCHING_FUNCTIONS_NFINST,
455 {Call.typedString(call), Function.candidateFuncListString(list(mfn.func for mfn in matchedFunctions))}, info);
456 ✗ fail();
457 end if;
458 end typeOverloadedStringCall;
459
460 function typeDiscreteCall
461 "Types a function call that can be typed normally, but which always has
462 discrete variability regardless of the variability of the arguments."
463 input Call call;
464 input InstContext.Type context;
465 input SourceInfo info;
466 output Expression callExp;
467 output Type ty;
468 output Variability var = Variability.DISCRETE;
469 output Purity purity;
470 protected
471 Call argtycall;
472 algorithm
473 210 argtycall := Call.typeMatchNormalCall(call, context, info);
474 210 ty := Call.typeOf(argtycall);
475 210 purity := Call.purity(argtycall);
476 210 callExp := Expression.CALL(Call.unboxArgs(argtycall));
477 end typeDiscreteCall;
478
479 function typeNdimsCall
480 input Call call;
481 input InstContext.Type context;
482 input SourceInfo info;
483 output Expression callExp;
484 output Type ty = Type.INTEGER();
485 output Variability variability = Variability.PARAMETER;
486 output Purity purity = Purity.PURE;
487 protected
488 list<Expression> args;
489 list<NamedArg> named_args;
490 Type arg_ty;
491 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
492 algorithm
493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
3 Call.UNTYPED_CALL(arguments = args, named_args = named_args) := call;
494
495 3 assertNoNamedParams("ndims", named_args, info);
496
497
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 if listLength(args) <> 1 then
498 ✗ Error.addSourceMessage(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
499 {Call.toString(call), "ndims(Any) => Integer"}, info);
500 ✗ fail();
501 end if;
502
503 // The number of dimensions an expression has is always known,
504 // so we might as well evaluate the ndims call here.
505 3 (_, arg_ty, _) := Typing.typeExp(listHead(args), arg_context, info);
506 3 callExp := Expression.INTEGER(Type.dimensionCount(arg_ty));
507 end typeNdimsCall;
508
509 function typePreCall
510 input Call call;
511 input InstContext.Type context;
512 input SourceInfo info;
513 output Expression callExp;
514 output Type ty;
515 output Variability variability;
516 output Purity purity;
517 algorithm
518 928 (callExp, ty, variability, purity) := typePreChangeCall("pre", call, context, info);
519 end typePreCall;
520
521 function typeChangeCall
522 input Call call;
523 input InstContext.Type context;
524 input SourceInfo info;
525 output Expression callExp;
526 output Type ty;
527 output Variability variability;
528 output Purity purity;
529 algorithm
530 17 (callExp, ty, variability, purity) := typePreChangeCall("change", call, context, info);
531 17 ty := Type.setArrayElementType(ty, Type.BOOLEAN());
532 end typeChangeCall;
533
534 function typePreChangeCall
535 input String name;
536 input Call call;
537 input InstContext.Type context;
538 input SourceInfo info;
539 output Expression callExp;
540 output Type ty;
541 output Variability variability = Variability.DISCRETE;
542 output Purity purity;
543 protected
544 ComponentRef fn_ref;
545 list<Expression> args;
546 list<NamedArg> named_args;
547 Expression arg;
548 Variability var;
549 Function fn;
550 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
551 algorithm
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 945 times.
945 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
553
554 945 assertNoNamedParams(name, named_args, info);
555
556
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 945 times.
945 if listLength(args) <> 1 then
557 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
558 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Any) => Any"}, info);
559 end if;
560
561 // pre/change may not be used in a function context.
562
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 945 times.
945 if InstContext.inFunction(context) then
563 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
564 {ComponentRef.toString(fn_ref)}, info);
565 end if;
566
567 945 (arg, ty, var, purity) := Typing.typeExp(listHead(args), arg_context, info);
568
569
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 945 times.
945 if not Expression.isCref(arg) then
570 ✗ Error.addSourceMessage(Error.ARGUMENT_MUST_BE_VARIABLE,
571 {"First", ComponentRef.toString(fn_ref), "<REMOVE ME>"}, info);
572 ✗ fail();
573 end if;
574
575
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 944 times.
945 if var == Variability.CONTINUOUS then
576 5 Error.addSourceMessageAndFail(Error.INVALID_ARGUMENT_VARIABILITY,
577 {"1", ComponentRef.toString(fn_ref), Prefixes.variabilityString(Variability.DISCRETE),
578 Expression.toString(arg), Prefixes.variabilityString(var)}, info);
579 end if;
580
581
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 944 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 944 times.
944 {fn} := Function.typeRefCache(fn_ref);
582 944 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, var, purity, ty));
583 end typePreChangeCall;
584
585 function typeDerCall
586 input Call call;
587 input InstContext.Type context;
588 input SourceInfo info;
589 output Expression callExp;
590 output Type ty;
591 output Variability variability;
592 output Purity purity;
593 protected
594 ComponentRef fn_ref;
595 list<Expression> args;
596 list<NamedArg> named_args;
597 Expression arg;
598 Function fn;
599 Type ety;
600 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
601 algorithm
602 // der may not be used in a function context.
603
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6733 times.
6733 if InstContext.inFunction(context) then
604 ✗ Error.addSourceMessage(Error.EXP_INVALID_IN_FUNCTION, {"der"}, info);
605 ✗ fail();
606 end if;
607
608
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6733 times.
6733 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
609 6733 assertNoNamedParams("der", named_args, info);
610
611
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6733 times.
6733 if listLength(args) <> 1 then
612 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
613 {Call.toString(call), "der(Real) => Real"}, info);
614 end if;
615
616
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6733 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6733 times.
6733 {arg} := args;
617 6733 (arg, ty, variability, purity) := Typing.typeExp(arg, arg_context, info);
618
619 // The argument of der must be a Real scalar or array.
620 6733 ety := Type.arrayElementType(ty);
621
622
2/2
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 6730 times.
6733 if Type.isInteger(ety) then
623
1/2
✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
3 if variability < Variability.DISCRETE then
624 3 ty := Type.setArrayElementType(ty, Type.REAL());
625 3 arg := Expression.typeCast(arg, Type.REAL());
626 else
627 ✗ Error.addSourceMessageAndFail(Error.DER_OF_NONDIFFERENTIABLE_EXP,
628 {Expression.toString(arg)}, info);
629 end if;
630 elseif not Type.isReal(ety) then
631 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
632 {"1", ComponentRef.toString(fn_ref), "", Expression.toString(arg),
633 Type.toString(ty), "Real"}, info);
634 end if;
635
636 // The argument must be differentiable, i.e. not discrete, unless where in a
637 // scope where everything is discrete (like an initial equation).
638
4/4
✓ Branch 0 taken 643 times.
✓ Branch 1 taken 6090 times.
✓ Branch 3 taken 1 time.
✓ Branch 4 taken 642 times.
6733 if variability == Variability.DISCRETE and not InstContext.inDiscreteScope(context) then
639 2 Error.addSourceMessageAndFail(Error.DER_OF_NONDIFFERENTIABLE_EXP,
640 {Expression.toString(arg)}, info);
641 end if;
642
643
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 6732 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 6732 times.
6732 {fn} := Function.typeRefCache(fn_ref);
644 6732 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
645 end typeDerCall;
646
647 function typeEdgeCall
648 input Call call;
649 input InstContext.Type context;
650 input SourceInfo info;
651 output Expression callExp;
652 output Type ty;
653 output Variability variability = Variability.DISCRETE;
654 output Purity purity;
655 protected
656 Call argtycall;
657 list<TypedArg> args;
658 TypedArg arg;
659 InstNode fn_node;
660 ComponentRef fn_ref;
661 algorithm
662 // edge may not be used in a function context.
663
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if InstContext.inFunction(context) then
664 ✗ Error.addSourceMessage(Error.EXP_INVALID_IN_FUNCTION, {"edge"}, info);
665 ✗ fail();
666 end if;
667
668
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 30 times.
30 argtycall as Call.ARG_TYPED_CALL(fn_ref as ComponentRef.CREF(), args, _) := Call.typeNormalCall(call, context, info);
669 30 fn_node := ComponentRef.node(fn_ref);
670 30 argtycall := Call.matchTypedNormalCall(argtycall, context, info);
671 30 ty := Call.typeOf(argtycall);
672 30 purity := Call.purity(argtycall);
673 30 callExp := Expression.CALL(Call.unboxArgs(argtycall));
674
675
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 30 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 30 times.
30 {arg} := args;
676
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
30 if not Expression.isCref(arg.value) then
677 ✗ Error.addSourceMessage(Error.ARGUMENT_MUST_BE_VARIABLE,
678 {"First", "edge", "<REMOVE ME>"}, info);
679 ✗ fail();
680 end if;
681 end typeEdgeCall;
682
683 function typeMinMaxCall
684 input String name;
685 input Call call;
686 input InstContext.Type context;
687 input SourceInfo info;
688 output Expression callExp;
689 output Type ty;
690 output Variability var;
691 output Purity purity;
692 protected
693 ComponentRef fn_ref;
694 list<Expression> args;
695 list<NamedArg> named_args;
696 Function fn;
697 Expression arg1, arg2;
698 Type ty1, ty2;
699 Variability var1, var2;
700 Purity pur1, pur2;
701 TypeCheck.MatchKind mk;
702 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
703
704 function is_valid_type
705 input Type ty;
706 output Boolean res;
707 algorithm
708 res := match ty
709 case Type.REAL() then true;
710 case Type.INTEGER() then true;
711 case Type.BOOLEAN() then true;
712 case Type.ENUMERATION() then true;
713 else false;
714 end match;
715 end is_valid_type;
716
717 function invalid_args_error
718 input Call call;
719 input String name;
720 input SourceInfo info;
721 algorithm
722 12 Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
723 {Call.toString(call),
724 name + "(Real, Real) => Real\n " +
725 name + "(Integer, Integer) => Integer\n " +
726 name + "(Boolean, Boolean) => Boolean\n " +
727 name + "(enumeration(:), enumeration(:)) => enumeration(:)\n " +
728 name + "(Real[:, ...]) => Real\n " +
729 name + "(Integer[:, ...]) => Integer\n " +
730 name + "(Boolean[:, ...]) => Boolean\n " +
731 name + "(enumeration(:)[:, ...]) => enumeration(:)"}, info);
732 end invalid_args_error;
733 algorithm
734
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2278 times.
2278 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
735 2278 assertNoNamedParams(name, named_args, info);
736
737 (args, ty, var, purity) := match args
738 case {arg1}
739 algorithm
740 140 (arg1, ty1, var, purity) := Typing.typeExp(arg1, arg_context, info);
741 140 ty := Type.arrayElementType(ty1);
742
743
2/4
✓ Branch 1 taken 140 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 140 times.
140 if not (Type.isArray(ty1) and is_valid_type(ty)) then
744 ✗ invalid_args_error(call, name, info);
745 end if;
746
747 // If the argument is an array with a single element we can just
748 // return that element instead of making a min/max call.
749
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 88 times.
140 if Type.isSingleElementArray(ty1) then
750 52 callExp := Expression.applySubscript(Subscript.first(listHead(Type.arrayDims(ty1))), arg1);
751 52 return;
752 end if;
753 88 then
754 ({arg1}, ty, var, purity);
755
756 case {arg1, arg2}
757 algorithm
758 2136 (arg1, ty1, var1, pur1) := Typing.typeExp(arg1, arg_context, info);
759 2136 (arg2, ty2, var2, pur2) := Typing.typeExp(arg2, arg_context, info);
760
761
3/4
✓ Branch 1 taken 2134 times.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2134 times.
2136 if not (is_valid_type(ty1) and is_valid_type(ty2)) then
762 2 invalid_args_error(call, name, info);
763 end if;
764
765 2134 (arg1, arg2, ty, mk) := TypeCheck.matchExpressions(arg1, ty1, arg2, ty2);
766
767
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2134 times.
2134 if not TypeCheck.isValidArgumentMatch(mk) then
768 ✗ invalid_args_error(call, name, info);
769 end if;
770 4268 then
771 ({arg1, arg2}, ty, Prefixes.variabilityMax(var1, var2), Purity.purityMin(pur1, pur2));
772
773 else
774 algorithm
775 2 invalid_args_error(call, name, info);
776 ✗ then
777 fail();
778 end match;
779
780 2222 fn := listHead(Function.typeRefCache(fn_ref));
781 2222 callExp := Expression.CALL(Call.makeTypedCall(fn, args, var, purity, ty));
782 end typeMinMaxCall;
783
784 function typePromoteCall
785 input Call call;
786 input InstContext.Type context;
787 input SourceInfo info;
788 output Expression callExp;
789 output Type ty;
790 output Variability variability;
791 output Purity purity;
792 protected
793 ComponentRef fn_ref;
794 list<Expression> args;
795 list<NamedArg> named_args;
796 Expression exp_arg, n_arg;
797 Type exp_ty, n_ty;
798 Variability n_var;
799 Integer n;
800 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
801 algorithm
802
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
803 1 assertNoNamedParams("promote", named_args, info);
804
805
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if listLength(args) <> 2 then
806 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
807 {Call.toString(call), "promote(Any[...], Integer) => Any[...]"}, info);
808 end if;
809
810
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 6 not taken.
✓ Branch 7 taken 1 time.
1 {exp_arg, n_arg} := args;
811 1 (exp_arg, exp_ty, variability, purity) := Typing.typeExp(exp_arg, arg_context, info);
812 1 (n_arg, n_ty, n_var) := Typing.typeExp(n_arg, arg_context, info);
813
814
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if not Type.isInteger(n_ty) then
815 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
816 {"2", "promote", "", Expression.toString(n_arg), Type.toString(n_ty), "Integer"}, info);
817 end if;
818
819
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if n_var > Variability.CONSTANT then
820 ✗ Error.addSourceMessageAndFail(Error.INVALID_ARGUMENT_VARIABILITY,
821 {"2", "promote", Prefixes.variabilityString(Variability.CONSTANT),
822 Expression.toString(n_arg), Prefixes.variabilityString(n_var)}, info);
823 end if;
824
825 1 n_arg := Ceval.evalExp(n_arg, Ceval.EvalTarget.new(info, arg_context));
826 1 n := Expression.integerValue(n_arg);
827
828
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if n < Type.dimensionCount(exp_ty) then
829 2 Error.addSourceMessageAndFail(Error.INVALID_NUMBER_OF_DIMENSIONS_FOR_PROMOTE,
830 {String(n), String(Type.dimensionCount(exp_ty))}, info);
831 end if;
832
833 ✗ (callExp, ty) := Expression.promote(exp_arg, Expression.typeOf(exp_arg), Expression.integerValue(n_arg));
834 end typePromoteCall;
835
836 function typeSmoothCall
837 input Call call;
838 input InstContext.Type context;
839 input SourceInfo info;
840 output Expression callExp;
841 output Type ty;
842 output Variability variability;
843 output Purity purity;
844 protected
845 ComponentRef fn_ref;
846 list<Expression> args;
847 list<NamedArg> named_args;
848 Expression arg1, arg2;
849 Type ty1, ty2;
850 Variability var;
851 Function fn;
852 TypeCheck.MatchKind mk;
853 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
854 algorithm
855
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
470 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
856 470 assertNoNamedParams("smooth", named_args, info);
857
858
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 470 times.
470 if listLength(args) <> 2 then
859 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
860 {Call.toString(call), "smooth(Integer, Any) => Any"}, info);
861 end if;
862
863
3/6
✗ Branch 0 not taken.
✓ Branch 1 taken 470 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 470 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 470 times.
470 {arg1, arg2} := args;
864 470 (arg1, ty1, var) := Typing.typeExp(arg1, arg_context, info);
865 470 (arg2, ty2, variability, purity) := Typing.typeExp(arg2, arg_context, info);
866
867 // First argument must be Integer.
868
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 470 times.
470 if not Type.isInteger(ty1) then
869 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
870 {"1", ComponentRef.toString(fn_ref), "", Expression.toString(arg1),
871 Type.toString(ty1), "Integer"}, info);
872 end if;
873
874 // First argument must be a parameter expression.
875
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 469 times.
470 if var > Variability.PARAMETER then
876 5 Error.addSourceMessageAndFail(Error.INVALID_ARGUMENT_VARIABILITY,
877 {"1", ComponentRef.toString(fn_ref), Prefixes.variabilityString(Variability.PARAMETER),
878 Expression.toString(arg1), Prefixes.variabilityString(variability)}, info);
879 end if;
880
881 // Second argument must be Real, array of allowed expressions or record
882 // containing only components of allowed expressions.
883 // TODO: Also handle records here.
884 469 (arg2, ty, mk) := TypeCheck.matchTypes(ty2, Type.setArrayElementType(ty2, Type.REAL()), arg2, NFTypeCheck.ALLOW_UNKNOWN);
885
886
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 468 times.
469 if not TypeCheck.isValidArgumentMatch(mk) then
887 4 Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
888 {"2", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
889 Type.toString(ty2), "Real\n Real[:, ...]\n Real record\n Real record[:, ...]"}, info);
890 end if;
891
892
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 468 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 468 times.
468 {fn} := Function.typeRefCache(fn_ref);
893 468 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg1, arg2}, var, purity, ty));
894 end typeSmoothCall;
895
896 function typeFillCall
897 input Call call;
898 input InstContext.Type context;
899 input SourceInfo info;
900 output Expression callExp;
901 output Type ty;
902 output Variability variability;
903 output Purity purity;
904 protected
905 ComponentRef fn_ref;
906 list<Expression> args;
907 list<NamedArg> named_args;
908 Expression fill_arg;
909 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
910 algorithm
911
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2128 times.
2128 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
912 2128 assertNoNamedParams("fill", named_args, info);
913
914 // fill can take any number of arguments, but needs at least two.
915
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2128 times.
2128 if listLength(args) < 2 then
916 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
917 {Call.toString(call), "fill(Any, Integer, ...) => Any[:, ...]"}, info);
918 end if;
919
920
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2128 times.
2128 fill_arg :: args := args;
921
922 // Type the first argument, which is the fill value.
923 2128 (fill_arg, ty, variability, purity) := Typing.typeExp(fill_arg, arg_context, info);
924 2128 (callExp, ty, variability, purity) :=
925 typeFillCall2(fn_ref, ty, fill_arg, variability, purity, args, arg_context, info);
926 end typeFillCall;
927
928 function typeFillCall2
929 input ComponentRef fnRef;
930 input Type fillType;
931 input Expression fillArg;
932 input Variability fillVariability;
933 input Purity fillPurity;
934 input list<Expression> dimensionArgs;
935 input InstContext.Type context;
936 input SourceInfo info;
937 output Expression callExp;
938 output Type ty;
939 output Variability variability = fillVariability;
940 output Purity purity = fillPurity;
941 protected
942 list<Expression> ty_args;
943 Variability arg_var;
944 Purity arg_pur;
945 Type arg_ty;
946 Function fn;
947 list<Dimension> dims;
948 Integer index = 1;
949 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
950 algorithm
951 ty_args := {fillArg};
952 dims := {};
953
954 // Type the dimension arguments.
955
2/2
✓ Branch 0 taken 7585 times.
✓ Branch 1 taken 7436 times.
15021 for arg in dimensionArgs loop
956 7585 (arg, arg_ty, arg_var, arg_pur) := Typing.typeExp(arg, arg_context, info);
957
958
4/4
✓ Branch 1 taken 7186 times.
✓ Branch 2 taken 399 times.
✓ Branch 4 taken 7124 times.
✓ Branch 5 taken 62 times.
7585 if not (InstContext.inAlgorithm(context) or InstContext.inFunction(context)) then
959
4/6
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7119 times.
✓ Branch 3 taken 5 times.
✗ Branch 4 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 5 times.
7124 if arg_var > Variability.PARAMETER and not (InstContext.inInstanceAPI(context) or Expression.contains(arg, Expression.isResizableCref)) then
960 ✗ Error.addSourceMessageAndFail(Error.NON_PARAMETER_EXPRESSION_DIMENSION,
961 {Expression.toString(arg), String(index),
962 List.toStringCustom(fillArg :: dimensionArgs, Expression.toString,
963 ComponentRef.toString(fnRef), "(", ", ", ")", true)}, info);
964 end if;
965
966 // a resizable size stays symbolic
967
5/6
✓ Branch 0 taken 7123 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 7123 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 7118 times.
✓ Branch 7 taken 5 times.
7124 if arg_pur == Purity.PURE and not Structural.isExpressionNotFixed(arg) and
968 not Expression.contains(arg, Expression.isResizableCref) then
969 7118 Structural.markExp(arg);
970
2/2
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 7111 times.
7118 arg := if InstContext.inInstanceAPI(context) then Ceval.tryEvalExp(arg) else Ceval.tryEvalExpResizable(arg);
971 7118 arg_ty := Expression.typeOf(arg);
972 end if;
973 end if;
974
975 // Each dimension argument must be an Integer expression.
976
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 7585 times.
7585 if not Type.isInteger(arg_ty) then
977 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
978 {intString(listLength(ty_args) + 1), ComponentRef.toString(fnRef), "",
979 Expression.toString(arg), Type.toString(arg_ty), "Integer"}, info);
980 end if;
981
982 7585 variability := Prefixes.variabilityMax(variability, arg_var);
983 7585 purity := Prefixes.purityMin(purity, arg_pur);
984 ty_args := arg :: ty_args;
985 7585 dims := Dimension.fromExp(arg, arg_var) :: dims;
986 7585 index := index + 1;
987 end for;
988
989 7436 ty_args := listReverseInPlace(ty_args);
990 7436 dims := listReverseInPlace(dims);
991
992
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 7436 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 7436 times.
7436 {fn} := Function.typeRefCache(fnRef);
993 7436 ty := Type.liftArrayLeftList(fillType, dims);
994
995 7436 callExp := Expression.CALL(
996 Call.makeTypedCall(NFBuiltinFuncs.FILL_FUNC, ty_args, variability, purity, ty));
997 end typeFillCall2;
998
999 function typeZerosOnesCall
1000 input String name;
1001 input Call call;
1002 input InstContext.Type context;
1003 input SourceInfo info;
1004 output Expression callExp;
1005 output Type ty;
1006 output Variability variability;
1007 output Purity purity;
1008 protected
1009 ComponentRef fn_ref;
1010 list<Expression> args;
1011 list<NamedArg> named_args;
1012 Expression fill_arg;
1013 algorithm
1014
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5308 times.
5308 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1015 5308 assertNoNamedParams(name, named_args, info);
1016
1017 // zeros/ones can take any number of arguments, but needs at least one.
1018
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5308 times.
5308 if listEmpty(args) then
1019 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1020 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Integer, ...) => Integer[:, ...]"}, info);
1021 end if;
1022
1023
3/4
✓ Branch 0 taken 171 times.
✓ Branch 1 taken 5137 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 171 times.
5308 fill_arg := Expression.INTEGER(if name == "ones" then 1 else 0);
1024 5308 (callExp, ty, variability, purity) :=
1025 typeFillCall2(fn_ref, Type.INTEGER(), fill_arg, Variability.CONSTANT, Purity.PURE, args, context, info);
1026 end typeZerosOnesCall;
1027
1028 function typeScalarCall
1029 input Call call;
1030 input InstContext.Type context;
1031 input SourceInfo info;
1032 output Expression callExp;
1033 output Type ty;
1034 output Variability variability;
1035 output Purity purity;
1036 protected
1037 ComponentRef fn_ref;
1038 list<Expression> args;
1039 list<NamedArg> named_args;
1040 Expression arg;
1041 Function fn;
1042 Boolean expanded;
1043 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1044 algorithm
1045
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
6 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1046 6 assertNoNamedParams("scalar", named_args, info);
1047
1048
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if listLength(args) <> 1 then
1049 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1050 {Call.toString(call), "scalar(Any[1, ...]) => Any"}, info);
1051 end if;
1052
1053 6 (arg, ty, variability, purity) := Typing.typeExp(listHead(args), arg_context, info);
1054
1055 // scalar requires all dimensions of the array to be 1.
1056
2/2
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 6 times.
16 for dim in Type.arrayDims(ty) loop
1057
2/4
✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 10 times.
10 if Dimension.isKnown(dim) and not Dimension.size(dim) == 1 then
1058 ✗ Error.addSourceMessageAndFail(Error.INVALID_ARRAY_DIM_IN_SCALAR_OP,
1059 {Type.toString(ty)}, info);
1060 end if;
1061 end for;
1062
1063 6 (arg, expanded) := ExpandExp.expand(arg);
1064 6 ty := Type.arrayElementType(ty);
1065
1066
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 if expanded then
1067 6 args := Expression.arrayScalarElements(arg);
1068
1069
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 if listLength(args) <> 1 then
1070 ✗ Error.terminate(getInstanceName() + " failed to expand scalar(" +
1071 Expression.toString(arg) + ") correctly", info);
1072 end if;
1073
1074 6 callExp := listHead(args);
1075 else
1076 ✗ {fn} := Function.typeRefCache(fn_ref);
1077 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1078 end if;
1079 end typeScalarCall;
1080
1081 function typeVectorCall
1082 input Call call;
1083 input InstContext.Type context;
1084 input SourceInfo info;
1085 output Expression callExp;
1086 output Type ty;
1087 output Variability variability;
1088 output Purity purity;
1089 protected
1090 ComponentRef fn_ref;
1091 list<Expression> args;
1092 list<NamedArg> named_args;
1093 Expression arg;
1094 Function fn;
1095 Dimension vector_dim = Dimension.fromInteger(1);
1096 Boolean dim_found = false;
1097 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1098 algorithm
1099
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 396 times.
396 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1100 396 assertNoNamedParams("vector", named_args, info);
1101
1102
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
396 if listLength(args) <> 1 then
1103 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1104 {Call.toString(call), "vector(Any) => Any[:]\n vector(Any[:, ...]) => Any[:]"}, info);
1105 end if;
1106
1107 396 (arg, ty, variability, purity) := Typing.typeExp(listHead(args), arg_context, info);
1108
1109 // vector requires that at most one dimension is > 1, and that dimension
1110 // determines the type of the vector call.
1111
2/2
✓ Branch 1 taken 783 times.
✓ Branch 2 taken 396 times.
1179 for dim in Type.arrayDims(ty) loop
1112
3/4
✓ Branch 1 taken 783 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 392 times.
✓ Branch 5 taken 391 times.
783 if not Dimension.isKnown(dim) or Dimension.size(dim) > 1 then
1113
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
392 if dim_found then
1114 ✗ Error.addSourceMessageAndFail(Error.NF_VECTOR_INVALID_DIMENSIONS,
1115 {Type.toString(ty), Call.toString(call)}, info);
1116 else
1117 vector_dim := dim;
1118 dim_found := true;
1119 end if;
1120 end if;
1121 end for;
1122
1123 // The array might be empty even if one dimension is larger than 1,
1124 // in that case the result will also be an empty array.
1125
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 395 times.
396 if Type.isEmptyArray(ty) then
1126 1 vector_dim := Dimension.fromInteger(0);
1127 end if;
1128
1129 396 ty := Type.ARRAY(Type.arrayElementType(ty), {vector_dim});
1130
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 396 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 396 times.
396 {fn} := Function.typeRefCache(fn_ref);
1131 396 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1132 end typeVectorCall;
1133
1134 function typeMatrixCall
1135 input Call call;
1136 input InstContext.Type context;
1137 input SourceInfo info;
1138 output Expression callExp;
1139 output Type ty;
1140 output Variability variability;
1141 output Purity purity;
1142 protected
1143 ComponentRef fn_ref;
1144 list<Expression> args;
1145 list<NamedArg> named_args;
1146 Expression arg;
1147 Function fn;
1148 list<Dimension> dims;
1149 Dimension dim1, dim2;
1150 Integer i, ndims;
1151 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1152 algorithm
1153
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1154 141 assertNoNamedParams("matrix", named_args, info);
1155
1156
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 if listLength(args) <> 1 then
1157 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1158 {Call.toString(call), "matrix(Any) => Any[:]\n matrix(Any[:, ...]) => Any[:]"}, info);
1159 end if;
1160
1161 141 (arg, ty, variability, purity) := Typing.typeExp(listHead(args), arg_context, info);
1162 141 dims := Type.arrayDims(ty);
1163 141 ndims := listLength(dims);
1164
1165
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 1 time.
141 if ndims < 2 then
1166 // matrix(A) where A is a scalar or vector returns promote(A, 2).
1167 140 (callExp, ty) := Expression.promote(arg, ty, 2);
1168 elseif ndims == 2 then
1169 // matrix(A) where A is a matrix just returns A.
1170 callExp := arg;
1171 else
1172 // matrix requires all but the first two dimensions to have size 1.
1173
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
1 dim1 :: dim2 :: dims := dims;
1174 i := 3;
1175
1176
1/2
✓ Branch 0 taken 1 time.
✗ Branch 1 not taken.
1 for dim in dims loop
1177
2/4
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 time.
✗ Branch 5 not taken.
1 if Dimension.isKnown(dim) and Dimension.size(dim) > 1 then
1178 2 Error.addSourceMessageAndFail(Error.INVALID_ARRAY_DIM_IN_CONVERSION_OP,
1179 {String(i), "matrix", "1", Dimension.toString(dim)}, info);
1180 end if;
1181
1182 ✗ i := i + 1;
1183 end for;
1184
1185 ✗ ty := Type.ARRAY(Type.arrayElementType(ty), {dim1, dim2});
1186 ✗ {fn} := Function.typeRefCache(fn_ref);
1187 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1188 end if;
1189 end typeMatrixCall;
1190
1191 function typeCatCall
1192 input Call call;
1193 input InstContext.Type context;
1194 input SourceInfo info;
1195 output Expression callExp;
1196 output Type ty;
1197 output Variability variability;
1198 output Purity purity;
1199 protected
1200 ComponentRef fn_ref;
1201 list<Expression> args, res;
1202 list<NamedArg> named_args;
1203 list<Type> tys;
1204 Expression arg;
1205 Variability var;
1206 Purity pur;
1207 TypeCheck.MatchKind mk;
1208 Integer n;
1209 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1210 algorithm
1211
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1212 498 assertNoNamedParams("cat", named_args, info);
1213
1214
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 498 times.
498 if listLength(args) < 2 then
1215 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1216 {Call.toString(call), "cat(Integer, Any[:,:], ...) => Any[:]"}, info);
1217 end if;
1218
1219
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 498 times.
498 arg::args := args;
1220
1221 498 (arg, ty, variability, purity) := Typing.typeExp(arg, arg_context, info);
1222 498 (arg, ty, mk) := TypeCheck.matchTypes(ty, Type.INTEGER(), arg);
1223
1224
2/4
✓ Branch 0 taken 498 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 498 times.
498 if variability > Variability.PARAMETER or purity <> Purity.PURE then
1225 ✗ Error.addSourceMessageAndFail(Error.NF_CAT_FIRST_ARG_EVAL, {Expression.toString(arg), Prefixes.variabilityString(variability)}, info);
1226 end if;
1227
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 498 times.
498 Expression.INTEGER(n) := Ceval.evalExp(arg, Ceval.EvalTarget.new(info, arg_context));
1228
1229 res := {};
1230 tys := {};
1231
1232
2/2
✓ Branch 0 taken 1229 times.
✓ Branch 1 taken 498 times.
1727 for a in args loop
1233 1229 (arg, ty, var, pur) := Typing.typeExp(a, arg_context, info);
1234 1229 variability := Prefixes.variabilityMax(var, variability);
1235 1229 purity := Prefixes.purityMin(pur, purity);
1236 res := arg :: res;
1237 1229 tys := ty :: tys;
1238 end for;
1239
1240 498 (callExp, ty) := makeCatExp(n, listReverse(res), listReverse(tys), variability, purity, info);
1241 end typeCatCall;
1242
1243 function typeSymmetricCall
1244 input Call call;
1245 input InstContext.Type context;
1246 input SourceInfo info;
1247 output Expression callExp;
1248 output Type ty;
1249 output Variability variability;
1250 output Purity purity;
1251 protected
1252 ComponentRef fn_ref;
1253 list<Expression> args;
1254 list<NamedArg> named_args;
1255 Expression arg;
1256 Function fn;
1257 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1258 algorithm
1259
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1260 1 assertNoNamedParams("symmetric", named_args, info);
1261
1262
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 if listLength(args) <> 1 then
1263 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1264 {Call.toString(call), "symmetric(Any[n, n]) => Any[n, n]"}, info);
1265 end if;
1266
1267 1 (arg, ty, variability, purity) := Typing.typeExp(listHead(args), arg_context, info);
1268
1269
1/2
✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
1 if not Type.isSquareMatrix(ty) then
1270 4 Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1271 {"1", ComponentRef.toString(fn_ref), "", Expression.toString(arg),
1272 Type.toString(ty), "Any[n, n]"}, info);
1273 end if;
1274
1275 ✗ {fn} := Function.typeRefCache(fn_ref);
1276 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1277 end typeSymmetricCall;
1278
1279 function typeTransposeCall
1280 input Call call;
1281 input InstContext.Type context;
1282 input SourceInfo info;
1283 output Expression callExp;
1284 output Type ty;
1285 output Variability variability;
1286 output Purity purity;
1287 protected
1288 ComponentRef fn_ref;
1289 list<Expression> args;
1290 list<NamedArg> named_args;
1291 Expression arg;
1292 Dimension dim1, dim2;
1293 list<Dimension> rest_dims;
1294 Function fn;
1295 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1296 algorithm
1297
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
392 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1298 392 assertNoNamedParams("transpose", named_args, info);
1299
1300
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 392 times.
392 if listLength(args) <> 1 then
1301 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1302 {Call.toString(call), "transpose(Any[n, m, ...]) => Any[m, n, ...]"}, info);
1303 end if;
1304
1305 392 (arg, ty, variability, purity) := Typing.typeExp(listHead(args), arg_context, info);
1306
1307 ty := match ty
1308 case Type.ARRAY(dimensions = dim1 :: dim2 :: rest_dims)
1309 392 then Type.ARRAY(ty.elementType, dim2 :: dim1 :: rest_dims);
1310
1311 else
1312 algorithm
1313 ✗ Error.addSourceMessage(Error.ARG_TYPE_MISMATCH,
1314 {"1", ComponentRef.toString(fn_ref), "", Expression.toString(arg),
1315 Type.toString(ty), "Any[:, :, ...]"}, info);
1316 ✗ then
1317 fail();
1318 end match;
1319
1320
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 392 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 392 times.
392 {fn} := Function.typeRefCache(fn_ref);
1321 392 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1322 end typeTransposeCall;
1323
1324 function typeCardinalityCall
1325 input Call call;
1326 input InstContext.Type context;
1327 input SourceInfo info;
1328 output Expression callExp;
1329 output Type ty;
1330 output Variability var = Variability.PARAMETER;
1331 output Purity purity = Purity.IMPURE;
1332 protected
1333 algorithm
1334 // cardinality may only be used in a condition of an assert or
1335 // if-statement/equation (the specification says only if-statement,
1336 // but e.g. the MSL only uses them in if-equations and asserts).
1337
5/6
✓ Branch 1 taken 2354 times.
✓ Branch 2 taken 1 time.
✓ Branch 4 taken 1746 times.
✓ Branch 5 taken 608 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 1746 times.
2355 if not (InstContext.inCondition(context) and
1338 (InstContext.inIf(context) or InstContext.inAssert(context))) then
1339 1 Error.addSourceMessageAndFail(Error.INVALID_CARDINALITY_CONTEXT, {}, info);
1340 end if;
1341
1342
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2354 times.
2354 if InstContext.inFunction(context) then
1343 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1344 {AbsynUtil.pathString(Call.functionName(call))}, info);
1345 end if;
1346
1347 2354 (callExp, ty, _, _) := typeBuiltinCallExp(call, context, info, vectorize = false);
1348 2354 System.setUsesCardinality(true);
1349 end typeCardinalityCall;
1350
1351 function typeConnectionsArgs
1352 input list<Expression> args;
1353 input InstContext.Type context;
1354 input SourceInfo info;
1355 input ComponentRef fnRef;
1356 output list<Expression> outArgs = {};
1357 protected
1358 Integer index = 1;
1359 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1360 algorithm
1361
2/2
✓ Branch 0 taken 2181 times.
✓ Branch 1 taken 1578 times.
3759 for arg in args loop
1362 2181 outArgs := typeConnectionsArg(arg, arg_context, info, fnRef, index) :: outArgs;
1363 2180 index := index + 1;
1364 end for;
1365
1366 1578 outArgs := listReverseInPlace(outArgs);
1367 end typeConnectionsArgs;
1368
1369 function typeConnectionsArg
1370 input Expression arg;
1371 input InstContext.Type context;
1372 input SourceInfo info;
1373 input ComponentRef fnRef;
1374 input Integer index;
1375 output Expression outArg;
1376 output Type outType;
1377 algorithm
1378 2407 (outArg, outType) := Typing.typeExp(arg, context, info);
1379 2407 checkConnectionsArgument(outArg, outType, fnRef, index, info);
1380 end typeConnectionsArg;
1381
1382 function typeBranchCall
1383 input Call call;
1384 input InstContext.Type context;
1385 input SourceInfo info;
1386 output Expression callExp;
1387 output Type ty;
1388 output Variability var = Variability.PARAMETER;
1389 output Purity purity = Purity.IMPURE;
1390 protected
1391 ComponentRef fn_ref;
1392 list<Expression> args;
1393 list<NamedArg> named_args;
1394 Function fn;
1395 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1396 algorithm
1397
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
602 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1398 602 assertNoNamedParams("Connections.branch", named_args, info);
1399
1400
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 602 times.
602 if listLength(args) <> 2 then
1401 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1402 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, Connector)"}, info);
1403 end if;
1404
1405
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 602 times.
602 if InstContext.inFunction(context) then
1406 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1407 {ComponentRef.toString(fn_ref)}, info);
1408 end if;
1409
1410 602 args := typeConnectionsArgs(args, arg_context, info, fn_ref);
1411
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 602 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 602 times.
602 {fn} := Function.typeRefCache(fn_ref);
1412 ty := Type.NORETCALL();
1413 602 callExp := Expression.CALL(Call.makeTypedCall(fn, args, var, purity, ty));
1414 end typeBranchCall;
1415
1416 function typeIsRootCall
1417 input Call call;
1418 input InstContext.Type context;
1419 input SourceInfo info;
1420 output Expression callExp;
1421 output Type ty;
1422 output Variability var = Variability.PARAMETER;
1423 output Purity purity = Purity.IMPURE;
1424 protected
1425 ComponentRef fn_ref;
1426 list<Expression> args;
1427 list<NamedArg> named_args;
1428 Function fn;
1429 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1430 algorithm
1431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 423 times.
423 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1432 423 assertNoNamedParams("Connections.isRoot", named_args, info);
1433
1434
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
423 if listLength(args) <> 1 then
1435 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1436 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
1437 end if;
1438
1439
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
423 if InstContext.inFunction(context) then
1440 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1441 {ComponentRef.toString(fn_ref)}, info);
1442 end if;
1443
1444 423 args := typeConnectionsArgs(args, arg_context, info, fn_ref);
1445
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 423 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 423 times.
423 {fn} := Function.typeRefCache(fn_ref);
1446 ty := Type.BOOLEAN();
1447 423 callExp := Expression.CALL(Call.makeTypedCall(fn, args, var, purity, ty));
1448 end typeIsRootCall;
1449
1450 function typePotentialRootCall
1451 input Call call;
1452 input InstContext.Type context;
1453 input SourceInfo info;
1454 output Expression callExp;
1455 output Type ty;
1456 output Variability var = Variability.PARAMETER;
1457 output Purity purity = Purity.IMPURE;
1458 protected
1459 ComponentRef fn_ref;
1460 list<Expression> args;
1461 list<NamedArg> named_args;
1462 Expression arg1, arg2;
1463 Function fn;
1464 Integer args_len;
1465 String name;
1466 Variability arg_var;
1467 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1468 algorithm
1469
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1470
1471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 for narg in named_args loop
1472 ✗ (name, arg2) := narg;
1473
1474 ✗ if name == "priority" then
1475 ✗ args := List.appendElt(arg2, args);
1476 else
1477 ✗ Error.addSourceMessageAndFail(Error.NO_SUCH_INPUT_PARAMETER,
1478 {ComponentRef.toString(fn_ref), name}, info);
1479 end if;
1480 end for;
1481
1482 226 args_len := listLength(args);
1483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 if args_len < 1 or args_len > 2 then
1484 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1485 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, Integer = 0)"}, info);
1486 end if;
1487
1488
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 226 times.
226 if InstContext.inFunction(context) then
1489 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1490 {ComponentRef.toString(fn_ref)}, info);
1491 end if;
1492
1493
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 226 times.
226 arg1 :: args := args;
1494
1495 226 arg1 := typeConnectionsArg(arg1, arg_context, info, fn_ref, 1);
1496
1497
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 206 times.
226 if args_len == 2 then
1498 20 arg2 := listHead(args);
1499 20 (arg2, ty, arg_var) := Typing.typeExp(arg2, arg_context, info);
1500
1501
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 if not Type.isInteger(ty) then
1502 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1503 {"2", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
1504 Type.toString(ty), "Integer"}, info);
1505 end if;
1506
1507
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 if arg_var > Variability.PARAMETER then
1508 ✗ Error.addSourceMessageAndFail(Error.INVALID_ARGUMENT_VARIABILITY,
1509 {"2", ComponentRef.toString(fn_ref), Prefixes.variabilityString(Variability.PARAMETER),
1510 Expression.toString(arg2), Prefixes.variabilityString(arg_var)}, info);
1511 end if;
1512
1513 20 Structural.markExp(arg2);
1514 else
1515 arg2 := Expression.INTEGER(0);
1516 end if;
1517
1518
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 226 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 226 times.
226 {fn} := Function.typeRefCache(fn_ref);
1519 226 ty := Type.NORETCALL();
1520 226 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg1, arg2}, var, purity, ty));
1521 end typePotentialRootCall;
1522
1523 function typeRootCall
1524 input Call call;
1525 input InstContext.Type context;
1526 input SourceInfo info;
1527 output Expression callExp;
1528 output Type ty;
1529 output Variability var = Variability.PARAMETER;
1530 output Purity purity = Purity.IMPURE;
1531 protected
1532 ComponentRef fn_ref;
1533 list<Expression> args;
1534 list<NamedArg> named_args;
1535 Function fn;
1536 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1537 algorithm
1538
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 413 times.
413 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1539 413 assertNoNamedParams("Connections.root", named_args, info);
1540
1541
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 413 times.
413 if listLength(args) <> 1 then
1542 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1543 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
1544 end if;
1545
1546
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 413 times.
413 if InstContext.inFunction(context) then
1547 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1548 {ComponentRef.toString(fn_ref)}, info);
1549 end if;
1550
1551 413 args := typeConnectionsArgs(args, arg_context, info, fn_ref);
1552
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 412 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 412 times.
412 {fn} := Function.typeRefCache(fn_ref);
1553 ty := Type.NORETCALL();
1554 412 callExp := Expression.CALL(Call.makeTypedCall(fn, args, var, purity, ty));
1555 end typeRootCall;
1556
1557 function typeRootedCall
1558 input Call call;
1559 input InstContext.Type context;
1560 input SourceInfo info;
1561 output Expression callExp;
1562 output Type ty;
1563 output Variability var = Variability.PARAMETER;
1564 output Purity purity = Purity.IMPURE;
1565 protected
1566 ComponentRef fn_ref;
1567 list<Expression> args;
1568 list<NamedArg> named_args;
1569 Function fn;
1570 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1571 algorithm
1572
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 141 times.
141 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1573 141 assertNoNamedParams("Connections.rooted", named_args, info);
1574
1575
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 if listLength(args) <> 1 then
1576 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1577 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector)"}, info);
1578 end if;
1579
1580
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 if InstContext.inFunction(context) then
1581 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1582 {ComponentRef.toString(fn_ref)}, info);
1583 end if;
1584
1585 141 args := typeConnectionsArgs(args, arg_context, info, fn_ref);
1586
1587
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
141 if ComponentRef.isSimple(fn_ref) then
1588 ✗ Error.addSourceMessage(Error.DEPRECATED_API_CALL, {"rooted", "Connections.rooted"}, info);
1589 end if;
1590
1591
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 141 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 141 times.
141 {fn} := Function.typeRefCache(fn_ref);
1592 ty := Type.BOOLEAN();
1593 141 callExp := Expression.CALL(Call.makeTypedCall(fn, args, var, purity, ty));
1594 end typeRootedCall;
1595
1596 function typeUniqueRootCall
1597 "see also typeUniqueRootIndicesCall"
1598 input Call call;
1599 input InstContext.Type context;
1600 input SourceInfo info;
1601 output Expression callExp;
1602 output Type ty;
1603 output Variability var = Variability.PARAMETER;
1604 output Purity purity = Purity.IMPURE;
1605 protected
1606 ComponentRef fn_ref;
1607 list<Expression> args;
1608 list<NamedArg> named_args;
1609 Expression arg1, arg2;
1610 Function fn;
1611 Integer args_len;
1612 String name;
1613 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1614 algorithm
1615 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRoot"}, info);
1616
1617 ✗ Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1618
1619 ✗ for narg in named_args loop
1620 ✗ (name, arg2) := narg;
1621
1622 ✗ if name == "message" then
1623 ✗ args := List.appendElt(arg2, args);
1624 else
1625 ✗ Error.addSourceMessageAndFail(Error.NO_SUCH_INPUT_PARAMETER,
1626 {ComponentRef.toString(fn_ref), name}, info);
1627 end if;
1628 end for;
1629
1630 ✗ args_len := listLength(args);
1631 ✗ if args_len < 1 or args_len > 2 then
1632 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1633 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, String = \"\")"}, info);
1634 end if;
1635
1636 ✗ if InstContext.inFunction(context) then
1637 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1638 {ComponentRef.toString(fn_ref)}, info);
1639 end if;
1640
1641 ✗ arg1 :: args := args;
1642
1643 ✗ arg1 := typeConnectionsArg(arg1, arg_context, info, fn_ref, 1);
1644
1645 ✗ if args_len == 2 then
1646 ✗ arg2 := listHead(args);
1647 ✗ (arg2, ty) := Typing.typeExp(arg2, arg_context, info);
1648
1649 ✗ if not Type.isString(ty) then
1650 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1651 {"2", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
1652 Type.toString(ty), "String"}, info);
1653 end if;
1654 else
1655 arg2 := Expression.STRING("");
1656 end if;
1657
1658 ✗ {fn} := Function.typeRefCache(fn_ref);
1659 ✗ ty := Type.NORETCALL();
1660 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg1, arg2}, var, purity, ty));
1661 end typeUniqueRootCall;
1662
1663 function typeUniqueRootIndicesCall
1664 "See Modelica_StateGraph2:
1665 https://github.com/modelica/Modelica_StateGraph2
1666 and
1667 https://trac.modelica.org/Modelica/ticket/984
1668 and
1669 http://www.ep.liu.se/ecp/043/041/ecp09430108.pdf
1670 for a specification of this operator"
1671 input Call call;
1672 input InstContext.Type context;
1673 input SourceInfo info;
1674 output Expression callExp;
1675 output Type ty;
1676 output Variability var = Variability.PARAMETER;
1677 output Purity purity = Purity.IMPURE;
1678 protected
1679 ComponentRef fn_ref;
1680 list<Expression> args;
1681 list<NamedArg> named_args;
1682 Expression arg1, arg2, arg3;
1683 Function fn;
1684 Integer args_len;
1685 String name;
1686 Type ty1, ty2, ty3;
1687 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
1688 algorithm
1689 ✗ Error.addSourceMessage(Error.NON_STANDARD_OPERATOR, {"Connections.uniqueRootIndices"}, info);
1690
1691 ✗ Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1692
1693 ✗ for narg in named_args loop
1694 ✗ (name, arg3) := narg;
1695
1696 ✗ if name == "message" then
1697 ✗ args := List.appendElt(arg3, args);
1698 else
1699 ✗ Error.addSourceMessageAndFail(Error.NO_SUCH_INPUT_PARAMETER,
1700 {ComponentRef.toString(fn_ref), name}, info);
1701 end if;
1702 end for;
1703
1704 ✗ args_len := listLength(args);
1705 ✗ if args_len < 2 or args_len > 3 then
1706 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1707 {Call.toString(call), ComponentRef.toString(fn_ref) + "(Connector, Connector, String = \"\")"}, info);
1708 end if;
1709
1710 ✗ if InstContext.inFunction(context) then
1711 ✗ Error.addSourceMessageAndFail(Error.EXP_INVALID_IN_FUNCTION,
1712 {ComponentRef.toString(fn_ref)}, info);
1713 end if;
1714
1715 ✗ arg1 :: arg2 :: args := args;
1716
1717 ✗ (arg1, ty1) := typeConnectionsArg(arg1, arg_context, info, fn_ref, 1);
1718
1719 ✗ if not Type.isArray(ty1) then
1720 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1721 {"1", ComponentRef.toString(fn_ref), "", Expression.toString(arg1),
1722 Type.toString(ty1), "Connector[:]"}, info);
1723 end if;
1724
1725 ✗ (arg2, ty2) := typeConnectionsArg(arg2, arg_context, info, fn_ref, 2);
1726
1727 ✗ if not Type.isArray(ty2) then
1728 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1729 {"2", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
1730 Type.toString(ty2), "Connector[:]"}, info);
1731 end if;
1732
1733 ✗ if args_len == 3 then
1734 ✗ arg3 := listHead(args);
1735 ✗ (arg3, ty3) := Typing.typeExp(arg3, arg_context, info);
1736
1737 ✗ if not Type.isString(ty3) then
1738 ✗ Error.addSourceMessageAndFail(Error.ARG_TYPE_MISMATCH,
1739 {"3", ComponentRef.toString(fn_ref), "", Expression.toString(arg2),
1740 Type.toString(ty3), "String"}, info);
1741 end if;
1742 else
1743 arg3 := Expression.STRING("");
1744 end if;
1745
1746 ✗ {fn} := Function.typeRefCache(fn_ref);
1747 ✗ assert(listLength(Type.arrayDims(ty1)) == listLength(Type.arrayDims(ty2)), "the first two parameters need to have the same size");
1748 ✗ ty := Type.ARRAY(Type.Type.INTEGER(), Type.arrayDims(ty1));
1749 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg1, arg2, arg3}, var, purity, ty));
1750
1751 end typeUniqueRootIndicesCall;
1752
1753 function checkConnectionsArgument
1754 input Expression arg;
1755 input Type ty;
1756 input ComponentRef fnRef;
1757 input Integer argIndex;
1758 input SourceInfo info;
1759 algorithm
1760 () := match arg
1761 local
1762 Type ty2;
1763 InstNode node;
1764 Boolean valid_cref, isConnector;
1765
1766 case Expression.CREF()
1767 algorithm
1768 (valid_cref, isConnector) := match arg.cref
1769 // check form A.R
1770 case ComponentRef.CREF(origin = NFComponentRef.Origin.CREF,
1771 restCref = ComponentRef.CREF(ty = ty2, origin = NFComponentRef.Origin.CREF))
1772 algorithm
1773 2406 node := ComponentRef.node(arg.cref);
1774 ty2 := match ty2
1775 case Type.ARRAY()
1776 guard listLength(ComponentRef.subscriptsAllFlat(arg.cref)) == listLength(ty2.dimensions)
1777 2 then ty2.elementType;
1778 else ty2;
1779 end match;
1780 2406 then (Class.isOverdetermined(InstNode.getClass(node)), Type.isConnector(ty2));
1781
1782 // adrpo #5821, allow for R only instead of A.R and issue a warning
1783 case ComponentRef.CREF(ty = ty2)
1784 algorithm
1785 1 node := ComponentRef.node(arg.cref);
1786 ty2 := match ty2
1787 case Type.ARRAY()
1788 guard listLength(ComponentRef.subscriptsAllFlat(arg.cref)) == listLength(ty2.dimensions)
1789 ✗ then ty2.elementType;
1790 else ty2;
1791 end match;
1792 1 then (Class.isOverdetermined(InstNode.getClass(node)), Type.isConnector(ty2));
1793
1794 else (false, false);
1795 end match;
1796
1797
2/2
✓ Branch 0 taken 1 time.
✓ Branch 1 taken 2406 times.
2407 if not (valid_cref and isConnector) then
1798
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 time.
1 if valid_cref then
1799 ✗ Error.addSourceMessage(
1800 if argIndex == 1 then Error.W_INVALID_ARGUMENT_TYPE_BRANCH_FIRST else
1801 Error.W_INVALID_ARGUMENT_TYPE_BRANCH_SECOND,
1802 {ComponentRef.toString(arg.cref), ComponentRef.toString(fnRef)}, info);
1803 else
1804
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 1 time.
3 Error.addSourceMessageAndFail(
1805 if argIndex == 1 then Error.INVALID_ARGUMENT_TYPE_BRANCH_FIRST else
1806 Error.INVALID_ARGUMENT_TYPE_BRANCH_SECOND,
1807 {ComponentRef.toString(arg.cref), ComponentRef.toString(fnRef)}, info);
1808 end if;
1809 end if;
1810 then
1811 ();
1812
1813 else
1814 algorithm
1815 ✗ Error.addSourceMessage(Error.ARG_TYPE_MISMATCH,
1816 {String(argIndex), ComponentRef.toString(fnRef), "",
1817 Expression.toString(arg), Type.toString(ty), "overconstrained type/record"}, info);
1818 ✗ then
1819 fail();
1820 end match;
1821 end checkConnectionsArgument;
1822
1823 function typeNoEventCall
1824 input Call call;
1825 input InstContext.Type context;
1826 input SourceInfo info;
1827 output Expression callExp;
1828 output Type ty;
1829 output Variability variability;
1830 output Purity purity;
1831 protected
1832 ComponentRef fn_ref;
1833 list<Expression> args;
1834 list<NamedArg> named_args;
1835 Expression arg;
1836 Function fn;
1837 InstContext.Type arg_context;
1838 algorithm
1839
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 814 times.
814 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
1840 814 assertNoNamedParams("noEvent", named_args, info);
1841
1842 // noEvent takes exactly one argument.
1843
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 814 times.
814 if listLength(args) <> 1 then
1844 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
1845 {Call.toString(call), "noEvent(Any) => Any"}, info);
1846 end if;
1847
1848
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 814 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 814 times.
814 {arg} := args;
1849 // Set the NOEVENT context flag, but not the SUBEXPRESSION one that would normally be set
1850 // for call arguments. noEvent works as a transparent wrapper, and its argument shouldn't
1851 // be treated as being part of a function call (e.g. function calls returning multiple
1852 // values should still return multiple values when wrapped in noEvent).
1853 814 arg_context := InstContext.set(context, NFInstContext.NOEVENT);
1854 814 (arg, ty, variability, purity) := Typing.typeExp(arg, arg_context, info);
1855
1856
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 813 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 813 times.
813 {fn} := Function.typeRefCache(fn_ref);
1857 813 callExp := Expression.CALL(Call.makeTypedCall(fn, {arg}, variability, purity, ty));
1858 end typeNoEventCall;
1859
1860 function typeNthRootCall
1861 input Call call;
1862 input InstContext.Type context;
1863 input SourceInfo info;
1864 output Expression callExp;
1865 output Type ty;
1866 output Variability var;
1867 output Purity purity;
1868 protected
1869 Expression v, n;
1870 Call c;
1871 algorithm
1872 6 c := Call.typeMatchNormalCall(call, context, info);
1873
4/8
✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 6 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 6 times.
6 Call.TYPED_CALL(arguments = {v, n}, ty = ty, var = var, purity = purity) := c;
1874 6 callExp := Expression.CALL(c);
1875
1876
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 5 times.
6 if Expression.isNonPositive(n) then
1877 3 Error.addSourceMessage(Error.NON_POSITIVE_NTH_ROOT,
1878 {Expression.toString(v), Expression.toString(n)}, info);
1879 1 fail();
1880 end if;
1881
1882
3/4
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
5 if Expression.isEven(n) and Expression.isNegative(v) then
1883 ✗ Error.addSourceMessage(Error.NEGATIVE_NTH_ROOT,
1884 {Expression.toString(v), Expression.toString(n)}, info);
1885 ✗ fail();
1886 end if;
1887 end typeNthRootCall;
1888
1889 function typeGetInstanceName
1890 input Call call;
1891 input InstContext.Type context;
1892 input SourceInfo info;
1893 output Expression result;
1894 output Type ty = Type.STRING();
1895 output Variability var = Variability.CONSTANT;
1896 output Purity purity = Purity.PURE;
1897 protected
1898 NFInstNode.ScopeRef scope;
1899 algorithm
1900
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 Call.UNTYPED_CALL(call_scope = scope) := call;
1901 60 Call.typeMatchNormalCall(call, context, info);
1902 // getInstanceName is normally derived from the prefix during the flattening,
1903 // but sometimes the call is constant evaluated instead (e.g. when it's used
1904 // in a package). So we create an expression here that contains the scope.
1905 60 result := Expression.INSTANCE_NAME(InstNode.fromCell(scope));
1906 end typeGetInstanceName;
1907
1908 function typeClockCall
1909 input Call call;
1910 input InstContext.Type context;
1911 input SourceInfo info;
1912 output Expression callExp;
1913 output Type outType = Type.CLOCK();
1914 output Variability var = Variability.PARAMETER;
1915 output Purity purity = Purity.IMPURE;
1916 protected
1917 list<Expression> args;
1918 Integer args_count;
1919 Expression e1, e2;
1920 algorithm
1921
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 89 times.
89 Call.TYPED_CALL(arguments = args) := Call.typeMatchNormalCall(call, context, info, vectorize = false);
1922 89 args_count := listLength(args);
1923
1924 callExp := match args
1925 // Clock() - inferred clock.
1926 11 case {} then Expression.CLKCONST(Expression.ClockKind.INFERRED_CLOCK(System.tmpTickIndex(Global.inferredClock_index)));
1927 // Clock(interval) - real clock.
1928 20 case {e1} then Expression.CLKCONST(Expression.ClockKind.REAL_CLOCK(e1));
1929 case {e1, e2}
1930 algorithm
1931 58 e2 := Ceval.evalExp(e2);
1932
1933 callExp := match Expression.typeOf(e2)
1934 // Clock(intervalCounter, resolution) - rational clock.
1935 case Type.INTEGER()
1936 algorithm
1937 60 Error.assertionOrAddSourceMessage(Expression.integerValue(e2) >= 1,
1938 Error.WRONG_VALUE_OF_ARG, {"Clock", "resolution", Expression.toString(e2), "=> 1"}, info);
1939 30 then
1940 Expression.CLKCONST(ClockKind.RATIONAL_CLOCK(e1, e2));
1941
1942 // Clock(condition, startInterval) - event clock.
1943 case Type.REAL()
1944 14 then Expression.CLKCONST(ClockKind.EVENT_CLOCK(e1, e2));
1945
1946 // Clock(c, solverMethod) - solver clock.
1947 case Type.STRING()
1948 14 then Expression.CLKCONST(ClockKind.SOLVER_CLOCK(e1, e2));
1949 end match;
1950 then
1951 callExp;
1952
1953 end match;
1954 end typeClockCall;
1955
1956 function typeSampleCall
1957 input Call call;
1958 input InstContext.Type context;
1959 input SourceInfo info;
1960 output Expression callExp;
1961 output Type outType;
1962 output Variability var;
1963 output Purity purity = Purity.IMPURE;
1964 protected
1965 Call ty_call;
1966 list<TypedArg> args;
1967 list<TypedArg> namedArgs;
1968 Expression e1, e2;
1969 Type t1;
1970 Variability v1;
1971 ComponentRef fn_ref;
1972 Function normalSample, clockedSample;
1973 InstNode recopnode;
1974 algorithm
1975
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
144 Call.ARG_TYPED_CALL(fn_ref, args, namedArgs) := Call.typeNormalCall(call, context, info);
1976
1977 144 recopnode := ComponentRef.node(fn_ref);
1978
1979 144 fn_ref := Function.instFunctionRef(fn_ref, context, InstNode.info(recopnode));
1980
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 144 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 144 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 144 times.
144 {normalSample, clockedSample} := Function.typeRefCache(fn_ref);
1981
1982 (callExp, outType, var) := match(args, namedArgs)
1983
1984 // sample(start, Real interval) - the usual stuff
1985 case ({TypedArg.TYPED_ARG(value = e1, ty = t1),
1986 TypedArg.TYPED_ARG(value = e2, ty = Type.INTEGER())}, {})
1987 algorithm
1988
2/2
✓ Branch 1 taken 9 times.
✓ Branch 2 taken 2 times.
11 if Type.isInteger(t1) then
1989 9 e1 := Expression.CAST(Type.REAL(), e1);
1990 end if;
1991 22 ty_call := Call.makeTypedCall(normalSample,
1992 {e1, Expression.CAST(Type.REAL(), e2)}, Variability.PARAMETER, purity, Type.BOOLEAN());
1993 11 then
1994 (Expression.CALL(ty_call), Type.BOOLEAN(), Variability.PARAMETER);
1995
1996 // sample(start, Real interval) - the usual stuff
1997 case ({TypedArg.TYPED_ARG(value = e1, ty = t1),
1998 TypedArg.TYPED_ARG(value = e2, ty = Type.REAL())}, {})
1999 algorithm
2000
2/2
✓ Branch 1 taken 16 times.
✓ Branch 2 taken 88 times.
104 if Type.isInteger(t1) then
2001 16 e1 := Expression.CAST(Type.REAL(), e1);
2002 end if;
2003 104 ty_call := Call.makeTypedCall(normalSample, {e1, e2}, Variability.PARAMETER, purity, Type.BOOLEAN());
2004 104 then
2005 (Expression.CALL(ty_call), Type.BOOLEAN(), Variability.PARAMETER);
2006
2007 // sample(start, Real interval = value) - the usual stuff
2008 case ({TypedArg.TYPED_ARG(value = e1, ty = t1)},
2009 {TypedArg.TYPED_ARG(name = SOME("interval"), value = e2, ty = Type.REAL())})
2010 algorithm
2011 ✗ if Type.isInteger(t1) then
2012 ✗ e1 := Expression.CAST(Type.REAL(), e1);
2013 end if;
2014 ✗ ty_call := Call.makeTypedCall(normalSample, {e1, e2}, Variability.PARAMETER, purity, Type.BOOLEAN());
2015 ✗ then
2016 (Expression.CALL(ty_call), Type.BOOLEAN(), Variability.PARAMETER);
2017
2018 // sample(u) - inferred clock
2019 case ({TypedArg.TYPED_ARG(value = e1, ty = t1, var = v1)}, {})
2020 algorithm
2021 22 ty_call := Call.makeTypedCall(clockedSample,
2022 {e1, Expression.CLKCONST(Expression.ClockKind.INFERRED_CLOCK(System.tmpTickIndex(Global.inferredClock_index)))}, v1, purity, t1);
2023 11 then
2024 (Expression.CALL(ty_call), t1, v1);
2025
2026 // sample(u, c) - specified clock
2027 case ({TypedArg.TYPED_ARG(value = e1, ty = t1, var = v1),
2028 TypedArg.TYPED_ARG(value = e2, ty = Type.CLOCK())}, {})
2029 algorithm
2030 18 ty_call := Call.makeTypedCall(clockedSample, {e1, e2}, v1, purity, t1);
2031 18 then
2032 (Expression.CALL(ty_call), t1, v1);
2033
2034 // sample(u, Clock c = c) - specified clock
2035 case ({TypedArg.TYPED_ARG(value = e1, ty = t1, var = v1)},
2036 {TypedArg.TYPED_ARG(name = SOME("c"), value = e2, ty = Type.CLOCK())})
2037 algorithm
2038 ✗ ty_call := Call.makeTypedCall(clockedSample, {e1, e2}, v1, purity, t1);
2039 ✗ then
2040 (Expression.CALL(ty_call), t1, v1);
2041
2042 else
2043 algorithm
2044 ✗ Error.addSourceMessage(Error.WRONG_TYPE_OR_NO_OF_ARGS, {Call.toString(call), "<NO COMPONENT>"}, info);
2045 ✗ then
2046 fail();
2047 end match;
2048 end typeSampleCall;
2049
2050 function typeActualInStreamCall
2051 input String name;
2052 input Call call;
2053 input InstContext.Type context;
2054 input SourceInfo info;
2055 output Expression callExp;
2056 output Type ty;
2057 output Variability variability = Variability.DISCRETE;
2058 output Purity purity = Purity.IMPURE;
2059 protected
2060 ComponentRef fn_ref;
2061 list<Expression> args;
2062 list<NamedArg> named_args;
2063 Expression arg;
2064 Variability var;
2065 Function fn;
2066 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
2067 algorithm
2068
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 957 times.
957 Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
2069 957 assertNoNamedParams(name, named_args, info);
2070
2071
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 957 times.
957 if listLength(args) <> 1 then
2072 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
2073 {Call.toString(call), ComponentRef.toString(fn_ref) + "(stream variable) => Real"}, info);
2074 end if;
2075
2076 957 (arg, ty, var) := Typing.typeExp(listHead(args), arg_context, info);
2077 957 arg := ExpandExp.expand(arg);
2078
2079
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 957 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 957 times.
957 {fn} := Function.typeRefCache(fn_ref);
2080 957 callExp := typeActualInStreamCall2(name, fn, arg, var, info);
2081 end typeActualInStreamCall;
2082
2083 function typeActualInStreamCall2
2084 input String name;
2085 input Function fn;
2086 input Expression arg;
2087 input Variability var;
2088 input SourceInfo info;
2089 output Expression callExp;
2090 algorithm
2091 callExp := match arg
2092 local
2093 InstNode arg_node;
2094
2095 case Expression.CREF()
2096 algorithm
2097 624 arg_node := ComponentRef.node(arg.cref);
2098
2099 // The argument of actualStream/inStream must be a stream variable.
2100
3/4
✓ Branch 1 taken 624 times.
✗ Branch 2 not taken.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 623 times.
624 if not InstNode.isComponent(arg_node) or
2101 not ConnectorType.isStream(Component.connectorType(InstNode.component(arg_node))) then
2102 2 Error.addSourceMessageAndFail(Error.NON_STREAM_OPERAND_IN_STREAM_OPERATOR,
2103 {ComponentRef.toString(arg.cref), name}, info);
2104 end if;
2105
2106 // The argument of actualStream/inStream must have subscripts that can be evaluated.
2107
2/2
✓ Branch 1 taken 213 times.
✓ Branch 2 taken 622 times.
835 for sub in ComponentRef.subscriptsAllFlat(arg.cref) loop
2108
2/2
✓ Branch 1 taken 1 time.
✓ Branch 2 taken 212 times.
213 if Subscript.variability(sub) > Variability.PARAMETER then
2109 3 Error.addSourceMessageAndFail(Error.CONNECTOR_NON_PARAMETER_SUBSCRIPT,
2110 {ComponentRef.toString(arg.cref), Subscript.toString(sub)}, info);
2111 end if;
2112 end for;
2113 622 then
2114 Expression.CALL(Call.makeTypedCall(fn, {arg}, var, Purity.IMPURE, arg.ty));
2115
2116 case Expression.ARRAY()
2117 algorithm
2118 972 arg.elements := Array.map(arg.elements, function
2119 typeActualInStreamCall2(name = name, fn = fn, var = var, info = info));
2120 then
2121 arg;
2122
2123 else
2124 algorithm
2125 4 Error.addSourceMessage(Error.NON_STREAM_OPERAND_IN_STREAM_OPERATOR,
2126 {Expression.toString(arg), name}, info);
2127 2 then
2128 fail();
2129
2130 end match;
2131 end typeActualInStreamCall2;
2132
2133 function typeDynamicSelectCall
2134 input String name;
2135 input Call call;
2136 input InstContext.Type context;
2137 input SourceInfo info;
2138 output Expression callExp;
2139 output Type ty;
2140 output Variability variability = Variability.CONTINUOUS;
2141 output Purity purity = Purity.IMPURE;
2142 protected
2143 ComponentRef fn_ref;
2144 list<Expression> args;
2145 list<NamedArg> named_args;
2146 Expression arg1, arg2;
2147 Variability var1, var2;
2148 Function fn;
2149 Type ty1, ty2;
2150 Expression expStatic, expDynamic;
2151 InstContext.Type arg_context = InstContext.set(context, NFInstContext.SUBEXPRESSION);
2152 algorithm
2153 ✗ Call.UNTYPED_CALL(ref = fn_ref, arguments = args, named_args = named_args) := call;
2154 ✗ assertNoNamedParams(name, named_args, info);
2155
2156 ✗ if listLength(args) <> 2 then
2157 ✗ Error.addSourceMessageAndFail(Error.NO_MATCHING_FUNCTION_FOUND_NFINST,
2158 {Call.toString(call), ComponentRef.toString(fn_ref) + "(static expression, dynamic expression)"}, info);
2159 end if;
2160
2161 ✗ {expStatic, expDynamic} := list(Expression.unbox(arg) for arg in args);
2162 ✗ (arg1, ty1, var1) := Typing.typeExp(expStatic, arg_context, info);
2163 ✗ arg1 := ExpandExp.expand(arg1);
2164
2165 // if we cannot typecheck the dynamic part, ignore it!
2166 // https://trac.openmodelica.org/OpenModelica/ticket/5631
2167 try
2168 ✗ (arg2, ty2, var2) := Typing.typeExp(expDynamic, arg_context, info);
2169 else
2170 ✗ if InstContext.inInstanceAPI(context) then
2171 ✗ fail();
2172 else
2173 ✗ variability := var1;
2174 ✗ callExp := arg1;
2175 ✗ return;
2176 end if;
2177 end try;
2178
2179 ✗ arg2 := ExpandExp.expand(arg2);
2180 ✗ ty := ty1;
2181 ✗ variability := var2;
2182
2183 ✗ {fn} := Function.typeRefCache(fn_ref);
2184
2185 ✗ if Flags.isSet(Flags.NF_API_DYNAMIC_SELECT) then
2186 ✗ callExp := Expression.CALL(Call.makeTypedCall(fn, {arg1, arg2}, variability, purity, ty1));
2187 else
2188 ✗ variability := var1;
2189 ✗ callExp := arg1;
2190 end if;
2191 end typeDynamicSelectCall;
2192
2193 function typeBackSampleCall
2194 input Call call;
2195 input InstContext.Type context;
2196 input SourceInfo info;
2197 output Expression callExp;
2198 output Type ty;
2199 output Variability var;
2200 output Purity purity = Purity.IMPURE;
2201 protected
2202 Call ty_call;
2203 Expression counter, resolution;
2204 algorithm
2205
5/10
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
2 ty_call as Call.TYPED_CALL(arguments = {_, counter, resolution}, ty = ty, var = var) :=
2206 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2207 2 Structural.markExp(counter);
2208 2 Structural.markExp(resolution);
2209 2 callExp := Expression.CALL(ty_call);
2210 end typeBackSampleCall;
2211
2212 function typeShiftSampleCall
2213 input Call call;
2214 input InstContext.Type context;
2215 input SourceInfo info;
2216 output Expression callExp;
2217 output Type ty;
2218 output Variability var;
2219 output Purity purity = Purity.IMPURE;
2220 protected
2221 Call ty_call;
2222 Expression counter, resolution;
2223 algorithm
2224
5/10
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 2 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 2 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 2 times.
2 ty_call as Call.TYPED_CALL(arguments = {_, counter, resolution}, ty = ty, var = var) :=
2225 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2226 2 Structural.markExp(counter);
2227 2 Structural.markExp(resolution);
2228 2 callExp := Expression.CALL(ty_call);
2229 end typeShiftSampleCall;
2230
2231 function typeSubSampleCall
2232 input Call call;
2233 input InstContext.Type context;
2234 input SourceInfo info;
2235 output Expression callExp;
2236 output Type ty;
2237 output Variability var;
2238 output Purity purity = Purity.IMPURE;
2239 protected
2240 Call ty_call;
2241 Expression factor;
2242 algorithm
2243
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 18 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 18 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 18 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 18 times.
18 ty_call as Call.TYPED_CALL(arguments = {_, factor}, ty = ty, var = var) :=
2244 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2245 18 Structural.markExp(factor);
2246 18 callExp := Expression.CALL(ty_call);
2247 end typeSubSampleCall;
2248
2249 function typeSuperSampleCall
2250 input Call call;
2251 input InstContext.Type context;
2252 input SourceInfo info;
2253 output Expression callExp;
2254 output Type ty;
2255 output Variability var;
2256 output Purity purity = Purity.IMPURE;
2257 protected
2258 Call ty_call;
2259 Expression factor;
2260 algorithm
2261
4/8
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 12 times.
✗ Branch 10 not taken.
✓ Branch 11 taken 12 times.
12 ty_call as Call.TYPED_CALL(arguments = {_, factor}, ty = ty, var = var) :=
2262 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2263 12 Structural.markExp(factor);
2264 12 callExp := Expression.CALL(ty_call);
2265 end typeSuperSampleCall;
2266
2267 function typeSpatialDistribution
2268 input Call call;
2269 input InstContext.Type context;
2270 input SourceInfo info;
2271 output Expression callExp;
2272 output Type ty;
2273 output Variability var;
2274 output Purity purity;
2275 protected
2276 Call ty_call;
2277 String context_str;
2278 algorithm
2279
3/4
✓ Branch 1 taken 12 times.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
13 if InstContext.inSubexpression(context) or InstContext.inAlgorithm(context) then
2280 1 Error.addSourceMessage(Error.SPATIAL_DISTRIBUTION_CONTEXT, {}, info);
2281 1 fail();
2282 end if;
2283
2284
3/4
✓ Branch 1 taken 11 times.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 11 times.
12 if InstContext.inIf(context) or InstContext.inWhen(context) then
2285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 context_str := if InstContext.inIf(context) then "an if-equation" else "a when-equation";
2286 1 Error.addSourceMessage(Error.ELEMENT_IS_NOT_ALLOWED_IN_CONTEXT,
2287 {"spatialDistribution", context_str}, info);
2288 1 fail();
2289 end if;
2290
2291
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 11 times.
11 ty_call as Call.TYPED_CALL(ty = ty, var = var, purity = purity) :=
2292 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2293 11 callExp := Expression.CALL(ty_call);
2294 end typeSpatialDistribution;
2295
2296 function typePureCall
2297 input Call call;
2298 input InstContext.Type context;
2299 input SourceInfo info;
2300 output Expression callExp;
2301 output Type ty;
2302 output Variability var;
2303 output Purity purity = Purity.PURE;
2304 protected
2305 Expression arg;
2306 Call c;
2307 algorithm
2308
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 time.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 time.
1 Call.TYPED_CALL(arguments = {arg}, ty = ty, var = var) :=
2309 Call.typeMatchNormalCall(call, context, info, vectorize = false);
2310 1 callExp := Expression.unbox(arg);
2311
2312 callExp := match callExp
2313 case Expression.CALL(call = c as Call.TYPED_CALL())
2314 algorithm
2315 ✗ c.purity := Expression.purityList(c.arguments);
2316 ✗ then
2317 Expression.CALL(c);
2318
2319 else
2320 algorithm
2321 1 Error.addSourceMessage(Error.FUNCTION_ARGUMENT_MUST_BE,
2322 {"pure", Error.FUNCTION_CALL_EXPRESSION}, info);
2323 1 then
2324 fail();
2325 end match;
2326 end typePureCall;
2327
2328 function typeBuiltinCallExp
2329 input Call call;
2330 input InstContext.Type context;
2331 input SourceInfo info;
2332 input Boolean vectorize = true;
2333 output Expression outExp;
2334 output Type ty;
2335 output Variability var;
2336 output Purity pur;
2337 protected
2338 Call c;
2339 algorithm
2340 2354 (c, ty, var, pur) := typeBuiltinCall(call, context, info, vectorize);
2341 2354 outExp := Expression.CALL(c);
2342 end typeBuiltinCallExp;
2343
2344 function typeBuiltinCall
2345 input Call call;
2346 input InstContext.Type context;
2347 input SourceInfo info;
2348 input Boolean vectorize = true;
2349 output Call outCall;
2350 output Type ty;
2351 output Variability var;
2352 output Purity pur;
2353 algorithm
2354 2354 outCall := Call.typeMatchNormalCall(call, context, info, vectorize);
2355 2354 ty := Call.typeOf(outCall);
2356 2354 var := Call.variability(outCall);
2357 2354 pur := Call.purity(outCall);
2358 end typeBuiltinCall;
2359
2360 annotation(__OpenModelica_Interface="nf_frontend");
2361 end NFBuiltinCall;
2362