Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 53.2% 235 / 0 / 442
Functions: -% 0 / 1 / 1
Branches: 36.9% 101 / 0 / 274

OMCompiler/Compiler/FrontEnd/OperatorOverloading.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 OperatorOverloading
37
38 public
39 import Absyn;
40 import AbsynUtil;
41 import DAE;
42 import FCore;
43 import SCode;
44 import Util;
45
46 protected
47
48 import Ceval;
49 import ClassInf;
50 import Config;
51 import Debug;
52 import Dump;
53 import Error;
54 import Expression;
55 protected import ExpressionBasics;
56 import ExpressionDump;
57 import ExpressionSimplify;
58 import FGraph;
59 import Flags;
60 import Global;
61 import Inline;
62 import List;
63 import Lookup;
64 import PrefixUtil;
65 import AbsynToSCode;
66 import SCodeUtil;
67 import Static;
68 import Types;
69 import Values;
70
71 public
72
73 function binary
74 input FCore.Cache inCache;
75 input FCore.Graph inEnv;
76 input Absyn.Operator inOperator1;
77 input DAE.Properties inProp1;
78 input DAE.Exp inExp1;
79 input DAE.Properties inProp2;
80 input DAE.Exp inExp2;
81 input Absyn.Exp AbExp "needed for function replaceOperatorWithFcall (not really sure what is done in there though.)";
82 input Absyn.Exp AbExp1 "We need this when/if we elaborate user defined operator functions";
83 input Absyn.Exp AbExp2 "We need this when/if we elaborate user defined operator functions";
84 input Boolean inImpl;
85 input DAE.Prefix inPre "For error-messages only";
86 input SourceInfo inInfo "For error-messages only";
87 output FCore.Cache outCache;
88 output DAE.Exp outExp;
89 output DAE.Properties outProp;
90 algorithm
91 (outCache, outExp, outProp) :=
92 match (inCache,inEnv,inOperator1, inProp1, inExp1, inProp2, inExp2)
93 local
94 FCore.Cache cache;
95 FCore.Graph env;
96 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> opList;
97 DAE.Type type1,type2, otype;
98 DAE.Exp exp1,exp2,exp;
99 DAE.Const const1,const2, const;
100 DAE.Operator oper;
101 Absyn.Operator aboper;
102 DAE.Properties prop, props1, props2;
103 AvlTreePathFunction.Tree functionTree;
104 Boolean didInline;
105
106 // handle tuple op non_tuple
107 case (_, _, _, props1 as DAE.PROP_TUPLE(), _, DAE.PROP(), _) guard not Config.acceptMetaModelicaGrammar()
108 algorithm
109 ✗ prop as DAE.PROP(type1, _) := Types.propTupleFirstProp(props1);
110 ✗ exp := DAE.TSUB(inExp1, 1, type1);
111 ✗ (cache, exp, prop) := binary(inCache, inEnv, inOperator1, prop, exp, inProp2, inExp2, AbExp, AbExp1, AbExp2, inImpl, inPre, inInfo);
112 then (cache, exp, prop);
113
114 // handle non_tuple op tuple
115 case (_, _, _, DAE.PROP(), _, props2 as DAE.PROP_TUPLE(), _) guard not Config.acceptMetaModelicaGrammar()
116 algorithm
117 ✗ prop as DAE.PROP(type2, _) := Types.propTupleFirstProp(props2);
118 ✗ exp := DAE.TSUB(inExp2, 1, type2);
119 ✗ (cache, exp, prop) := binary(inCache, inEnv, inOperator1, inProp1, inExp1, prop, exp, AbExp, AbExp1, AbExp2, inImpl, inPre, inInfo);
120 then (cache, exp, prop);
121
122 case (cache, env, aboper, DAE.PROP(type1,const1), exp1, DAE.PROP(type2,const2), exp2)
123 algorithm
124
4/4
✓ Branch 2 taken 203355 times.
✓ Branch 3 taken 160 times.
✓ Branch 6 taken 1 time.
✓ Branch 7 taken 203354 times.
203515 if Types.isRecord(Types.arrayElementType(type1)) or Types.isRecord(Types.arrayElementType(type2)) then
125 // Overloaded records
126 161 (cache, exp, _, otype) := binaryUserdef(cache,env,aboper,inExp1,inExp2,type1,type2,inImpl,inPre,inInfo);
127 161 functionTree := FCore.getFunctionTree(cache);
128 161 exp := ExpressionSimplify.simplify1(exp);
129 161 (exp,_,didInline,_) := Inline.inlineExp(exp,(SOME(functionTree),{DAE.BUILTIN_EARLY_INLINE(),DAE.EARLY_INLINE()}),DAE.emptyElementSource);
130 161 exp := ExpressionSimplify.condsimplify(didInline,exp);
131 161 const := Types.constAnd(const1, const2);
132 161 prop := DAE.PROP(otype,const);
133 else // Normal operator deoverloading
134
4/4
✓ Branch 1 taken 12403 times.
✓ Branch 2 taken 190951 times.
✓ Branch 4 taken 12363 times.
✓ Branch 5 taken 40 times.
203354 if Types.isBoxedType(type1) and Types.isBoxedType(type2) then
135 // Do the MetaModelica type-casting here for simplicity
136 12363 (exp1, type1) := Types.matchType(exp1, type1, Types.unboxedType(type1), true);
137 12363 (exp2, type2) := Types.matchType(exp2, type2, Types.unboxedType(type2), true);
138 end if;
139 203354 (opList, type1, exp1, type2, exp2) := operatorsBinary(aboper, type1, exp1, type2, exp2);
140
3/6
✗ Branch 3 not taken.
✓ Branch 4 taken 203353 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 203353 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 203353 times.
406708 (oper, {exp1,exp2}, otype) := deoverload(opList, {(exp1,type1), (exp2,type2)}, AbExp, inPre, inInfo);
141 203353 const := Types.constAnd(const1, const2);
142 203353 exp := replaceOperatorWithFcall(AbExp, exp1,oper,SOME(exp2), const);
143 203353 exp := ExpressionSimplify.simplify(exp);
144 203353 prop := DAE.PROP(otype,const);
145 203353 warnUnsafeRelations(inEnv,AbExp,const, type1,type2,exp1,exp2,oper,inPre,inInfo);
146 end if;
147
1/2
✓ Branch 0 taken 203514 times.
✗ Branch 1 not taken.
203514 then (cache, exp, prop);
148
149 end match;
150 end binary;
151
152 function unary
153 "used to resolve unary operations.
154
155 also used to resolve user overloaded unary operators for operator records
156 It looks if there is an operator function defined for the specific
157 operation. If there is then it will call that function and returns the
158 resulting expression. "
159 input FCore.Cache inCache;
160 input FCore.Graph inEnv;
161 input Absyn.Operator inOperator1;
162 input DAE.Properties inProp1;
163 input DAE.Exp inExp1;
164 input Absyn.Exp AbExp "needed for function replaceOperatorWithFcall (not really sure what is done in there though.)";
165 input Absyn.Exp AbExp1 "We need this when/if we elaborate user defined operator functions";
166 input Boolean inImpl;
167 input DAE.Prefix inPre "For error-messages only";
168 input SourceInfo inInfo "For error-messages only";
169 output FCore.Cache outCache;
170 output DAE.Exp outExp;
171 output DAE.Properties outProp;
172 algorithm
173 (outCache, outExp, outProp) :=
174 matchcontinue(inCache, inEnv, inOperator1, inProp1, inExp1, AbExp1)
175 local
176 String str1;
177 FCore.Cache cache;
178 list<Absyn.Path> operNames;
179 Absyn.Path path;
180 FCore.Graph operatorEnv,recordEnv;
181 SCode.Element operatorCl;
182 list<DAE.Type> types;
183 FCore.Graph env;
184 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> opList;
185 DAE.Type type1, otype;
186 DAE.Exp exp1,exp;
187 DAE.Const const;
188 DAE.Operator oper;
189 Absyn.Operator aboper;
190 DAE.Properties prop;
191 Absyn.Exp absexp1;
192
193 // handle op tuple
194 case (_, _, _, DAE.PROP_TUPLE(), exp1, _)
195 algorithm
196 ✗ false := Config.acceptMetaModelicaGrammar();
197 ✗ prop as DAE.PROP(type1, _) := Types.propTupleFirstProp(inProp1);
198 ✗ exp := DAE.TSUB(exp1, 1, type1);
199 ✗ (cache, exp, prop) := unary(inCache, inEnv, inOperator1, prop, exp, AbExp, AbExp1, inImpl, inPre, inInfo);
200 then
201 (cache, exp, prop);
202
203 case (_, _, aboper, DAE.PROP(type1,const), exp1, _)
204 algorithm
205
2/2
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 97522 times.
97524 false := Types.isRecord(Types.arrayElementType(type1));
206 97522 opList := operatorsUnary(aboper);
207
2/4
✗ Branch 2 not taken.
✓ Branch 3 taken 97522 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 97522 times.
195044 (oper, {exp1}, otype) := deoverload(opList, {(exp1,type1)}, AbExp, inPre, inInfo);
208 97522 exp := replaceOperatorWithFcall(AbExp, exp1,oper,NONE(), const);
209 // (exp,_) = ExpressionSimplify.simplify(exp);
210 97522 prop := DAE.PROP(otype,const);
211 97522 then
212 (inCache,exp, prop);
213
214 // if we have a record check for overloaded operators
215 // TODO: Improve this the same way we improved binary operators!
216 case(cache, env, aboper, DAE.PROP(type1,_), _, absexp1)
217 algorithm
218
219 2 path := getRecordPath(type1);
220 2 path := AbsynUtil.makeFullyQualified(path);
221 2 (cache,_,recordEnv) := Lookup.lookupClass(cache,env,path);
222
223 2 str1 := "'" + Dump.opSymbolCompact(aboper) + "'";
224 2 path := AbsynUtil.joinPaths(path, Absyn.IDENT(str1));
225
226 2 (cache,operatorCl,operatorEnv) := Lookup.lookupClass(cache,recordEnv,path);
227
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 true := SCodeUtil.isOperator(operatorCl);
228
229 2 operNames := AbsynToSCode.getListofQualOperatorFuncsfromOperator(operatorCl);
230
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
2 (cache,types as _::_) := Lookup.lookupFunctionsListInEnv(cache, operatorEnv, operNames, inInfo, {});
231
232
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
2 (cache,SOME((exp,prop))) := Static.elabCallArgs3(cache,env,types,path,{absexp1},{},{},inImpl,inPre,inInfo);
233
234 2 then
235 (cache,exp,prop);
236
237 end matchcontinue;
238 end unary;
239
240 function string
241 "This functions checks if the builtin function string is overloaded for opertor records"
242 input FCore.Cache inCache;
243 input FCore.Graph inEnv;
244 input Absyn.Exp inExp1;
245 input Boolean inImpl;
246 input Boolean inDoVect;
247 input DAE.Prefix inPre;
248 input SourceInfo inInfo;
249 output FCore.Cache outCache;
250 output DAE.Exp outExp;
251 output DAE.Properties outProp;
252 algorithm
253 (outCache,outExp,outProp) :=
254 match (inCache, inEnv,inExp1)
255 local
256 String str1;
257 Absyn.Path path;
258 list<Absyn.Path> operNames;
259 FCore.Graph recordEnv,operatorEnv,env;
260 SCode.Element operatorCl;
261 FCore.Cache cache;
262 list<DAE.Type> types;
263 DAE.Properties prop;
264 DAE.Type type1;
265 Absyn.Exp exp1;
266 DAE.Exp daeExp;
267 list<Absyn.Exp> restargs;
268 list<Absyn.NamedArg> nargs;
269
270 case (cache,env,Absyn.CALL(function_ = Absyn.CREF_IDENT("String",_),functionArgs = Absyn.FUNCTIONARGS(args = exp1::restargs,argNames = nargs)))
271 algorithm
272
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1486 times.
1486 (cache,_,DAE.PROP(type1,_)) := Static.elabExp(cache,env,exp1,inImpl,inDoVect,inPre,inInfo);
273
274 1486 path := getRecordPath(type1);
275 1 path := AbsynUtil.makeFullyQualified(path);
276 1 (cache,_,recordEnv) := Lookup.lookupClass(cache,env,path);
277
278 str1 := "'String'";
279 1 path := AbsynUtil.joinPaths(path, Absyn.IDENT(str1));
280
281 1 (cache,operatorCl,operatorEnv) := Lookup.lookupClass(cache,recordEnv,path);
282
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 true := SCodeUtil.isOperator(operatorCl);
283
284 1 operNames := AbsynToSCode.getListofQualOperatorFuncsfromOperator(operatorCl);
285
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 (cache,types as _::_) := Lookup.lookupFunctionsListInEnv(cache, operatorEnv, operNames, inInfo, {});
286
287
3/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 6 not taken.
1 (cache,SOME((daeExp,prop))) := Static.elabCallArgs3(cache,env,types,path,exp1::restargs,nargs,{},inImpl,inPre,inInfo);
288 then
289 (cache,daeExp,prop);
290
291 end match;
292
293 end string;
294
295 function elabArglist
296 "Given a list of parameter types and an argument list, this
297 function tries to match the two, promoting the type of
298 arguments when necessary."
299 input list<DAE.Type> inTypes;
300 input list<tuple<DAE.Exp, DAE.Type>> inArgs;
301 output list<DAE.Exp> outArgs;
302 output list<DAE.Type> outTypes;
303 algorithm
304 (outArgs, outTypes) := match(inTypes, inArgs)
305 local
306 DAE.Exp arg_1,arg;
307 DAE.Type atype_1,pt,atype;
308 list<DAE.Exp> args_1;
309 list<DAE.Type> atypes_1,pts;
310 list<tuple<DAE.Exp, DAE.Type>> args;
311
312 // empty lists
313 case ({},{}) then ({},{});
314
315 // we have something
316 case ((pt :: pts),((arg,atype) :: args))
317 algorithm
318 885910 (arg_1,atype_1) := Types.matchType(arg, atype, pt, false);
319 513016 (args_1,atypes_1) := elabArglist(pts, args);
320 504241 then
321 ((arg_1 :: args_1),(atype_1 :: atypes_1));
322 end match;
323 end elabArglist;
324
325 function initCache
326 algorithm
327 4866 setGlobalRoot(Global.operatorOverloadingCache, (AvlTreePathPathEnv.Tree.EMPTY(),AvlTreePathOperatorTypes.Tree.EMPTY()));
328 end initCache;
329
330
331 protected
332
333 /* We have these as constants instead of function calls as done previously
334 * because it takes a long time to generate these types over and over again.
335 * The types are a bit hard to read, but they are simply 1 through 9-dimensional
336 * arrays of the basic types. */
337 constant list<DAE.Type> intarrtypes = {
338 DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}), // 1-dim
339 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 2-dim
340 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 3-dim
341 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 4-dim
342 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 5-dim
343 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 6-dim
344 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 7-dim
345 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 8-dim
346 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}) // 9-dim
347 };
348 constant list<DAE.Type> realarrtypes = {
349 DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}), // 1-dim
350 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 2-dim
351 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 3-dim
352 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 4-dim
353 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 5-dim
354 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 6-dim
355 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 7-dim
356 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 8-dim
357 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}) // 9-dim
358 };
359 constant list<DAE.Type> boolarrtypes = {
360 DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}), // 1-dim
361 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 2-dim
362 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 3-dim
363 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 4-dim
364 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 5-dim
365 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 6-dim
366 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 7-dim
367 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 8-dim
368 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_BOOL_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}) // 9-dim
369 };
370 constant list<DAE.Type> stringarrtypes = {
371 DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}), // 1-dim
372 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 2-dim
373 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 3-dim
374 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 4-dim
375 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 5-dim
376 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 6-dim
377 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 7-dim
378 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}), // 8-dim
379 DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_ARRAY(DAE.T_STRING_DEFAULT,{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}),{DAE.DIM_UNKNOWN()}) // 9-dim
380 };
381 /* Simply a list of 9 of that basic type; used to match with the array types */
382 constant list<DAE.Type> inttypes = {
383 DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT
384 };
385 constant list<DAE.Type> realtypes = {
386 DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT
387 };
388 constant list<DAE.Type> stringtypes = {
389 DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT
390 };
391
392 function deoverloadBinaryUserdefNoConstructor
393 input list<DAE.Type> inTypeList;
394 input DAE.Exp inLhs;
395 input DAE.Exp inRhs;
396 input DAE.Type lhsType;
397 input DAE.Type rhsType;
398 input list<tuple<DAE.Exp,Option<DAE.Type>>> inAcc;
399 output list<tuple<DAE.Exp,Option<DAE.Type>>> outExps;
400 algorithm
401 outExps := matchcontinue (inTypeList, inAcc)
402 local
403 list<DAE.Type> types;
404 DAE.Exp daeExp;
405 list<DAE.FuncArg> restArgs;
406 DAE.Type ty,ty1,ty2;
407 DAE.FunctionAttributes attr;
408 Absyn.Path path;
409 DAE.Exp lhs,rhs;
410 list<tuple<DAE.Exp,Option<DAE.Type>>> acc;
411 tuple<DAE.Exp,Option<DAE.Type>> tpl;
412
413 // Matching types. Yay.
414 case ((DAE.T_FUNCTION(path=path,funcResultType=ty,functionAttributes=attr,funcArg=DAE.FUNCARG(ty=ty1)::DAE.FUNCARG(ty=ty2)::restArgs))::types, acc)
415 algorithm
416 213 (lhs,_) := Types.matchType(inLhs,lhsType,ty1,false);
417 164 (rhs,_) := Types.matchType(inRhs,rhsType,ty2,false);
418 161 daeExp := makeCallFillRestDefaults(path,{lhs,rhs},restArgs,Types.makeCallAttr(ty,attr));
419 161 tpl := (daeExp,overloadFoldType(ty1,ty2,ty));
420 161 acc := deoverloadBinaryUserdefNoConstructor(types,inLhs,inRhs,lhsType,rhsType,tpl::acc);
421 then acc;
422
423 case (_::types, _)
424 algorithm
425 52 acc := deoverloadBinaryUserdefNoConstructor(types,inLhs,inRhs,lhsType,rhsType,inAcc);
426 then acc;
427
428 case ({}, _)
429 then inAcc;
430
431 end matchcontinue;
432 end deoverloadBinaryUserdefNoConstructor;
433
434 function overloadFoldType "It is only possible to fold this overloaded function if it has the same inputs and output"
435 input DAE.Type inType1;
436 input DAE.Type inType2;
437 input DAE.Type inType3;
438 output Option<DAE.Type> optType;
439 algorithm
440
3/4
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 159 times.
✓ Branch 5 taken 2 times.
161 optType := if Types.equivtypesOrRecordSubtypeOf(inType1,inType2) and Types.equivtypesOrRecordSubtypeOf(inType1,inType3)
441 then SOME(inType1) else NONE();
442 end overloadFoldType;
443
444 function deoverloadBinaryUserdefNoConstructorListLhs
445 input list<DAE.Type> types;
446 input list<DAE.Exp> inLhs;
447 input DAE.Exp inRhs;
448 input DAE.Type rhsType;
449 input list<tuple<DAE.Exp,Option<DAE.Type>>> inAcc;
450 output list<tuple<DAE.Exp,Option<DAE.Type>>> outExps;
451 algorithm
452 outExps := match (inLhs, inAcc)
453 local
454 DAE.Exp lhs;
455 list<tuple<DAE.Exp,Option<DAE.Type>>> acc;
456 list<DAE.Exp> rest;
457
458 // Matching types. Yay.
459 case (lhs::rest, acc)
460 algorithm
461 1 acc := deoverloadBinaryUserdefNoConstructor(types,lhs,inRhs,Expression.typeof(lhs),rhsType,acc);
462 1 acc := deoverloadBinaryUserdefNoConstructorListLhs(types,rest,inRhs,rhsType,acc);
463 then acc;
464
465 else inAcc;
466
467 end match;
468 end deoverloadBinaryUserdefNoConstructorListLhs;
469
470 function deoverloadBinaryUserdefNoConstructorListRhs
471 input list<DAE.Type> types;
472 input DAE.Exp inLhs;
473 input list<DAE.Exp> inRhs;
474 input DAE.Type lhsType;
475 input list<tuple<DAE.Exp,Option<DAE.Type>>> inAcc;
476 output list<tuple<DAE.Exp,Option<DAE.Type>>> outExps;
477 algorithm
478 outExps := match (inRhs, inAcc)
479 local
480 DAE.Exp rhs;
481 list<tuple<DAE.Exp,Option<DAE.Type>>> acc;
482 list<DAE.Exp> rest;
483
484 // Matching types. Yay.
485 case (rhs::rest, acc)
486 algorithm
487 3 acc := deoverloadBinaryUserdefNoConstructor(types,inLhs,rhs,lhsType,Expression.typeof(rhs),acc);
488 3 acc := deoverloadBinaryUserdefNoConstructorListRhs(types,inLhs,rest,lhsType,acc);
489 then acc;
490
491 else inAcc;
492
493 end match;
494 end deoverloadBinaryUserdefNoConstructorListRhs;
495
496 function deoverloadUnaryUserdefNoConstructor
497 input list<DAE.Type> inTypeList;
498 input DAE.Exp inExp;
499 input DAE.Type inType;
500 input list<DAE.Exp> inAcc;
501 output list<DAE.Exp> outExps;
502 algorithm
503 outExps := matchcontinue (inTypeList, inAcc)
504 local
505 list<DAE.Type> types;
506 DAE.Exp exp,daeExp;
507 list<DAE.FuncArg> restArgs;
508 DAE.Type ty,ty1;
509 DAE.FunctionAttributes attr;
510 Absyn.Path path;
511 list<DAE.Exp> acc;
512
513 // Matching types. Yay.
514 case (DAE.T_FUNCTION(path=path,funcResultType=ty,functionAttributes=attr,funcArg=DAE.FUNCARG(ty=ty1)::restArgs)::types, acc)
515 algorithm
516 8 (exp,_) := Types.matchType(inExp,inType,ty1,false);
517 4 daeExp := makeCallFillRestDefaults(path,{exp},restArgs,Types.makeCallAttr(ty,attr));
518 4 acc := deoverloadUnaryUserdefNoConstructor(types,inExp,ty,daeExp::acc);
519 then acc;
520
521 case (_::types, _)
522 algorithm
523 4 acc := deoverloadUnaryUserdefNoConstructor(types,inExp,inType,inAcc);
524 then acc;
525
526 case ({}, _)
527 then inAcc;
528
529 end matchcontinue;
530 end deoverloadUnaryUserdefNoConstructor;
531
532 function binaryUserdef
533 "used to resolve overloaded binary operators for operator records
534 It looks if there is an operator function defined for the specific
535 operation. If there is then it will call that function and returns the
536 resulting expression. "
537 input FCore.Cache inCache;
538 input FCore.Graph inEnv;
539 input Absyn.Operator inOper;
540 input DAE.Exp inExp1;
541 input DAE.Exp inExp2;
542 input DAE.Type inType1;
543 input DAE.Type inType2;
544 input Boolean impl;
545 input DAE.Prefix pre;
546 input SourceInfo info;
547 output FCore.Cache outCache;
548 output DAE.Exp outExp;
549 output Option<DAE.Type> foldType;
550 output DAE.Type outType;
551 algorithm
552 (outCache,outExp,foldType,outType) :=
553 match (inCache, inEnv, inOper,inExp1,inExp2,inType1,inType2)
554 local
555 Boolean bool1,bool2;
556 String opStr;
557 FCore.Graph env;
558 FCore.Cache cache;
559 list<DAE.Type> types,types1,types2;
560 DAE.Type type1, type2;
561 DAE.Exp exp1,exp2;
562 Absyn.Operator op;
563 DAE.Exp daeExp;
564 list<tuple<DAE.Exp,Option<DAE.Type>>> exps;
565
566 case (cache, env, op, exp1, exp2, type1, type2)
567 algorithm
568 // Step 1 already failed (pre-defined types)
569 // Apply operation according to the Specifications.See the function.
570 161 bool1 := Types.arrayType(type1);
571 161 bool2 := Types.arrayType(type2);
572
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
161 if bool1 and bool2 and AbsynUtil.opIsElementWise(op) then
573 types := {};
574 else
575 161 opStr := "'" + Dump.opSymbolCompact(op) + "'";
576 // print("Try overloading for " + opStr + " " + TypesDump.unparseType(inType1) + "," + TypesDump.unparseType(inType2) + "\n");
577 161 (cache,types1) := getOperatorFuncsOrEmpty(cache,env,{type1},opStr,info,{});
578 161 (cache,types2) := getOperatorFuncsOrEmpty(cache,env,{type2},opStr,info,{});
579 // Spec: [...] function f in the union of A.op and B.op [...]
580 161 types := List.union(types1,types2);
581 161 types := List.select1(types, isOperatorBinaryFunctionOrWarn, info);
582 end if;
583 // Step 2: Look for exactly 1 matching function
584 161 exps := deoverloadBinaryUserdefNoConstructor(types,exp1,exp2,type1,type2,{});
585 // Step 3: Look for constructors to call that would have made Step 2 work
586 161 (cache,exps) := binaryCastConstructor(cache,env,inExp1,inExp2,inType1,inType2,exps,types,info);
587 161 (cache,exps) := binaryUserdefArray(cache,env,exps,bool1 or bool2,inOper,inExp1,inExp2,inType1,inType2,impl,pre,info);
588
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 161 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 161 times.
161 {(daeExp,foldType)} := exps;
589 161 then
590 (cache,daeExp,foldType,Expression.typeof(daeExp) /*FIXME?*/);
591
592 end match;
593 end binaryUserdef;
594
595 function binaryUserdefArray
596 input FCore.Cache inCache;
597 input FCore.Graph env;
598 input list<tuple<DAE.Exp,Option<DAE.Type>>> inExps;
599 input Boolean isArray;
600 input Absyn.Operator inOper;
601 input DAE.Exp inExp1;
602 input DAE.Exp inExp2;
603 input DAE.Type inType1;
604 input DAE.Type inType2;
605 input Boolean impl;
606 input DAE.Prefix pre;
607 input SourceInfo info;
608 output FCore.Cache cache;
609 output list<tuple<DAE.Exp,Option<DAE.Type>>> exps;
610 algorithm
611 (cache,exps) := match (inExps, isArray)
612 local
613 Boolean isRelation,isVector1,isVector2,isScalar1,isScalar2,isMatrix1,isMatrix2;
614 // Already found a match
615 161 case ({_}, _) then (inCache,inExps);
616 // No match in Step 3; look for array expansions
617 case ({}, true)
618 algorithm
619 ✗ isRelation := listMember(inOper,{Absyn.LESS(),Absyn.LESSEQ(),Absyn.GREATER(),Absyn.GREATEREQ(),Absyn.EQUAL(),Absyn.NEQUAL()});
620 ✗ Error.assertionOrAddSourceMessage(not isRelation,Error.COMPILER_ERROR,{"Not supporting overloading of relation array operations"},info);
621 ✗ isScalar1 := not Types.arrayType(inType1);
622 ✗ isScalar2 := not Types.arrayType(inType2);
623 ✗ isVector1 := Types.isArray1D(inType1);
624 ✗ isVector2 := Types.isArray1D(inType2);
625 ✗ isMatrix1 := Types.isArray2D(inType1);
626 ✗ isMatrix2 := Types.isArray2D(inType2);
627 ✗ (cache,exps) := binaryUserdefArray2(inCache,env,isScalar1,isVector1,isMatrix1,isScalar2,isVector2,isMatrix2,
628 inOper,inExp1,inExp2,inType1,inType2,impl,pre,info);
629 then (cache,exps);
630 /*
631 case ({},_,_)
632 // Error-message? collect all functions we tried to match? use matchcontinue?
633 then fail();
634 */
635 else
636 algorithm
637 ✗ errorMultipleValid(List.map(inExps,Util.tuple21),info);
638 ✗ then fail();
639 end match;
640 end binaryUserdefArray;
641
642 function binaryUserdefArray2
643 input FCore.Cache inCache;
644 input FCore.Graph env;
645 input Boolean isScalar1;
646 input Boolean isVector1;
647 input Boolean isMatrix1;
648 input Boolean isScalar2;
649 input Boolean isVector2;
650 input Boolean isMatrix2;
651 input Absyn.Operator inOper;
652 input DAE.Exp inExp1;
653 input DAE.Exp inExp2;
654 input DAE.Type inType1;
655 input DAE.Type inType2;
656 input Boolean impl;
657 input DAE.Prefix pre;
658 input SourceInfo info;
659 output FCore.Cache cache;
660 output list<tuple<DAE.Exp,Option<DAE.Type>>> exps;
661 algorithm
662 (cache,exps) := match (inCache, isScalar1, isVector1, isMatrix1, isScalar2, isVector2, isMatrix2, inOper)
663 local
664 DAE.Exp mulExp,exp,cr,cr1,cr2,cr3,cr4,cr5,cr6,foldExp,transposed;
665 DAE.Type newType1,newType2,resType,newType1_1,newType2_1,ty;
666 DAE.Dimension dim1,dim2,dim1_1,dim1_2,dim2_1,dim2_2;
667 DAE.ReductionIterator iter,iter1,iter2,iter3,iter4;
668 String foldName,resultName,foldName1,resultName1,foldName2,resultName2,iterName,iterName1,iterName2,iterName3,iterName4;
669 Option<Values.Value> zeroConstructor;
670 list<DAE.Type> zeroTypes;
671 Absyn.Operator op;
672 case (cache, false, _, _, true, _, _, _) // non-scalar op scalar
673 algorithm
674 ✗ DAE.T_ARRAY(ty=newType1,dims=dim1::{}) := inType1;
675 // Not all operators are valid operations
676 ✗ op := Util.assoc(inOper, {
677 (Absyn.ADD_EW(),Absyn.ADD_EW()),
678 (Absyn.SUB_EW(),Absyn.SUB_EW()),
679 (Absyn.MUL(),Absyn.MUL_EW()),
680 (Absyn.MUL_EW(),Absyn.MUL_EW()),
681 (Absyn.DIV(),Absyn.DIV_EW()),
682 (Absyn.DIV_EW(),Absyn.DIV_EW()),
683 (Absyn.POW_EW(),Absyn.POW_EW())
684 });
685 ✗ iterName := Util.getTempVariableIndex();
686 ✗ foldName := Util.getTempVariableIndex();
687 ✗ resultName := Util.getTempVariableIndex();
688 ✗ cr := DAE.CREF(DAE.CREF_IDENT(iterName,newType1,{}),newType1);
689 ✗ (cache,exp,_,resType) := binaryUserdef(cache,env,op,cr,inExp2,newType1,inType2,impl,pre,info);
690 ✗ resType := Types.liftArray(resType,dim1);
691 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.COMBINE(),resType,NONE(),foldName,resultName,NONE()),exp,DAE.REDUCTIONITER(iterName,inExp1,NONE(),newType1)::{});
692 // exp = ExpressionSimplify.simplify1(exp);
693 ✗ then (cache,{(exp,NONE())});
694 case (cache, true, _, _, false, _, _, _) // scalar op non-scalar
695 algorithm
696 ✗ op := Util.assoc(inOper, {
697 (Absyn.ADD_EW(),Absyn.ADD_EW()),
698 (Absyn.SUB_EW(),Absyn.SUB_EW()),
699 (Absyn.MUL(),Absyn.MUL_EW()),
700 (Absyn.MUL_EW(),Absyn.MUL_EW()),
701 (Absyn.DIV_EW(),Absyn.DIV_EW()),
702 (Absyn.POW_EW(),Absyn.POW_EW())
703 });
704 ✗ DAE.T_ARRAY(ty=newType2,dims=dim2::_) := inType2;
705 ✗ iterName := Util.getTempVariableIndex();
706 ✗ foldName := Util.getTempVariableIndex();
707 ✗ resultName := Util.getTempVariableIndex();
708 ✗ cr := DAE.CREF(DAE.CREF_IDENT(iterName,newType2,{}),newType2);
709 ✗ (cache,exp,_,resType) := binaryUserdef(cache,env,op,inExp1,cr,inType1,newType2,impl,pre,info);
710 ✗ resType := DAE.T_ARRAY(resType,{dim2});
711 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.COMBINE(),resType,NONE(),foldName,resultName,NONE()),exp,DAE.REDUCTIONITER(iterName,inExp2,NONE(),newType2)::{});
712 // exp = ExpressionSimplify.simplify1(exp);
713 ✗ then (cache,{(exp,NONE())});
714 // '*' invalid operations: vector*vector or vector*matrix
715 ✗ case (_, _, true, _, _, true, _, Absyn.MUL()) then fail();
716 ✗ case (_, _, true, _, _, _, true, Absyn.MUL()) then fail();
717 // matrix-vector-multiply
718 case (cache, _, _, true, _, true, _, Absyn.MUL())
719 algorithm
720 ✗ DAE.T_ARRAY(ty=newType1_1,dims=dim1_1::{}) := inType1;
721 ✗ DAE.T_ARRAY(ty=newType1,dims=dim1_2::{}) := newType1_1;
722 ✗ DAE.T_ARRAY(ty=newType2,dims=dim2::{}) := inType2;
723 ✗ true := Expression.dimensionsEqual(dim1_2,dim2);
724 // true = Types.equivtypes(newType1,newType2); // Else we cannot sum() the expressions - we need to be able to fold them...
725 // print("Got mvm (3)\n");
726 // array(sum(a*rhs[b] for a in lhs[:,b]) for b in size(rhs,1))
727 // array(sum(a*b for a in c) for c in lhs, b in rhs)
728
729 ✗ foldName1 := Util.getTempVariableIndex();
730 ✗ resultName1 := Util.getTempVariableIndex();
731 ✗ foldName2 := Util.getTempVariableIndex();
732 ✗ resultName2 := Util.getTempVariableIndex();
733 ✗ iterName := Util.getTempVariableIndex();
734 ✗ iterName1 := Util.getTempVariableIndex();
735 ✗ iterName2 := Util.getTempVariableIndex();
736 ✗ cr := DAE.CREF(DAE.CREF_IDENT(iterName,newType1_1,{}),newType1);
737 ✗ cr1 := DAE.CREF(DAE.CREF_IDENT(iterName1,newType1,{}),newType1);
738 ✗ cr2 := DAE.CREF(DAE.CREF_IDENT(iterName2,newType2,{}),newType2);
739 ✗ cr3 := DAE.CREF(DAE.CREF_IDENT(foldName1,newType1,{}),newType1);
740 ✗ cr4 := DAE.CREF(DAE.CREF_IDENT(resultName1,newType2,{}),newType2);
741 // TODO: SUM?
742 ✗ (cache,exp,SOME(ty),resType) := binaryUserdef(cache,env,Absyn.ADD(),cr1,cr2,newType1,newType2,impl,pre,info);
743 ✗ (cache,foldExp,_,_) := binaryUserdef(cache,env,Absyn.ADD(),cr3,cr4,ty,ty,impl,pre,info);
744 // TODO: Check that the expression can be folded? Pass it as input to the function, or pass the chosen function as output, or pass the chosen lhs,rhs types as outputs!
745 ✗ (cache,zeroTypes) := getOperatorFuncsOrEmpty(cache,env,{ty},"'0'",info,{});
746 ✗ (cache,zeroConstructor) := getZeroConstructor(cache,env,List.filterMap(zeroTypes,getZeroConstructorExpression),impl,info);
747
748 ✗ resType := DAE.T_ARRAY(resType,{dim1_1});
749 ✗ iter := DAE.REDUCTIONITER(iterName1,cr,NONE(),newType1);
750 ✗ iter1 := DAE.REDUCTIONITER(iterName,inExp1,NONE(),newType1);
751 ✗ iter2 := DAE.REDUCTIONITER(iterName2,inExp2,NONE(),newType2);
752 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("sum"),Absyn.THREAD(),resType,zeroConstructor,foldName1,resultName1,SOME(foldExp)),exp,iter::iter2::{});
753 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.COMBINE(),resType,NONE(),foldName2,resultName2,NONE()),exp,iter1::{});
754 ✗ then (cache,{(exp,NONE())});
755 // matrix-matrix-multiply
756 case (cache, _, _, true, _, _, true, Absyn.MUL())
757 algorithm
758 ✗ DAE.T_ARRAY(ty=newType1_1,dims=dim1_1::{}) := inType1;
759 ✗ DAE.T_ARRAY(ty=newType1,dims=dim1_2::{}) := newType1_1;
760 ✗ DAE.T_ARRAY(ty=newType2_1,dims=dim2_1::{}) := inType2;
761 ✗ DAE.T_ARRAY(ty=newType2,dims=dim2_2::{}) := newType2_1;
762 ✗ true := Expression.dimensionsEqual(dim1_2,dim2_1);
763 ✗ transposed := Expression.makePureBuiltinCall("transpose",{inExp2},Types.liftArray(Types.liftArray(newType2,dim2_1),dim2_2));
764 ✗ iterName1 := Util.getTempVariableIndex();
765 ✗ iterName2 := Util.getTempVariableIndex();
766 ✗ iterName3 := Util.getTempVariableIndex();
767 ✗ iterName4 := Util.getTempVariableIndex();
768 ✗ foldName1 := Util.getTempVariableIndex();
769 ✗ resultName1 := Util.getTempVariableIndex();
770 ✗ foldName2 := Util.getTempVariableIndex();
771 ✗ resultName2 := Util.getTempVariableIndex();
772 ✗ foldName := Util.getTempVariableIndex();
773 ✗ resultName := Util.getTempVariableIndex();
774 ✗ cr1 := DAE.CREF(DAE.CREF_IDENT(iterName1,newType1_1,{}),newType1_1);
775 ✗ cr2 := DAE.CREF(DAE.CREF_IDENT(iterName2,newType2_1,{}),newType2_1);
776 ✗ cr3 := DAE.CREF(DAE.CREF_IDENT(iterName3,newType1,{}),newType1);
777 ✗ cr4 := DAE.CREF(DAE.CREF_IDENT(iterName4,newType2,{}),newType2);
778
779 ✗ (cache,mulExp,_,ty) := binaryUserdef(cache,env,Absyn.MUL(),cr3,cr4,newType1,newType2,impl,pre,info);
780 ✗ cr5 := DAE.CREF(DAE.CREF_IDENT(foldName,ty,{}),ty);
781 ✗ cr6 := DAE.CREF(DAE.CREF_IDENT(resultName,ty,{}),ty);
782 ✗ (cache,foldExp,SOME(ty),_) := binaryUserdef(cache,env,Absyn.ADD(),cr5,cr6,ty,ty,impl,pre,info);
783 ✗ (cache,zeroTypes) := getOperatorFuncsOrEmpty(cache,env,{ty},"'0'",info,{});
784 ✗ (cache,zeroConstructor) := getZeroConstructor(cache,env,List.filterMap(zeroTypes,getZeroConstructorExpression),impl,info);
785
786 ✗ iter1 := DAE.REDUCTIONITER(iterName1,inExp1,NONE(),newType1_1);
787 ✗ iter2 := DAE.REDUCTIONITER(iterName2,transposed,NONE(),newType2_1);
788 ✗ iter3 := DAE.REDUCTIONITER(iterName3,cr1,NONE(),newType1_1);
789 ✗ iter4 := DAE.REDUCTIONITER(iterName4,cr2,NONE(),newType2_1);
790
791 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("sum"),Absyn.THREAD(),ty,zeroConstructor,foldName,resultName,SOME(foldExp)),mulExp,iter3::iter4::{});
792 ✗ ty := Types.liftArray(ty,dim2_2);
793 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.COMBINE(),ty,NONE(),foldName2,resultName2,NONE()),exp,iter2::{});
794 ✗ ty := Types.liftArray(ty,dim1_1);
795 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.COMBINE(),ty,NONE(),foldName1,resultName1,NONE()),exp,iter1::{});
796 ✗ then (cache,{(exp,NONE())});
797 // The rest are array op array, which are element-wise operations
798 // We thus change the operator to the element-wise one to avoid other vector operations than this one
799 case (cache, false, _, _, false, _, _, _) // array op array, 1-D through n-D
800 algorithm
801 ✗ op := Util.assoc(inOper, {
802 (Absyn.ADD(),Absyn.ADD_EW()),
803 (Absyn.ADD_EW(),Absyn.ADD_EW()),
804 (Absyn.SUB(),Absyn.SUB_EW()),
805 (Absyn.SUB_EW(),Absyn.SUB_EW()),
806 (Absyn.MUL_EW(),Absyn.MUL_EW()),
807 (Absyn.DIV_EW(),Absyn.DIV_EW()),
808 (Absyn.POW_EW(),Absyn.POW_EW()),
809 (Absyn.AND(),Absyn.AND()),
810 (Absyn.OR(),Absyn.OR())
811 });
812 ✗ DAE.T_ARRAY(ty=newType1,dims=dim1::{}) := inType1;
813 ✗ DAE.T_ARRAY(ty=newType2,dims=dim2::{}) := inType2;
814 ✗ true := Expression.dimensionsEqual(dim1,dim2);
815 ✗ foldName := Util.getTempVariableIndex();
816 ✗ resultName := Util.getTempVariableIndex();
817 ✗ iterName1 := Util.getTempVariableIndex();
818 ✗ iterName2 := Util.getTempVariableIndex();
819 ✗ cr1 := DAE.CREF(DAE.CREF_IDENT(iterName1,newType1,{}),newType1);
820 ✗ cr2 := DAE.CREF(DAE.CREF_IDENT(iterName2,newType2,{}),newType2);
821 ✗ (cache,exp,_,resType) := binaryUserdef(cache,env,op,cr1,cr2,newType1,newType2,impl,pre,info);
822 ✗ resType := DAE.T_ARRAY(resType,{dim2});
823 ✗ iter1 := DAE.REDUCTIONITER(iterName1,inExp1,NONE(),newType1);
824 ✗ iter2 := DAE.REDUCTIONITER(iterName2,inExp2,NONE(),newType2);
825 ✗ exp := DAE.REDUCTION(DAE.REDUCTIONINFO(Absyn.IDENT("array"),Absyn.THREAD(),resType,NONE(),foldName,resultName,NONE()),exp,iter1::iter2::{});
826 ✗ then (cache,{(exp,NONE())});
827 end match;
828 end binaryUserdefArray2;
829
830 function operatorsBinary "This function relates the operators in the abstract syntax to the
831 de-overloaded operators in the SCode. It produces a list of available
832 types for a specific operator, that the overload function chooses from.
833 Therefore, in order for the builtin type conversion from Integer to
834 Real to work, operators that work on both Integers and Reals must
835 return the Integer type -before- the Real type in the list."
836 input Absyn.Operator inOperator;
837 output list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> ops;
838 input output DAE.Type t1;
839 input output DAE.Exp e1;
840 input output DAE.Type t2;
841 input output DAE.Exp e2;
842 output DAE.Type oty1 = t1;
843 output DAE.Exp oe1 = e1;
844 output DAE.Type oty2 = t2;
845 output DAE.Exp oe2 = e2;
846 protected
847 constant DAE.Operator
848 int_mul = DAE.MUL(DAE.T_INTEGER_DEFAULT),
849 real_mul = DAE.MUL(DAE.T_REAL_DEFAULT),
850 real_div = DAE.DIV(DAE.T_REAL_DEFAULT),
851 real_pow = DAE.POW(DAE.T_REAL_DEFAULT),
852 int_mul_sp = DAE.MUL_SCALAR_PRODUCT(DAE.T_INTEGER_DEFAULT),
853 real_mul_sp = DAE.MUL_SCALAR_PRODUCT(DAE.T_REAL_DEFAULT),
854 int_mul_mp = DAE.MUL_MATRIX_PRODUCT(DAE.T_INTEGER_DEFAULT),
855 real_mul_mp = DAE.MUL_MATRIX_PRODUCT(DAE.T_REAL_DEFAULT);
856 constant DAE.Type
857 int_vector = DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT,{DAE.DIM_UNKNOWN()}),
858 int_matrix = DAE.T_ARRAY(int_vector,{DAE.DIM_UNKNOWN()}),
859 real_vector = DAE.T_ARRAY(DAE.T_REAL_DEFAULT,{DAE.DIM_UNKNOWN()}),
860 real_matrix = DAE.T_ARRAY(real_vector,{DAE.DIM_UNKNOWN()});
861 constant list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>>
862 // ADD
863 addIntArrays = list((DAE.ADD_ARR(int_vector), {at,at},at) for at in intarrtypes),
864 addRealArrays = list((DAE.ADD_ARR(real_vector), {at,at},at) for at in realarrtypes),
865 addStringArrays = list((DAE.ADD_ARR(DAE.T_ARRAY(DAE.T_STRING_DEFAULT, {DAE.DIM_UNKNOWN()})), {at,at},at) for at in stringarrtypes),
866 addScalars = {
867 (DAE.ADD(DAE.T_INTEGER_DEFAULT), {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_INTEGER_DEFAULT),
868 (DAE.ADD(DAE.T_REAL_DEFAULT), {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT),
869 (DAE.ADD(DAE.T_STRING_DEFAULT), {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_STRING_DEFAULT)
870 },
871 addTypes = listAppend(addScalars, listAppend(addIntArrays, listAppend(addRealArrays, addStringArrays))),
872 // ADD_EW
873 addIntArrayScalars = list((DAE.ADD_ARRAY_SCALAR(int_vector), {at,rhs},at) threaded for at in intarrtypes, rhs in inttypes),
874 addRealArrayScalars = list((DAE.ADD_ARRAY_SCALAR(real_vector), {at,rhs},at) threaded for at in realarrtypes, rhs in realtypes),
875 // TODO: This will give the wrong result since String concatenation isn't
876 // commutative, an ADD_SCALAR_ARRAY would need to be added to fix it.
877 //addStringArrayScalars = list((DAE.ADD_ARRAY_SCALAR(DAE.T_ARRAY(DAE.T_STRING_DEFAULT, {DAE.DIM_UNKNOWN()})), {at,rhs},at) threaded for at in stringarrtypes, rhs in stringtypes),
878 addStringArrayScalars = {},
879 addEwTypes = listAppend(addIntArrayScalars, listAppend(addRealArrayScalars, listAppend(addStringArrayScalars, addTypes))),
880 // SUB
881 subIntArrays = list((DAE.SUB_ARR(int_vector), {at,at},at) for at in intarrtypes),
882 subRealArrays = list((DAE.SUB_ARR(real_vector), {at,at},at) for at in realarrtypes),
883 subScalars = {
884 (DAE.SUB(DAE.T_INTEGER_DEFAULT),{DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_INTEGER_DEFAULT),
885 (DAE.SUB(DAE.T_REAL_DEFAULT),{DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT)
886 },
887 subTypes = listAppend(subScalars, listAppend(subIntArrays, subRealArrays)),
888 // SUB_EW
889 subIntArrayScalars = list((DAE.SUB_SCALAR_ARRAY(int_vector), {lhs,at},at) threaded for at in intarrtypes, lhs in inttypes),
890 subRealArrayScalars = list((DAE.SUB_SCALAR_ARRAY(real_vector), {lhs,at},at) threaded for at in realarrtypes, lhs in realtypes),
891 subEwTypes = listAppend(subScalars, listAppend(subIntArrayScalars, listAppend(subRealArrayScalars, listAppend(subIntArrays, subRealArrays)))),
892 // MUL
893 mulScalars = {
894 (int_mul,{DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_INTEGER_DEFAULT),
895 (real_mul,{DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT)
896 },
897 mulScalarProduct = {
898 (int_mul_sp,{int_vector,int_vector},DAE.T_INTEGER_DEFAULT),
899 (real_mul_sp,{real_vector,real_vector},DAE.T_REAL_DEFAULT)
900 },
901 mulMatrixProduct = {
902 (int_mul_mp,{int_vector,int_matrix},int_vector),
903 (int_mul_mp,{int_matrix,int_vector},int_vector),
904 (int_mul_mp,{int_matrix,int_matrix},int_matrix),
905 (real_mul_mp,{real_vector,real_matrix},real_vector),
906 (real_mul_mp,{real_matrix,real_vector},real_vector),
907 (real_mul_mp,{real_matrix,real_matrix},real_matrix)
908 },
909 mulIntArrayScalars = list((DAE.MUL_ARRAY_SCALAR(int_vector), {at,rhs},at) threaded for at in intarrtypes, rhs in inttypes),
910 mulRealArrayScalars = list((DAE.MUL_ARRAY_SCALAR(real_vector), {at,rhs},at) threaded for at in realarrtypes, rhs in realtypes),
911 mulTypes = listAppend(mulScalars, listAppend(mulIntArrayScalars, listAppend(mulRealArrayScalars, listAppend(mulScalarProduct,mulMatrixProduct)))),
912 // MUL_EW
913 mulIntArray = list((DAE.MUL_ARR(int_vector), {at,at},at) for at in intarrtypes),
914 mulRealArray = list((DAE.MUL_ARR(real_vector), {at,at},at) for at in realarrtypes),
915 mulEwTypes = listAppend(mulScalars, listAppend(mulIntArrayScalars, listAppend(mulRealArrayScalars, listAppend(mulIntArray, mulRealArray)))),
916 // DIV
917 divTypes = (real_div,{DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT) ::
918 list((DAE.DIV_ARRAY_SCALAR(real_vector), {at,rhs},at) threaded for at in realarrtypes, rhs in realtypes),
919 // DIV_EW
920 divRealScalarArray = list((DAE.DIV_SCALAR_ARRAY(real_vector), {lhs,at},at) threaded for at in realarrtypes, lhs in realtypes),
921 divArrs = list((DAE.DIV_ARR(real_vector), {at,at},at) for at in realarrtypes),
922 divEwTypes = listAppend(divTypes, listAppend(divRealScalarArray, divArrs)),
923 // POW
924 powTypes = {
925 (real_pow,{DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT),
926 (DAE.POW_ARR(DAE.T_REAL_DEFAULT),{real_matrix,DAE.T_INTEGER_DEFAULT},real_matrix)
927 },
928 // AND
929 andTypes = (DAE.AND(DAE.T_BOOL_DEFAULT), {DAE.T_BOOL_DEFAULT, DAE.T_BOOL_DEFAULT}, DAE.T_BOOL_DEFAULT) ::
930 list((DAE.AND(DAE.T_BOOL_DEFAULT), {at,at},at) threaded for at in boolarrtypes),
931 // OR
932 orTypes = (DAE.OR(DAE.T_BOOL_DEFAULT), {DAE.T_BOOL_DEFAULT, DAE.T_BOOL_DEFAULT}, DAE.T_BOOL_DEFAULT) ::
933 list((DAE.OR(DAE.T_BOOL_DEFAULT), {at,at},at) threaded for at in boolarrtypes);
934 Absyn.Operator op=inOperator;
935 Boolean ia1=Types.isArray(t1), ia2=Types.isArray(t2);
936 algorithm
937
2/2
✓ Branch 0 taken 939 times.
✓ Branch 1 taken 202415 times.
203354 if ia2 and (not ia1) then
938 (e1,e2,t1,t2) := match op
939 // element-wise equivalent operators
940 case Absyn.ADD_EW() then (e2,e1,t2,t1);
941 case Absyn.MUL() then (e2,e1,t2,t1);
942 case Absyn.MUL_EW() then (e2,e1,t2,t1);
943 // Does not need EW-equiv operators
944 else (e1,e2,t1,t2);
945 end match;
946 elseif ia1 and (not ia2) then
947 (op,e2) := match op
948 // element-wise equivalent operators
949 2 case Absyn.SUB_EW() then (Absyn.ADD_EW(),Expression.negate(e2));
950 // Does not need EW-equiv operators
951 else (op,e2);
952 end match;
953 end if;
954 try
955 ops := match op
956 local
957 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> realarrs,scalars,types,realscalararrs,realarrsscalar;
958 tuple<DAE.Operator, list<DAE.Type>, DAE.Type> enum_op;
959
960 case Absyn.ADD() then addTypes;
961 case Absyn.ADD_EW() then addEwTypes;
962 case Absyn.SUB() then subTypes;
963 case Absyn.SUB_EW() then subEwTypes;
964 case Absyn.MUL() then mulTypes;
965 case Absyn.MUL_EW() then mulEwTypes;
966 case Absyn.DIV() then divTypes;
967 case Absyn.DIV_EW() then divEwTypes;
968 case Absyn.POW() then powTypes;
969
970 case Absyn.POW_EW()
971 algorithm
972
9/10
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
152 realarrs := operatorReturn(DAE.POW_ARR2(DAE.T_ARRAY(DAE.T_REAL_DEFAULT, {DAE.DIM_UNKNOWN()})),
973 realarrtypes, realarrtypes, realarrtypes);
974 scalars := {
975 (DAE.POW(DAE.T_REAL_DEFAULT),
976 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_REAL_DEFAULT)};
977
9/10
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
152 realscalararrs := operatorReturn(DAE.POW_SCALAR_ARRAY(DAE.T_ARRAY(DAE.T_REAL_DEFAULT, {DAE.DIM_UNKNOWN()})),
978 realtypes, realarrtypes, realarrtypes);
979
9/10
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 72 times.
✓ Branch 5 taken 8 times.
✓ Branch 6 taken 72 times.
✓ Branch 7 taken 8 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 8 times.
152 realarrsscalar := operatorReturn(DAE.POW_ARRAY_SCALAR(DAE.T_ARRAY(DAE.T_REAL_DEFAULT, {DAE.DIM_UNKNOWN()})),
980 realarrtypes, realtypes, realarrtypes);
981 8 types := List.flatten({scalars,realscalararrs,
982 realarrsscalar,realarrs});
983 then types;
984
985 case Absyn.AND() then andTypes;
986 case Absyn.OR() then orTypes;
987
988 // Relational operators
989 case Absyn.LESS()
990 algorithm
991 1288 enum_op := makeEnumOperator(DAE.LESS(DAE.T_ENUMERATION_DEFAULT), t1, t2);
992 scalars := {
993 (DAE.LESS(DAE.T_INTEGER_DEFAULT),
994 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT),
995 enum_op,
996 (DAE.LESS(DAE.T_REAL_DEFAULT),
997 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT),
998 (DAE.LESS(DAE.T_BOOL_DEFAULT),
999 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT),
1000 (DAE.LESS(DAE.T_STRING_DEFAULT),
1001 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)};
1002 1288 types := List.flatten({scalars});
1003 then types;
1004
1005 case Absyn.LESSEQ()
1006 algorithm
1007 917 enum_op := makeEnumOperator(DAE.LESSEQ(DAE.T_ENUMERATION_DEFAULT), t1, t2);
1008 scalars := {
1009 (DAE.LESSEQ(DAE.T_INTEGER_DEFAULT),
1010 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT),
1011 enum_op,
1012 (DAE.LESSEQ(DAE.T_REAL_DEFAULT),
1013 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT),
1014 (DAE.LESSEQ(DAE.T_BOOL_DEFAULT),
1015 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT),
1016 (DAE.LESSEQ(DAE.T_STRING_DEFAULT),
1017 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)};
1018 917 types := List.flatten({scalars});
1019 then types;
1020
1021 case Absyn.GREATER()
1022 algorithm
1023 3050 enum_op := makeEnumOperator(DAE.GREATER(DAE.T_ENUMERATION_DEFAULT), t1, t2);
1024 scalars := {
1025 (DAE.GREATER(DAE.T_INTEGER_DEFAULT),
1026 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT),
1027 enum_op,
1028 (DAE.GREATER(DAE.T_REAL_DEFAULT),
1029 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT),
1030 (DAE.GREATER(DAE.T_BOOL_DEFAULT),
1031 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT),
1032 (DAE.GREATER(DAE.T_STRING_DEFAULT),
1033 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)};
1034 3050 types := List.flatten({scalars});
1035 then types;
1036
1037 case Absyn.GREATEREQ()
1038 algorithm
1039 871 enum_op := makeEnumOperator(DAE.GREATEREQ(DAE.T_ENUMERATION_DEFAULT), t1, t2);
1040 scalars := {
1041 (DAE.GREATEREQ(DAE.T_INTEGER_DEFAULT),
1042 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT),
1043 enum_op,
1044 (DAE.GREATEREQ(DAE.T_REAL_DEFAULT),
1045 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT),
1046 (DAE.GREATEREQ(DAE.T_BOOL_DEFAULT),
1047 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT),
1048 (DAE.GREATEREQ(DAE.T_STRING_DEFAULT),
1049 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)};
1050 871 types := List.flatten({scalars});
1051 then types;
1052
1053 case Absyn.EQUAL()
1054 algorithm
1055 5364 enum_op := makeEnumOperator(DAE.EQUAL(DAE.T_ENUMERATION_DEFAULT), t1, t2);
1056 types :=
1057 (DAE.EQUAL(DAE.T_INTEGER_DEFAULT),
1058 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT)::
1059 enum_op::
1060 (DAE.EQUAL(DAE.T_REAL_DEFAULT),
1061 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT)::
1062 (DAE.EQUAL(DAE.T_STRING_DEFAULT),
1063 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)::
1064 (DAE.EQUAL(DAE.T_BOOL_DEFAULT),
1065 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT)::
1066 {};
1067 then types;
1068
1069 case Absyn.NEQUAL()
1070 algorithm
1071 1861 enum_op := makeEnumOperator(DAE.NEQUAL(DAE.T_ENUMERATION_DEFAULT), t1, t2);
1072 types :=
1073 (DAE.NEQUAL(DAE.T_INTEGER_DEFAULT),
1074 {DAE.T_INTEGER_DEFAULT,DAE.T_INTEGER_DEFAULT},DAE.T_BOOL_DEFAULT)::
1075 enum_op::
1076 (DAE.NEQUAL(DAE.T_REAL_DEFAULT),
1077 {DAE.T_REAL_DEFAULT,DAE.T_REAL_DEFAULT},DAE.T_BOOL_DEFAULT)::
1078 (DAE.NEQUAL(DAE.T_STRING_DEFAULT),
1079 {DAE.T_STRING_DEFAULT,DAE.T_STRING_DEFAULT},DAE.T_BOOL_DEFAULT)::
1080 (DAE.NEQUAL(DAE.T_BOOL_DEFAULT),
1081 {DAE.T_BOOL_DEFAULT,DAE.T_BOOL_DEFAULT},DAE.T_BOOL_DEFAULT)::
1082 {};
1083 then types;
1084 end match;
1085 else
1086 ✗ true := Flags.isSet(Flags.FAILTRACE);
1087 ✗ Debug.traceln("OperatorOverloading.operatorsBinary failed, op: " + Dump.opSymbol(op));
1088 ✗ fail();
1089 end try;
1090 end operatorsBinary;
1091
1092 function operatorsUnary "This function relates the operators in the abstract syntax to the
1093 de-overloaded operators in the SCode. It produces a list of available
1094 types for a specific operator, that the overload function chooses from.
1095 Therefore, in order for the builtin type conversion from Integer to
1096 Real to work, operators that work on both Integers and Reals must
1097 return the Integer type -before- the Real type in the list."
1098 input Absyn.Operator op;
1099 output list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> ops;
1100 algorithm
1101 ops := match op
1102 local
1103 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> intarrs,realarrs,boolarrs,scalars,types;
1104
1105 case Absyn.UMINUS()
1106 algorithm
1107 scalars := {
1108 (DAE.UMINUS(DAE.T_INTEGER_DEFAULT),{DAE.T_INTEGER_DEFAULT},
1109 DAE.T_INTEGER_DEFAULT),
1110 (DAE.UMINUS(DAE.T_REAL_DEFAULT),{DAE.T_REAL_DEFAULT},
1111 DAE.T_REAL_DEFAULT)} "The UMINUS operator, unary minus" ;
1112 95779 intarrs := operatorReturnUnary(DAE.UMINUS_ARR(DAE.T_ARRAY(DAE.T_INTEGER_DEFAULT, {DAE.DIM_UNKNOWN()})),
1113 intarrtypes, intarrtypes);
1114 95779 realarrs := operatorReturnUnary(DAE.UMINUS_ARR(DAE.T_ARRAY(DAE.T_REAL_DEFAULT, {DAE.DIM_UNKNOWN()})),
1115 realarrtypes, realarrtypes);
1116 95779 types := List.flatten({scalars,intarrs,realarrs});
1117 then types;
1118
1119 case Absyn.NOT()
1120 algorithm
1121 scalars := {(DAE.NOT(DAE.T_BOOL_DEFAULT), {DAE.T_BOOL_DEFAULT}, DAE.T_BOOL_DEFAULT)};
1122 1743 boolarrs := operatorReturnUnary(DAE.NOT(DAE.T_BOOL_DEFAULT), boolarrtypes, boolarrtypes);
1123 1743 types := List.flatten({scalars, boolarrs});
1124 then types;
1125
1126 case _
1127 algorithm
1128 ✗ true := Flags.isSet(Flags.FAILTRACE);
1129 ✗ Debug.traceln("OperatorOverloading.operatorsUnary failed, op: " + Dump.opSymbol(op));
1130 ✗ then fail();
1131 end match;
1132 end operatorsUnary;
1133
1134 function makeEnumOperator
1135 "Used by operators to create an operator with enumeration type. It sets the
1136 correct expected type of the operator, so that for example integer=>enum type
1137 casts work correctly without matching things that it shouldn't match."
1138 input DAE.Operator inOp;
1139 input DAE.Type inType1;
1140 input DAE.Type inType2;
1141 output tuple<DAE.Operator, list<DAE.Type>, DAE.Type> outOp;
1142 algorithm
1143 outOp := matchcontinue(inType1, inType2)
1144 local
1145 DAE.Type op_ty;
1146 DAE.Operator op;
1147
1148 case (DAE.T_ENUMERATION(), DAE.T_ENUMERATION())
1149 algorithm
1150 3317 op_ty := Types.simplifyType(inType1);
1151 3317 op := Expression.setOpType(inOp, op_ty);
1152 3317 then
1153 ((op, {inType1, inType2}, DAE.T_BOOL_DEFAULT));
1154
1155 case (DAE.T_ENUMERATION(), _)
1156 algorithm
1157 1 op_ty := Types.simplifyType(inType1);
1158 1 op := Expression.setOpType(inOp, op_ty);
1159 1 then
1160 ((op, {inType1, inType1}, DAE.T_BOOL_DEFAULT));
1161
1162 case (_, DAE.T_ENUMERATION())
1163 algorithm
1164 1 op_ty := Types.simplifyType(inType2);
1165 1 op := Expression.setOpType(inOp, op_ty);
1166 1 then
1167 ((op, {inType2, inType2}, DAE.T_BOOL_DEFAULT));
1168
1169 10032 else ((inOp, {DAE.T_ENUMERATION_DEFAULT, DAE.T_ENUMERATION_DEFAULT}, DAE.T_BOOL_DEFAULT));
1170 end matchcontinue;
1171 end makeEnumOperator;
1172
1173 function buildOperatorTypes
1174 "This function takes the types operator overloaded user functions and
1175 builds the type list structure suitable for the deoverload function."
1176 input list<DAE.Type> inTypes;
1177 input Absyn.Path inPath;
1178 output list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> outOperatorTypes;
1179 algorithm
1180 outOperatorTypes := match (inTypes, inPath)
1181 local
1182 list<DAE.Type> argtypes,tps;
1183 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> rest;
1184 list<DAE.FuncArg> args;
1185 DAE.Type tp;
1186 Absyn.Path funcname;
1187 case ({},_) then {};
1188 case (DAE.T_FUNCTION(funcArg = args,funcResultType = tp) :: tps,funcname)
1189 algorithm
1190 ✗ argtypes := List.map(args, Types.funcArgType);
1191 ✗ rest := buildOperatorTypes(tps, funcname);
1192 ✗ then
1193 ((DAE.USERDEFINED(funcname),argtypes,tp) :: rest);
1194 end match;
1195 end buildOperatorTypes;
1196
1197 function operatorReturn "This function collects the types and operator lists into a tuple list, suitable
1198 for the deoverloading function for binary operations."
1199 input DAE.Operator inOperator;
1200 input list<DAE.Type> inLhsTypes;
1201 input list<DAE.Type> inRhsTypes;
1202 input list<DAE.Type> inReturnTypes;
1203 output list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> outOperators;
1204 algorithm
1205 ✗ outOperators := list((inOperator,{l,r},re) threaded for l in inLhsTypes, r in inRhsTypes, re in inReturnTypes);
1206 annotation(__OpenModelica_EarlyInline=true);
1207 end operatorReturn;
1208
1209 function operatorReturnUnary "This function collects the types and operator lists into a tuple list,
1210 suitable for the deoverloading function to be used for unary
1211 expressions."
1212 input DAE.Operator inOperator;
1213 input list<DAE.Type> inArgTypes;
1214 input list<DAE.Type> inReturnTypes;
1215 output list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> outOperators;
1216 algorithm
1217 outOperators := match(inOperator, inArgTypes, inReturnTypes)
1218 local
1219 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> rest;
1220 tuple<DAE.Operator, list<DAE.Type>, DAE.Type> t;
1221 DAE.Operator op;
1222 DAE.Type l,re;
1223 list<DAE.Type> lr,rer;
1224 case (_,{},{}) then {};
1225 case (op,(l :: lr),(re :: rer))
1226 algorithm
1227 1739709 rest := operatorReturnUnary(op, lr, rer);
1228 1739709 t := (op,{l},re) "list only contains one type, i.e. for UNARY operations" ;
1229 then
1230 (t :: rest);
1231 end match;
1232 end operatorReturnUnary;
1233
1234 function getOperatorFuncsOrEmpty
1235 input FCore.Cache inCache;
1236 input FCore.Graph env;
1237 input list<DAE.Type> tys;
1238 input String opName;
1239 input SourceInfo info;
1240 input list<DAE.Type> acc;
1241 output FCore.Cache cache;
1242 output list<DAE.Type> funcs;
1243 algorithm
1244 (cache,funcs) := matchcontinue tys
1245 local
1246 DAE.Type ty;
1247 list<DAE.Type> rest;
1248 case ty::rest
1249 algorithm
1250 330 (cache,funcs) := getOperatorFuncsOrEmptySingleTy(inCache,env,ty,opName,info);
1251 326 (cache,funcs) := getOperatorFuncsOrEmpty(cache,env,rest,opName,info,listAppend(funcs,acc));
1252 then (cache,funcs);
1253 case _::rest
1254 algorithm
1255 4 (cache,funcs) := getOperatorFuncsOrEmpty(inCache,env,rest,opName,info,acc);
1256 then (cache,funcs);
1257 case {}
1258 algorithm
1259
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 330 times.
330 (cache,Util.SUCCESS()) := Static.instantiateDaeFunctionFromTypes(inCache, env, acc, false, NONE(), true, Util.SUCCESS());
1260
1/2
✗ Branch 2 not taken.
✓ Branch 3 taken 330 times.
330 (DAE.T_TUPLE(funcs,_),_) := Types.traverseType(DAE.T_TUPLE(acc,NONE()), -1, Types.makeExpDimensionsUnknown);
1261 330 then (cache,funcs);
1262 end matchcontinue;
1263 end getOperatorFuncsOrEmpty;
1264
1265 package AvlTreePathPathEnv "AvlTree Path -> Path"
1266 extends BaseAvlTree;
1267 redeclare type Key = Absyn.Path;
1268 redeclare type Value = Absyn.Path;
1269 redeclare function extends keyStr
1270 algorithm
1271 ✗ outString := AbsynUtil.pathString(inKey);
1272 end keyStr;
1273 redeclare function extends valueStr
1274 algorithm
1275 ✗ outString := AbsynUtil.pathString(inValue);
1276 end valueStr;
1277 redeclare function extends keyCompare
1278 algorithm
1279 320 outResult := AbsynUtil.pathCompareNoQual(inKey1,inKey2);
1280 end keyCompare;
1281 redeclare function addConflictDefault = addConflictKeep;
1282 annotation(__OpenModelica_Interface="util");
1283 end AvlTreePathPathEnv;
1284
1285 package AvlTreePathOperatorTypes "AvlTree Path -> list<Type>"
1286 extends BaseAvlTree;
1287 redeclare type Key = Absyn.Path;
1288 redeclare type Value = list<DAE.Type>;
1289 redeclare function extends keyStr
1290 algorithm
1291 ✗ outString := AbsynUtil.pathString(inKey);
1292 end keyStr;
1293 redeclare function extends valueStr
1294 algorithm
1295 ✗ outString := TypesDump.unparseType(DAE.T_METATUPLE(inValue));
1296 end valueStr;
1297 redeclare function extends keyCompare
1298 algorithm
1299 671 outResult := AbsynUtil.pathCompareNoQual(inKey1,inKey2);
1300 end keyCompare;
1301 redeclare function addConflictDefault = addConflictKeep;
1302 annotation(__OpenModelica_Interface="util");
1303 end AvlTreePathOperatorTypes;
1304
1305 function getOperatorFuncsOrEmptySingleTy
1306 input output FCore.Cache cache;
1307 input FCore.Graph env;
1308 input DAE.Type ty;
1309 input String opName;
1310 input SourceInfo info;
1311 output list<DAE.Type> funcs;
1312 protected
1313 Absyn.Path path,pathIn,opNamePath;
1314 SCode.Element operatorCl;
1315 FCore.Graph recordEnv,operEnv;
1316 list<Absyn.Path> paths;
1317 DAE.Type scalarType;
1318 AvlTreePathPathEnv.Tree tree1;
1319 AvlTreePathOperatorTypes.Tree tree2;
1320 tuple<AvlTreePathPathEnv.Tree,AvlTreePathOperatorTypes.Tree> trees;
1321 algorithm
1322 330 scalarType := Types.arrayElementType(ty);
1323 330 pathIn := AbsynUtil.makeFullyQualified(getRecordPath(scalarType));
1324 326 trees := getGlobalRoot(Global.operatorOverloadingCache);
1325 326 (tree1,tree2) := trees;
1326 try
1327 326 path := AvlTreePathPathEnv.get(tree1, pathIn);
1328 else
1329 6 (cache,operatorCl,recordEnv) := Lookup.lookupClass(cache,env,pathIn);
1330 6 (cache,path,recordEnv) := lookupOperatorBaseClass(cache,recordEnv,operatorCl);
1331 6 tree1 := AvlTreePathPathEnv.add(tree1, pathIn, path);
1332 6 setGlobalRoot(Global.operatorOverloadingCache, (tree1,tree2));
1333 end try;
1334 326 opNamePath := Absyn.IDENT(opName);
1335 326 path := AbsynUtil.makeFullyQualified(AbsynUtil.joinPaths(path, opNamePath));
1336 try
1337 326 funcs := AvlTreePathOperatorTypes.get(tree2, path);
1338 else
1339 // check if the operator is defined. i.e overloaded
1340 17 (cache,operatorCl,operEnv) := Lookup.lookupClass(cache,env,path);
1341
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
17 true := SCodeUtil.isOperator(operatorCl);
1342 // get the list of functions in the operator. !! there can be multiple options
1343 17 paths := AbsynToSCode.getListofQualOperatorFuncsfromOperator(operatorCl);
1344 17 (cache,funcs) := Lookup.lookupFunctionsListInEnv(cache, operEnv, paths, info, {});
1345
6/8
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 15 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 13 times.
✓ Branch 6 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 13 times.
17 funcs := List.select2(funcs, if opName=="'constructor'" or opName=="'0'" then checkOperatorFunctionOutput else checkOperatorFunctionOneOutput, scalarType,info);
1346 17 tree2 := AvlTreePathOperatorTypes.add(tree2, path, funcs);
1347 17 setGlobalRoot(Global.operatorOverloadingCache, (tree1,tree2));
1348 end try;
1349 end getOperatorFuncsOrEmptySingleTy;
1350
1351 function lookupOperatorBaseClass "From a derived class, we find the parent.
1352 This is required because we take the union of functions from lhs and rhs.
1353 If one is Complex and one is named ComplexVoltage, we would get different types.
1354 This also reduces the total number of functions that are instantiated.
1355 "
1356 input FCore.Cache inCache;
1357 input FCore.Graph inEnv;
1358 input SCode.Element inClass;
1359 output FCore.Cache cache;
1360 output Absyn.Path path;
1361 output FCore.Graph env;
1362 algorithm
1363 (cache,path,env) := match (inCache,inEnv,inClass)
1364 local
1365 SCode.Element cl;
1366 String name;
1367 case (cache,env,SCode.CLASS(classDef=SCode.DERIVED(typeSpec=Absyn.TPATH(path,NONE()))))
1368 algorithm
1369 ✗ (cache,cl,env) := Lookup.lookupClass(cache,env,path);
1370 ✗ (cache,path,env) := lookupOperatorBaseClass(cache,env,cl);
1371 then (cache,path,env);
1372
1373 case (cache,env,SCode.CLASS(name=name))
1374 algorithm
1375 6 path := FGraph.joinScopePath(env,Absyn.IDENT(name));
1376
1/2
✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
6 then (cache,path,env);
1377 end match;
1378 end lookupOperatorBaseClass;
1379
1380 function checkOperatorFunctionOneOutput
1381 input DAE.Type ty;
1382 input DAE.Type opType;
1383 input SourceInfo info;
1384 output Boolean isOK;
1385 algorithm
1386 isOK := match ty
1387 local
1388 DAE.Type ty1,ty2;
1389 Boolean b;
1390 case DAE.T_FUNCTION(funcResultType=DAE.T_TUPLE()) then false;
1391 case DAE.T_FUNCTION(funcArg=DAE.FUNCARG(ty=ty1,defaultBinding=NONE())::DAE.FUNCARG(ty=ty2,defaultBinding=NONE())::_)
1392 algorithm
1393
1/4
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
19 b := Types.equivtypesOrRecordSubtypeOf(Types.arrayElementType(ty1),opType) or Types.equivtypesOrRecordSubtypeOf(Types.arrayElementType(ty2),opType);
1394 19 checkOperatorFunctionOneOutputError(b,opType,ty,info);
1395 then b;
1396 case DAE.T_FUNCTION(funcArg=DAE.FUNCARG(ty=ty1,defaultBinding=NONE())::_)
1397 algorithm
1398 3 b := Types.equivtypesOrRecordSubtypeOf(Types.arrayElementType(ty1),opType);
1399 3 checkOperatorFunctionOneOutputError(b,opType,ty,info);
1400 then b;
1401 else true;
1402 end match;
1403 end checkOperatorFunctionOneOutput;
1404
1405 function checkOperatorFunctionOneOutputError
1406 input Boolean ok;
1407 input DAE.Type opType;
1408 input DAE.Type ty;
1409 input SourceInfo info;
1410 algorithm
1411 () := match ok
1412 local
1413 String str1,str2;
1414 case true then ();
1415 else
1416 algorithm
1417 ✗ str1 := TypesDump.unparseType(opType);
1418 ✗ str2 := TypesDump.unparseType(ty);
1419 ✗ Error.addSourceMessage(Error.OP_OVERLOAD_OPERATOR_NOT_INPUT,{str1,str2},info);
1420 ✗ then fail();
1421 end match;
1422 end checkOperatorFunctionOneOutputError;
1423
1424 function checkOperatorFunctionOutput
1425 input DAE.Type ty;
1426 input DAE.Type expected;
1427 input SourceInfo info;
1428 output Boolean isOK;
1429 algorithm
1430 isOK := match ty
1431 local
1432 DAE.Type actual;
1433 case DAE.T_FUNCTION(funcResultType=actual)
1434 algorithm
1435 2 isOK := Types.equivtypesOrRecordSubtypeOf(actual,expected);
1436 // Error.assertionOrAddSourceMessage(isOK, Error.COMPILER_WARNING, {"TODO: Better warning for: " + TypesDump.unparseType(actual) + ", expected: " + TypesDump.unparseType(actual)}, info);
1437 then isOK;
1438 else false;
1439 end match;
1440 end checkOperatorFunctionOutput;
1441
1442 function isOperatorBinaryFunctionOrWarn
1443 input DAE.Type ty;
1444 input SourceInfo info;
1445 output Boolean isBinaryFunc;
1446 algorithm
1447 isBinaryFunc := match ty
1448 local
1449 list<DAE.FuncArg> rest;
1450 case DAE.T_FUNCTION(funcArg={_}) then false; // Unary functions are legal even if we are not interested in them
1451 case DAE.T_FUNCTION(funcArg=DAE.FUNCARG(defaultBinding=NONE())::DAE.FUNCARG(defaultBinding=NONE())::rest)
1452 algorithm
1453 207 isBinaryFunc := List.mapMapBoolAnd(rest, Types.funcArgDefaultBinding, isSome);
1454 // Error.assertionOrAddSourceMessage(isBinaryFunc, Error.COMPILER_WARNING, {"TODO: Better warning for: " + TypesDump.unparseType(ty) + ", expected arguments 3..n to have default values"}, info);
1455 then isBinaryFunc; // Unary functions are legal even if we are not interested in them
1456 else
1457 algorithm
1458 // Error.addSourceMessage(Error.COMPILER_WARNING, {"TODO: Better warning for: " + TypesDump.unparseType(ty) + ", expected arguments 1&2 to not have default values"}, info);
1459 then false;
1460 end match;
1461 end isOperatorBinaryFunctionOrWarn;
1462
1463 function isOperatorUnaryFunction
1464 input DAE.Type ty;
1465 output Boolean isBinaryFunc;
1466 algorithm
1467 isBinaryFunc := match ty
1468 local
1469 list<DAE.FuncArg> rest;
1470 case DAE.T_FUNCTION(funcArg=DAE.FUNCARG(defaultBinding=NONE())::rest)
1471 algorithm
1472 8 isBinaryFunc := List.mapMapBoolAnd(rest, Types.funcArgDefaultBinding, isSome);
1473 then isBinaryFunc;
1474 else false;
1475 end match;
1476 end isOperatorUnaryFunction;
1477
1478 function getZeroConstructorExpression
1479 input DAE.Type ty;
1480 output DAE.Exp result;
1481 algorithm
1482 result := match ty
1483 local
1484 list<DAE.FuncArg> args;
1485 Absyn.Path path;
1486 DAE.FunctionAttributes attr;
1487 case DAE.T_FUNCTION(funcArg=args,functionAttributes=attr,path=path)
1488 algorithm
1489 ✗ result := makeCallFillRestDefaults(path,{},args,Types.makeCallAttr(ty,attr));
1490 then result;
1491 end match;
1492 end getZeroConstructorExpression;
1493
1494 function makeCallFillRestDefaults
1495 input Absyn.Path path;
1496 input list<DAE.Exp> inExps;
1497 input list<DAE.FuncArg> restArgs;
1498 input DAE.CallAttributes attr;
1499 output DAE.Exp exp;
1500 protected
1501 list<DAE.Exp> exps;
1502 algorithm
1503 165 exps := listAppend(inExps,List.mapMap(restArgs,Types.funcArgDefaultBinding,Util.getOption));
1504 165 exp := DAE.CALL(path,exps,attr);
1505 end makeCallFillRestDefaults;
1506
1507 function getRecordPath
1508 input DAE.Type inType1;
1509 output Absyn.Path outPath;
1510 algorithm
1511
3/4
✓ Branch 1 taken 1489 times.
✓ Branch 2 taken 329 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 329 times.
1818 DAE.T_COMPLEX(complexClassType = ClassInf.RECORD(outPath)) :=
1512 Types.arrayElementType(inType1);
1513 end getRecordPath;
1514
1515 function deoverload "Given several lists of parameter types and one argument list,
1516 this function tries to find one list of parameter types which
1517 is compatible with the argument list. It uses elabArglist to
1518 do the matching, which means that automatic type conversions
1519 will be made when necessary. The new argument list, together
1520 with a new operator that corresponds to the parameter type list
1521 is returned.
1522
1523 The basic principle is that the first operator that matches is chosen.
1524 ."
1525 input list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> inOperators;
1526 input list<tuple<DAE.Exp, DAE.Type>> inArgs;
1527 input Absyn.Exp aexp "for error-messages";
1528 input DAE.Prefix inPrefix;
1529 input SourceInfo info;
1530 output DAE.Operator outOperator;
1531 output list<DAE.Exp> outArgs;
1532 output DAE.Type outType;
1533 algorithm
1534 (outOperator, outArgs, outType) :=
1535 matchcontinue (inOperators, inArgs, inPrefix)
1536 local
1537 list<DAE.Exp> exps,args_1;
1538 list<DAE.Type> types_1,params,tps;
1539 DAE.Type rtype_1,rtype;
1540 DAE.Operator op;
1541 list<tuple<DAE.Exp, DAE.Type>> args;
1542 list<tuple<DAE.Operator, list<DAE.Type>, DAE.Type>> xs;
1543 DAE.Prefix pre;
1544 DAE.Type ty;
1545 list<String> exps_str,tps_str;
1546 String pre_str, s, tpsstr;
1547
1548 case (((op,params,rtype) :: _), args, pre)
1549 algorithm
1550 //Debug.fprint(Flags.DOVL, stringDelimitList(List.map(params, TypesDump.printTypeStr),"\n"));
1551 //Debug.fprint(Flags.DOVL, "\n===\n");
1552 673769 (args_1,types_1) := elabArglist(params, args);
1553 300875 rtype_1 := computeReturnType(op, types_1, rtype,pre,info);
1554 300875 ty := Types.simplifyType(rtype_1);
1555 300875 op := Expression.setOpType(op, ty);
1556 300875 then
1557 (op,args_1,rtype_1);
1558
1559 case ((_ :: xs), args, pre)
1560 algorithm
1561 372894 (op,args_1,rtype) := deoverload(xs,args,aexp,pre,info);
1562 then
1563 (op,args_1,rtype);
1564
1565 //Don't fail and dont print error messages. Operators can be overloaded
1566 //for records.
1567 //mahge: TODO move this to the proper place and print.
1568 case ({}, args, pre)
1569 algorithm
1570 1 s := Dump.printExpStr(aexp);
1571 1 exps := List.map(args, Util.tuple21);
1572 1 tps := List.map(args, Util.tuple22);
1573 1 exps_str := List.map(exps, ExpressionBasics.printExpStr);
1574 1 stringDelimitList(exps_str, ", ");
1575 1 tps_str := List.map(tps, TypesDump.unparseType);
1576 1 tpsstr := stringDelimitList(tps_str, ", ");
1577 1 pre_str := PrefixUtil.printPrefixStr3(pre);
1578 1 Error.addSourceMessage(Error.UNRESOLVABLE_TYPE, {s,tpsstr,pre_str}, info);
1579 1 then
1580 fail();
1581 end matchcontinue;
1582 end deoverload;
1583
1584 function computeReturnType "This function determines the return type of
1585 an operator and the types of the operands."
1586 input DAE.Operator inOperator;
1587 input list<DAE.Type> inTypesTypeLst;
1588 input DAE.Type inType;
1589 input DAE.Prefix inPrefix;
1590 input SourceInfo inInfo;
1591 output DAE.Type outType;
1592 algorithm
1593 outType := matchcontinue (inOperator, inTypesTypeLst, inType, inPrefix)
1594 local
1595 DAE.Type typ1,typ2,rtype,etype,typ;
1596 String t1_str,t2_str,pre_str;
1597 DAE.Dimension n1,n2,m,n,m1,m2,p;
1598 DAE.Prefix pre;
1599
1600 case (DAE.ADD_ARR(), {typ1,typ2}, _, _)
1601 algorithm
1602
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2931 times.
2931 true := Types.subtype(typ1, typ2);
1603 then
1604 typ1;
1605
1606 case (DAE.ADD_ARR(), {typ1,typ2}, _, _)
1607 algorithm
1608 ✗ true := Types.subtype(typ2, typ1);
1609 then
1610 typ1;
1611
1612 case (DAE.ADD_ARR(), {typ1,typ2}, _, pre)
1613 algorithm
1614 ✗ t1_str := TypesDump.unparseType(typ1);
1615 ✗ t2_str := TypesDump.unparseType(typ2);
1616 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1617 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1618 {"vector addition", pre_str, t1_str, t2_str}, inInfo);
1619 ✗ then
1620 fail();
1621
1622 case (DAE.SUB_ARR(), {typ1,typ2}, _, _)
1623 algorithm
1624
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1690 times.
1690 true := Types.subtype(typ1, typ2);
1625 then
1626 typ1;
1627
1628 case (DAE.SUB_ARR(), {typ1,typ2}, _, _)
1629 algorithm
1630 ✗ true := Types.subtype(typ2, typ1);
1631 then
1632 typ1;
1633
1634 case (DAE.SUB_ARR(), {typ1,typ2}, _, pre)
1635 algorithm
1636 ✗ t1_str := TypesDump.unparseType(typ1);
1637 ✗ t2_str := TypesDump.unparseType(typ2);
1638 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1639 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1640 {"vector subtraction", pre_str, t1_str, t2_str}, inInfo);
1641 ✗ then
1642 fail();
1643
1644 case (DAE.MUL_ARR(), {typ1,typ2}, _, _)
1645 algorithm
1646
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 27 times.
27 true := Types.subtype(typ1, typ2);
1647 then
1648 typ1;
1649
1650 case (DAE.MUL_ARR(), {typ1,typ2}, _, _)
1651 algorithm
1652 ✗ true := Types.subtype(typ2, typ1);
1653 then
1654 typ1;
1655
1656 case (DAE.MUL_ARR(), {typ1,typ2}, _, pre)
1657 algorithm
1658 ✗ t1_str := TypesDump.unparseType(typ1);
1659 ✗ t2_str := TypesDump.unparseType(typ2);
1660 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1661 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1662 {"vector elementwise multiplication", pre_str, t1_str, t2_str}, inInfo);
1663 ✗ then
1664 fail();
1665
1666 case (DAE.DIV_ARR(), {typ1,typ2}, _, _)
1667 algorithm
1668
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
29 true := Types.subtype(typ1, typ2);
1669 then
1670 typ1;
1671
1672 case (DAE.DIV_ARR(), {typ1,typ2}, _, _)
1673 algorithm
1674 ✗ true := Types.subtype(typ2, typ1);
1675 then
1676 typ1;
1677
1678 case (DAE.DIV_ARR(), {typ1,typ2}, _, pre)
1679 algorithm
1680 ✗ t1_str := TypesDump.unparseType(typ1);
1681 ✗ t2_str := TypesDump.unparseType(typ2);
1682 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1683 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1684 {"vector elementwise division", pre_str, t1_str, t2_str}, inInfo);
1685 ✗ then
1686 fail();
1687
1688 // Matrix[n,m]^i
1689 case (DAE.POW_ARR(), {typ1,_}, _, _)
1690 algorithm
1691
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 2 := nDims(typ1);
1692 5 n := Types.getDimensionNth(typ1, 1);
1693 5 m := Types.getDimensionNth(typ1, 2);
1694
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 true := Expression.dimensionsKnownAndEqual(n, m);
1695 then
1696 typ1;
1697
1698 case (DAE.POW_ARR2(), {typ1,typ2}, _, _)
1699 algorithm
1700
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 true := Types.subtype(typ1, typ2);
1701 then
1702 typ1;
1703
1704 case (DAE.POW_ARR2(), {typ1,typ2}, _, _)
1705 algorithm
1706 ✗ true := Types.subtype(typ2, typ1);
1707 then
1708 typ1;
1709
1710 case (DAE.POW_ARR2(), {typ1,typ2}, _, pre)
1711 algorithm
1712 ✗ t1_str := TypesDump.unparseType(typ1);
1713 ✗ t2_str := TypesDump.unparseType(typ2);
1714 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1715 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1716 {"elementwise vector^vector", pre_str, t1_str, t2_str}, inInfo);
1717 ✗ then
1718 fail();
1719
1720 case (DAE.MUL_SCALAR_PRODUCT(), {typ1,typ2}, rtype, _)
1721 algorithm
1722
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 638 times.
638 true := Types.subtype(typ1, typ2);
1723 then
1724 rtype;
1725
1726 case (DAE.MUL_SCALAR_PRODUCT(), {typ1,typ2}, rtype, _)
1727 algorithm
1728 ✗ true := Types.subtype(typ2, typ1);
1729 then
1730 rtype;
1731
1732 case (DAE.MUL_SCALAR_PRODUCT(), {typ1,typ2}, _, pre)
1733 algorithm
1734 ✗ t1_str := TypesDump.unparseType(typ1);
1735 ✗ t2_str := TypesDump.unparseType(typ2);
1736 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1737 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1738 {"scalar product", pre_str, t1_str, t2_str}, inInfo);
1739 ✗ then
1740 fail();
1741
1742 // Vector[n]*Matrix[n,m] = Vector[m]
1743 case (DAE.MUL_MATRIX_PRODUCT(), {typ1,typ2}, _, _)
1744 algorithm
1745
2/2
✓ Branch 1 taken 603 times.
✓ Branch 2 taken 4 times.
607 1 := nDims(typ1);
1746
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 2 := nDims(typ2);
1747
1748 4 n1 := Types.getDimensionNth(typ1, 1);
1749 4 n2 := Types.getDimensionNth(typ2, 1);
1750 4 m := Types.getDimensionNth(typ2, 2);
1751
1752
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
4 true := isValidMatrixProductDims(n1, n2);
1753 4 etype := elementType(typ1);
1754 4 rtype := Types.liftArray(etype, m);
1755 then
1756 rtype;
1757
1758 // Matrix[n,m]*Vector[m] = Vector[n]
1759 case (DAE.MUL_MATRIX_PRODUCT(), {typ1,typ2}, _, _)
1760 algorithm
1761
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 603 times.
603 2 := nDims(typ1);
1762
2/2
✓ Branch 1 taken 145 times.
✓ Branch 2 taken 458 times.
603 1 := nDims(typ2);
1763
1764 458 n := Types.getDimensionNth(typ1, 1);
1765 458 m1 := Types.getDimensionNth(typ1, 2);
1766 458 m2 := Types.getDimensionNth(typ2, 1);
1767
1768
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 458 times.
458 true := isValidMatrixProductDims(m1, m2);
1769 458 etype := elementType(typ2);
1770 458 rtype := Types.liftArray(etype, n);
1771 then
1772 rtype;
1773
1774 // Matrix[n,m] * Matrix[m,p] = Matrix[n, p]
1775 case (DAE.MUL_MATRIX_PRODUCT(), {typ1,typ2}, _, _)
1776 algorithm
1777
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 145 times.
145 2 := nDims(typ1);
1778
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 145 times.
145 2 := nDims(typ2);
1779
1780 145 n := Types.getDimensionNth(typ1, 1);
1781 145 m1 := Types.getDimensionNth(typ1, 2);
1782 145 m2 := Types.getDimensionNth(typ2, 1);
1783 145 p := Types.getDimensionNth(typ2, 2);
1784
1785
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 145 times.
145 true := isValidMatrixProductDims(m1, m2);
1786 145 etype := elementType(typ1);
1787 145 rtype := Types.liftArrayListDims(etype, {n, p});
1788 then
1789 rtype;
1790
1791 case (DAE.MUL_MATRIX_PRODUCT(), {typ1,typ2}, _, pre)
1792 algorithm
1793 ✗ t1_str := TypesDump.unparseType(typ1);
1794 ✗ t2_str := TypesDump.unparseType(typ2);
1795 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1796 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1797 {"matrix multiplication", pre_str, t1_str, t2_str}, inInfo);
1798 ✗ then
1799 fail();
1800
1801 case (DAE.MUL_ARRAY_SCALAR(), {typ1,_}, _, _) then typ1; /* rtype */
1802
1803 case (DAE.ADD_ARRAY_SCALAR(), {typ1,_}, _, _) then typ1; /* rtype */
1804
1805 case (DAE.SUB_SCALAR_ARRAY(), {_,typ2}, _, _) then typ2; /* rtype */
1806
1807 case (DAE.DIV_SCALAR_ARRAY(), {_,typ2}, _, _) then typ2; /* rtype */
1808
1809 case (DAE.DIV_ARRAY_SCALAR(), {typ1,_}, _, _) then typ1; /* rtype */
1810
1811 case (DAE.POW_ARRAY_SCALAR(), {typ1,_}, _, _) then typ1; /* rtype */
1812
1813 case (DAE.POW_SCALAR_ARRAY(), {_,typ2}, _, _) then typ2; /* rtype */
1814
1815 case (DAE.ADD(), _, typ, _) then typ;
1816
1817 case (DAE.SUB(), _, typ, _) then typ;
1818
1819 case (DAE.MUL(), _, typ, _) then typ;
1820
1821 case (DAE.DIV(), _, typ, _) then typ;
1822
1823 case (DAE.POW(), _, typ, _) then typ;
1824
1825 case (DAE.UMINUS(), _, typ, _) then typ;
1826
1827 case (DAE.UMINUS_ARR(), (typ1 :: _), _, _) then typ1;
1828
1829 case (DAE.AND(), {typ1, typ2}, _, _)
1830 algorithm
1831
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3255 times.
3255 true := Types.equivtypes(typ1, typ2);
1832 then
1833 typ1;
1834
1835 case (DAE.AND(), {typ1, typ2}, _, pre)
1836 algorithm
1837 ✗ t1_str := TypesDump.unparseType(typ1);
1838 ✗ t2_str := TypesDump.unparseType(typ2);
1839 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1840 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1841 {"and", pre_str, t1_str, t2_str}, inInfo);
1842 ✗ then
1843 fail();
1844
1845 case (DAE.OR(), {typ1, typ2}, _, _)
1846 algorithm
1847
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1768 times.
1768 true := Types.equivtypes(typ1, typ2);
1848 then
1849 typ1;
1850
1851 case (DAE.OR(), {typ1, typ2}, _, pre)
1852 algorithm
1853 ✗ t1_str := TypesDump.unparseType(typ1);
1854 ✗ t2_str := TypesDump.unparseType(typ2);
1855 ✗ pre_str := PrefixUtil.printPrefixStr3(pre);
1856 ✗ Error.addSourceMessage(Error.INCOMPATIBLE_TYPES,
1857 {"or", pre_str, t1_str, t2_str}, inInfo);
1858 ✗ then
1859 fail();
1860
1861 case (DAE.NOT(), {typ1}, _, _) then typ1;
1862
1863 case (DAE.LESS(), _, typ, _) then typ;
1864
1865 case (DAE.LESSEQ(), _, typ, _) then typ;
1866
1867 case (DAE.GREATER(), _, typ, _) then typ;
1868
1869 case (DAE.GREATEREQ(), _, typ, _) then typ;
1870
1871 case (DAE.EQUAL(), _, typ, _) then typ;
1872
1873 case (DAE.NEQUAL(), _, typ, _) then typ;
1874
1875 case (DAE.USERDEFINED(), _, typ, _) then typ;
1876 end matchcontinue;
1877 end computeReturnType;
1878
1879 function nDims "Returns the number of dimensions of a Type."
1880 input DAE.Type inType;
1881 output Integer outInteger;
1882 algorithm
1883 outInteger := match inType
1884 local
1885 Integer ns;
1886 DAE.Type t;
1887 case DAE.T_INTEGER() then 0;
1888 case DAE.T_REAL() then 0;
1889 case DAE.T_STRING() then 0;
1890 case DAE.T_BOOL() then 0;
1891 case DAE.T_ARRAY(ty = t)
1892 algorithm
1893 ns := nDims(t);
1894 then
1895 ns + 1;
1896 case DAE.T_SUBTYPE_BASIC(complexType = t)
1897 algorithm
1898 4 ns := nDims(t);
1899 then ns;
1900 end match;
1901 end nDims;
1902
1903 function isValidMatrixProductDims
1904 "Checks if two dimensions are equal, which is a prerequisite for matrix
1905 multiplication."
1906 input DAE.Dimension dim1;
1907 input DAE.Dimension dim2;
1908 output Boolean res;
1909 algorithm
1910
1/10
✗ Branch 1 not taken.
✓ Branch 2 taken 607 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
607 res := // Naturally dimensions 1 and 1 are equal
1911 Expression.dimensionsKnownAndEqual(dim1, dim2)
1912 // We need run-time checks for DIM_EXP=DIM_EXP
1913 or (not (Expression.dimensionKnown(dim1) or Expression.dimensionKnown(dim2)))
1914 // If checkModel is used we might get unknown dimensions. So use
1915 // dimensionsEqual instead, which matches anything against DIM_UNKNOWN.
1916 or (Flags.getConfigBool(Flags.CHECK_MODEL) and Expression.dimensionsEqual(dim1, dim2));
1917 end isValidMatrixProductDims;
1918
1919 function elementType "Returns the element type of a type, i.e. for arrays, return the
1920 element type, and for bulitin scalar types return the type itself."
1921 input DAE.Type inType;
1922 output DAE.Type outType;
1923 algorithm
1924 outType := match inType
1925 local DAE.Type t,t_1;
1926 case t as DAE.T_INTEGER() then t;
1927 case t as DAE.T_REAL() then t;
1928 case t as DAE.T_STRING() then t;
1929 case t as DAE.T_BOOL() then t;
1930 case DAE.T_ARRAY(ty = t)
1931 algorithm
1932 752 t_1 := elementType(t);
1933 then
1934 t_1;
1935 case DAE.T_SUBTYPE_BASIC(complexType = t)
1936 algorithm
1937 4 t_1 := elementType(t);
1938 then t_1;
1939 end match;
1940 end elementType;
1941
1942 function replaceOperatorWithFcall "Replaces a userdefined operator expression with a corresponding function
1943 call expression. Other expressions just passes through."
1944 input Absyn.Exp AbExp;
1945 input DAE.Exp inExp1;
1946 input DAE.Operator inOper;
1947 input Option<DAE.Exp> inExp2;
1948 input DAE.Const inConst;
1949 output DAE.Exp outExp;
1950 algorithm
1951 outExp := match (AbExp, inExp1, inOper, inExp2)
1952 local
1953 DAE.Exp e1,e2;
1954 Absyn.Path funcname;
1955
1956 case (Absyn.BINARY(_,_,_), e1, DAE.USERDEFINED(fqName = funcname), SOME(e2))
1957 ✗ then DAE.CALL(funcname,{e1,e2},DAE.callAttrOther);
1958
1959 case (Absyn.BINARY(_,_,_), e1, _, SOME(e2))
1960 184979 then DAE.BINARY(e1, inOper, e2);
1961
1962 case (Absyn.UNARY(_, _), e1, DAE.USERDEFINED(fqName = funcname), NONE())
1963 ✗ then DAE.CALL(funcname,{e1},DAE.callAttrOther);
1964
1965 case (Absyn.UNARY(_, _), e1, _, NONE())
1966 95779 then DAE.UNARY(inOper,e1);
1967
1968 case (Absyn.LBINARY(_, _, _), e1, DAE.USERDEFINED(fqName = funcname), SOME(e2))
1969 ✗ then DAE.CALL(funcname,{e1,e2},DAE.callAttrOther);
1970
1971 case (Absyn.LBINARY(_,_,_), e1, _, SOME(e2))
1972 5023 then DAE.LBINARY(e1, inOper, e2);
1973
1974 case (Absyn.LUNARY(_, _), e1, DAE.USERDEFINED(fqName = funcname), NONE())
1975 ✗ then DAE.CALL(funcname,{e1},DAE.callAttrOther);
1976
1977 case (Absyn.LUNARY(_, _), e1, _, NONE())
1978 1743 then DAE.LUNARY(inOper,e1);
1979
1980 case (Absyn.RELATION(_, _, _), e1, DAE.USERDEFINED(fqName = funcname), SOME(e2))
1981 ✗ then DAE.CALL(funcname,{e1,e2},DAE.callAttrOther);
1982
1983 case (Absyn.RELATION(_,_,_), e1, _, SOME(e2))
1984 13351 then DAE.RELATION(e1, inOper, e2, -1, NONE());
1985
1986 end match;
1987 end replaceOperatorWithFcall;
1988
1989 function warnUnsafeRelations "Check if we have Real == Real or Real != Real, if so give a warning."
1990 input FCore.Graph inEnv;
1991 input Absyn.Exp inExp;
1992 input DAE.Const variability;
1993 input DAE.Type t1,t2;
1994 input DAE.Exp e1,e2;
1995 input DAE.Operator op;
1996 input DAE.Prefix inPrefix;
1997 input SourceInfo inInfo;
1998 algorithm
1999 () := matchcontinue(inExp, variability)
2000 local
2001 Boolean b1,b2;
2002 String stmtString,opString;
2003 // == or != on Real is permitted in functions, so don't print an error if
2004 // we're in a function.
2005 case (_, _)
2006 algorithm
2007
2/2
✓ Branch 1 taken 87645 times.
✓ Branch 2 taken 115708 times.
203353 true := FGraph.inFunctionScope(inEnv);
2008 then ();
2009
2010 case(Absyn.RELATION(_, _, _), DAE.C_VAR())
2011 algorithm
2012 6036 b1 := Types.isReal(t1);
2013 6036 b2 := Types.isReal(t1);
2014
2/2
✓ Branch 0 taken 4228 times.
✓ Branch 1 taken 1808 times.
6036 true := boolOr(b1,b2);
2015 1808 verifyOp(op);
2016 1 opString := ExpressionDump.relopSymbol(op);
2017 1 stmtString := ExpressionBasics.printExpStr(e1) + opString + ExpressionBasics.printExpStr(e2);
2018 1 Error.addSourceMessage(Error.WARNING_RELATION_ON_REAL, {stmtString,opString}, inInfo);
2019 then
2020 ();
2021 else ();
2022 end matchcontinue;
2023 end warnUnsafeRelations;
2024
2025 function verifyOp "
2026 Helper function for warnUnsafeRelations
2027 We only want to check DAE.EQUAL and Expression.NEQUAL since they are the only illegal real operations."
2028 input DAE.Operator op;
2029 algorithm () := match op
2030 case DAE.EQUAL(_) then ();
2031 case DAE.NEQUAL(_) then ();
2032 end match;
2033 end verifyOp;
2034
2035 function errorMultipleValid
2036 input list<DAE.Exp> exps;
2037 input SourceInfo info;
2038 protected
2039 String str1,str2;
2040 algorithm
2041 ✗ str1 := intString(listLength(exps));
2042 ✗ str2 := stringDelimitList(List.map(exps,ExpressionBasics.printExpStr), ",");
2043 ✗ Error.addSourceMessage(Error.OP_OVERLOAD_MULTIPLE_VALID, {str1,str2}, info);
2044 end errorMultipleValid;
2045
2046 function binaryCastConstructor
2047 input FCore.Cache inCache;
2048 input FCore.Graph env;
2049 input DAE.Exp inExp1;
2050 input DAE.Exp inExp2;
2051 input DAE.Type inType1;
2052 input DAE.Type inType2;
2053 input list<tuple<DAE.Exp,Option<DAE.Type>>> exps;
2054 input list<DAE.Type> types;
2055 input SourceInfo info;
2056 output FCore.Cache cache;
2057 output list<tuple<DAE.Exp,Option<DAE.Type>>> resExps;
2058 algorithm
2059 (cache,resExps) := match exps
2060 local
2061 list<list<DAE.FuncArg>> args;
2062 list<DAE.Type> tys1,tys2;
2063 list<DAE.Exp> exps1,exps2;
2064 case {_} then (inCache,exps); // We already have exactly 1 match, so don't look for more
2065 case {}
2066 algorithm
2067 // Step 3: Call constructor functions to try matching inputs
2068 4 args := List.map(types, Types.getFuncArg);
2069 4 tys1 := List.mapMap(args, listHead, Types.funcArgType);
2070 4 args := List.map(args, listRest);
2071 4 tys2 := List.mapMap(args, listHead, Types.funcArgType);
2072 // We only look for constructors that are not of the initial type. Filter duplicates.
2073 4 tys1 := List.setDifference(List.union(tys1,{}),{inType1});
2074 4 tys2 := List.setDifference(List.union(tys2,{}),{inType2});
2075 // Get the constructors
2076 4 (cache,tys1) := getOperatorFuncsOrEmpty(inCache,env,tys1,"'constructor'",info,{});
2077 4 (cache,tys2) := getOperatorFuncsOrEmpty(cache,env,tys2,"'constructor'",info,{});
2078 // Filter out functions with more than 1 argument, since we cannot automatically construct such values anyway
2079 4 tys1 := List.select(tys1, isOperatorUnaryFunction);
2080 4 tys2 := List.select(tys2, isOperatorUnaryFunction);
2081 // Now see if any constructors were valid
2082 4 exps1 := deoverloadUnaryUserdefNoConstructor(tys1,inExp1,inType1,{});
2083 4 exps2 := deoverloadUnaryUserdefNoConstructor(tys2,inExp2,inType2,{});
2084
2085 4 resExps := deoverloadBinaryUserdefNoConstructorListLhs(types,exps1,inExp2,inType2,{});
2086 4 resExps := deoverloadBinaryUserdefNoConstructorListRhs(types,inExp1,exps2,inType1,resExps);
2087 then (cache,resExps);
2088 else
2089 algorithm
2090 ✗ errorMultipleValid(List.map(exps,Util.tuple21),info);
2091 ✗ then fail();
2092 end match;
2093 end binaryCastConstructor;
2094
2095 function getZeroConstructor
2096 input FCore.Cache inCache;
2097 input FCore.Graph env;
2098 input list<DAE.Exp> zexps;
2099 input Boolean impl;
2100 input SourceInfo info;
2101 output FCore.Cache cache;
2102 output Option<Values.Value> zeroExpression;
2103 algorithm
2104 (cache,zeroExpression) := match zexps
2105 local
2106 DAE.Exp zc;
2107 Values.Value v;
2108 case {} then (inCache,NONE());
2109 case {zc}
2110 algorithm
2111 ✗ (cache, v) := Ceval.ceval(inCache, env, zc, impl, Absyn.MSG(info), 0);
2112 ✗ then (cache,SOME(v));
2113 else
2114 algorithm
2115 errorMultipleValid(zexps,info);
2116 ✗ then fail();
2117 end match;
2118 end getZeroConstructor;
2119
2120 annotation(__OpenModelica_Interface="frontend");
2121 end OperatorOverloading;
2122