Linux GNU 11.4.0 Code Coverage Report


Directory: ./
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 85.8% 199 / 0 / 232
Functions: -% 0 / 1 / 1
Branches: 59.5% 207 / 0 / 348

OMCompiler/Compiler/NFFrontEnd/NFUnit.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 NFUnit
37 " file: NFUnit.mo
38 package: Unit
39 description: This package defines the type Unit, which represents a unit based
40 on SI base units, and some auxiliary functions therefore.
41
42 authors: Jan Hagemann and Lennart Ochel (FH Bielefeld, Germany)"
43
44 public
45 import ComponentRef = NFComponentRef;
46 import Absyn;
47 import NFInstNode.InstNode;
48 import Type = NFType;
49 import UnorderedMap;
50
51 protected
52 import Debug;
53 import Error;
54 import Flags;
55 import Util;
56
57 public
58 type StringToUnitTable = UnorderedMap<String, Unit>;
59 type UnitToStringTable = UnorderedMap<Unit, String>;
60 type CrefToUnitTable = UnorderedMap<ComponentRef, Unit>;
61
62 public uniontype Unit
63 record UNIT "based on SI base units"
64 Integer s "second";
65 Integer m "meter";
66 Integer g "gram";
67 Integer A "ampere";
68 Integer K "kelvin";
69 Integer mol "mole";
70 Integer cd "candela";
71 Real factor "prefix";
72 Real offset "v_SI = factor*v + offset; nonzero only for a bare affine unit
73 (degC, degF), since composing units drops it";
74 end UNIT;
75
76 record MASTER "unknown unit that belongs to all the variables from varList"
77 list<ComponentRef> varList;
78 end MASTER;
79
80 record UNKNOWN "unknown SI base unit decomposition"
81 String unit;
82 end UNKNOWN;
83 end Unit;
84
85 public constant Unit ONE = UNIT(0, 0, 0, 0, 0, 0, 0, 1e0, 0.0);
86 public constant Unit SECOND = UNIT(1, 0, 0, 0, 0, 0, 0, 1e0, 0.0);
87 //public constant Unit THRICE = ?
88
89 protected uniontype Token
90 record T_NUMBER
91 Integer number;
92 end T_NUMBER;
93
94 record T_UNIT
95 String unit;
96 end T_UNIT;
97
98 record T_MUL end T_MUL;
99 record T_DIV end T_DIV;
100 record T_LPAREN end T_LPAREN;
101 record T_RPAREN end T_RPAREN;
102 end Token;
103
104 public constant ComponentRef UPDATECREF = ComponentRef.CREF(InstNode.NAME_NODE("jhagemann"), {},
105 Type.UNKNOWN(), NFComponentRef.Origin.CREF, ComponentRef.EMPTY());
106
107 /* from https://www.bipm.org/documents/d/guest/si-brochure-9-en-pdf */
108 public constant list<tuple<String, Unit>> LU_COMPLEXUNITS = {
109 /* s, m, g, A, K,mol,cd,factor,offset */
110 ("1", UNIT(0, 0, 0, 0, 0, 0, 0, 1e0, 0.0)), // 1
111
112 /* base units */
113 ("s", UNIT(1, 0, 0, 0, 0, 0, 0, 1e0, 0.0)), // second
114 ("m", UNIT(0, 1, 0, 0, 0, 0, 0, 1e0, 0.0)), // meter
115 ("g", UNIT(0, 0, 1, 0, 0, 0, 0, 1e0, 0.0)), // gram
116 ("A", UNIT(0, 0, 0, 1, 0, 0, 0, 1e0, 0.0)), // ampere
117 ("K", UNIT(0, 0, 0, 0, 1, 0, 0, 1e0, 0.0)), // kelvin
118 ("mol", UNIT(0, 0, 0, 0, 0, 1, 0, 1e0, 0.0)), // mole
119 ("cd", UNIT(0, 0, 0, 0, 0, 0, 1, 1e0, 0.0)), // candela
120
121 /* derived units */
122 ("rad", UNIT(0, 0, 0, 0, 0, 0, 0, 1e0, 0.0)), // radian
123 //("sr", UNIT(0, 0, 0, 0, 0, 0, 0, 1e0, 0.0)), // steradian
124 ("Hz", UNIT(-1,0, 0, 0, 0, 0, 0, 1e0, 0.0)), // hertz
125 ("N", UNIT(-2,1, 1, 0, 0, 0, 0, 1e3, 0.0)), // newton
126 ("Pa", UNIT(-2,-1,1, 0, 0, 0, 0, 1e3, 0.0)), // pascal
127 ("J", UNIT(-2,2, 1, 0, 0, 0, 0, 1e3, 0.0)), // joule
128 ("W", UNIT(-3,2, 1, 0, 0, 0, 0, 1e3, 0.0)), // watt
129 ("C", UNIT(1, 0, 0, 1, 0, 0, 0, 1e0, 0.0)), // coulomb
130 ("V", UNIT(-3,2, 1,-1, 0, 0, 0, 1e3, 0.0)), // volt
131 ("F", UNIT(4,-2,-1, 2, 0, 0, 0,1e-3, 0.0)), // farad
132 ("Ohm", UNIT(-3,2, 1,-2, 0, 0, 0, 1e3, 0.0)), // ohm
133 ("S", UNIT(3,-2,-1, 2, 0, 0, 0,1e-3, 0.0)), // siemens
134 ("Wb", UNIT(-2,2, 1,-1, 0, 0, 0, 1e3, 0.0)), // weber
135 ("T", UNIT(-2,0, 1,-1, 0, 0, 0, 1e3, 0.0)), // tesla
136 ("H", UNIT(-2,2, 1,-2, 0, 0, 0, 1e3, 0.0)), // henry
137 ("degC", UNIT(0, 0, 0, 0, 1, 0, 0, 1e0, 273.15)), // °Celsius
138 //("lm", UNIT(0, 0, 0, 0, 0, 0, 1, 1e0, 0.0)), // lumen
139 //("lx", UNIT(0,-2, 0, 0, 0, 0, 1, 1e0, 0.0)), // lux
140 //("Bq", UNIT(-1,0, 0, 0, 0, 0, 0, 1e0, 0.0)), // becquerel
141 //("Gy", UNIT(-2,2, 0, 0, 0, 0, 0, 1e0, 0.0)), // gray
142 //("Sv", UNIT(-2,2, 0, 0, 0, 0, 0, 1e0, 0.0)), // sievert
143 ("kat", UNIT(-1,0, 0, 0, 0, 1, 0, 1e0, 0.0)), // katal
144
145 /* accepted non-SI units */
146 ("min", UNIT(1, 0, 0, 0, 0, 0, 0, 60, 0.0)), // minute
147 ("h", UNIT(1, 0, 0, 0, 0, 0, 0,3600, 0.0)), // hour
148 ("d", UNIT(1, 0, 0, 0, 0, 0, 0,86400, 0.0)), // day
149 //("au", UNIT(0, 1, 0, 0, 0, 0, 0,149597870700, 0.0)), // astronomical unit
150 //("deg", UNIT(0, 0, 0, 0, 0, 0, 0,1.7453292519943295e-2, 0.0)), // degree
151 //("???", UNIT(0, 0, 0, 0, 0, 0, 0,2.908882086657216e-4, 0.0)), // arcminute
152 //("???", UNIT(0, 0, 0, 0, 0, 0, 0,4.84813681109536e-6, 0.0)), // arcsecond
153 //("ha", UNIT(0, 2, 0, 0, 0, 0, 0, 1e4, 0.0)), // hectare
154 ("l", UNIT(0, 3, 0, 0, 0, 0, 0,1e-3, 0.0)), // liter
155 //("L", UNIT(0, 3, 0, 0, 0, 0, 0,1e-3, 0.0)), // liter
156 //("t", UNIT(0, 0, 1, 0, 0, 0, 0, 1e6, 0.0)), // tonne
157 //("eV", UNIT(-2,2, 1, 0, 0, 0, 0,1.602176634e-16, 0.0)), // electronvolt
158 //("B", UNIT(0, 0, 0, 0, 0, 0, 0,1e-2, 0.0)), // bel (dezibel dB)
159
160 /* custom units */
161 ("bar", UNIT(-2,-1,1, 0, 0, 0, 0, 1e8, 0.0)), // bar = 100kPa
162 ("degF", UNIT(0, 0, 0, 0, 1, 0, 0, 5.0/9.0, 459.67*5.0/9.0))//°Fahrenheit
163
164 /* old implementation */
165 /* fac,mol,cd, m, s, A, K, g*/
166 //("VA", UNIT(1e3, 0, 0, 2,-3, 0, 0, 1, 0.0)), //Voltampere=Watt
167 //("var", UNIT(1e3, 0, 0, 2,-3, 0, 0, 1, 0.0)), //Var=Watt
168 //("R", UNIT(2.58e-7, 0, 0, 0, 1, 1, 0,-1, 0.0)), //Röntgen 2, 58*10^-4 C/kg
169 //("phon", UNIT(1e0, 0, 0, 0, 0, 0, 0, 0, 0.0)), //Phon
170 //("sone", UNIT(1e0, 0, 0, 0, 0, 0, 0, 0, 0.0)), //Sone
171 };
172
173 public function getKnownUnits
174 output StringToUnitTable outKnownUnits;
175 protected
176 String s;
177 Unit ut;
178 algorithm
179 11971 outKnownUnits := UnorderedMap.new<Unit>(stringHashDjb2, stringEq, Util.nextPrime(listLength(LU_COMPLEXUNITS)));
180
181
2/2
✓ Branch 0 taken 359130 times.
✓ Branch 1 taken 11971 times.
371101 for unit in LU_COMPLEXUNITS loop
182 359130 (s, ut) := unit;
183 359130 UnorderedMap.add(s, ut, outKnownUnits);
184 end for;
185 end getKnownUnits;
186
187 public function getKnownUnitsInverse
188 output UnitToStringTable outKnownUnitsInverse;
189 algorithm
190 80 outKnownUnitsInverse := UnorderedMap.new<String>(hash, isEqual, Util.nextPrime(listLength(LU_COMPLEXUNITS)));
191 80 addKnownUnitsInverse(outKnownUnitsInverse);
192 end getKnownUnitsInverse;
193
194 public function addKnownUnitsInverse
195 "Fills a table from UnorderedMap.new<String>(hash, isEqual) the way
196 getKnownUnitsInverse does, so it can be built only when first needed."
197 input UnitToStringTable table;
198 protected
199 String s;
200 Unit ut;
201 algorithm
202
2/2
✓ Branch 0 taken 8640 times.
✓ Branch 1 taken 288 times.
8928 for unit in LU_COMPLEXUNITS loop
203 8640 (s, ut) := unit;
204 8640 UnorderedMap.tryAdd(ut, s, table);
205 end for;
206 end addKnownUnitsInverse;
207
208 public function newCrefUnitTable
209 input Integer size;
210 output CrefToUnitTable table;
211 algorithm
212 80 table := UnorderedMap.new<Unit>(ComponentRef.hash, ComponentRef.isEqual, size);
213 end newCrefUnitTable;
214
215 public function isUnit
216 input Unit inUnit;
217 output Boolean b;
218 algorithm
219 b := match inUnit
220 case UNIT() then true;
221 else false;
222 end match;
223 end isUnit;
224
225 public function isMaster
226 input Unit unit;
227 output Boolean res;
228 algorithm
229 res := match unit
230 case MASTER() then true;
231 else false;
232 end match;
233 end isMaster;
234
235 public function hash
236 input Unit inKey;
237 output Integer outHash = stringHashDjb2(unit2string(inKey));
238 end hash;
239
240 function realAlmostEqRel
241 // TODO move to MetaModelicaBuiltin.mo?
242 input Real a;
243 input Real b;
244 input Real relTol = 1e-3;
245 output Boolean c;
246 algorithm
247
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 34154 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
34154 c := if a == b then true else relTol > abs(a - b)/(abs(a) + abs(b));
248 end realAlmostEqRel;
249
250 public function isEqual
251 "Dimensional equality: the offset is deliberately not compared, so degC and K
252 remain the same unit to the unit checker (and to `hash`, which goes through
253 unit2string). The offset exists to be exported, not to split unit identity."
254 input Unit unit1;
255 input Unit unit2;
256 output Boolean res;
257 algorithm
258 res := match (unit1, unit2)
259 case (UNIT(), UNIT())
260
10/16
✓ Branch 0 taken 34166 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 34154 times.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 34154 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 34154 times.
✗ Branch 7 not taken.
✓ Branch 8 taken 34154 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 34154 times.
✗ Branch 11 not taken.
✓ Branch 12 taken 34154 times.
✗ Branch 13 not taken.
✗ Branch 15 not taken.
✓ Branch 16 taken 34154 times.
34172 then unit1.s == unit2.s
261 and unit1.m == unit2.m
262 and unit1.g == unit2.g
263 and unit1.A == unit2.A
264 and unit1.K == unit2.K
265 and unit1.mol == unit2.mol
266 and unit1.cd == unit2.cd
267 and realAlmostEqRel(unit1.factor, unit2.factor);
268
269 case (MASTER(), MASTER()) //equation
270 // lcr comparison????
271 then true;
272
273
2/4
✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
4 case (UNKNOWN(), UNKNOWN()) then unit1.unit == unit2.unit;
274
275 else false;
276 end match;
277 end isEqual;
278
279 public function unit2string
280 input Unit unit;
281 output String outString;
282 algorithm
283 outString := match unit
284 local
285 String s, str;
286 Boolean b;
287
288 case UNIT() algorithm
289 19386 str := realString(unit.factor) + " * ";
290
291 b := false;
292 19386 s := "mol^(" + intString(unit.mol) + ")";
293
2/2
✓ Branch 0 taken 18810 times.
✓ Branch 1 taken 576 times.
19386 s := if intEq(unit.mol, 0) then "" else s;
294
2/2
✓ Branch 0 taken 18810 times.
✓ Branch 1 taken 576 times.
19386 b := b or intNe(unit.mol, 0);
295 19386 str := str + s;
296
297
3/4
✓ Branch 0 taken 576 times.
✓ Branch 1 taken 18810 times.
✓ Branch 2 taken 576 times.
✗ Branch 3 not taken.
19386 s := if b and intNe(unit.cd, 0) then " * " else "";
298 19386 str := str + s;
299 19386 s := "cd^(" + intString(unit.cd) + ")";
300
2/2
✓ Branch 0 taken 19098 times.
✓ Branch 1 taken 288 times.
19386 s := if intEq(unit.cd, 0) then "" else s;
301
4/4
✓ Branch 0 taken 18810 times.
✓ Branch 1 taken 576 times.
✓ Branch 2 taken 18522 times.
✓ Branch 3 taken 288 times.
19386 b := b or intNe(unit.cd, 0);
302 19386 str := str + s;
303
304
3/4
✓ Branch 0 taken 864 times.
✓ Branch 1 taken 18522 times.
✓ Branch 2 taken 864 times.
✗ Branch 3 not taken.
19386 s := if b and intNe(unit.m, 0) then " * " else "";
305 19386 str := str + s;
306 19386 s := "m^(" + intString(unit.m) + ")";
307
2/2
✓ Branch 0 taken 10618 times.
✓ Branch 1 taken 8768 times.
19386 s := if intEq(unit.m, 0) then "" else s;
308
4/4
✓ Branch 0 taken 18522 times.
✓ Branch 1 taken 864 times.
✓ Branch 2 taken 9754 times.
✓ Branch 3 taken 8768 times.
19386 b := b or intNe(unit.m, 0);
309 19386 str := str + s;
310
311
4/4
✓ Branch 0 taken 9632 times.
✓ Branch 1 taken 9754 times.
✓ Branch 2 taken 4045 times.
✓ Branch 3 taken 5587 times.
19386 s := if b and intNe(unit.s, 0) then " * " else "";
312 19386 str := str + s;
313 19386 s := "s^(" + intString(unit.s) + ")";
314
2/2
✓ Branch 0 taken 9499 times.
✓ Branch 1 taken 9887 times.
19386 s := if intEq(unit.s, 0) then "" else s;
315
4/4
✓ Branch 0 taken 9754 times.
✓ Branch 1 taken 9632 times.
✓ Branch 2 taken 5454 times.
✓ Branch 3 taken 4300 times.
19386 b := b or intNe(unit.s, 0);
316 19386 str := str + s;
317
318
4/4
✓ Branch 0 taken 13932 times.
✓ Branch 1 taken 5454 times.
✓ Branch 2 taken 11021 times.
✓ Branch 3 taken 2911 times.
19386 s := if b and intNe(unit.A, 0) then " * " else "";
319 19386 str := str + s;
320 19386 s := "A^(" + intString(unit.A) + ")";
321
2/2
✓ Branch 0 taken 16187 times.
✓ Branch 1 taken 3199 times.
19386 s := if intEq(unit.A, 0) then "" else s;
322
4/4
✓ Branch 0 taken 5454 times.
✓ Branch 1 taken 13932 times.
✓ Branch 2 taken 5166 times.
✓ Branch 3 taken 288 times.
19386 b := b or intNe(unit.A, 0);
323 19386 str := str + s;
324
325
4/4
✓ Branch 0 taken 14220 times.
✓ Branch 1 taken 5166 times.
✓ Branch 2 taken 13937 times.
✓ Branch 3 taken 283 times.
19386 s := if b and intNe(unit.K, 0) then " * " else "";
326 19386 str := str + s;
327 //s := "(K-" + realString(unit.shift) + ")^(" + intString(unit.K) + ")";
328 19386 s := "K^(" + intString(unit.K) + ")";
329
2/2
✓ Branch 0 taken 18238 times.
✓ Branch 1 taken 1148 times.
19386 s := if intEq(unit.K, 0) then "" else s;
330
4/4
✓ Branch 0 taken 5166 times.
✓ Branch 1 taken 14220 times.
✓ Branch 2 taken 4301 times.
✓ Branch 3 taken 865 times.
19386 b := b or intNe(unit.K, 0);
331 19386 str := str + s;
332
333
4/4
✓ Branch 0 taken 15085 times.
✓ Branch 1 taken 4301 times.
✓ Branch 2 taken 9148 times.
✓ Branch 3 taken 5937 times.
19386 s := if b and intNe(unit.g, 0) then " * " else "";
334 19386 str := str + s;
335 19386 s := "g^(" + intString(unit.g) + ")";
336
2/2
✓ Branch 0 taken 12970 times.
✓ Branch 1 taken 6416 times.
19386 s := if intEq(unit.g, 0) then "" else s;
337
4/4
✓ Branch 0 taken 4301 times.
✓ Branch 1 taken 15085 times.
✓ Branch 2 taken 3822 times.
✓ Branch 3 taken 479 times.
19386 b := b or intNe(unit.g, 0);
338 19386 str := str + s;
339
340
2/2
✓ Branch 0 taken 3822 times.
✓ Branch 1 taken 15564 times.
23208 str := str + (if b then "" else "1");
341 then str;
342
343 17908 case MASTER() then List.toStringCustom(unit.varList, ComponentRef.toString, "MASTER", "(", ", ", ")");
344 16 case UNKNOWN() then "UNKOWN(" + unit.unit + ")";
345 end match;
346 end unit2string;
347
348 protected function isOne
349 "The dimensionless identity, which composing against changes nothing."
350 input Unit unit;
351 output Boolean res;
352 algorithm
353 res := match unit
354
15/18
✓ Branch 0 taken 12351 times.
✓ Branch 1 taken 5174 times.
✓ Branch 2 taken 8863 times.
✓ Branch 3 taken 3488 times.
✓ Branch 4 taken 8033 times.
✓ Branch 5 taken 830 times.
✓ Branch 6 taken 7934 times.
✓ Branch 7 taken 99 times.
✓ Branch 8 taken 7603 times.
✓ Branch 9 taken 331 times.
✓ Branch 10 taken 7560 times.
✓ Branch 11 taken 43 times.
✓ Branch 12 taken 7560 times.
✗ Branch 13 not taken.
✓ Branch 14 taken 7560 times.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✓ Branch 17 taken 7560 times.
17525 case UNIT() then unit.s == 0 and unit.m == 0 and unit.g == 0 and unit.A == 0
355 and unit.K == 0 and unit.mol == 0 and unit.cd == 0
356 and unit.factor == 1.0 and unit.offset == 0.0;
357 else false;
358 end match;
359 end isOne;
360
361 public function unitMul
362 "An affine unit only survives multiplication by the identity: degC*s is a
363 ratio scale, not a shifted one, and parser3 builds every unit as ONE*u."
364 input Unit inUnit1;
365 input Unit inUnit2;
366 output Unit outUnit;
367 algorithm
368 outUnit := match (inUnit1, inUnit2)
369 case (UNIT(), UNIT())
370
4/4
✓ Branch 1 taken 7326 times.
✓ Branch 2 taken 1811 times.
✓ Branch 4 taken 25 times.
✓ Branch 5 taken 1786 times.
9137 then UNIT(
371 s = inUnit1.s + inUnit2.s,
372 m = inUnit1.m + inUnit2.m,
373 g = inUnit1.g + inUnit2.g,
374 A = inUnit1.A + inUnit2.A,
375 K = inUnit1.K + inUnit2.K,
376 mol = inUnit1.mol + inUnit2.mol,
377 cd = inUnit1.cd + inUnit2.cd,
378 factor = inUnit1.factor * inUnit2.factor,
379 offset = if isOne(inUnit1) then inUnit2.offset
380 elseif isOne(inUnit2) then inUnit1.offset else 0.0
381 );
382 end match;
383 end unitMul;
384
385 public function unitDiv
386 input Unit inUnit1;
387 input Unit inUnit2;
388 output Unit outUnit;
389 algorithm
390 outUnit := match (inUnit1, inUnit2)
391 case (UNIT(), UNIT())
392
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6577 times.
✓ Branch 3 taken 209 times.
✓ Branch 4 taken 6368 times.
6577 then UNIT(
393 s = inUnit1.s - inUnit2.s,
394 m = inUnit1.m - inUnit2.m,
395 g = inUnit1.g - inUnit2.g,
396 A = inUnit1.A - inUnit2.A,
397 K = inUnit1.K - inUnit2.K,
398 mol = inUnit1.mol - inUnit2.mol,
399 cd = inUnit1.cd - inUnit2.cd,
400 factor = inUnit1.factor / inUnit2.factor,
401 offset = if isOne(inUnit2) then inUnit1.offset else 0.0
402 );
403 end match;
404 end unitDiv;
405
406 public function unitPow
407 input Unit inUnit;
408 input Integer inExp "exponent";
409 output Unit outUnit;
410 algorithm
411 outUnit := match inUnit
412 case UNIT()
413
4/24
✗ Branch 0 not taken.
✓ Branch 1 taken 2528 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 2528 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 2528 times.
✗ Branch 22 not taken.
✓ Branch 23 taken 2528 times.
2528 then UNIT(
414 s = inUnit.s * inExp,
415 m = inUnit.m * inExp,
416 g = inUnit.g * inExp,
417 A = inUnit.A * inExp,
418 K = inUnit.K * inExp,
419 mol = inUnit.mol * inExp,
420 cd = inUnit.cd * inExp,
421 factor = inUnit.factor^inExp,
422 offset = if inExp == 1 then inUnit.offset else 0.0
423 );
424 end match;
425 end unitPow;
426
427 public function unitMulReal
428 input Unit inUnit;
429 input Real inFactor;
430 output Unit outUnit;
431 algorithm
432 outUnit := match inUnit
433 local
434 Unit unit;
435 case unit as UNIT() algorithm
436 1174 unit.factor := unit.factor * inFactor;
437 1174 unit.offset := unit.offset * inFactor;
438 then unit;
439 end match;
440 end unitMulReal;
441
442 public function unitRoot
443 input Unit inUnit;
444 input Real inExponent;
445 output Unit outUnit;
446 algorithm
447 outUnit := match inUnit
448 local
449 Real r, factor;
450 Integer i, s, m, g, A, K, mol, cd;
451
452 case UNIT() algorithm
453 20 i := realInt(inExponent);
454
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 r := realDiv(1.0, inExponent);
455
3/22
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
✗ Branch 12 not taken.
✗ Branch 13 not taken.
✗ Branch 14 not taken.
✗ Branch 15 not taken.
✗ Branch 16 not taken.
✗ Branch 17 not taken.
✓ Branch 18 taken 20 times.
✗ Branch 19 not taken.
✗ Branch 20 not taken.
✓ Branch 21 taken 20 times.
20 factor := realPow(inUnit.factor, r);
456
457 20 r := realDiv(intReal(inUnit.s),inExponent);
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 s := intDiv(inUnit.s, i);
459
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(s));
460
461 20 r := realDiv(intReal(inUnit.m),inExponent);
462 20 m := intDiv(inUnit.m, i);
463
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(m));
464
465 20 r := realDiv(intReal(inUnit.g),inExponent);
466 20 g := intDiv(inUnit.g, i);
467
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(g));
468
469 20 r := realDiv(intReal(inUnit.A),inExponent);
470 20 A := intDiv(inUnit.A, i);
471
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(A));
472
473 20 r := realDiv(intReal(inUnit.K),inExponent);
474 20 K := intDiv(inUnit.K, i);
475
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(K));
476
477 20 r := realDiv(intReal(inUnit.mol),inExponent);
478 20 mol := intDiv(inUnit.mol, i);
479
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(mol));
480
481 20 r := realDiv(intReal(inUnit.cd),inExponent);
482 20 cd := intDiv(inUnit.cd, i);
483
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
20 true := realEq(r, intReal(cd));
484 20 then UNIT(s, m, g, A, K, mol, cd, factor, 0.0);
485 end match;
486 end unitRoot;
487
488 public function unitString "Unit to Modelica unit string"
489 input Unit inUnit;
490 input UnitToStringTable inHtU2S = getKnownUnitsInverse();
491 output String outString;
492 protected
493 Option<String> opt_s;
494 String s, s1, s2, s3, s4, s5, s6, s7, sExponent;
495 Boolean b;
496 Unit unit;
497 algorithm
498 6484 opt_s := UnorderedMap.get(inUnit, inHtU2S);
499
500
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 6484 times.
✓ Branch 2 taken 1674 times.
✓ Branch 3 taken 4810 times.
6484 if isSome(opt_s) then
501 4810 SOME(outString) := opt_s;
502 4810 return;
503 end if;
504
505 outString := match inUnit
506 case unit as UNIT() algorithm
507
2/2
✓ Branch 0 taken 771 times.
✓ Branch 1 taken 903 times.
1674 s := if unit.factor == 1.0 then "" else prefix2String(unit.factor);
508 b := false;
509
1/2
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
1674 sExponent := if intEq(unit.mol, 1) then "" else intString(unit.mol);
510 1674 s1 := "mol" + sExponent;
511
1/2
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
1674 s1 := if intEq(unit.mol, 0) then "" else s1;
512
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1674 times.
1674 b := b or intNe(unit.mol, 0);
513
514 ✗ s2 := if b and intNe(unit.cd, 0) then "." else "";
515
1/2
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
1674 sExponent := if intEq(unit.cd, 1) then "" else intString(unit.cd);
516 1674 s2 := s2 + "cd" + sExponent;
517
1/2
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
1674 s2 := if intEq(unit.cd, 0) then "" else s2;
518
2/4
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1674 times.
1674 b := b or intNe(unit.cd, 0);
519
520 ✗ s3 := if b and intNe(unit.m, 0) then "." else "";
521
2/2
✓ Branch 0 taken 1511 times.
✓ Branch 1 taken 163 times.
1674 sExponent := if intEq(unit.m, 1) then "" else intString(unit.m);
522 1674 s3 := s3 + "m" + sExponent;
523
2/2
✓ Branch 0 taken 713 times.
✓ Branch 1 taken 961 times.
1674 s3 := if intEq(unit.m, 0) then "" else s3;
524
3/4
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 961 times.
✓ Branch 3 taken 713 times.
1674 b := b or intNe(unit.m, 0);
525
526
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 909 times.
961 s4 := if b and intNe(unit.s, 0) then "." else "";
527
1/2
✓ Branch 0 taken 1674 times.
✗ Branch 1 not taken.
1674 sExponent := if intEq(unit.s, 1) then "" else intString(unit.s);
528 1674 s4 := s4 + "s" + sExponent;
529
2/2
✓ Branch 0 taken 52 times.
✓ Branch 1 taken 1622 times.
1674 s4 := if intEq(unit.s, 0) then "" else s4;
530
3/4
✓ Branch 0 taken 713 times.
✓ Branch 1 taken 961 times.
✓ Branch 2 taken 713 times.
✗ Branch 3 not taken.
1674 b := b or intNe(unit.s, 0);
531
532
2/2
✓ Branch 0 taken 1118 times.
✓ Branch 1 taken 556 times.
1674 s5 := if b and intNe(unit.A, 0) then "." else "";
533
2/2
✓ Branch 0 taken 1561 times.
✓ Branch 1 taken 113 times.
1674 sExponent := if intEq(unit.A, 1) then "" else intString(unit.A);
534 1674 s5 := s5 + "A" + sExponent;
535
2/2
✓ Branch 0 taken 1118 times.
✓ Branch 1 taken 556 times.
1674 s5 := if intEq(unit.A, 0) then "" else s5;
536
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1674 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1674 b := b or intNe(unit.A, 0);
537
538
2/2
✓ Branch 0 taken 1401 times.
✓ Branch 1 taken 273 times.
1674 s6 := if b and intNe(unit.K, 0) then "." else "";
539
2/2
✓ Branch 0 taken 1402 times.
✓ Branch 1 taken 272 times.
1674 sExponent := if intEq(unit.K, 1) then "" else intString(unit.K);
540 1674 s6 := s6 + "K" + sExponent;
541
2/2
✓ Branch 0 taken 1401 times.
✓ Branch 1 taken 273 times.
1674 s6 := if intEq(unit.K, 0) then "" else s6;
542
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1674 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1674 b := b or intNe(unit.K, 0);
543
544
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 771 times.
1674 s7 := if b and intNe(unit.g, 0) then "." else "";
545
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 771 times.
1674 sExponent := if intEq(unit.g, 1) then "" else intString(unit.g);
546 1674 s7 := s7 + "g" + sExponent;
547
2/2
✓ Branch 0 taken 903 times.
✓ Branch 1 taken 771 times.
1674 s7 := if intEq(unit.g, 0) then "" else s7;
548
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1674 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
1674 b := b or intNe(unit.g, 0);
549
550 1674 s := if b then s + s1 + s2 + s3 + s4 + s5 + s6 + s7 else "1";
551 then s;
552
553 else algorithm
554 ✗ Error.addCompilerWarning("function Unit.unitString failed for \"" + unit2string(inUnit) +"\".");
555 ✗ then fail();
556 end match;
557 end unitString;
558
559 protected function prefix2String
560 "from https://www.bipm.org/en/measurement-units/si-prefixes"
561 input Real inReal;
562 output String outPrefix;
563 algorithm
564 outPrefix := match inReal
565 case 1e30 then "Q"; // quetta
566 case 1e27 then "R"; // ronna
567 case 1e24 then "Y"; // yotta
568 case 1e21 then "Z"; // zetta
569 case 1e18 then "E"; // exa
570 case 1e15 then "P"; // peta
571 case 1e12 then "T"; // tera
572 case 1e9 then "G"; // giga
573 case 1e6 then "M"; // mega
574 case 1e3 then "k"; // kilo
575 case 1e2 then "h"; // hecto
576 case 1e1 then "da"; // deca
577 case 1e-1 then "d"; // deci
578 case 1e-2 then "c"; // centi
579 case 1e-3 then "m"; // milli
580 case 1e-6 then "u"; // micro
581 case 1e-9 then "n"; // nano
582 case 1e-12 then "p"; // pico
583 case 1e-15 then "f"; // femto
584 case 1e-18 then "a"; // atto
585 case 1e-21 then "z"; // zepto
586 case 1e-24 then "y"; // yocto
587 case 1e-27 then "r"; // ronto
588 case 1e-30 then "q"; // quecto
589 ✗ else realString(inReal);
590 end match;
591 end prefix2String;
592
593 public function parseUnitString "author: lochel
594 The second argument is optional."
595 input String inUnitString;
596 input StringToUnitTable inKnownUnits = getKnownUnits();
597 input SourceInfo info = Absyn.dummyInfo;
598 output Unit outUnit;
599 protected
600 list<String> charList;
601 list<Token> tokenList;
602 algorithm
603 12919 charList := stringListStringChar(inUnitString);
604
2/2
✓ Branch 0 taken 5535 times.
✓ Branch 1 taken 7384 times.
12919 if listEmpty(charList) then
605 5535 fail();
606 end if;
607
608 try
609 7384 tokenList := lexer(charList);
610 else
611 ✗ Error.addSourceMessage(Error.INVALID_UNIT, {inUnitString}, info);
612 ✗ fail();
613 end try;
614
615 7384 outUnit := parser3({true, true}, tokenList, NFUnit.ONE, inKnownUnits);
616
2/2
✓ Branch 1 taken 7299 times.
✓ Branch 2 taken 85 times.
7384 if not isUnit(outUnit) then
617
1/2
✓ Branch 1 taken 85 times.
✗ Branch 2 not taken.
85 if Flags.isSet(Flags.FAILTRACE) then
618 ✗ Debug.traceln(getInstanceName() + ": failed to parse unit string " + inUnitString);
619 end if;
620 end if;
621 end parseUnitString;
622
623 protected function parser3
624 input list<Boolean> inMul "true=Mul, false=Div, initial call with true";
625 input list<Token> inTokenList "Tokenliste";
626 input Unit inUnit "initial call with NFUnit.ONE";
627 input StringToUnitTable inHtS2U;
628 output Unit outUnit;
629 algorithm
630 outUnit := matchcontinue(inMul, inTokenList)
631 local
632 String s, unit;
633 list<Token> tokens;
634 Unit ut;
635 Integer exponent;
636 Boolean bMul, b;
637 list<Boolean> bRest;
638
639 // ""
640 case ({true}, {}) then inUnit;
641
642 // "1"
643 case (bMul::bRest, T_NUMBER(number=1)::tokens) algorithm
644 ut := NFUnit.ONE;
645
1/2
✓ Branch 0 taken 395 times.
✗ Branch 1 not taken.
395 ut := if bMul then unitMul(inUnit,ut) else unitDiv(inUnit, ut);
646 395 ut := parser3(bRest, tokens, ut, inHtS2U);
647 then ut;
648
649 // "unit^i"
650 case (bMul::bRest, T_UNIT(unit=s)::T_NUMBER(exponent)::tokens) algorithm
651 1848 ut := unitToken2unit(s, inHtS2U);
652 1848 ut := unitPow(ut, exponent);
653
2/2
✓ Branch 0 taken 1037 times.
✓ Branch 1 taken 811 times.
1848 ut := if bMul then unitMul(inUnit,ut) else unitDiv(inUnit, ut);
654 1848 ut := parser3(bRest, tokens, ut, inHtS2U);
655 then ut;
656
657 // "unit"
658 case (bMul::bRest, T_UNIT(unit=s)::tokens) algorithm
659 8700 ut := unitToken2unit(s, inHtS2U);
660
2/2
✓ Branch 0 taken 6770 times.
✓ Branch 1 taken 1865 times.
8635 ut := if bMul then unitMul(inUnit,ut) else unitDiv(inUnit, ut);
661 8627 ut := parser3(bRest, tokens, ut, inHtS2U);
662 then ut;
663
664 // "*("
665 case (bMul::_, T_MUL()::T_LPAREN()::tokens) algorithm
666 ✗ ut := parser3(bMul::bMul::inMul, tokens, inUnit, inHtS2U);
667 then ut;
668
669 // "/("
670 case (bMul::_, T_DIV()::T_LPAREN()::tokens) algorithm
671 b := not bMul;
672
1/2
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
304 ut := parser3(b::b::inMul, tokens, inUnit, inHtS2U);
673 then ut;
674
675 // ")"
676 case (_::bRest, T_RPAREN()::tokens) algorithm
677 148 ut := parser3(bRest, tokens, inUnit, inHtS2U);
678 then ut;
679
680 // "*"
681 case (bMul::_, T_MUL()::tokens) algorithm
682
2/2
✓ Branch 0 taken 147 times.
✓ Branch 1 taken 882 times.
2058 ut := parser3(bMul::inMul, tokens, inUnit, inHtS2U);
683 then ut;
684
685 // "/"
686 case (bMul::_, T_DIV()::tokens) algorithm
687 b := not bMul;
688
2/2
✓ Branch 0 taken 2384 times.
✓ Branch 1 taken 6 times.
4780 ut := parser3(b::inMul, tokens, inUnit, inHtS2U);
689 then ut;
690
691 else UNKNOWN("");
692 end matchcontinue;
693 end parser3;
694
695 protected function unitToken2unit
696 input String inS;
697 input StringToUnitTable inHtS2U;
698 output Unit outUnit;
699 protected
700 Option<Unit> opt_unit;
701 String s;
702 Real r;
703 algorithm
704 11753 opt_unit := UnorderedMap.get(inS, inHtS2U);
705
706
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 11753 times.
✓ Branch 2 taken 1270 times.
✓ Branch 3 taken 10483 times.
11753 if isSome(opt_unit) then
707 10483 SOME(outUnit) := opt_unit;
708 else
709 1270 s := stringGetStringChar(inS, 1);
710 1269 (r, s) := getPrefix(s, inS);
711 1205 outUnit := unitToken2unit(s, inHtS2U);
712 1174 outUnit := unitMulReal(outUnit, r);
713 end if;
714 end unitToken2unit;
715
716 protected function getPrefix
717 input String inS;
718 input String inS2;
719 output Real outR;
720 output String outUnit;
721 algorithm
722 (outR, outUnit) := matchcontinue inS
723 local
724 list<String> strRest;
725 String s;
726
727 case "y" //-24
728 algorithm
729
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 _::strRest := stringListStringChar(inS2);
730 3 s := stringCharListString(strRest);
731 then (1e-24, s);
732
733 case "z" //-21
734 algorithm
735 ✗ _::strRest := stringListStringChar(inS2);
736 ✗ s := stringCharListString(strRest);
737 then (1e-21, s);
738
739 case "a" //-18
740 algorithm
741
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 _::strRest := stringListStringChar(inS2);
742 1 s := stringCharListString(strRest);
743 then (1e-18, s);
744
745 case "f" //-15
746 algorithm
747 ✗ _::strRest := stringListStringChar(inS2);
748 ✗ s := stringCharListString(strRest);
749 then (1e-15, s);
750
751 case "p" //-12
752 algorithm
753 ✗ _::strRest := stringListStringChar(inS2);
754 ✗ s := stringCharListString(strRest);
755 then (1e-12, s);
756
757 case "u" //-6
758 algorithm
759 ✗ _::strRest := stringListStringChar(inS2);
760 ✗ s := stringCharListString(strRest);
761 then (1e-6, s);
762
763 case "m" //-3
764 algorithm
765
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
1 _::strRest := stringListStringChar(inS2);
766 1 s := stringCharListString(strRest);
767 then (1e-3, s);
768
769 case "c" //-2
770 algorithm
771
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 _::strRest := stringListStringChar(inS2);
772 6 s := stringCharListString(strRest);
773 then (1e-2, s);
774
775 case "d" //+1
776 algorithm
777 20 strRest := stringListStringChar(inS2);
778
6/12
✗ Branch 0 not taken.
✓ Branch 1 taken 20 times.
✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 20 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 20 times.
✓ Branch 8 taken 20 times.
✗ Branch 9 not taken.
✓ Branch 10 taken 20 times.
✗ Branch 11 not taken.
20 "d"::"a"::strRest := strRest;
779 ✗ s := stringCharListString(strRest);
780 then (1e1, s);
781
782 case "d" //-1
783 algorithm
784
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20 times.
20 _::strRest := stringListStringChar(inS2);
785 20 s := stringCharListString(strRest);
786 then (1e-1, s);
787
788 case "h" //+2
789 algorithm
790
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
6 _::strRest := stringListStringChar(inS2);
791 6 s := stringCharListString(strRest);
792 then (1e2, s);
793
794 case "k" //+3
795 algorithm
796
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1160 times.
1160 _::strRest := stringListStringChar(inS2);
797 1160 s := stringCharListString(strRest);
798 then (1e3, s);
799
800 case "M" //+6
801 algorithm
802
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5 times.
5 _::strRest := stringListStringChar(inS2);
803 5 s := stringCharListString(strRest);
804 then (1e6, s);
805
806 case "G" //+9
807 algorithm
808
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
3 _::strRest := stringListStringChar(inS2);
809 3 s := stringCharListString(strRest);
810 then (1e9, s);
811
812 case "T" //+12
813 algorithm
814 ✗ _::strRest := stringListStringChar(inS2);
815 ✗ s := stringCharListString(strRest);
816 then (1e12, s);
817
818 case "P" //+15
819 algorithm
820 ✗ _::strRest := stringListStringChar(inS2);
821 ✗ s := stringCharListString(strRest);
822 then (1e15, s);
823
824 case "E" //+18
825 algorithm
826 ✗ _::strRest := stringListStringChar(inS2);
827 ✗ s := stringCharListString(strRest);
828 then (1e18, s);
829
830 case "Z" //+21
831 algorithm
832 ✗ _::strRest := stringListStringChar(inS2);
833 ✗ s := stringCharListString(strRest);
834 then (1e21, s);
835
836 case "Y" //+24
837 algorithm
838 ✗ _::strRest := stringListStringChar(inS2);
839 ✗ s := stringCharListString(strRest);
840 then (1e24, s);
841
842 else fail();
843 end matchcontinue;
844 end getPrefix;
845
846 protected function lexer "author: lochel
847 Tokenizer: charList to tokenList"
848 input list<String> inCharList;
849 output list<Token> outTokenList;
850 algorithm
851 outTokenList := matchcontinue inCharList
852 local
853 list<String> charList;
854 String number;
855 String unit;
856 list<Token> tokenList;
857 Integer i;
858
859 case {} then {};
860
861 case "."::charList algorithm
862 1041 tokenList := lexer(charList);
863 then T_MUL()::tokenList;
864
865 case "("::charList algorithm
866 174 tokenList := lexer(charList);
867 then T_LPAREN()::tokenList;
868
869 case ")"::charList algorithm
870 174 tokenList := lexer(charList);
871 then T_RPAREN()::tokenList;
872
873 case "/"::charList algorithm
874 2585 tokenList := lexer(charList);
875 then T_DIV()::tokenList;
876
877 case "+"::charList algorithm
878 ✗ (charList, number) := popNumber(charList);
879 ✗ false := (number == "");
880 ✗ tokenList := lexer(charList);
881 ✗ i := stringInt(number);
882 ✗ then T_NUMBER(i)::tokenList;
883
884 case "-"::charList algorithm
885 401 (charList, number) := popNumber(charList);
886
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 401 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
401 false := (number == "");
887 401 tokenList := lexer(charList);
888 401 i := -stringInt(number);
889 401 then T_NUMBER(i)::tokenList;
890
891 case charList algorithm
892 12459 (charList, number) := popNumber(charList);
893
3/4
✓ Branch 0 taken 10615 times.
✓ Branch 1 taken 1844 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 10615 times.
12459 false := (number == "");
894 1844 tokenList := lexer(charList);
895 1844 i := stringInt(number);
896 1844 then T_NUMBER(i)::tokenList;
897
898 case charList algorithm
899 10615 (charList, unit) := popUnit(charList);
900
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 10615 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
10615 false := (unit == "");
901 10615 tokenList := lexer(charList);
902 10615 then T_UNIT(unit)::tokenList;
903
904 end matchcontinue;
905 end lexer;
906
907 protected function popUnit
908 input list<String> inCharList;
909 output list<String> outCharList;
910 output String outUnit;
911 algorithm
912 (outCharList, outUnit) := match inCharList
913 local
914 String s1, s2;
915 list<String> strRest;
916
917 case {}
918 then ({}, "");
919
920 case s1::strRest guard (stringCompare(s1, "a") >= 0) and (stringCompare(s1, "z") <= 0) algorithm
921 11756 (strRest, s2) := popUnit(strRest);
922 11756 then (strRest, s1 + s2);
923
924 case s1::strRest guard (stringCompare(s1, "A") >= 0) and (stringCompare(s1, "Z") <= 0) algorithm
925 3805 (strRest, s2) := popUnit(strRest);
926 3805 then (strRest, s1 + s2);
927
928 else (inCharList, "");
929 end match;
930 end popUnit;
931
932 protected function popNumber
933 input list<String> inCharList;
934 output list<String> outCharList;
935 output String outNumber;
936 algorithm
937 (outCharList, outNumber) := matchcontinue inCharList
938 local
939 String s1, s2;
940 list<String> strRest;
941 Integer i;
942
943 case {}
944 then ({}, "");
945
946 case s1::strRest algorithm
947 13640 i := stringInt(s1);
948
2/4
✓ Branch 1 taken 2245 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 2245 times.
✗ Branch 6 not taken.
2245 true := (intString(i) == s1);
949 2245 (strRest, s2) := popNumber(strRest);
950 2245 then (strRest, s1 + s2);
951
952 else (inCharList, "");
953 end matchcontinue;
954 end popNumber;
955
956 annotation(__OpenModelica_Interface="nf_frontend");
957 end NFUnit;
958