Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 4.2% 15 / 0 / 354
Functions: -% 0 / 1 / 1
Branches: 8.9% 8 / 0 / 90

OMCompiler/Compiler/FrontEnd/UnitAbsynBuilder.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 UnitAbsynBuilder
37
38 public import UnitAbsyn;
39 public import DAE;
40 public import MMath;
41 public import FCore;
42 public import HashTable;
43 public import Absyn;
44 public import AbsynUtil;
45
46 protected import Array;
47 protected import BaseHashTable;
48 protected import ComponentReference;
49 protected import ComponentReferenceBasics;
50 protected import DAEUtil;
51 protected import Expression;
52 protected import ExpressionBasics;
53 protected import Flags;
54 protected import FNode;
55 protected import FGraph;
56 protected import List;
57 protected import Lookup;
58 protected import SCode;
59 protected import SCodeUtil;
60 protected import AbsynToSCode;
61 protected import Types;
62 protected import UnitParserExt;
63 protected import Util;
64
65 public function registerUnitWeights "traverses all dae variables and adjusts weights depending on defineunits defined
66 in the scopes of the classLst for each variable"
67 input FCore.Cache cache;
68 input FCore.Graph env;
69 input DAE.DAElist dae;
70 protected
71 list<Absyn.Path> paths; list<SCode.Element> du;
72 algorithm
73 () := match dae
74 local
75 list<DAE.Element> elts;
76 case _ algorithm
77 // phi: very old unit checking
78 /*
79 false = Flags.getConfigBool(Flags.UNIT_CHECKING);
80 */
81 then ();
82
83 case DAE.DAE(elementLst=elts) algorithm
84 /* TODO: This is very unefficient. It increases instantiationtime by factor 2 for
85 instantiation of largeTests/TestNandTotal.mo */
86 ✗ paths := List.unionList(List.map(elts,DAEUtil.getClassList));
87 ✗ du := List.unionList(List.map1(paths,retrieveUnitsFromEnv,(cache,env)));
88 ✗ registerUnitWeightDefineunits(du);
89 then ();
90 end match;
91 end registerUnitWeights;
92
93 protected function retrieveUnitsFromEnv "help function to registerUnitWeights"
94 input Absyn.Path p;
95 input tuple<FCore.Cache,FCore.Graph> tpl;
96 output list<SCode.Element> du;
97
98 algorithm
99 du := matchcontinue tpl
100 local
101 FCore.Graph env;
102 FCore.Ref r;
103
104 case _ algorithm
105 ✗ (_,_,env) := Lookup.lookupClass(Util.tuple21(tpl),Util.tuple22(tpl),p,NONE());
106 ✗ r := FGraph.lastScopeRef(env);
107 // get the defined units node
108 ✗ r := FNode.child(r, FNode.duNodeName);
109 ✗ FCore.N(data = FCore.DU(du)) := FNode.fromRef(r);
110 then du;
111 else {};
112 end matchcontinue;
113 end retrieveUnitsFromEnv;
114
115
116 protected function registerUnitWeightDefineunits "help function to registerUnitWeightForClass"
117 input list<SCode.Element> du;
118 algorithm
119 () := match du
120 /* No defineunits found, for backward compatibility, use default implementation:
121 SI system ,with lower cost on Hz and Bq */
122 case {} algorithm
123 ✗ registerUnitWeightDefineunits2({
124 SCode.DEFINEUNIT("m",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
125 SCode.DEFINEUNIT("kg",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
126 SCode.DEFINEUNIT("s",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
127 SCode.DEFINEUNIT("A",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
128 SCode.DEFINEUNIT("k",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
129 SCode.DEFINEUNIT("mol",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
130 SCode.DEFINEUNIT("cd",SCode.PUBLIC(),NONE(),NONE(), SCodeUtil.dummyInfo),
131 SCode.DEFINEUNIT("rad",SCode.PUBLIC(),SOME("m/m"),NONE(), SCodeUtil.dummyInfo),
132 SCode.DEFINEUNIT("sr",SCode.PUBLIC(),SOME("m2/m2"),NONE(), SCodeUtil.dummyInfo),
133 SCode.DEFINEUNIT("Hz",SCode.PUBLIC(),SOME("s-1"),SOME(0.8), SCodeUtil.dummyInfo),
134 SCode.DEFINEUNIT("N",SCode.PUBLIC(),SOME("m.kg.s-2"),NONE(), SCodeUtil.dummyInfo),
135 SCode.DEFINEUNIT("Pa",SCode.PUBLIC(),SOME("N/m2"),NONE(), SCodeUtil.dummyInfo),
136 SCode.DEFINEUNIT("W",SCode.PUBLIC(),SOME("J/s"),NONE(), SCodeUtil.dummyInfo),
137 SCode.DEFINEUNIT("J",SCode.PUBLIC(),SOME("N.m"),NONE(), SCodeUtil.dummyInfo),
138 SCode.DEFINEUNIT("C",SCode.PUBLIC(),SOME("s.A"),NONE(), SCodeUtil.dummyInfo),
139 SCode.DEFINEUNIT("V",SCode.PUBLIC(),SOME("W/A"),NONE(), SCodeUtil.dummyInfo),
140 SCode.DEFINEUNIT("F",SCode.PUBLIC(),SOME("C/V"),NONE(), SCodeUtil.dummyInfo),
141 SCode.DEFINEUNIT("Ohm",SCode.PUBLIC(),SOME("V/A"),NONE(), SCodeUtil.dummyInfo),
142 SCode.DEFINEUNIT("S",SCode.PUBLIC(),SOME("A/V"),NONE(), SCodeUtil.dummyInfo),
143 SCode.DEFINEUNIT("Wb",SCode.PUBLIC(),SOME("V.s"),NONE(), SCodeUtil.dummyInfo),
144 SCode.DEFINEUNIT("T",SCode.PUBLIC(),SOME("Wb/m2"),NONE(), SCodeUtil.dummyInfo),
145 SCode.DEFINEUNIT("H",SCode.PUBLIC(),SOME("Wb/A"),NONE(), SCodeUtil.dummyInfo),
146 SCode.DEFINEUNIT("lm",SCode.PUBLIC(),SOME("cd.sr"),NONE(), SCodeUtil.dummyInfo),
147 SCode.DEFINEUNIT("lx",SCode.PUBLIC(),SOME("lm/m2"),NONE(), SCodeUtil.dummyInfo),
148 SCode.DEFINEUNIT("Bq",SCode.PUBLIC(),SOME("s-1"),SOME(0.8), SCodeUtil.dummyInfo),
149 SCode.DEFINEUNIT("Gy",SCode.PUBLIC(),SOME("J/kg"),NONE(), SCodeUtil.dummyInfo),
150 SCode.DEFINEUNIT("Sv",SCode.PUBLIC(),SOME("cd.sr"),NONE(), SCodeUtil.dummyInfo),
151 SCode.DEFINEUNIT("kat",SCode.PUBLIC(),SOME("s-1.mol"),NONE(), SCodeUtil.dummyInfo)
152 }); then ();
153 ✗ else algorithm registerUnitWeightDefineunits2(du); then ();
154 end match;
155 end registerUnitWeightDefineunits;
156
157
158 protected function registerUnitWeightDefineunits2 "help function to registerUnitWeightDefineunits"
159 input list<SCode.Element> idu;
160 algorithm
161 () := match idu
162 local String n; Real w; list<SCode.Element> du;
163 case SCode.DEFINEUNIT(name=n,weight = SOME(w))::du algorithm
164 ✗ UnitParserExt.registerWeight(n,w);
165 ✗ registerUnitWeightDefineunits2(du);
166 then ();
167 case SCode.DEFINEUNIT(weight = NONE())::du algorithm
168 ✗ registerUnitWeightDefineunits2(du);
169 then ();
170 case _::du algorithm
171 ✗ registerUnitWeightDefineunits2(du);
172 then ();
173 case {} then ();
174
175 end match;
176 end registerUnitWeightDefineunits2;
177
178 public function registerUnits "traverses the Absyn.Program and registers all defineunits.
179 Note: this requires that instantiation is done on a 'total program', so only defineunits that
180 are referenced in the model are picked up
181 "
182 input Absyn.Program prg;
183 algorithm
184 () := match prg
185 case _
186 algorithm
187 // phi: very old unit checking
188 /*
189 true = Flags.getConfigBool(Flags.UNIT_CHECKING);
190 ((_,_,_)) = AbsynUtil.traverseClasses(prg,NONE(),registerUnitInClass,0,false); // defineunits must be in public section.
191 */
192 then ();
193
194 else
195 algorithm
196 ✗ false := Flags.getConfigBool(Flags.UNIT_CHECKING);
197 then ();
198 end match;
199 end registerUnits;
200
201 protected function registerUnitInClass " help function to registerUnits"
202 input tuple<Absyn.Class,Option<Absyn.Path>,Integer> inTpl;
203 output tuple<Absyn.Class,Option<Absyn.Path>,Integer> outTpl;
204 algorithm
205 outTpl := matchcontinue inTpl
206 local Absyn.Class cl;
207 Option<Absyn.Path> pa;
208 Integer i;
209 list<Absyn.Element> defunits;
210 list<Absyn.ElementItem> elts;
211 case (cl as Absyn.CLASS(),pa,i) algorithm
212 ✗ elts := AbsynUtil.getElementItemsInClass(cl);
213 ✗ defunits := AbsynUtil.getDefineUnitsInElements(elts);
214 ✗ registerDefineunits(defunits);
215 ✗ then ((cl,pa,i));
216 ✗ case (cl,pa,i) then ((cl,pa,i));
217 end matchcontinue;
218 end registerUnitInClass;
219
220 protected function registerDefineunits "help function to registerUnitInClass"
221 input list<Absyn.Element> elts;
222 algorithm
223 () := matchcontinue elts
224 local case {}
225 ✗ algorithm registerDefineunits2({
226 Absyn.DEFINEUNIT("m",{}, Absyn.dummyInfo),
227 Absyn.DEFINEUNIT("kg",{}, Absyn.dummyInfo),
228 Absyn.DEFINEUNIT("s",{}, Absyn.dummyInfo),
229 Absyn.DEFINEUNIT("A",{}, Absyn.dummyInfo),
230 Absyn.DEFINEUNIT("k",{}, Absyn.dummyInfo),
231 Absyn.DEFINEUNIT("mol",{}, Absyn.dummyInfo),
232 Absyn.DEFINEUNIT("cd",{}, Absyn.dummyInfo),
233 Absyn.DEFINEUNIT("rad",{Absyn.NAMEDARG("exp",Absyn.STRING("m/m"))}, Absyn.dummyInfo),
234 Absyn.DEFINEUNIT("sr",{Absyn.NAMEDARG("exp",Absyn.STRING("m2/m2"))}, Absyn.dummyInfo),
235 Absyn.DEFINEUNIT("Hz",{Absyn.NAMEDARG("exp",Absyn.STRING("s-1")),Absyn.NAMEDARG("weight",Absyn.REAL("0.8"))}, Absyn.dummyInfo),
236 Absyn.DEFINEUNIT("N",{Absyn.NAMEDARG("exp",Absyn.STRING("m.kg.s-2"))}, Absyn.dummyInfo),
237 Absyn.DEFINEUNIT("Pa",{Absyn.NAMEDARG("exp",Absyn.STRING("N/m2"))}, Absyn.dummyInfo),
238 Absyn.DEFINEUNIT("W",{Absyn.NAMEDARG("exp",Absyn.STRING("J/s"))}, Absyn.dummyInfo),
239 Absyn.DEFINEUNIT("J",{Absyn.NAMEDARG("exp",Absyn.STRING("N.m"))}, Absyn.dummyInfo),
240 Absyn.DEFINEUNIT("C",{Absyn.NAMEDARG("exp",Absyn.STRING("s.A"))}, Absyn.dummyInfo),
241 Absyn.DEFINEUNIT("V",{Absyn.NAMEDARG("exp",Absyn.STRING("W/A"))}, Absyn.dummyInfo),
242 Absyn.DEFINEUNIT("F",{Absyn.NAMEDARG("exp",Absyn.STRING("C/V"))}, Absyn.dummyInfo),
243 Absyn.DEFINEUNIT("Ohm",{Absyn.NAMEDARG("exp",Absyn.STRING("V/A"))}, Absyn.dummyInfo),
244 Absyn.DEFINEUNIT("S",{Absyn.NAMEDARG("exp",Absyn.STRING("A/V"))}, Absyn.dummyInfo),
245 Absyn.DEFINEUNIT("Wb",{Absyn.NAMEDARG("exp",Absyn.STRING("V.s"))}, Absyn.dummyInfo),
246 Absyn.DEFINEUNIT("T",{Absyn.NAMEDARG("exp",Absyn.STRING("Wb/m2"))}, Absyn.dummyInfo),
247 Absyn.DEFINEUNIT("H",{Absyn.NAMEDARG("exp",Absyn.STRING("Wb/A"))}, Absyn.dummyInfo),
248 Absyn.DEFINEUNIT("lm",{Absyn.NAMEDARG("exp",Absyn.STRING("cd.sr"))}, Absyn.dummyInfo),
249 Absyn.DEFINEUNIT("lx",{Absyn.NAMEDARG("exp",Absyn.STRING("lm/m2"))}, Absyn.dummyInfo),
250 Absyn.DEFINEUNIT("Bq",{Absyn.NAMEDARG("exp",Absyn.STRING("s-1")),Absyn.NAMEDARG("weight",Absyn.REAL("0.8"))}, Absyn.dummyInfo),
251 Absyn.DEFINEUNIT("Gy",{Absyn.NAMEDARG("exp",Absyn.STRING("J/kg"))}, Absyn.dummyInfo),
252 Absyn.DEFINEUNIT("Sv",{Absyn.NAMEDARG("exp",Absyn.STRING("cd.sr"))}, Absyn.dummyInfo),
253 Absyn.DEFINEUNIT("kat",{Absyn.NAMEDARG("exp",Absyn.STRING("s-1.mol"))}, Absyn.dummyInfo)
254 });
255 then ();
256
257 else
258 algorithm
259 ✗ registerDefineunits2(elts);
260 then ();
261 end matchcontinue;
262 end registerDefineunits;
263
264 protected function registerDefineunits2 "help function to registerUnitInClass"
265 input list<Absyn.Element> elts;
266 algorithm
267 () := matchcontinue elts
268 local
269 String exp,name;
270 Absyn.Element du;
271 list<Absyn.Element> rest;
272
273 case {} then ();
274 /* Derived unit with weigth */
275 /*case((du as Absyn.DEFINEUNIT(name=_))::elts) equation
276 {SCode.DEFINEUNIT(name,SOME(exp),_)} = AbsynToSCode.translateElement(du,false);
277 UnitParserExt.addDerivedWeight(name,exp,weight);
278 registerDefineunits(elts);
279 then ();*/
280
281 /* Derived unit without weigth */
282 case (du as Absyn.DEFINEUNIT())::rest
283 algorithm
284 ✗ {SCode.DEFINEUNIT(name,_,SOME(exp),_)} := AbsynToSCode.translateElement(du,SCode.PUBLIC());
285 ✗ UnitParserExt.addDerived(name,exp);
286 ✗ registerDefineunits2(rest);
287 then ();
288
289 /* base unit does not not have weight*/
290 case (du as Absyn.DEFINEUNIT())::rest
291 algorithm
292 ✗ {SCode.DEFINEUNIT(name,_,NONE(),_)} := AbsynToSCode.translateElement(du,SCode.PUBLIC());
293 ✗ UnitParserExt.addBase(name);
294 ✗ registerDefineunits2(rest);
295 then ();
296
297 else
298 algorithm
299 ✗ print("registerDefineunits failed\n");
300 ✗ then fail();
301 end matchcontinue;
302 end registerDefineunits2;
303
304 public function add "Adds a unit to the UnitAbsyn.Store"
305 input UnitAbsyn.Unit unit;
306 input UnitAbsyn.Store ist;
307 output UnitAbsyn.Store outSt;
308 output Integer index;
309 algorithm
310 (outSt,index) := matchcontinue ist
311 local array<Option<UnitAbsyn.Unit>> vector; Integer newIndx,numElts; UnitAbsyn.Store st;
312 case st as UnitAbsyn.STORE(storeVector=vector,numElts = numElts) algorithm
313 ✗ true := numElts == arrayLength(vector);
314 ✗ st := expandStore(st);
315 ✗ (st,index) := add(unit,st);
316 then (st,index);
317 case UnitAbsyn.STORE(storeVector=vector,numElts = numElts) algorithm
318 ✗ newIndx := numElts+1;
319 ✗ vector := arrayUpdate(vector,newIndx,SOME(unit));
320 ✗ then (UnitAbsyn.STORE(vector,newIndx),newIndx);
321 end matchcontinue;
322 end add;
323
324 public function updateInstStore " "
325 input UnitAbsyn.InstStore store;
326 input UnitAbsyn.Store st;
327 output UnitAbsyn.InstStore outStore;
328 algorithm
329 outStore := match store
330 local HashTable.HashTable ht; Option<UnitAbsyn.UnitCheckResult> res;
331 ✗ case UnitAbsyn.INSTSTORE(_,ht,res) then UnitAbsyn.INSTSTORE(st,ht,res);
332 case UnitAbsyn.NOSTORE() then UnitAbsyn.NOSTORE();
333 end match;
334 end updateInstStore;
335
336 protected function expandStore "Expands store to make room for more entries.
337 Expansion factor: 1.4
338 "
339 input UnitAbsyn.Store st;
340 output UnitAbsyn.Store outSt;
341 algorithm
342 outSt := match st
343 local array<Option<UnitAbsyn.Unit>> vector; Integer indx,incr;
344 case UnitAbsyn.STORE(vector,indx) algorithm
345 ✗ incr := intMin(1,realInt(intReal(indx) * 0.4));
346 ✗ vector := Array.expand(incr,vector,NONE());
347 ✗ then UnitAbsyn.STORE(vector,indx);
348 end match;
349 end expandStore;
350
351
352 public function update "Updates unit at index in UnitAbsyn.Store"
353 input UnitAbsyn.Unit unit;
354 input Integer index;
355 input UnitAbsyn.Store st;
356 output UnitAbsyn.Store outSt;
357 algorithm
358 outSt := matchcontinue st
359 local array<Option<UnitAbsyn.Unit>> vector; Integer indx;
360 case UnitAbsyn.STORE(vector,indx) algorithm
361 ✗ vector := arrayUpdate(vector,index,SOME(unit)) "destroys ";
362 ✗ then UnitAbsyn.STORE(vector,indx);
363
364 else algorithm
365 ✗ print("storing unit at index ");print(intString(index));print(" failed\n");
366 ✗ then fail();
367 end matchcontinue;
368 end update;
369
370 public function find "finds a unit in the UnitAbsyn.Store given an index"
371 input Integer index;
372 input UnitAbsyn.Store st;
373 output UnitAbsyn.Unit unit;
374 algorithm
375 unit := matchcontinue st
376 local
377 array<Option<UnitAbsyn.Unit>> vector;
378 case UnitAbsyn.STORE(vector,_) algorithm
379 ✗ SOME(unit) := vector[index];
380 then unit;
381 else algorithm
382 ✗ print(" finding store at index ");print(intString(index));
383 ✗ print(" failed\n");
384 ✗ then fail();
385 end matchcontinue;
386 end find;
387
388 public function instGetStore "Retrives the Store from an InstStore"
389 input UnitAbsyn.InstStore store;
390 output UnitAbsyn.Store st;
391 algorithm
392 st := match store
393 case UnitAbsyn.INSTSTORE(st,_,_) then st;
394 ✗ case UnitAbsyn.NOSTORE() then emptyStore();
395 end match;
396 end instGetStore;
397
398 public function emptyInstStore "returns an empty InstStore"
399 output UnitAbsyn.InstStore st;
400 algorithm
401 // phi: very old unit checking
402 98175 st := emptyInstStore2(/*Flags.getConfigBool(Flags.UNIT_CHECKING)*/false);
403 end emptyInstStore;
404
405 protected function emptyInstStore2 "returns an empty InstStore"
406 input Boolean wantInstStore;
407 output UnitAbsyn.InstStore st;
408 algorithm
409 st := match wantInstStore
410 local
411 UnitAbsyn.Store s;
412 HashTable.HashTable ht;
413 case true
414 algorithm
415 ✗ s := emptyStore();
416 ✗ ht := HashTable.emptyHashTable();
417 ✗ then UnitAbsyn.INSTSTORE(s,ht,NONE());
418 else UnitAbsyn.noStore;
419 end match;
420 end emptyInstStore2;
421
422 public function emptyStore "Returns an empty store with 10 empty array elements"
423 output UnitAbsyn.Store st;
424 protected
425 array<Option<UnitAbsyn.Unit>> vector;
426 algorithm
427 ✗ vector := arrayCreate(10,NONE());
428 ✗ st := UnitAbsyn.STORE(vector,0);
429 end emptyStore;
430
431 public function printTerms "print the terms to stdout"
432 input UnitAbsyn.UnitTerms terms;
433 algorithm
434 ✗ print(printTermsStr(terms));
435 end printTerms;
436
437 public function printTermsStr "print the terms to a string"
438 input UnitAbsyn.UnitTerms terms;
439 output String str;
440 algorithm
441 ✗ str := "{" + stringDelimitList(List.map(terms,printTermStr),",") + "}";
442 end printTermsStr;
443
444 public function printTermStr "print one term to a string"
445 input UnitAbsyn.UnitTerm term;
446 output String str;
447 algorithm
448 str := match term
449 local String s1;
450 DAE.Exp e;
451 case UnitAbsyn.ADD(_,_,e) algorithm
452 ✗ s1 := ExpressionBasics.printExpStr(e);
453 then s1;
454
455 case UnitAbsyn.SUB(_,_,e) algorithm
456 ✗ s1 := ExpressionBasics.printExpStr(e);
457 then s1;
458
459 case UnitAbsyn.MUL(_,_,e) algorithm
460 ✗ s1 := ExpressionBasics.printExpStr(e);
461 then s1;
462
463 case UnitAbsyn.DIV(_,_,e) algorithm
464 ✗ s1 := ExpressionBasics.printExpStr(e);
465 then s1;
466
467 case UnitAbsyn.EQN(_,_,e) algorithm
468 ✗ s1 := ExpressionBasics.printExpStr(e);
469 then s1;
470
471 case UnitAbsyn.LOC(_,e) algorithm
472 ✗ s1 := ExpressionBasics.printExpStr(e);
473 then s1;
474
475 case UnitAbsyn.POW(_,MMath.RATIONAL(_,_),e) algorithm
476 ✗ s1 := ExpressionBasics.printExpStr(e);
477 then s1;
478
479 end match;
480 end printTermStr;
481
482 public function printInstStore "prints the inst store to stdout"
483 input UnitAbsyn.InstStore st;
484 algorithm
485 () := match st
486 local UnitAbsyn.Store s; HashTable.HashTable h;
487 case UnitAbsyn.INSTSTORE(s,h,_) algorithm
488 ✗ print("instStore, s:");
489 ✗ printStore(s);
490 ✗ print("\nht:");
491 ✗ BaseHashTable.dumpHashTable(h);
492 then ();
493 case UnitAbsyn.NOSTORE() then ();
494 end match;
495 end printInstStore;
496
497 public function printStore "prints the store to stdout"
498 input UnitAbsyn.Store st;
499 algorithm
500 () := match st
501 local array<Option<UnitAbsyn.Unit>> vector; list<Option<UnitAbsyn.Unit>> lst;
502 case UnitAbsyn.STORE(vector,_) algorithm
503 ✗ lst := arrayList(vector);
504 ✗ printStore2(lst,1);
505 then ();
506 end match;
507 end printStore;
508
509 protected function printStore2 "help function to printStore"
510 input list<Option<UnitAbsyn.Unit>> lst;
511 input Integer indx;
512 algorithm
513 () := match lst
514 local
515 UnitAbsyn.Unit unit;
516 list<Option<UnitAbsyn.Unit>> rest;
517 case {} then ();
518
519 case SOME(unit)::rest algorithm
520 ✗ print(intString(indx));print("->");
521 ✗ printUnit(unit);
522 ✗ print("\n");
523 ✗ printStore2(rest,indx+1);
524 then();
525 case NONE()::_ then ();
526 end match;
527 end printStore2;
528
529 protected function printUnit "prints a unit to stdout (only for debugging)"
530 input UnitAbsyn.Unit unit;
531 algorithm
532 () := matchcontinue unit
533 local list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> typeparams;
534 list<MMath.Rational> baseunits;
535 /*case(unit) equation
536 print(unit2str(unit));
537 then();*/
538 case UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},baseunits)) algorithm
539 ✗ print(printBaseUnitsStr(baseunits));
540 ✗ print(" [");print(unit2str(unit)); print("]");
541 then();
542 case UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(typeparams,baseunits)) algorithm
543 ✗ print(stringDelimitList(List.map(typeparams,printTypeParameterStr),","));
544 ✗ print(printBaseUnitsStr(baseunits));
545 ✗ print(" [");print(unit2str(unit)); print("]");
546 then();
547 case UnitAbsyn.UNSPECIFIED() algorithm
548 ✗ print("Unspecified");
549 then ();
550 end matchcontinue;
551 end printUnit;
552
553 protected function printBaseUnitsStr "help function to printUnit"
554 input list<MMath.Rational> lst;
555 output String str;
556 algorithm
557 str := match lst
558 local Integer i1,i2,i3,i4;
559 case MMath.RATIONAL(i1,i2)::MMath.RATIONAL(i3,i4)::_ algorithm
560 ✗ str := "m^("+intString(i1)+"/"+intString(i2)+")"
561 + "s^("+intString(i3)+"/"+intString(i4)+")" ;
562 then str;
563 case {} then "";
564 ✗ else "printBaseUnitsStr failed len:" + intString(listLength(lst)) + "\n";
565 end match;
566 end printBaseUnitsStr;
567
568 protected function printTypeParameterStr "help function to printUnit"
569 input tuple<MMath.Rational,UnitAbsyn.TypeParameter> typeParam;
570 output String str;
571 algorithm
572 str := match typeParam
573 local String name; Integer i1,i2,indx;
574 case (MMath.RATIONAL(0,0),UnitAbsyn.TYPEPARAMETER(name,indx)) algorithm
575 ✗ str := name + "[indx =" + intString(indx) + "]";
576 then str;
577 case (MMath.RATIONAL(i1,1),UnitAbsyn.TYPEPARAMETER(name,indx)) algorithm
578 ✗ str := name + "^" + intString(i1) + "[indx=" + intString(indx) + "]";
579 then str;
580 case (MMath.RATIONAL(i1,i2),UnitAbsyn.TYPEPARAMETER(name,indx)) algorithm
581 ✗ str := name+ "^("+ intString(i1) + "/" + intString(i2)+")" + "[indx=" + intString(indx) + "]";
582 then str;
583 end match;
584 end printTypeParameterStr;
585
586 public function splitRationals "splits a list of Rationals into a list of numerators and denominators"
587 input list<MMath.Rational> inRationals;
588 output list<Integer> nums;
589 output list<Integer> denoms;
590 algorithm
591 (nums,denoms) := match inRationals
592 local Integer i1,i2; list<MMath.Rational> rationals;
593 case {} then ({},{});
594 case MMath.RATIONAL(i1,i2)::rationals algorithm
595 ✗ (nums,denoms) := splitRationals(rationals);
596 ✗ then (i1::nums,i2::denoms);
597 end match;
598 end splitRationals;
599
600 public function joinRationals "joins a lists of numerators and denominators into list of Rationals"
601 input list<Integer> inums;
602 input list<Integer> idenoms;
603 output list<MMath.Rational> rationals;
604 algorithm
605 rationals := match(inums,idenoms)
606 local Integer i1,i2; list<Integer> nums,denoms;
607 case({},{}) then ({});
608 case(i1::nums,i2::denoms) algorithm
609 8806 rationals := joinRationals(nums,denoms);
610 8806 then (MMath.RATIONAL(i1,i2)::rationals);
611 end match;
612 end joinRationals;
613
614 public function joinTypeParams "creates type parameter lists from list of numerators , denominators and typeparameter names"
615 input list<Integer> inums;
616 input list<Integer> idenoms;
617 input list<String> itpstrs;
618 input Option<Integer> funcInstIdOpt;
619 output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> typeParams;
620 algorithm
621 typeParams := match(inums, idenoms, itpstrs)
622 local Integer i1,i2; String tpParam,s; list<Integer> nums, denoms; list<String> tpstrs;
623 case({}, {}, {}) then {};
624 case(i1::nums, i2::denoms, tpParam::tpstrs) algorithm
625 ✗ typeParams := joinTypeParams(nums,denoms,tpstrs,funcInstIdOpt);
626 ✗ s := Util.applyOptionOrDefault(funcInstIdOpt, intString, "");
627 ✗ tpParam := tpParam + s;
628 ✗ then (MMath.RATIONAL(i1,i2),UnitAbsyn.TYPEPARAMETER(tpParam,0))::typeParams;
629 end match;
630 end joinTypeParams;
631
632 public function splitTypeParams "splits type parameter lists into numerators, denominators and typeparameter names"
633 input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> iTypeParams;
634 output list<Integer> nums;
635 output list<Integer> denoms;
636 output list<String> tpstrs;
637 algorithm
638 (nums,denoms,tpstrs) := match iTypeParams
639 local String tpParam; Integer i1,i2; list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> typeParams;
640 case {} then ({},{},{});
641 case (MMath.RATIONAL(i1,i2),UnitAbsyn.TYPEPARAMETER(tpParam,_))::typeParams algorithm
642 ✗ (nums,denoms,tpstrs) := splitTypeParams(typeParams);
643 ✗ then (i1::nums,i2::denoms,tpParam::tpstrs);
644 end match;
645 end splitTypeParams;
646
647 public function instBuildUnitTerms "builds unit terms and stores for a DAE. It also returns a hashtable that maps
648 variable names to store locations."
649 input FCore.Graph env;
650 input DAE.DAElist dae;
651 input DAE.DAElist compDae "to collect variable bindings";
652 input UnitAbsyn.InstStore store;
653 output UnitAbsyn.InstStore outStore;
654 output UnitAbsyn.UnitTerms terms;
655 algorithm
656 (outStore,terms) := matchcontinue store
657 local
658 UnitAbsyn.Store st;
659 HashTable.HashTable ht;
660 UnitAbsyn.UnitTerms terms2;
661 Option<UnitAbsyn.UnitCheckResult> res;
662 case UnitAbsyn.NOSTORE() then (UnitAbsyn.NOSTORE(),{});
663 case UnitAbsyn.INSTSTORE(st,ht,res)
664 algorithm
665 ✗ (terms,st) := buildTerms(env,dae,ht,st);
666 ✗ (terms2,st) := buildTerms(env,compDae,ht,st) "to get bindings of scalar variables";
667 ✗ terms := listReverse(terms);
668 ✗ terms := List.append_reverse(terms2,terms);
669 //print("built terms, store :"); printStore(st);
670 //print("ht =");BaseHashTable.dumpHashTable(ht);
671 ✗ st := createTypeParameterLocations(st);
672 // print("built type param, store :"); printStore(st);
673 ✗ then (UnitAbsyn.INSTSTORE(st,ht,res),terms);
674 else algorithm
675 ✗ print("instBuildUnitTerms failed!!\n");
676 ✗ then fail();
677 end matchcontinue;
678 end instBuildUnitTerms;
679
680
681 public function buildUnitTerms "builds unit terms and stores for a DAE. It also returns a hashtable that maps
682 variable names to store locations."
683 input FCore.Graph env;
684 input DAE.DAElist dae;
685 output UnitAbsyn.UnitTerms terms;
686 output UnitAbsyn.Store store;
687 output HashTable.HashTable ht;
688 algorithm
689 ✗ (store,ht) := buildStores(dae);
690 ✗ (terms,store) := buildTerms(env,dae,ht,store);
691 ✗ store := createTypeParameterLocations(store);
692 end buildUnitTerms;
693
694 public function instAddStore "Called when instantiating a Real class"
695 input UnitAbsyn.InstStore istore;
696 input DAE.Type itp;
697 input DAE.ComponentRef cr;
698 output UnitAbsyn.InstStore outStore;
699 algorithm
700 outStore := matchcontinue(istore, itp)
701 local
702 UnitAbsyn.Store st;
703 HashTable.HashTable ht;
704 String unitStr;
705 UnitAbsyn.Unit unit; Integer indx;
706 list<DAE.Var> varLst;
707 Option<UnitAbsyn.UnitCheckResult> res;
708 UnitAbsyn.InstStore store;
709 DAE.Type tp;
710
711 case(UnitAbsyn.NOSTORE(), _)
712 then istore;
713
714 case(UnitAbsyn.INSTSTORE(st,ht,res), DAE.T_REAL(varLst = varLst))
715 algorithm
716 ✗ for v in varLst loop
717 () := match v
718 case DAE.TYPES_VAR(name="unit",binding = DAE.EQBOUND(exp=DAE.SCONST(unitStr)))
719 algorithm
720 ✗ unit := str2unit(unitStr,NONE());
721 ✗ unit := if 0 == stringCompare(unitStr,"") then UnitAbsyn.UNSPECIFIED() else unit;
722 ✗ (st,indx) := add(unit,st);
723 ✗ ht := BaseHashTable.add((cr,indx),ht);
724 ✗ outStore := UnitAbsyn.INSTSTORE(st,ht,res);
725 ✗ return;
726 then ();
727 else ();
728 end match;
729 end for;
730 ✗ (st,indx) := add(UnitAbsyn.UNSPECIFIED(),st);
731 ✗ ht := BaseHashTable.add((cr,indx),ht);
732 ✗ then UnitAbsyn.INSTSTORE(st,ht,res);
733
734 case(store, DAE.T_SUBTYPE_BASIC(complexType=tp))
735 ✗ then instAddStore(store,tp,cr);
736 else istore;
737 end matchcontinue;
738 end instAddStore;
739
740 public function storeSize "return the number of elements of the store"
741 input UnitAbsyn.Store store;
742 output Integer size;
743 algorithm
744 size := match store
745 case UnitAbsyn.STORE(_,size) then size;
746 end match;
747 end storeSize;
748
749 protected function createTypeParameterLocations "for each unique type parameter, create an UNSPECIFIED unit
750 and add to the store."
751 input UnitAbsyn.Store store;
752 output UnitAbsyn.Store outStore;
753 protected
754 Integer nextElement, storeSz;
755 algorithm
756 ✗ storeSz := storeSize(store);
757 ✗ (outStore,_,nextElement) := createTypeParameterLocations2(store,HashTable.emptyHashTable(),1,storeSz+1);
758 ✗ outStore := addUnspecifiedStores((nextElement -storeSz) -1,outStore);
759 end createTypeParameterLocations;
760
761 protected function addUnspecifiedStores " adds n unspecified"
762 input Integer n;
763 input UnitAbsyn.Store istore;
764 output UnitAbsyn.Store outStore;
765 algorithm
766 outStore := matchcontinue(n,istore)
767 local UnitAbsyn.Store store;
768 case(0,store) then store;
769 case(_,_) algorithm
770 ✗ true := n < 0;
771 ✗ print("addUnspecifiedStores n < 0!\n");
772 ✗ then fail();
773 case(_,store) algorithm
774 ✗ true := n > 0;
775 ✗ (store,_) := add(UnitAbsyn.UNSPECIFIED(),store);
776 ✗ store := addUnspecifiedStores(n-1,store);
777 then store;
778 end matchcontinue;
779 end addUnspecifiedStores;
780
781 protected function createTypeParameterLocations2 "help function"
782 input UnitAbsyn.Store istore;
783 input HashTable.HashTable iht;
784 input Integer i "iterated";
785 input Integer inextElt;
786 output UnitAbsyn.Store outStore;
787 output HashTable.HashTable outHt;
788 output Integer outNextElt;
789 algorithm
790 (outStore,outHt,outNextElt) := matchcontinue(istore, iht, inextElt)
791 local
792 Integer numElts;
793 array<Option<UnitAbsyn.Unit>> vect;
794 UnitAbsyn.Unit unit;
795 UnitAbsyn.Store store;
796 HashTable.HashTable ht;
797 Integer nextElt;
798
799 case(store as UnitAbsyn.STORE(_,numElts), ht, nextElt) algorithm
800 ✗ true := i > numElts;
801 ✗ then (store,ht,nextElt);
802
803 case(UnitAbsyn.STORE(vect,numElts), ht, nextElt) algorithm
804 ✗ SOME(unit) := vect[i];
805 ✗ (unit,ht,nextElt) := createTypeParameterLocations3(unit,ht,nextElt);
806 ✗ vect := arrayUpdate(vect,i,SOME(unit));
807 ✗ (store,ht,nextElt) := createTypeParameterLocations2(UnitAbsyn.STORE(vect,numElts),ht,i+1,nextElt);
808 then (store,ht,nextElt);
809
810 case(UnitAbsyn.STORE(vect,numElts), ht, nextElt) algorithm
811 ✗ (store,ht,nextElt) := createTypeParameterLocations2(UnitAbsyn.STORE(vect,numElts),ht,i+1,nextElt);
812 then (store,ht,nextElt);
813 end matchcontinue;
814 end createTypeParameterLocations2;
815
816 protected function createTypeParameterLocations3 "help function to createTypeParameterLocations2"
817 input UnitAbsyn.Unit unit;
818 input HashTable.HashTable iht;
819 input Integer inextElt;
820 output UnitAbsyn.Unit outUnit;
821 output HashTable.HashTable outHt;
822 output Integer outNextElt;
823 algorithm
824 (outUnit,outHt,outNextElt) := match(unit,iht,inextElt)
825 local
826 list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params;
827 list<MMath.Rational> units;
828 HashTable.HashTable ht;
829 Integer nextElt;
830
831 // Only succeeds for units with type parameters
832 case(UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(params as _::_,units)),ht,nextElt) algorithm
833 ✗ (params,ht,nextElt) := createTypeParameterLocations4(params,ht,nextElt);
834 ✗ then (UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(params,units)),ht,nextElt);
835 end match;
836 end createTypeParameterLocations3;
837
838 protected function createTypeParameterLocations4 "help function to createTypeParameterLocations3"
839 input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> iparams;
840 input HashTable.HashTable iht;
841 input Integer inextElt;
842 output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> outParams;
843 output HashTable.HashTable outHt;
844 output Integer outNextElt;
845 algorithm
846 (outParams,outHt,outNextElt) := matchcontinue(iparams,iht,inextElt)
847 local
848 Integer indx; String name; MMath.Rational r;
849 tuple<MMath.Rational,UnitAbsyn.TypeParameter> param;
850 DAE.ComponentRef cref_;
851 list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params;
852 HashTable.HashTable ht;
853 Integer nextElt;
854
855 case({},ht,nextElt) then ({},ht,nextElt);
856
857 case((r,UnitAbsyn.TYPEPARAMETER(name,0))::params,ht,nextElt) algorithm
858 ✗ cref_ := ComponentReferenceBasics.makeCrefIdent(name,DAE.T_UNKNOWN_DEFAULT,{});
859 ✗ indx := BaseHashTable.get(cref_,ht);
860 ✗ (params,ht,nextElt) := createTypeParameterLocations4(params,ht,nextElt);
861 ✗ then ((r,UnitAbsyn.TYPEPARAMETER(name,indx))::params,ht,nextElt);
862
863 case((r,UnitAbsyn.TYPEPARAMETER(name,0))::params,ht,nextElt) algorithm
864 ✗ cref_ := ComponentReferenceBasics.makeCrefIdent(name,DAE.T_UNKNOWN_DEFAULT,{});
865 ✗ ht := BaseHashTable.add((cref_,nextElt),ht);
866 ✗ (params,ht,nextElt) := createTypeParameterLocations4(params,ht,nextElt);
867 ✗ then((r,UnitAbsyn.TYPEPARAMETER(name,nextElt))::params,ht,nextElt+1);
868
869 case(param::params,ht,nextElt) algorithm
870 ✗ (params,ht,nextElt) := createTypeParameterLocations4(params,ht,nextElt);
871 ✗ then(param::params,ht,nextElt);
872 else algorithm
873 ✗ print("createTypeParameterLocations4 failed\n");
874 ✗ then fail();
875 end matchcontinue;
876 end createTypeParameterLocations4;
877
878 protected function buildStores "builds the stores and creates a hashtable from variable names to store locations"
879 input DAE.DAElist dae;
880 output UnitAbsyn.Store store;
881 output HashTable.HashTable ht;
882 algorithm
883 ✗ (store,ht) := buildStores2(dae,emptyStore(),HashTable.emptyHashTable()) "Build stores from variables";
884 ✗ (store,ht) := buildStores3(dae,store,ht) "build stores from constants and function calls in expressions";
885 end buildStores;
886
887 protected function buildTerms "builds the unit terms from DAE elements (equations)"
888 input FCore.Graph env;
889 input DAE.DAElist dae;
890 input HashTable.HashTable ht;
891 input UnitAbsyn.Store istore;
892 output UnitAbsyn.UnitTerms terms;
893 output UnitAbsyn.Store outStore;
894 algorithm
895 (terms,outStore) := matchcontinue(dae, istore)
896 local
897 DAE.Exp e1,e2,crefExp1,crefExp2;
898 UnitAbsyn.UnitTerm ut1,ut2;
899 list<UnitAbsyn.UnitTerm> terms1,terms2;
900 DAE.ComponentRef cr1,cr2;
901 list<DAE.Element> elts;
902 UnitAbsyn.Store store;
903
904 ✗ case (DAE.DAE(elementLst={}), store) then ({},store);
905
906 case(DAE.DAE(elementLst=DAE.EQUATION(e1,e2,_)::elts), store) algorithm
907 ✗ (ut1,terms1,store) := buildTermExp(env,e1,false,ht,store);
908 ✗ (ut2,terms2,store) := buildTermExp(env,e2,false,ht,store);
909 ✗ (terms,store) := buildTerms(env,DAE.DAE(elts),ht,store);
910 ✗ terms := listAppend(terms1,listAppend(terms2,terms));
911 ✗ then (UnitAbsyn.EQN(ut1,ut2,DAE.BINARY(e1,DAE.SUB(DAE.T_REAL_DEFAULT),e2))::terms,store);
912
913 case(DAE.DAE(elementLst=DAE.EQUEQUATION(cr1,cr2,_)::elts), store) algorithm
914 ✗ crefExp1 := Expression.crefExp(cr1);
915 ✗ crefExp2 := Expression.crefExp(cr2);
916 ✗ (ut1,terms1,store) := buildTermExp(env,crefExp1,false,ht,store);
917 ✗ (ut2,terms2,store) := buildTermExp(env,crefExp2,false,ht,store);
918 ✗ (terms,store) := buildTerms(env,DAE.DAE(elts),ht,store);
919 ✗ terms := listAppend(terms1,listAppend(terms2,terms));
920 ✗ then
921 (UnitAbsyn.EQN(ut1,ut2,DAE.BINARY(crefExp1,DAE.SUB(DAE.T_REAL_DEFAULT),crefExp2))::terms,store);
922
923 /* Only consider variables with binding from this instance level, not furhter down */
924 case(DAE.DAE(elementLst=DAE.VAR(componentRef=cr1 as DAE.CREF_IDENT(_,_,_),binding = SOME(e1))::elts), store) algorithm
925 ✗ crefExp1 := Expression.crefExp(cr1);
926 ✗ (ut1,terms1,store) := buildTermExp(env,crefExp1,false,ht,store);
927 ✗ (ut2,terms2,store) := buildTermExp(env,e1,false,ht,store);
928 ✗ (terms,store) := buildTerms(env,DAE.DAE(elts),ht,store);
929 ✗ terms := listAppend(terms1,listAppend(terms2,terms));
930 ✗ then
931 (UnitAbsyn.EQN(ut1,ut2,DAE.BINARY(crefExp1,DAE.SUB(DAE.T_REAL_DEFAULT),e1))::terms,store);
932
933 case(DAE.DAE(elementLst=DAE.DEFINE(cr1,e1,_)::elts), store) algorithm
934 ✗ crefExp1 := Expression.crefExp(cr1);
935 ✗ (ut1,terms1,store) := buildTermExp(env,crefExp1,false,ht,store);
936 ✗ (ut2,terms2,store) := buildTermExp(env,e1,false,ht,store);
937 ✗ (terms,store) := buildTerms(env,DAE.DAE(elts),ht,store);
938 ✗ terms := listAppend(terms1,listAppend(terms2,terms));
939 ✗ then
940 (UnitAbsyn.EQN(ut1,ut2,DAE.BINARY(crefExp1,DAE.SUB(DAE.T_REAL_DEFAULT),e1))::terms,store);
941
942 case(DAE.DAE(elementLst=_::elts), store) algorithm
943 ✗ (terms,store) := buildTerms(env,DAE.DAE(elts),ht,store);
944 then (terms,store);
945 end matchcontinue;
946 end buildTerms;
947
948 protected function buildTermExp "help function to buildTerms, handles expressions"
949 input FCore.Graph env;
950 input DAE.Exp exp;
951 input Boolean idivOrMul "is true if surrounding expression is division or multiplication. In that case
952 the constant will be treated as dimensionless, otherwise it will be treated as unspecified
953 ";
954 input HashTable.HashTable iht;
955 input UnitAbsyn.Store istore;
956 output UnitAbsyn.UnitTerm ut;
957 output list<UnitAbsyn.UnitTerm> extraTerms "additional terms from e.g. function calls";
958 output UnitAbsyn.Store outStore;
959 algorithm
960 (ut,extraTerms,outStore) := matchcontinue(exp, idivOrMul, iht, istore)
961 local
962 Real r;
963 DAE.Operator op;
964 Integer indx,i;
965 UnitAbsyn.UnitTerm ut1,ut2;
966 String s1;
967 DAE.ComponentRef cr;
968 DAE.Exp e,e1,e2;
969 Absyn.Path path;
970 list<list<DAE.Exp>> mexpl;
971 list<UnitAbsyn.UnitTerm> terms1,terms2,terms,uts;
972 list<DAE.Exp> expl;
973 UnitAbsyn.Unit u;
974 HashTable.HashTable ht;
975 UnitAbsyn.Store store;
976 Boolean divOrMul;
977
978 /*case(env,e as DAE.RCONST(r),ht,store) equation
979 s1 = realString(r);
980 indx = BaseHashTable.get(ComponentReferenceBasics.makeCrefIdent(s1,DAE.T_UNKNOWN_DEFAULT,{}),ht);
981 then (UnitAbsyn.LOC(indx,e),{},store);*/
982
983 case(e as DAE.ICONST(i), divOrMul, ht, store) algorithm
984 ✗ s1 := "$"+intString(tick())+"_"+intString(i);
985 ✗ u := if divOrMul then str2unit("1",NONE()) else UnitAbsyn.UNSPECIFIED();
986 ✗ (store,indx) := add(u,store);
987 ✗ ht := BaseHashTable.add((ComponentReferenceBasics.makeCrefIdent(s1,DAE.T_UNKNOWN_DEFAULT,{}),indx),ht);
988 ✗ then (UnitAbsyn.LOC(indx,e),{},store);
989
990 /* for each constant, add new unspecified unit*/
991 case(e as DAE.RCONST(r), divOrMul, ht, store)algorithm
992 ✗ s1 := "$"+intString(tick())+"_"+realString(r);
993 ✗ u := if divOrMul then str2unit("1",NONE()) else UnitAbsyn.UNSPECIFIED();
994 ✗ (store,indx) := add(u,store);
995 ✗ ht := BaseHashTable.add((ComponentReferenceBasics.makeCrefIdent(s1,DAE.T_UNKNOWN_DEFAULT,{}),indx),ht);
996 ✗ then (UnitAbsyn.LOC(indx,e),{},store);
997
998 case(DAE.CAST(_,e1), divOrMul, ht, store) algorithm
999 ✗ (ut,terms,store) := buildTermExp(env,e1,divOrMul,ht,store);
1000 then (ut,terms,store);
1001
1002 case(e as DAE.CREF(cr,_), _, ht, store) algorithm
1003 ✗ indx := BaseHashTable.get(cr,ht);
1004 ✗ then (UnitAbsyn.LOC(indx,e),{},store);
1005
1006 /* special case for pow */
1007 case(e as DAE.BINARY(e1,DAE.POW(_),e2 as DAE.ICONST(i)), divOrMul, ht, store)
1008 algorithm
1009 ✗ (ut1,terms1,store) := buildTermExp(env,e1,divOrMul,ht,store);
1010 ✗ (_,terms2,store) := buildTermExp(env,e2,divOrMul,ht,store);
1011 ✗ terms := listAppend(terms1,terms2);
1012 ✗ ut := UnitAbsyn.POW(ut1,MMath.RATIONAL(i,1),e);
1013 ✗ then (ut,terms,store);
1014
1015 case(e as DAE.BINARY(e1,DAE.POW(_),e2 as DAE.RCONST(r)), divOrMul, ht, store)
1016 algorithm
1017 ✗ (ut1,terms1,store) := buildTermExp(env,e1,divOrMul,ht,store);
1018 ✗ (_,terms2,store) := buildTermExp(env,e2,divOrMul,ht,store);
1019 ✗ terms := listAppend(terms1,terms2);
1020 ✗ i := realInt(r);
1021 ✗ true := intReal(i) - r == 0.0;
1022 ✗ ut := UnitAbsyn.POW(ut1,MMath.RATIONAL(i,1),e);
1023 ✗ then (ut,terms,store);
1024
1025 case(e as DAE.BINARY(e1,op,e2), divOrMul, ht, store) algorithm
1026 ✗ divOrMul := Expression.operatorDivOrMul(op);
1027 ✗ (ut1,terms1,store) := buildTermExp(env,e1,divOrMul,ht,store);
1028 ✗ (ut2,terms2,store) := buildTermExp(env,e2,divOrMul,ht,store);
1029 ✗ terms := listAppend(terms1,terms2);
1030 ✗ ut := buildTermOp(ut1,ut2,op,e);
1031 ✗ then (ut,terms,store);
1032
1033 /* failed to build term for e2, use e1*/
1034 case(DAE.BINARY(e1,op,_), divOrMul, ht, store) algorithm
1035 ✗ divOrMul := Expression.operatorDivOrMul(op);
1036 ✗ (ut,terms,store) := buildTermExp(env,e1,divOrMul,ht,store);
1037 ✗ failure(buildTermExp(env,e1,divOrMul,ht,store));
1038 ✗ then (ut,terms,store);
1039
1040 /* failed to build term for e1, use e2*/
1041 case(DAE.BINARY(e1,op,e2), divOrMul, ht, store) algorithm
1042 ✗ divOrMul := Expression.operatorDivOrMul(op);
1043 ✗ failure(buildTermExp(env,e1,divOrMul,ht,store));
1044 ✗ (ut,terms,store) := buildTermExp(env,e2,divOrMul,ht,store);
1045 then (ut,terms,store);
1046
1047 case(DAE.UNARY(_,e1), divOrMul, ht, store) algorithm
1048 ✗ (ut,terms,store) := buildTermExp(env,e1,divOrMul,ht,store);
1049 then (ut,terms,store);
1050
1051 case(e as DAE.IFEXP(_,e1,e2), divOrMul, ht, store) algorithm
1052 ✗ divOrMul := false;
1053 ✗ (ut1,terms1,store) := buildTermExp(env,e1,divOrMul,ht,store);
1054 ✗ (ut2,terms2,store) := buildTermExp(env,e2,divOrMul,ht,store);
1055 ✗ terms := listAppend(terms1,terms2);
1056 ✗ then (UnitAbsyn.EQN(ut1,ut2,e),terms,store);
1057
1058 /* function call */
1059 case(e as DAE.CALL(path=path,expLst=expl), divOrMul, ht, store) algorithm
1060 ✗ divOrMul := false;
1061 ✗ (ut,terms,store) := buildTermCall(env,path,e,expl,divOrMul,ht,store);
1062 then (ut,terms,store);
1063
1064 /* Array, all elements must be of same dimension, since an array with different units in different positions
1065 can not be declared in Modelica, since modifiers on arrays must affect the whole array */
1066 case(e as DAE.ARRAY(_,_,expl), _, ht, store)
1067 algorithm
1068 ✗ print("vector ="+ExpressionBasics.printExpStr(e)+"\n");
1069 ✗ (uts,terms,store) := buildTermExpList(env,expl,ht,store);
1070 ✗ ut::uts := buildArrayElementTerms(uts,expl);
1071 ✗ uts := listAppend(terms,uts);
1072 ✗ then (ut,uts,store);
1073
1074 case(e as DAE.MATRIX(matrix=mexpl), _, ht, store)
1075 algorithm
1076 ✗ print("Matrix ="+ExpressionBasics.printExpStr(e)+"\n");
1077 ✗ expl := List.flatten(mexpl);
1078 ✗ (uts,terms,store) := buildTermExpList(env,expl,ht,store);
1079 ✗ ut::uts := buildArrayElementTerms(uts,expl);
1080 ✗ uts := listAppend(terms,uts);
1081 ✗ then (ut,uts,store);
1082
1083 case(e as DAE.CALL(), _, _, _) algorithm
1084 ✗ print("buildTermDAE.CALL failed exp: "+ExpressionBasics.printExpStr(e)+"\n");
1085 ✗ then fail();
1086 end matchcontinue;
1087 end buildTermExp;
1088
1089 protected function buildArrayElementTerms "help function to buildTermExpression. For each two terms from an array expression, it create
1090 and EQN to make the constraint that they must have the same unit"
1091 input list<UnitAbsyn.UnitTerm> iuts;
1092 input list<DAE.Exp> iexpl;
1093 output list<UnitAbsyn.UnitTerm> outUts = {};
1094 protected
1095 list<UnitAbsyn.UnitTerm> rest_ut = iuts;
1096 UnitAbsyn.UnitTerm ut1, ut2;
1097 DAE.Type ty;
1098 list<DAE.Exp> rest_expl = iexpl;
1099 DAE.Exp e1, e2;
1100 algorithm
1101 ✗ while not listEmpty(rest_ut) loop
1102 ✗ ut1 :: ut2 :: rest_ut := rest_ut;
1103 ✗ e1 :: e2 :: rest_expl := rest_expl;
1104 ✗ ty := Expression.typeof(e1);
1105 ✗ outUts := UnitAbsyn.EQN(ut1, ut2, DAE.ARRAY(ty, true, {e1, e2})) :: outUts;
1106 end while;
1107
1108 ✗ outUts := listReverse(outUts);
1109 end buildArrayElementTerms;
1110
1111 protected function buildTermCall "builds a term and additional terms from a function call"
1112 input FCore.Graph env;
1113 input Absyn.Path path;
1114 input DAE.Exp funcCallExp;
1115 input list<DAE.Exp> expl;
1116 input Boolean divOrMul;
1117 input HashTable.HashTable ht;
1118 input UnitAbsyn.Store istore;
1119 output UnitAbsyn.UnitTerm ut;
1120 output list<UnitAbsyn.UnitTerm> extraTerms "additional terms from e.g. function calls";
1121 output UnitAbsyn.Store outStore;
1122 algorithm
1123 (ut,extraTerms,outStore) := match istore
1124 local
1125 list<Integer> formalParamIndxs;
1126 Integer funcInstId;
1127 list<UnitAbsyn.UnitTerm> actTermLst,terms,extraTerms2;
1128 DAE.Type functp;
1129 UnitAbsyn.Store store;
1130
1131 case store algorithm
1132 ✗ (_,functp,_) := Lookup.lookupType(FCore.noCache(),env,path,NONE());
1133 ✗ funcInstId:=tick();
1134 ✗ (store,formalParamIndxs) := buildFuncTypeStores(functp,funcInstId,store);
1135 ✗ (actTermLst,extraTerms,store) := buildTermExpList(env,expl,ht,store);
1136 ✗ terms := buildFormal2ActualParamTerms(formalParamIndxs,actTermLst);
1137 ✗ ({ut},extraTerms2,store) := buildResultTerms(functp,funcInstId,funcCallExp,store);
1138 ✗ extraTerms := List.flatten({extraTerms, extraTerms2, terms});
1139 ✗ then (ut,extraTerms,store);
1140 end match;
1141 end buildTermCall;
1142
1143 protected function buildResultTerms "build stores and terms for assigning formal output arguments to
1144 new locations"
1145 input DAE.Type ifunctp;
1146 input Integer funcInstId;
1147 input DAE.Exp funcCallExp;
1148 input UnitAbsyn.Store istore;
1149 output list<UnitAbsyn.UnitTerm> terms;
1150 output list<UnitAbsyn.UnitTerm> extraTerms;
1151 output UnitAbsyn.Store outStore;
1152 algorithm
1153 (terms,extraTerms,outStore) := matchcontinue(ifunctp, istore)
1154 local
1155 String unitStr; UnitAbsyn.Unit unit; Integer indx,indx2; Boolean unspec;
1156 list<DAE.Type> typeLst;
1157 DAE.Type functp;
1158 UnitAbsyn.Store store;
1159 // Real
1160 case(DAE.T_FUNCTION(_,functp,_,_), store) algorithm
1161 ✗ unitStr := getUnitStr(functp);
1162 //print("Got unit='"+unitStr+"'\n");
1163 ✗ unspec := 0 == stringCompare(unitStr,"");
1164
1165 ✗ unit := str2unit(unitStr,SOME(funcInstId));
1166 ✗ unit := if unspec then UnitAbsyn.UNSPECIFIED() else unit;
1167 ✗ (store,indx) := add(unit,store);
1168 ✗ (store,indx2) := add(UnitAbsyn.UNSPECIFIED(),store);
1169 ✗ then ({UnitAbsyn.LOC(indx2,funcCallExp)},{UnitAbsyn.EQN(UnitAbsyn.LOC(indx2,funcCallExp),UnitAbsyn.LOC(indx,funcCallExp),funcCallExp)},store);
1170
1171 // Tuple
1172 case(DAE.T_FUNCTION(funcResultType=DAE.T_TUPLE(types = typeLst)), store) algorithm
1173 ✗ (terms,extraTerms,store) := buildTupleResultTerms(typeLst,funcInstId,funcCallExp,store);
1174 then (terms,extraTerms,store);
1175 else algorithm
1176 ✗ print("buildResultTerms failed\n");
1177 ✗ then fail();
1178 end matchcontinue;
1179 end buildResultTerms;
1180
1181 protected function buildTupleResultTerms "help function to buildResultTerms"
1182 input list<DAE.Type> ifunctps;
1183 input Integer funcInstId;
1184 input DAE.Exp funcCallExp;
1185 input UnitAbsyn.Store istore;
1186 output list<UnitAbsyn.UnitTerm> terms;
1187 output list<UnitAbsyn.UnitTerm> extraTerms;
1188 output UnitAbsyn.Store outStore;
1189 algorithm
1190 (terms,extraTerms,outStore) := match(ifunctps, istore)
1191 local
1192 list<UnitAbsyn.UnitTerm> terms1,terms2,extraTerms1,extraTerms2; DAE.Type tp;
1193 list<DAE.Type> functps;
1194 UnitAbsyn.Store store;
1195 case({}, store) then ({},{},store);
1196 case(tp::functps, store) algorithm
1197 ✗ (terms1,extraTerms1,store) := buildResultTerms(tp,funcInstId,funcCallExp,store);
1198 ✗ (terms2,extraTerms2,store) := buildTupleResultTerms(functps,funcInstId,funcCallExp,store);
1199 ✗ terms := listAppend(terms1,terms2);
1200 ✗ extraTerms := listAppend(extraTerms1,extraTerms2);
1201 ✗ then (terms,extraTerms,store);
1202 end match;
1203 end buildTupleResultTerms;
1204
1205 protected function buildTermExpList "build terms from list of expressions"
1206 input FCore.Graph env;
1207 input list<DAE.Exp> iexpl;
1208 input HashTable.HashTable ht;
1209 input UnitAbsyn.Store istore;
1210 output list<UnitAbsyn.UnitTerm> terms;
1211 output list<UnitAbsyn.UnitTerm> extraTerms;
1212 output UnitAbsyn.Store outStore;
1213 algorithm
1214 (terms,extraTerms,outStore) := matchcontinue(iexpl, istore)
1215 local
1216 DAE.Exp e;
1217 list<UnitAbsyn.UnitTerm> eterms1,eterms2;
1218 UnitAbsyn.UnitTerm ut;
1219 list<DAE.Exp> expl;
1220 UnitAbsyn.Store store;
1221
1222 case ({}, store) then ({},{},store);
1223 case(e::expl, store) algorithm
1224 ✗ (ut,eterms1,store) := buildTermExp(env,e,false,ht,store);
1225 ✗ (terms,eterms2,store) := buildTermExpList(env,expl,ht,store);
1226 ✗ extraTerms := listAppend(eterms1,eterms2);
1227 ✗ then (ut::terms,extraTerms,store);
1228 case(e::_, _) algorithm
1229 ✗ print("buildTermExpList failed for exp"+ExpressionBasics.printExpStr(e)+"\n");
1230 ✗ then fail();
1231 end matchcontinue;
1232 end buildTermExpList;
1233
1234
1235 protected function buildFuncTypeStores "help function to buildTermCall"
1236 input DAE.Type funcType;
1237 input Integer funcInstId "unique id for each function call to make unique type parameter names";
1238 input UnitAbsyn.Store istore;
1239 output UnitAbsyn.Store outStore;
1240 output list<Integer> indxs;
1241 algorithm
1242 (outStore,indxs) := matchcontinue(funcType, istore)
1243 local list<DAE.FuncArg> args; DAE.Type tp; UnitAbsyn.Store store;
1244 case(DAE.T_FUNCTION(funcArg = args), store) algorithm
1245 ✗ (store,indxs) := buildFuncTypeStores2(args,funcInstId,store);
1246 then (store,indxs);
1247 case(tp, _) algorithm
1248 ✗ print("buildFuncTypeStores failed, tp"+TypesDump.unparseType(tp)+"\n");
1249 ✗ then fail();
1250 end matchcontinue;
1251 end buildFuncTypeStores;
1252
1253 protected function buildFuncTypeStores2 "help function to buildFuncTypeStores"
1254 input list<DAE.FuncArg> ifargs;
1255 input Integer funcInstId;
1256 input UnitAbsyn.Store istore;
1257 output UnitAbsyn.Store outStore;
1258 output list<Integer> indxs;
1259 algorithm
1260 (outStore,indxs) := match(ifargs, istore)
1261 local
1262 String unitStr;
1263 Integer indx;
1264 DAE.Type tp;
1265 UnitAbsyn.Unit unit;
1266 list<DAE.FuncArg> fargs;
1267 UnitAbsyn.Store store;
1268
1269 case({}, store) then (store,{});
1270 case(DAE.FUNCARG(ty=tp)::fargs, store) algorithm
1271 ✗ unitStr := getUnitStr(tp);
1272
1273 ✗ unit := str2unit(unitStr,SOME(funcInstId));
1274 ✗ unit := if 0 == stringCompare(unitStr,"") then UnitAbsyn.UNSPECIFIED() else unit;
1275 ✗ (store,indx) := add(unit,store);
1276 ✗ (store,indxs) := buildFuncTypeStores2(fargs,funcInstId,store);
1277 ✗ then (store,indx::indxs);
1278 end match;
1279 end buildFuncTypeStores2;
1280
1281 protected function getUnitStr "help function to e.g. buildFuncTypeStores2, retrieve a unit string
1282 from a Type (must be T_REAL)"
1283 input DAE.Type itp;
1284 output String str;
1285 algorithm
1286 str := matchcontinue itp
1287 local
1288 list<DAE.Var> varLst;
1289 DAE.Type tp;
1290
1291 case DAE.T_REAL(varLst = varLst)
1292 algorithm
1293 ✗ for v in varLst loop
1294 () := match v
1295 ✗ case DAE.TYPES_VAR(name="unit",binding=DAE.EQBOUND(exp=DAE.SCONST(str))) algorithm return; then ();
1296 else ();
1297 end match;
1298 end for;
1299 then "";
1300 case DAE.T_INTEGER() then "";
1301 ✗ case DAE.T_ARRAY(ty=tp) then getUnitStr(tp);
1302 ✗ case tp algorithm print("getUnitStr for type "+TypesDump.unparseType(tp)+" failed\n"); then fail();
1303 end matchcontinue;
1304 end getUnitStr;
1305
1306 protected function buildFormal2ActualParamTerms " help function to buildTermCall"
1307 input list<Integer> iformalParamIndxs;
1308 input list<UnitAbsyn.UnitTerm> iactualParamIndxs;
1309 output UnitAbsyn.UnitTerms terms;
1310 algorithm
1311 terms := matchcontinue(iformalParamIndxs,iactualParamIndxs)
1312 local
1313 Integer loc1; UnitAbsyn.UnitTerm ut; DAE.Exp e;
1314 list<Integer> formalParamIndxs;
1315 list<UnitAbsyn.UnitTerm> actualParamIndxs;
1316
1317 case({},{}) then {};
1318 case(loc1::formalParamIndxs,ut::actualParamIndxs) algorithm
1319 ✗ terms := buildFormal2ActualParamTerms(formalParamIndxs,actualParamIndxs);
1320 ✗ e := origExpInTerm(ut);
1321 ✗ then UnitAbsyn.EQN(UnitAbsyn.LOC(loc1,e),ut,e)::terms;
1322 else algorithm
1323 ✗ print("buildFormal2ActualParamTerms failed\n");
1324 ✗ then fail();
1325 end matchcontinue;
1326 end buildFormal2ActualParamTerms;
1327
1328 protected function origExpInTerm "Returns the origExp of a term"
1329 input UnitAbsyn.UnitTerm ut;
1330 output DAE.Exp origExp;
1331 algorithm
1332 origExp := match ut local DAE.Exp e;
1333 case UnitAbsyn.ADD(_,_,e) then e;
1334 case UnitAbsyn.SUB(_,_,e) then e;
1335 case UnitAbsyn.MUL(_,_,e) then e;
1336 case UnitAbsyn.DIV(_,_,e) then e;
1337 case UnitAbsyn.EQN(_,_,e) then e;
1338 case UnitAbsyn.LOC(_,e) then e;
1339 case UnitAbsyn.POW(_,_,e) then e;
1340 end match;
1341 end origExpInTerm;
1342
1343 protected function buildTermOp "Takes two UnitTerms and and DAE.Operator and creates a new UnitTerm "
1344 input UnitAbsyn.UnitTerm ut1;
1345 input UnitAbsyn.UnitTerm ut2;
1346 input DAE.Operator op;
1347 input DAE.Exp origExp;
1348 output UnitAbsyn.UnitTerm ut;
1349 algorithm
1350 ut := match op
1351 ✗ case DAE.ADD() then UnitAbsyn.ADD(ut1,ut2,origExp);
1352 ✗ case DAE.SUB() then UnitAbsyn.SUB(ut1,ut2,origExp);
1353 ✗ case DAE.MUL() then UnitAbsyn.MUL(ut1,ut2,origExp);
1354 ✗ case DAE.DIV() then UnitAbsyn.DIV(ut1,ut2,origExp);
1355 end match;
1356 end buildTermOp;
1357
1358 protected function buildStores2 "help function"
1359 input DAE.DAElist dae;
1360 input UnitAbsyn.Store inStore;
1361 input HashTable.HashTable inHt;
1362 output UnitAbsyn.Store outStore;
1363 output HashTable.HashTable outHt;
1364 algorithm
1365 (outStore,outHt) := matchcontinue dae
1366 local
1367 DAE.ComponentRef cr;
1368 Option<DAE.VariableAttributes> attropt;
1369 Integer indx;
1370 String unitStr;
1371 UnitAbsyn.Unit unit;
1372 list<DAE.Element> elts;
1373 UnitAbsyn.Store store;
1374 HashTable.HashTable ht;
1375 ✗ case DAE.DAE(elementLst = {}) then (inStore,inHt);
1376 case DAE.DAE(elementLst = DAE.VAR(componentRef=cr,variableAttributesOption=attropt)::elts)
1377 algorithm
1378 ✗ DAE.SCONST(unitStr) := DAEUtil.getUnitAttr(attropt);
1379 ✗ unit := str2unit(unitStr,NONE()); /* Scale and offset not used yet*/
1380 ✗ (store,indx) := add(unit,inStore);
1381 ✗ ht := BaseHashTable.add((cr,indx),inHt);
1382 ✗ (store,ht) := buildStores2(DAE.DAE(elts),store,ht);
1383 then (store,ht);
1384
1385 /* Failed to parse will give unspecified unit*/
1386 case DAE.DAE(elementLst = DAE.VAR(componentRef=cr)::_)
1387 algorithm
1388 ✗ (store,indx) := add(UnitAbsyn.UNSPECIFIED(),inStore);
1389 ✗ ht := BaseHashTable.add((cr,indx),inHt);
1390 ✗ then (store,ht);
1391
1392 case DAE.DAE(elementLst = _::elts)
1393 algorithm
1394 ✗ (store,ht) := buildStores2(DAE.DAE(elts),inStore,inHt);
1395 then (store,ht);
1396 end matchcontinue;
1397 end buildStores2;
1398
1399 protected function buildStores3 "help function"
1400 input DAE.DAElist dae;
1401 input UnitAbsyn.Store inStore;
1402 input HashTable.HashTable inHt;
1403 output UnitAbsyn.Store outStore;
1404 output HashTable.HashTable outHt;
1405 algorithm
1406 (outStore,outHt) := matchcontinue(dae,inStore,inHt)
1407 local DAE.Exp e1,e2;
1408 list<DAE.Element> elts;
1409 UnitAbsyn.Store store;
1410 HashTable.HashTable ht;
1411
1412 ✗ case(DAE.DAE({}),store,ht) then (store,ht);
1413 case(DAE.DAE(DAE.EQUATION(e1,e2,_)::elts),store,ht) algorithm
1414 ✗ (store,ht) := buildStoreExp(e1,store,ht,NONE());
1415 ✗ (store,ht) := buildStoreExp(e2,store,ht,NONE());
1416 ✗ (store,ht) := buildStores3(DAE.DAE(elts),store,ht);
1417 then (store,ht);
1418
1419 case(DAE.DAE(_::elts),store,ht) algorithm
1420 ✗ (store,ht) := buildStores3(DAE.DAE(elts),store,ht);
1421 then (store,ht);
1422 end matchcontinue;
1423 end buildStores3;
1424
1425 protected function buildStoreExp " build stores from constants in expressions and from function calls"
1426 input DAE.Exp exp;
1427 input UnitAbsyn.Store inStore;
1428 input HashTable.HashTable inHt;
1429 input Option<DAE.Operator> parentOp;
1430 output UnitAbsyn.Store outStore;
1431 output HashTable.HashTable outHt;
1432 algorithm
1433 (outStore,outHt) := matchcontinue(exp, inStore, inHt)
1434 local Real r; String s1; Integer i,indx; UnitAbsyn.Unit unit; DAE.Exp e1,e2; DAE.Operator op;
1435 DAE.ComponentRef cref_;
1436 UnitAbsyn.Store store;
1437 HashTable.HashTable ht;
1438 /* Constant on top level, e.g. x = 1 => unspecified type */
1439 case(DAE.RCONST(r), store, ht) algorithm
1440 ✗ unit := selectConstantUnit(parentOp);
1441 ✗ (store,indx) := add(unit,store);
1442 ✗ s1 := realString(r);
1443 ✗ cref_ := ComponentReferenceBasics.makeCrefIdent(s1,DAE.T_UNKNOWN_DEFAULT,{});
1444 ✗ ht := BaseHashTable.add((cref_,indx),ht);
1445 ✗ then (store,ht);
1446
1447 case(DAE.CAST(_,DAE.ICONST(i)), store, ht) algorithm
1448 ✗ unit := selectConstantUnit(parentOp);
1449 ✗ (store,indx) := add(unit,store);
1450 ✗ s1 := intString(i);
1451 ✗ cref_ := ComponentReferenceBasics.makeCrefIdent(s1,DAE.T_UNKNOWN_DEFAULT,{});
1452 ✗ ht := BaseHashTable.add((cref_,indx),ht);
1453 ✗ then (store,ht);
1454
1455 case(DAE.BINARY(e1,op,e2), store, ht) algorithm
1456 ✗ (store,ht) := buildStoreExp(e1,store,ht,SOME(op));
1457 ✗ (store,ht) := buildStoreExp(e2,store,ht,SOME(op));
1458 then (store,ht);
1459
1460 case(DAE.UNARY(_,e1), store, ht) algorithm
1461 ✗ (store,ht) := buildStoreExp(e1,store,ht,parentOp);
1462 then (store,ht);
1463
1464 case(DAE.IFEXP(_,e1,e2), store, ht) algorithm
1465 ✗ (store,ht) := buildStoreExp(e1,store,ht,parentOp);
1466 ✗ (store,ht) := buildStoreExp(e2,store,ht,parentOp);
1467 then (store,ht);
1468
1469 ✗ case(_, store, ht) then (store,ht);
1470 end matchcontinue;
1471 end buildStoreExp;
1472
1473 public function unitMultiply "Multiplying two units corresponds to adding the units and joining the typeParameter list"
1474 input UnitAbsyn.Unit u1;
1475 input UnitAbsyn.Unit u2;
1476 output UnitAbsyn.Unit u;
1477
1478 algorithm
1479 u := match(u1,u2)
1480 local list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> tparams1,tparams2,tparams;
1481 list<MMath.Rational> units,units1,units2;
1482 case(UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(tparams1,units1)),UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(tparams2,units2))) algorithm
1483 ✗ tparams := listAppend(tparams1,tparams2);
1484 ✗ units := List.threadMap(units1,units2,MMath.addRational);
1485 ✗ then UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(tparams,units));
1486 end match;
1487 end unitMultiply;
1488
1489
1490 protected function selectConstantUnit "returns UNSPECIFIED or dimensionless depending on
1491 parent expression as type of a constant expression"
1492 input Option<DAE.Operator> op;
1493 output UnitAbsyn.Unit unit;
1494 algorithm
1495 unit := match op
1496 case NONE() then UnitAbsyn.UNSPECIFIED();
1497 case SOME(DAE.ADD(_)) then UnitAbsyn.UNSPECIFIED();
1498 case SOME(DAE.SUB(_)) then UnitAbsyn.UNSPECIFIED();
1499 ✗ case SOME(_) then str2unit("1",NONE());
1500 end match;
1501 end selectConstantUnit;
1502
1503 public function unit2str "Translate a unit to a string"
1504 input UnitAbsyn.Unit unit;
1505 output String res;
1506 algorithm
1507 res := match unit
1508 local
1509 list<Integer> nums,denoms,tpnoms,tpdenoms;
1510 list<String> tpstrs;
1511 list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> typeParams;
1512 list<MMath.Rational> units;
1513
1514 case UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(typeParams,units)) algorithm
1515 ✗ (nums,denoms) := splitRationals(units);
1516 ✗ (tpnoms,tpdenoms,tpstrs) := splitTypeParams(typeParams);
1517 ✗ res := UnitParserExt.unit2str(nums,denoms,tpnoms,tpdenoms,tpstrs,1.0/*scaleFactor*/,0.0/*offset*/);
1518 then res;
1519 case UnitAbsyn.UNSPECIFIED() then "unspecified";
1520 end match;
1521 end unit2str;
1522
1523 public function str2unit "Translate a unit string to a unit"
1524 input String res;
1525 input Option<Integer> funcInstIdOpt;
1526 output UnitAbsyn.Unit unit;
1527 algorithm
1528 160 (unit,_,_) := str2unitWithScaleFactor(res,funcInstIdOpt);
1529 end str2unit;
1530
1531 public function str2unitWithScaleFactor "Translate a unit string to a unit"
1532 input String res;
1533 input Option<Integer> funcInstIdOpt;
1534 output UnitAbsyn.Unit unit;
1535 output Real scaleFactor;
1536 output Real offset;
1537 protected
1538 list<Integer> nums,denoms,tpnoms,tpdenoms;
1539 list<String> tpstrs;
1540 list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> typeParams;
1541 list<MMath.Rational> units;
1542 algorithm
1543 1260 (nums,denoms,tpnoms,tpdenoms,tpstrs,scaleFactor,offset) := UnitParserExt.str2unit(res);
1544 1258 units := joinRationals(nums,denoms);
1545 1258 typeParams := joinTypeParams(tpnoms,tpdenoms,tpstrs,funcInstIdOpt);
1546 1258 unit := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(typeParams,units));
1547 end str2unitWithScaleFactor;
1548
1549 protected function getDerivedUnitsHelper
1550 input UnitAbsyn.Unit baseUnit;
1551 input String baseUnitStr;
1552 input list<String> inUnits;
1553 output list<String> outUnits = {};
1554 protected
1555 UnitAbsyn.Unit unit;
1556 Boolean b;
1557 algorithm
1558
2/2
✓ Branch 0 taken 159 times.
✓ Branch 1 taken 3 times.
162 for unitStr in inUnits loop
1559
4/4
✓ Branch 0 taken 54 times.
✓ Branch 1 taken 105 times.
✓ Branch 3 taken 51 times.
✓ Branch 4 taken 3 times.
159 if boolNot(stringEq(baseUnitStr, unitStr)) then // skip same units
1560 156 unit := str2unit(unitStr, NONE());
1561 156 b := valueEq(baseUnit, unit);
1562
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 147 times.
156 if b then
1563 outUnits := unitStr::outUnits;
1564 end if;
1565 end if;
1566 end for;
1567 end getDerivedUnitsHelper;
1568
1569 public function getDerivedUnits
1570 input UnitAbsyn.Unit baseUnit;
1571 input String baseUnitStr;
1572 output list<String> derivedUnits;
1573 protected
1574 list<String> unitSymbols;
1575 algorithm
1576 3 unitSymbols := UnitParserExt.allUnitSymbols();
1577 3 derivedUnits := getDerivedUnitsHelper(baseUnit, baseUnitStr, unitSymbols);
1578 end getDerivedUnits;
1579
1580 /* Tests */
1581
1582 /* Test1:
1583
1584 model Test1 "CONSISTENT: All units defined. No inference"
1585 Position x;
1586 Velocity v;
1587 Acceleration a;
1588 algorithm
1589 der(x) = v;
1590 der(v) = a;
1591 end Test1;
1592 */
1593
1594 public function buildTest1
1595
1596 output UnitAbsyn.UnitTerms ut;
1597 output UnitAbsyn.Store sigma;
1598 protected
1599 MMath.Rational r0,r1,nr1,nr2;
1600 UnitAbsyn.Unit unitderx,unitderv,unitx,unitv,unita;
1601 algorithm
1602 r0 := MMath.RATIONAL(0,0);
1603 r1 := MMath.RATIONAL(1,0);
1604 nr1 := MMath.RATIONAL(-1,0);
1605 nr2 := MMath.RATIONAL(-2,0);
1606 ut := {
1607 UnitAbsyn.EQN(UnitAbsyn.LOC(1,DAE.SCONST("1")),UnitAbsyn.LOC(4,DAE.SCONST("4")),DAE.SCONST("1==4")),
1608 UnitAbsyn.EQN(UnitAbsyn.LOC(2,DAE.SCONST("2")),UnitAbsyn.LOC(5,DAE.SCONST("5")),DAE.SCONST("2==5"))
1609 };
1610
1611 ✗ unitderx := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr1,r0,r0,r0,r0,r0}));/* der("m") -> m/s*/
1612 ✗ unitderv := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr2,r0,r0,r0,r0,r0})); /* der("m/s") -> m/s2 */
1613 ✗ unitx := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0})); /* x -> m */
1614 ✗ unitv := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr1,r0,r0,r0,r0,r0})); /* v -> m/s */
1615 ✗ unita := UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr2,r0,r0,r0,r0,r0}));
1616 ✗ sigma := emptyStore();
1617 ✗ (sigma,_) := add(unitderx,sigma); /*1*/
1618 ✗ (sigma,_) := add(unitderv,sigma); /*2*/
1619 ✗ (sigma,_) := add(unitx,sigma); /*3*/
1620 ✗ (sigma,_) := add(unitv,sigma); /*4*/
1621 ✗ (sigma,_) := add(unita,sigma); /*5*/
1622 ✗ printStore(sigma);
1623 end buildTest1;
1624
1625 /* Test2:
1626 model Test2 "CONSISTENT: Subtraction operator. All units defined. No inference"
1627 Position x,y,z;
1628 algorithm
1629 z = x-y;
1630 end Test2;
1631 */
1632
1633 /*public function buildTest2
1634
1635 output UnitAbsyn.UnitTerms ut;
1636 output UnitAbsyn.Locations sigma;
1637 protected
1638 MMath.Rational r0,r1;
1639 algorithm
1640 r0 := MMath.RATIONAL(0,0);
1641 r1 := MMath.RATIONAL(1,0);
1642 ut := {
1643 UnitAbsyn.EQN(UnitAbsyn.LOC("z"),UnitAbsyn.SUB(UnitAbsyn.LOC("x"),UnitAbsyn.LOC("y")))
1644 };
1645 sigma := {
1646 UnitAbsyn.LOCATION("x",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // x -> m
1647 UnitAbsyn.LOCATION("y",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // y -> m
1648 UnitAbsyn.LOCATION("z",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))) // z -> m
1649 };
1650 end buildTest2;
1651 */
1652
1653 /* Test3
1654 model Test3 "OVERDETERMINED: All units defined. No inference"
1655 Position x,y;
1656 Velocity z;
1657 algorithm
1658 z = x-y;
1659 end Test3;
1660 */
1661
1662 /*public function buildTest3
1663 output UnitAbsyn.UnitTerms ut;
1664 output UnitAbsyn.Locations sigma;
1665 protected
1666 MMath.Rational r0,r1,nr1;
1667 algorithm
1668 r0 := MMath.RATIONAL(0,0);
1669 r1 := MMath.RATIONAL(1,0);
1670 nr1 := MMath.RATIONAL(-1,0);
1671 ut := {
1672 UnitAbsyn.EQN(UnitAbsyn.LOC("z"),UnitAbsyn.SUB(UnitAbsyn.LOC("x"),UnitAbsyn.LOC("y")))
1673 };
1674 sigma := {
1675 UnitAbsyn.LOCATION("x",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // x -> m
1676 UnitAbsyn.LOCATION("y",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // y -> m
1677 UnitAbsyn.LOCATION("z",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr1,r0,r0,r0,r0,r0}))) // z -> m/s
1678 };
1679 end buildTest3;
1680 */
1681 /*
1682 Test5
1683
1684 model Test5 "CONSTISTENT: Multiplication operator. Not all units defined. inference"
1685 Position x,y;
1686 Real z;
1687 algorithm
1688 z = x*y;
1689 end test5;
1690 */
1691
1692 /*
1693 public function buildTest5
1694 output UnitAbsyn.UnitTerms ut;
1695 output UnitAbsyn.Locations sigma;
1696 protected
1697 MMath.Rational r0,r1,nr1;
1698 algorithm
1699 r0 := MMath.RATIONAL(0,0);
1700 r1 := MMath.RATIONAL(1,0);
1701 nr1 := MMath.RATIONAL(-1,0);
1702 ut := {
1703 UnitAbsyn.EQN(UnitAbsyn.LOC("z"),UnitAbsyn.MUL(UnitAbsyn.LOC("x"),UnitAbsyn.LOC("y")))
1704 };
1705 sigma := {
1706 UnitAbsyn.LOCATION("x",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // x -> m
1707 UnitAbsyn.LOCATION("y",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // y -> m
1708 UnitAbsyn.LOCATION("z",UnitAbsyn.UNSPECIFIED()) // z -> unspecified
1709 };
1710 end buildTest5;
1711 */
1712
1713 /* Test 8
1714
1715
1716 function Foo8
1717 input Real x;
1718 output Real y;
1719 algorithm
1720 y := x+1; // 1 has unkown unit
1721 end Foo8;
1722
1723 model Test8 "CONSISTENT. type inference in function call "
1724 Position x,y;
1725 Velocity v1,v2;
1726
1727 algorithm
1728 x = Foo8(y);
1729 v1 = Foo8(v2);
1730 end Test8;
1731 */
1732
1733 /*public function buildTest8
1734 output UnitAbsyn.UnitTerms ut;
1735 output UnitAbsyn.Locations sigma;
1736 protected
1737 MMath.Rational r0,r1,nr1;
1738 algorithm
1739 r0 := MMath.RATIONAL(0,0);
1740 r1 := MMath.RATIONAL(1,0);
1741 nr1 := MMath.RATIONAL(-1,0);
1742 ut := {
1743 UnitAbsyn.EQN(UnitAbsyn.LOC("x"),UnitAbsyn.LOC("Foo8(x)")),
1744 UnitAbsyn.EQN(UnitAbsyn.LOC("v1"),UnitAbsyn.LOC("Foo8(v2)"))
1745 };
1746 sigma := {
1747 UnitAbsyn.LOCATION("Foo8(y)",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))), // Foo8(x) -> m
1748 UnitAbsyn.LOCATION("Foo8(v2)",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr1,r0,r0,r0,r0,r0}))), // Foo8(v2) -> m/s
1749 UnitAbsyn.LOCATION("v1",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,nr1,r0,r0,r0,r0,r0}))), // Foo8(v2) -> m/s
1750 UnitAbsyn.LOCATION("x",UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT({},{r1,r0,r0,r0,r0,r0,r0}))) // Foo8(v2) -> m
1751 };
1752 end buildTest8;
1753 */
1754 annotation(__OpenModelica_Interface="frontend");
1755 end UnitAbsynBuilder;
1756