OMCompiler/Compiler/FrontEnd/UnitChecker.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 UnitChecker | ||
| 37 | " | ||
| 38 | file: UnitChecker.mo | ||
| 39 | package: UnitChecker | ||
| 40 | description: Physical unit checking. | ||
| 41 | |||
| 42 | This package is used for checking if an equation system is consistent, inconsistent or unknown (not enough information to determine). | ||
| 43 | " | ||
| 44 | |||
| 45 | public import UnitAbsyn; | ||
| 46 | public import MMath; | ||
| 47 | public import UnitAbsynBuilder; | ||
| 48 | |||
| 49 | protected import Debug; | ||
| 50 | protected import Error; | ||
| 51 | protected import Flags; | ||
| 52 | protected import HashTable; | ||
| 53 | |||
| 54 | public function check "Check if a list of unit terms are consistent" | ||
| 55 | input UnitAbsyn.UnitTerms tms; | ||
| 56 | input UnitAbsyn.InstStore ist; | ||
| 57 | output UnitAbsyn.InstStore outSt; | ||
| 58 | algorithm | ||
| 59 | outSt := matchcontinue(tms,ist) | ||
| 60 | local | ||
| 61 | UnitAbsyn.Store st1,st2; | ||
| 62 | UnitAbsyn.UnitTerms rest1; | ||
| 63 | UnitAbsyn.UnitTerm tm1; | ||
| 64 | UnitAbsyn.SpecUnit su1,su2; | ||
| 65 | String s1,s2,s3; | ||
| 66 | HashTable.HashTable ht; | ||
| 67 | UnitAbsyn.InstStore st; | ||
| 68 | |||
| 69 | case (_,st) | ||
| 70 | algorithm | ||
| 71 | // phi: very old unit checking | ||
| 72 | /* | ||
| 73 | false = Flags.getConfigBool(Flags.UNIT_CHECKING); | ||
| 74 | */ | ||
| 75 | then (st); | ||
| 76 | |||
| 77 | // No more terms? | ||
| 78 | case ({},UnitAbsyn.INSTSTORE(st1,ht,_)) | ||
| 79 | ✗ | then UnitAbsyn.INSTSTORE(st1,ht,SOME(UnitAbsyn.CONSISTENT())); | |
| 80 | |||
| 81 | // Is consistent? | ||
| 82 | case (tm1::rest1,UnitAbsyn.INSTSTORE(st1,ht,_)) | ||
| 83 | algorithm | ||
| 84 | ✗ | (UnitAbsyn.CONSISTENT(),_,st2) := checkTerm(tm1,st1); | |
| 85 | ✗ | st := check(rest1,UnitAbsyn.INSTSTORE(st2,ht,SOME(UnitAbsyn.CONSISTENT()))); | |
| 86 | then(st); | ||
| 87 | |||
| 88 | // Is inconsistent? | ||
| 89 | case (tm1::_,UnitAbsyn.INSTSTORE(st1,ht,_)) | ||
| 90 | algorithm | ||
| 91 | ✗ | (UnitAbsyn.INCONSISTENT(su1,su2),_,_) := checkTerm(tm1,st1); | |
| 92 | ✗ | s1 := UnitAbsynBuilder.printTermsStr({tm1}); | |
| 93 | ✗ | s2 := UnitAbsynBuilder.unit2str(UnitAbsyn.SPECIFIED(su1)); | |
| 94 | ✗ | s3 := UnitAbsynBuilder.unit2str(UnitAbsyn.SPECIFIED(su2)); | |
| 95 | ✗ | Error.addMessage(Error.INCONSISTENT_UNITS,{s1,s2,s3}); | |
| 96 | ✗ | then | |
| 97 | UnitAbsyn.INSTSTORE(st1,ht,SOME(UnitAbsyn.INCONSISTENT(su1,su2))); | ||
| 98 | |||
| 99 | // failtrace | ||
| 100 | else | ||
| 101 | algorithm | ||
| 102 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 103 | ✗ | Debug.trace("UnitChecker::check() failed\n"); | |
| 104 | ✗ | print("check failed\n"); | |
| 105 | ✗ | then | |
| 106 | fail(); | ||
| 107 | end matchcontinue; | ||
| 108 | end check; | ||
| 109 | |||
| 110 | public function isComplete "returns true if the store is complete, else false" | ||
| 111 | input UnitAbsyn.Store st; | ||
| 112 | output Boolean complete; | ||
| 113 | output UnitAbsyn.Store stout; | ||
| 114 | algorithm | ||
| 115 | (complete,stout) := match st | ||
| 116 | local | ||
| 117 | array<Option<UnitAbsyn.Unit>> vector; Integer indx; | ||
| 118 | list<Option<UnitAbsyn.Unit>> lst; | ||
| 119 | Boolean comp; | ||
| 120 | UnitAbsyn.Store st2; | ||
| 121 | |||
| 122 | case UnitAbsyn.STORE(vector,indx) | ||
| 123 | algorithm | ||
| 124 | ✗ | lst := arrayList(vector); | |
| 125 | ✗ | (comp,st2) := completeCheck(lst,1,UnitAbsyn.STORE(vector,indx)); | |
| 126 | then | ||
| 127 | (comp,st2); | ||
| 128 | end match; | ||
| 129 | end isComplete; | ||
| 130 | |||
| 131 | protected function completeCheck "help function to isComplete" | ||
| 132 | input list<Option<UnitAbsyn.Unit>> ilst; | ||
| 133 | input Integer indx; | ||
| 134 | input UnitAbsyn.Store st; | ||
| 135 | output Boolean isComplete; | ||
| 136 | output UnitAbsyn.Store stout; | ||
| 137 | algorithm | ||
| 138 | (isComplete,stout) := matchcontinue(ilst, st) | ||
| 139 | local | ||
| 140 | UnitAbsyn.Unit u2; | ||
| 141 | Boolean comp1; | ||
| 142 | UnitAbsyn.Store st2,st3; | ||
| 143 | list<Option<UnitAbsyn.Unit>> lst; | ||
| 144 | |||
| 145 | case ({}, st2) then (true,st2); | ||
| 146 | |||
| 147 | case (SOME(_)::lst, st2) | ||
| 148 | algorithm | ||
| 149 | ✗ | (u2,st3) := normalize(indx,st2); | |
| 150 | ✗ | false := unitHasUnknown(u2); | |
| 151 | ✗ | (comp1,_) := completeCheck(lst,indx+1,st3); | |
| 152 | ✗ | then | |
| 153 | (comp1,st3); | ||
| 154 | |||
| 155 | case (SOME(_)::_, st2) | ||
| 156 | algorithm | ||
| 157 | ✗ | (u2,_) := normalize(indx,st2); | |
| 158 | ✗ | true := unitHasUnknown(u2); | |
| 159 | then | ||
| 160 | (false,st2); | ||
| 161 | |||
| 162 | case(NONE()::_, st2) then (true,st2); | ||
| 163 | end matchcontinue; | ||
| 164 | end completeCheck; | ||
| 165 | |||
| 166 | public function checkTerm "check if one term is ok" | ||
| 167 | input UnitAbsyn.UnitTerm tm; | ||
| 168 | input UnitAbsyn.Store st; | ||
| 169 | output UnitAbsyn.UnitCheckResult result; | ||
| 170 | output UnitAbsyn.SpecUnit outUnit; | ||
| 171 | output UnitAbsyn.Store outSt; | ||
| 172 | algorithm | ||
| 173 | (result,outUnit,outSt) := matchcontinue(tm,st) | ||
| 174 | local | ||
| 175 | UnitAbsyn.Store st1,st2,st3,st4; | ||
| 176 | UnitAbsyn.UnitCheckResult res1,res2,res3,res4; | ||
| 177 | UnitAbsyn.UnitTerm ut1,ut2; | ||
| 178 | UnitAbsyn.SpecUnit su1,su2,su3; | ||
| 179 | MMath.Rational expo1; | ||
| 180 | Integer loc; | ||
| 181 | |||
| 182 | case (UnitAbsyn.ADD(ut1,ut2,_),st1) | ||
| 183 | algorithm | ||
| 184 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 185 | ✗ | (res2,su2,st3) := checkTerm(ut2,st2); | |
| 186 | ✗ | (res3,st4) := unify(su1,su2,st3); | |
| 187 | ✗ | res4 := chooseResult(res1,res2,res3); | |
| 188 | ✗ | then (res4,su1,st4); | |
| 189 | |||
| 190 | case (UnitAbsyn.SUB(ut1,ut2,_),st1) | ||
| 191 | algorithm | ||
| 192 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 193 | ✗ | (res2,su2,st3) := checkTerm(ut2,st2); | |
| 194 | ✗ | (res3,st4) := unify(su1,su2,st3); | |
| 195 | ✗ | res4 := chooseResult(res1,res2,res3); | |
| 196 | ✗ | then (res4,su1,st4); | |
| 197 | |||
| 198 | case (UnitAbsyn.MUL(ut1,ut2,_),st1) | ||
| 199 | algorithm | ||
| 200 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 201 | ✗ | (res2,su2,st3) := checkTerm(ut2,st2); | |
| 202 | ✗ | su3 := mulSpecUnit(su1,su2); | |
| 203 | ✗ | res4 := chooseResult(res1,res2,UnitAbsyn.CONSISTENT()); | |
| 204 | ✗ | then(res4,su3,st3); | |
| 205 | |||
| 206 | case (UnitAbsyn.DIV(ut1,ut2,_),st1) | ||
| 207 | algorithm | ||
| 208 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 209 | ✗ | (res2,su2,st3) := checkTerm(ut2,st2); | |
| 210 | ✗ | su3 := divSpecUnit(su1,su2); | |
| 211 | ✗ | res4 := chooseResult(res1,res2,UnitAbsyn.CONSISTENT()); | |
| 212 | ✗ | then(res4,su3,st3); | |
| 213 | |||
| 214 | case (UnitAbsyn.EQN(ut1,ut2,_),st1) | ||
| 215 | algorithm | ||
| 216 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 217 | ✗ | (res2,su2,st3) := checkTerm(ut2,st2); | |
| 218 | ✗ | (res3,st4) := unify(su1,su2,st3); | |
| 219 | ✗ | res4 := chooseResult(res1,res2,res3); | |
| 220 | ✗ | then(res4,su1,st4); | |
| 221 | |||
| 222 | case (UnitAbsyn.LOC(loc,_),st1) | ||
| 223 | algorithm | ||
| 224 | ✗ | UnitAbsyn.UNSPECIFIED() := UnitAbsynBuilder.find(loc,st1); | |
| 225 | ✗ | then(UnitAbsyn.CONSISTENT(),UnitAbsyn.SPECUNIT((MMath.RATIONAL(1,1),UnitAbsyn.TYPEPARAMETER("",loc))::{},{}),st1); | |
| 226 | |||
| 227 | case (UnitAbsyn.LOC(loc,_),st1) | ||
| 228 | algorithm | ||
| 229 | ✗ | UnitAbsyn.SPECIFIED(su1) := UnitAbsynBuilder.find(loc,st1); | |
| 230 | then(UnitAbsyn.CONSISTENT(),su1,st1); | ||
| 231 | |||
| 232 | case (UnitAbsyn.POW(ut1,expo1,_),st1) | ||
| 233 | algorithm | ||
| 234 | ✗ | (res1,su1,st2) := checkTerm(ut1,st1); | |
| 235 | ✗ | su2 := powSpecUnit(su1,expo1); | |
| 236 | ✗ | then(res1,su2,st2); | |
| 237 | |||
| 238 | else | ||
| 239 | algorithm | ||
| 240 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 241 | ✗ | Debug.trace("UnitChecker::checkTerm() failed\n"); | |
| 242 | ✗ | then fail(); | |
| 243 | end matchcontinue; | ||
| 244 | end checkTerm; | ||
| 245 | |||
| 246 | protected function chooseResult "Returns the first result that is UnitAbsyn.INCONSISTENT. If not, CONISTENT will be returned" | ||
| 247 | input UnitAbsyn.UnitCheckResult res1; | ||
| 248 | input UnitAbsyn.UnitCheckResult res2; | ||
| 249 | input UnitAbsyn.UnitCheckResult res3; | ||
| 250 | output UnitAbsyn.UnitCheckResult resout; | ||
| 251 | protected | ||
| 252 | UnitAbsyn.UnitCheckResult incon; | ||
| 253 | algorithm | ||
| 254 | resout := match(res1,res2,res3) | ||
| 255 | case(UnitAbsyn.CONSISTENT(),UnitAbsyn.CONSISTENT(),UnitAbsyn.CONSISTENT()) then UnitAbsyn.CONSISTENT(); | ||
| 256 | case(UnitAbsyn.CONSISTENT(),UnitAbsyn.CONSISTENT(),incon) then incon; | ||
| 257 | case(UnitAbsyn.CONSISTENT(),incon,_) then incon; | ||
| 258 | case(incon,_,_) then incon; | ||
| 259 | else | ||
| 260 | algorithm | ||
| 261 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 262 | ✗ | Debug.trace("UnitChecker::chooseResult() failed\n"); | |
| 263 | ✗ | then fail(); | |
| 264 | end match; | ||
| 265 | end chooseResult; | ||
| 266 | |||
| 267 | protected function unify | ||
| 268 | input UnitAbsyn.SpecUnit insu1; | ||
| 269 | input UnitAbsyn.SpecUnit insu2; | ||
| 270 | input UnitAbsyn.Store st; | ||
| 271 | output UnitAbsyn.UnitCheckResult outresult; | ||
| 272 | output UnitAbsyn.Store outSt; | ||
| 273 | protected | ||
| 274 | UnitAbsyn.SpecUnit su1,su2; | ||
| 275 | UnitAbsyn.Store st1,st2; | ||
| 276 | algorithm | ||
| 277 | ✗ | (UnitAbsyn.SPECIFIED(su1),st1) := normalizeOnUnit(UnitAbsyn.SPECIFIED(insu1),st); | |
| 278 | ✗ | (UnitAbsyn.SPECIFIED(su2),st2) := normalizeOnUnit(UnitAbsyn.SPECIFIED(insu2),st1); | |
| 279 | ✗ | (outresult,outSt) := unifyunits(su1,su2,st2); | |
| 280 | end unify; | ||
| 281 | |||
| 282 | protected function isSpecUnitEq "checks if twp spec units are equal (presupposed that they have no unknowns" | ||
| 283 | input UnitAbsyn.SpecUnit insu1; | ||
| 284 | input UnitAbsyn.SpecUnit insu2; | ||
| 285 | output Boolean res; | ||
| 286 | algorithm | ||
| 287 | res := match(insu1,insu2) | ||
| 288 | local | ||
| 289 | Boolean r1; | ||
| 290 | Integer i1a,i1b,i2a,i2b; | ||
| 291 | list<MMath.Rational> rest1,rest2; | ||
| 292 | |||
| 293 | case(UnitAbsyn.SPECUNIT(_,{}),UnitAbsyn.SPECUNIT(_,{})) | ||
| 294 | then true; | ||
| 295 | |||
| 296 | case(UnitAbsyn.SPECUNIT(_,{}),UnitAbsyn.SPECUNIT(_,MMath.RATIONAL(0,_)::rest1)) | ||
| 297 | algorithm | ||
| 298 | ✗ | r1 := isSpecUnitEq(UnitAbsyn.SPECUNIT({},{}), UnitAbsyn.SPECUNIT({},rest1)); | |
| 299 | then r1; | ||
| 300 | |||
| 301 | case(UnitAbsyn.SPECUNIT(_,MMath.RATIONAL(0,_)::rest1),UnitAbsyn.SPECUNIT(_,{})) | ||
| 302 | algorithm | ||
| 303 | ✗ | r1 := isSpecUnitEq(UnitAbsyn.SPECUNIT({},rest1),UnitAbsyn.SPECUNIT({},{})); | |
| 304 | then r1; | ||
| 305 | |||
| 306 | case(UnitAbsyn.SPECUNIT(_,MMath.RATIONAL(i1a,i1b)::rest1), UnitAbsyn.SPECUNIT(_,MMath.RATIONAL(i2a,i2b)::rest2)) guard intEq(i1a, i2a) and intEq(i1b, i2b) | ||
| 307 | algorithm | ||
| 308 | ✗ | r1 := isSpecUnitEq(UnitAbsyn.SPECUNIT({},rest1),UnitAbsyn.SPECUNIT({},rest2)); | |
| 309 | then r1; | ||
| 310 | |||
| 311 | else | ||
| 312 | then false; | ||
| 313 | end match; | ||
| 314 | end isSpecUnitEq; | ||
| 315 | |||
| 316 | protected function unifyunits | ||
| 317 | input UnitAbsyn.SpecUnit insu1; | ||
| 318 | input UnitAbsyn.SpecUnit insu2; | ||
| 319 | input UnitAbsyn.Store st; | ||
| 320 | output UnitAbsyn.UnitCheckResult outresult; | ||
| 321 | output UnitAbsyn.Store outSt; | ||
| 322 | algorithm | ||
| 323 | (outresult,outSt) := matchcontinue(insu1,insu2,st) | ||
| 324 | local | ||
| 325 | UnitAbsyn.SpecUnit su1,su2,su3,su4; | ||
| 326 | UnitAbsyn.Store st1,st2; | ||
| 327 | Integer loc1; | ||
| 328 | |||
| 329 | // No unknown and the same on both sides | ||
| 330 | case(su1,su2,st1) | ||
| 331 | algorithm | ||
| 332 | ✗ | false := hasUnknown(su1); | |
| 333 | ✗ | false := hasUnknown(su2); | |
| 334 | ✗ | true := isSpecUnitEq(su1,su2); | |
| 335 | then | ||
| 336 | (UnitAbsyn.CONSISTENT(),st1); | ||
| 337 | |||
| 338 | // No unknown, but different on the sides | ||
| 339 | case(su1,su2,st1) | ||
| 340 | algorithm | ||
| 341 | ✗ | false := hasUnknown(su1); | |
| 342 | ✗ | false := hasUnknown(su2); | |
| 343 | ✗ | then | |
| 344 | (UnitAbsyn.INCONSISTENT(su1,su2),st1); | ||
| 345 | |||
| 346 | // Move the unknown to left side and substitute | ||
| 347 | case(su1,su2,st1) | ||
| 348 | algorithm | ||
| 349 | ✗ | su3 := divSpecUnit(su2,su1); | |
| 350 | ✗ | (loc1,su4) := getUnknown(su3); | |
| 351 | ✗ | st2 := UnitAbsynBuilder.update(UnitAbsyn.SPECIFIED(su4),loc1,st1); | |
| 352 | then | ||
| 353 | (UnitAbsyn.CONSISTENT(),st2); | ||
| 354 | |||
| 355 | // Unknowns are cancelling each other out | ||
| 356 | case(_,_,st1) | ||
| 357 | then(UnitAbsyn.CONSISTENT(),st1); | ||
| 358 | end matchcontinue; | ||
| 359 | end unifyunits; | ||
| 360 | |||
| 361 | public function newDimlessSpecUnit "creates a new dimensionless unit" | ||
| 362 | output UnitAbsyn.SpecUnit su; | ||
| 363 | algorithm | ||
| 364 | ✗ | UnitAbsyn.SPECIFIED(su) := UnitAbsynBuilder.str2unit("1",NONE()); | |
| 365 | end newDimlessSpecUnit; | ||
| 366 | |||
| 367 | public function getUnknown "gets the first unknown in a specified unit" | ||
| 368 | input UnitAbsyn.SpecUnit suin; | ||
| 369 | output Integer loc; | ||
| 370 | output UnitAbsyn.SpecUnit suout; | ||
| 371 | algorithm | ||
| 372 | (loc,suout) := matchcontinue suin | ||
| 373 | local | ||
| 374 | UnitAbsyn.SpecUnit su1,su2; | ||
| 375 | MMath.Rational expo1,expo2; | ||
| 376 | Integer loc1; | ||
| 377 | list<MMath.Rational> unitvec1; | ||
| 378 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest1; | ||
| 379 | |||
| 380 | case UnitAbsyn.SPECUNIT((expo1,UnitAbsyn.TYPEPARAMETER(_,loc1))::rest1,unitvec1) | ||
| 381 | algorithm | ||
| 382 | ✗ | su1 := divSpecUnit(newDimlessSpecUnit(),UnitAbsyn.SPECUNIT(rest1,unitvec1)); | |
| 383 | ✗ | expo2 := MMath.divRational(MMath.RATIONAL(1,1), expo1); | |
| 384 | ✗ | su2 := powSpecUnit(su1,expo2); | |
| 385 | then (loc1,su2); | ||
| 386 | |||
| 387 | else | ||
| 388 | algorithm | ||
| 389 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 390 | ✗ | Debug.trace("UnitChecker::getUnknown() failed\n"); | |
| 391 | ✗ | then | |
| 392 | fail(); | ||
| 393 | end matchcontinue; | ||
| 394 | end getUnknown; | ||
| 395 | |||
| 396 | public function hasUnknown | ||
| 397 | input UnitAbsyn.SpecUnit su; | ||
| 398 | output Boolean res; | ||
| 399 | algorithm | ||
| 400 | res := match su | ||
| 401 | case UnitAbsyn.SPECUNIT({},_) then false; | ||
| 402 | case UnitAbsyn.SPECUNIT(_,_) then true; | ||
| 403 | else | ||
| 404 | algorithm | ||
| 405 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 406 | ✗ | Debug.trace("UnitChecker::hasUnknown() failed\n"); | |
| 407 | ✗ | then fail(); | |
| 408 | end match; | ||
| 409 | end hasUnknown; | ||
| 410 | |||
| 411 | public function unitHasUnknown | ||
| 412 | input UnitAbsyn.Unit u; | ||
| 413 | output Boolean res; | ||
| 414 | algorithm | ||
| 415 | res := match u | ||
| 416 | local | ||
| 417 | UnitAbsyn.SpecUnit su; | ||
| 418 | Boolean unk; | ||
| 419 | case UnitAbsyn.SPECIFIED(su) | ||
| 420 | algorithm | ||
| 421 | ✗ | unk := hasUnknown(su); | |
| 422 | then unk; | ||
| 423 | else true; | ||
| 424 | end match; | ||
| 425 | end unitHasUnknown; | ||
| 426 | |||
| 427 | public function mulSpecUnit "Multiplying two units corresponds to adding the units and joining the typeParameter list." | ||
| 428 | input UnitAbsyn.SpecUnit u1; | ||
| 429 | input UnitAbsyn.SpecUnit u2; | ||
| 430 | output UnitAbsyn.SpecUnit u; | ||
| 431 | algorithm | ||
| 432 | u := matchcontinue(u1,u2) | ||
| 433 | local | ||
| 434 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> tparams1,tparams2,tparams3,tparams4; | ||
| 435 | list<MMath.Rational> units,units1,units2; | ||
| 436 | |||
| 437 | case (UnitAbsyn.SPECUNIT(tparams1,units1),UnitAbsyn.SPECUNIT(tparams2,units2)) | ||
| 438 | algorithm | ||
| 439 | ✗ | tparams3 := listAppend(tparams1,tparams2); | |
| 440 | ✗ | tparams4 := normalizeParamsExponents(tparams3); | |
| 441 | ✗ | units := mulUnitVec(units1,units2); | |
| 442 | ✗ | then | |
| 443 | UnitAbsyn.SPECUNIT(tparams4,units); | ||
| 444 | |||
| 445 | else | ||
| 446 | algorithm | ||
| 447 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 448 | ✗ | Debug.trace("UnitChecker::mulSpecUnit() failed\n"); | |
| 449 | ✗ | then | |
| 450 | fail(); | ||
| 451 | end matchcontinue; | ||
| 452 | end mulSpecUnit; | ||
| 453 | |||
| 454 | public function mulUnitVec "multiplication of two unit vector" | ||
| 455 | input list<MMath.Rational> inunitvec1; | ||
| 456 | input list<MMath.Rational> inunitvec2; | ||
| 457 | output list<MMath.Rational> outunitvec; | ||
| 458 | algorithm | ||
| 459 | outunitvec := matchcontinue(inunitvec1,inunitvec2) | ||
| 460 | local | ||
| 461 | MMath.Rational expo1,expo2,expo3; | ||
| 462 | list<MMath.Rational> rest1,rest2,rest3; | ||
| 463 | |||
| 464 | // empty list | ||
| 465 | case ({},{}) then {}; | ||
| 466 | |||
| 467 | case(expo1::rest1,expo2::rest2) | ||
| 468 | algorithm | ||
| 469 | ✗ | expo3 := MMath.addRational(expo1,expo2); | |
| 470 | ✗ | rest3 := mulUnitVec(rest1,rest2); | |
| 471 | then | ||
| 472 | (expo3::rest3); | ||
| 473 | |||
| 474 | case(expo1::rest1,{}) | ||
| 475 | algorithm | ||
| 476 | ✗ | rest3 := mulUnitVec(rest1,{}); | |
| 477 | then | ||
| 478 | (expo1::rest3); | ||
| 479 | |||
| 480 | case({},expo1::rest1) | ||
| 481 | algorithm | ||
| 482 | ✗ | rest3 := mulUnitVec({},rest1); | |
| 483 | then (expo1::rest3); | ||
| 484 | |||
| 485 | else | ||
| 486 | algorithm | ||
| 487 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 488 | ✗ | Debug.trace("UnitChecker::powUnitVec() failed\n"); | |
| 489 | ✗ | then fail(); | |
| 490 | end matchcontinue; | ||
| 491 | end mulUnitVec; | ||
| 492 | |||
| 493 | public function divSpecUnit "Divide two specified units" | ||
| 494 | input UnitAbsyn.SpecUnit u1; | ||
| 495 | input UnitAbsyn.SpecUnit u2; | ||
| 496 | output UnitAbsyn.SpecUnit u; | ||
| 497 | algorithm | ||
| 498 | u := matchcontinue(u1,u2) | ||
| 499 | local | ||
| 500 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> tparams1,tparams2,tparams3,tparams4,tparams5; | ||
| 501 | list<MMath.Rational> units,units1,units2; | ||
| 502 | |||
| 503 | case(UnitAbsyn.SPECUNIT(tparams1,units1),UnitAbsyn.SPECUNIT(tparams2,units2)) | ||
| 504 | algorithm | ||
| 505 | ✗ | tparams3 := negParamList(tparams2,{}); | |
| 506 | ✗ | tparams4 := listAppend(tparams1,tparams3); | |
| 507 | ✗ | tparams5 := normalizeParamsExponents(tparams4); | |
| 508 | ✗ | units := divUnitVec(units1,units2); | |
| 509 | ✗ | then | |
| 510 | UnitAbsyn.SPECUNIT(tparams5,units); | ||
| 511 | |||
| 512 | else | ||
| 513 | algorithm | ||
| 514 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 515 | ✗ | Debug.trace("UnitChecker::divSpecUnit() failed\n"); | |
| 516 | ✗ | then fail(); | |
| 517 | end matchcontinue; | ||
| 518 | end divSpecUnit; | ||
| 519 | |||
| 520 | public function divUnitVec "division of two unit vectors" | ||
| 521 | input list<MMath.Rational> inunitvec1; | ||
| 522 | input list<MMath.Rational> inunitvec2; | ||
| 523 | output list<MMath.Rational> outunitvec; | ||
| 524 | algorithm | ||
| 525 | outunitvec := matchcontinue(inunitvec1,inunitvec2) | ||
| 526 | local | ||
| 527 | MMath.Rational expo1,expo2,expo3; | ||
| 528 | list<MMath.Rational> rest1,rest2,rest3; | ||
| 529 | |||
| 530 | case ({},{}) then {}; | ||
| 531 | |||
| 532 | case(expo1::rest1,expo2::rest2) | ||
| 533 | algorithm | ||
| 534 | ✗ | expo3 := MMath.subRational(expo1,expo2); | |
| 535 | ✗ | rest3 := divUnitVec(rest1,rest2); | |
| 536 | then | ||
| 537 | (expo3::rest3); | ||
| 538 | |||
| 539 | case(expo1::rest1,{}) | ||
| 540 | algorithm | ||
| 541 | ✗ | rest3 := divUnitVec(rest1,{}); | |
| 542 | then | ||
| 543 | (expo1::rest3); | ||
| 544 | |||
| 545 | case({},expo1::rest1) | ||
| 546 | algorithm | ||
| 547 | ✗ | expo2 := MMath.subRational(MMath.RATIONAL(0,1),expo1); | |
| 548 | ✗ | rest3 := divUnitVec({},rest1); | |
| 549 | then | ||
| 550 | (expo2::rest3); | ||
| 551 | |||
| 552 | else | ||
| 553 | algorithm | ||
| 554 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 555 | ✗ | Debug.trace("UnitChecker::powUnitVec() failed\n"); | |
| 556 | ✗ | then fail(); | |
| 557 | end matchcontinue; | ||
| 558 | end divUnitVec; | ||
| 559 | |||
| 560 | public function powSpecUnit "Power of a specified unit" | ||
| 561 | input UnitAbsyn.SpecUnit suin; | ||
| 562 | input MMath.Rational expo; | ||
| 563 | output UnitAbsyn.SpecUnit uout; | ||
| 564 | algorithm | ||
| 565 | uout := matchcontinue suin | ||
| 566 | local | ||
| 567 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params1,params2; | ||
| 568 | list<MMath.Rational> unitvec1,unitvec2; | ||
| 569 | |||
| 570 | case UnitAbsyn.SPECUNIT(params1,unitvec1) | ||
| 571 | algorithm | ||
| 572 | ✗ | params2 := powUnitParams(params1,expo); | |
| 573 | ✗ | unitvec2 := powUnitVec(unitvec1,expo); | |
| 574 | ✗ | then | |
| 575 | UnitAbsyn.SPECUNIT(params2,unitvec2); | ||
| 576 | |||
| 577 | else | ||
| 578 | algorithm | ||
| 579 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 580 | ✗ | Debug.trace("UnitChecker::powSpecUnit() failed\n"); | |
| 581 | ✗ | then | |
| 582 | fail(); | ||
| 583 | end matchcontinue; | ||
| 584 | end powSpecUnit; | ||
| 585 | |||
| 586 | public function powUnitParams "exponent power of the unit type parameters" | ||
| 587 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> inparams; | ||
| 588 | input MMath.Rational expo; | ||
| 589 | output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> outparams; | ||
| 590 | algorithm | ||
| 591 | outparams := matchcontinue(inparams,expo) | ||
| 592 | local | ||
| 593 | MMath.Rational expo1,expo2,expo3; | ||
| 594 | UnitAbsyn.TypeParameter param; | ||
| 595 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest1,rest2; | ||
| 596 | |||
| 597 | case ({},_) then {}; | ||
| 598 | |||
| 599 | case((expo1,param)::rest1,expo2) | ||
| 600 | algorithm | ||
| 601 | ✗ | expo3 := MMath.multRational(expo1,expo2); | |
| 602 | ✗ | rest2 := powUnitParams(rest1,expo2); | |
| 603 | ✗ | then | |
| 604 | ((expo3,param)::rest2); | ||
| 605 | |||
| 606 | else | ||
| 607 | algorithm | ||
| 608 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 609 | ✗ | Debug.trace("UnitChecker::powUnitParams() failed\n"); | |
| 610 | ✗ | then fail(); | |
| 611 | end matchcontinue; | ||
| 612 | end powUnitParams; | ||
| 613 | |||
| 614 | public function powUnitVec "exponent power of the unit vector" | ||
| 615 | input list<MMath.Rational> inunitvec; | ||
| 616 | input MMath.Rational expo; | ||
| 617 | output list<MMath.Rational> outunitvec; | ||
| 618 | algorithm | ||
| 619 | outunitvec := matchcontinue(inunitvec,expo) | ||
| 620 | local | ||
| 621 | MMath.Rational expo1,expo2,expo3; | ||
| 622 | list<MMath.Rational> rest1,rest2; | ||
| 623 | |||
| 624 | case ({},_) then {}; | ||
| 625 | |||
| 626 | case(expo1::rest1,expo2) | ||
| 627 | algorithm | ||
| 628 | ✗ | expo3 := MMath.multRational(expo1,expo2); | |
| 629 | ✗ | rest2 := powUnitVec(rest1,expo2); | |
| 630 | then | ||
| 631 | (expo3::rest2); | ||
| 632 | |||
| 633 | else | ||
| 634 | algorithm | ||
| 635 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 636 | ✗ | Debug.trace("UnitChecker::powUnitVec() failed\n"); | |
| 637 | ✗ | then fail(); | |
| 638 | end matchcontinue; | ||
| 639 | end powUnitVec; | ||
| 640 | |||
| 641 | protected function negParamList | ||
| 642 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> ine; | ||
| 643 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> ac; | ||
| 644 | output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> oute; | ||
| 645 | algorithm | ||
| 646 | oute := matchcontinue(ine,ac) | ||
| 647 | local | ||
| 648 | MMath.Rational qr; | ||
| 649 | Integer i1,i2,indx; | ||
| 650 | String name; | ||
| 651 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest,pres,ac2; | ||
| 652 | |||
| 653 | case ({},ac2) then ac2; | ||
| 654 | |||
| 655 | case ((MMath.RATIONAL(i1,i2),UnitAbsyn.TYPEPARAMETER(name,indx))::rest,ac2) | ||
| 656 | algorithm | ||
| 657 | ✗ | qr := MMath.multRational(MMath.RATIONAL(-1,1),MMath.RATIONAL(i1,i2)); | |
| 658 | ✗ | pres := negParamList(rest,(qr,UnitAbsyn.TYPEPARAMETER(name,indx))::ac2); | |
| 659 | then pres; | ||
| 660 | |||
| 661 | else | ||
| 662 | algorithm | ||
| 663 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 664 | ✗ | Debug.trace("UnitChecker::negParamList() failed\n"); | |
| 665 | ✗ | then fail(); | |
| 666 | end matchcontinue; | ||
| 667 | end negParamList; | ||
| 668 | |||
| 669 | public function normalize "normalizes the unit pointed by 'loc'. Returns the normalized unit." | ||
| 670 | input Integer loc; | ||
| 671 | input UnitAbsyn.Store st; | ||
| 672 | output UnitAbsyn.Unit unit; | ||
| 673 | output UnitAbsyn.Store outSt; | ||
| 674 | protected | ||
| 675 | UnitAbsyn.Unit u1,u2; | ||
| 676 | UnitAbsyn.Store st2; | ||
| 677 | algorithm | ||
| 678 | ✗ | u1 := UnitAbsynBuilder.find(loc,st); | |
| 679 | ✗ | (u2,st2) := normalizeOnUnit(u1,st); | |
| 680 | ✗ | outSt := UnitAbsynBuilder.update(u2,loc,st2); | |
| 681 | unit := u2; | ||
| 682 | end normalize; | ||
| 683 | |||
| 684 | public function normalizeOnUnit "switch on each kind of unit" | ||
| 685 | input UnitAbsyn.Unit u; | ||
| 686 | input UnitAbsyn.Store st; | ||
| 687 | output UnitAbsyn.Unit unit; | ||
| 688 | output UnitAbsyn.Store outSt; | ||
| 689 | algorithm | ||
| 690 | (unit,outSt) := matchcontinue u | ||
| 691 | local | ||
| 692 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params1,params2,params3; | ||
| 693 | list<MMath.Rational> unitvec1,unitvec2; | ||
| 694 | UnitAbsyn.Store st2; | ||
| 695 | |||
| 696 | case UnitAbsyn.UNSPECIFIED() | ||
| 697 | then (UnitAbsyn.UNSPECIFIED(),st); | ||
| 698 | |||
| 699 | case UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(params1,unitvec1)) | ||
| 700 | algorithm | ||
| 701 | ✗ | (UnitAbsyn.SPECUNIT(params2,unitvec2),st2) := normalizeParamsValues(params1,UnitAbsyn.SPECUNIT({},unitvec1),st); | |
| 702 | ✗ | params3 := normalizeParamsExponents(params2); | |
| 703 | ✗ | then | |
| 704 | (UnitAbsyn.SPECIFIED(UnitAbsyn.SPECUNIT(params3,unitvec2)),st2); | ||
| 705 | |||
| 706 | else | ||
| 707 | algorithm | ||
| 708 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 709 | ✗ | Debug.trace("UnitChecker::normalizeOnUnit() failed\n"); | |
| 710 | ✗ | then fail(); | |
| 711 | end matchcontinue; | ||
| 712 | end normalizeOnUnit; | ||
| 713 | |||
| 714 | protected function normalizeParamsExponents "normalize the exponents of a parameter list" | ||
| 715 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> inparams; | ||
| 716 | output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> outparams; | ||
| 717 | algorithm | ||
| 718 | outparams := matchcontinue inparams | ||
| 719 | local | ||
| 720 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest1,rest2,rest3; | ||
| 721 | String name; | ||
| 722 | Integer loc1; | ||
| 723 | MMath.Rational expo1,expo2,expo3; | ||
| 724 | tuple<MMath.Rational,UnitAbsyn.TypeParameter> param; | ||
| 725 | |||
| 726 | // Case: No more elements in list | ||
| 727 | case {} then {}; | ||
| 728 | |||
| 729 | // Case: Found duplicate parameter in list | ||
| 730 | case (expo1,UnitAbsyn.TYPEPARAMETER(name,loc1))::rest1 | ||
| 731 | algorithm | ||
| 732 | ✗ | (true,expo2,rest2) := getParam(rest1,loc1); | |
| 733 | ✗ | expo3 := MMath.addRational(expo1,expo2); | |
| 734 | ✗ | rest3 := normalizeParamsExponents((expo3,UnitAbsyn.TYPEPARAMETER(name,loc1))::rest2); | |
| 735 | then | ||
| 736 | rest3; | ||
| 737 | |||
| 738 | // Case: No duplicates in list and exponent IS zero | ||
| 739 | case (MMath.RATIONAL(0,1),_)::rest1 | ||
| 740 | algorithm | ||
| 741 | ✗ | rest2 := normalizeParamsExponents(rest1); | |
| 742 | then | ||
| 743 | rest2; | ||
| 744 | |||
| 745 | // Case: No duplicates in list and exponent is not zero | ||
| 746 | case param::rest1 | ||
| 747 | algorithm | ||
| 748 | ✗ | rest2 := normalizeParamsExponents(rest1); | |
| 749 | then | ||
| 750 | (param::rest2); | ||
| 751 | |||
| 752 | else | ||
| 753 | algorithm | ||
| 754 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 755 | ✗ | Debug.trace("UnitChecker::normalizeParamsExponents() failed\n"); | |
| 756 | ✗ | then | |
| 757 | fail(); | ||
| 758 | end matchcontinue; | ||
| 759 | end normalizeParamsExponents; | ||
| 760 | |||
| 761 | protected function getParam "returns the next param in list and removes it from the list. 'found'=true if an location existed" | ||
| 762 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> inparams; | ||
| 763 | input Integer loc; | ||
| 764 | output Boolean found; | ||
| 765 | output MMath.Rational outexpo; | ||
| 766 | output list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> outparams; | ||
| 767 | algorithm | ||
| 768 | (found,outexpo,outparams) := match inparams | ||
| 769 | local | ||
| 770 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest,rest2; | ||
| 771 | Integer loc2; | ||
| 772 | MMath.Rational expo; | ||
| 773 | Boolean found2; | ||
| 774 | tuple<MMath.Rational,UnitAbsyn.TypeParameter> param; | ||
| 775 | |||
| 776 | case {} then (false,MMath.RATIONAL(1,1),{}); | ||
| 777 | |||
| 778 | case (expo,UnitAbsyn.TYPEPARAMETER(_,loc2))::rest guard intEq(loc2, loc) | ||
| 779 | then | ||
| 780 | (true,expo,rest); | ||
| 781 | |||
| 782 | case param::rest | ||
| 783 | algorithm | ||
| 784 | ✗ | (found2,expo,rest2) := getParam(rest,loc); | |
| 785 | ✗ | then | |
| 786 | (found2,expo,param::rest2); | ||
| 787 | |||
| 788 | else | ||
| 789 | algorithm | ||
| 790 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 791 | ✗ | Debug.trace("UnitChecker::getParam() failed\n"); | |
| 792 | ✗ | then fail(); | |
| 793 | end match; | ||
| 794 | end getParam; | ||
| 795 | |||
| 796 | protected function normalizeParamsValues "normalize the values that the the list of unit parameters points at" | ||
| 797 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> inparams; | ||
| 798 | input UnitAbsyn.SpecUnit suin; | ||
| 799 | input UnitAbsyn.Store st; | ||
| 800 | output UnitAbsyn.SpecUnit uout; | ||
| 801 | output UnitAbsyn.Store outSt; | ||
| 802 | algorithm | ||
| 803 | (uout,outSt) := matchcontinue inparams | ||
| 804 | local | ||
| 805 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest; | ||
| 806 | UnitAbsyn.Store st2,st3; | ||
| 807 | UnitAbsyn.Unit u2; | ||
| 808 | UnitAbsyn.SpecUnit su2,su3; | ||
| 809 | String name; | ||
| 810 | Integer loc; | ||
| 811 | MMath.Rational expo; | ||
| 812 | |||
| 813 | ✗ | case {} then (suin,st); | |
| 814 | |||
| 815 | case (expo,UnitAbsyn.TYPEPARAMETER(name,loc))::rest | ||
| 816 | algorithm | ||
| 817 | ✗ | (u2,st2) := normalize(loc,st); | |
| 818 | ✗ | su2 := mulSpecUnitWithNorm(suin,u2,name,loc,expo); | |
| 819 | ✗ | (su3,st3) := normalizeParamsValues(rest,su2,st2); | |
| 820 | then | ||
| 821 | (su3,st3); | ||
| 822 | |||
| 823 | else | ||
| 824 | algorithm | ||
| 825 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 826 | ✗ | Debug.trace("UnitChecker::normalizeParamsValues() failed\n"); | |
| 827 | ✗ | then fail(); | |
| 828 | end matchcontinue; | ||
| 829 | end normalizeParamsValues; | ||
| 830 | |||
| 831 | protected function mulSpecUnitWithNorm | ||
| 832 | input UnitAbsyn.SpecUnit suin; | ||
| 833 | input UnitAbsyn.Unit normunit; | ||
| 834 | input String name; | ||
| 835 | input Integer loc; | ||
| 836 | input MMath.Rational expo; | ||
| 837 | output UnitAbsyn.SpecUnit suout; | ||
| 838 | algorithm | ||
| 839 | suout := matchcontinue(suin, normunit) | ||
| 840 | local | ||
| 841 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params; | ||
| 842 | list<MMath.Rational> unitvec; | ||
| 843 | UnitAbsyn.SpecUnit su2,sunorm,su3,su4; | ||
| 844 | |||
| 845 | case (UnitAbsyn.SPECUNIT(params,unitvec), UnitAbsyn.UNSPECIFIED()) | ||
| 846 | ✗ | then (UnitAbsyn.SPECUNIT((expo,UnitAbsyn.TYPEPARAMETER(name,loc))::params,unitvec)); | |
| 847 | |||
| 848 | case (su2, UnitAbsyn.SPECIFIED(sunorm)) | ||
| 849 | algorithm | ||
| 850 | ✗ | su3 := powSpecUnit(sunorm,expo); | |
| 851 | ✗ | su4 := mulSpecUnit(su2,su3); | |
| 852 | then | ||
| 853 | su4; | ||
| 854 | |||
| 855 | else | ||
| 856 | algorithm | ||
| 857 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 858 | ✗ | Debug.trace("UnitChecker::mulSpecUnitWithNorm() failed\n"); | |
| 859 | ✗ | then fail(); | |
| 860 | end matchcontinue; | ||
| 861 | end mulSpecUnitWithNorm; | ||
| 862 | |||
| 863 | public function printSpecUnit | ||
| 864 | input String text; | ||
| 865 | input UnitAbsyn.SpecUnit su; | ||
| 866 | algorithm | ||
| 867 | () := match(text,su) | ||
| 868 | local | ||
| 869 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params; | ||
| 870 | String str; | ||
| 871 | |||
| 872 | case(str,UnitAbsyn.SPECUNIT(params,_)) | ||
| 873 | algorithm | ||
| 874 | ✗ | print(str); | |
| 875 | ✗ | print(" \""); | |
| 876 | ✗ | print(UnitAbsynBuilder.unit2str(UnitAbsyn.SPECIFIED(su))); | |
| 877 | ✗ | print("\" {"); | |
| 878 | ✗ | printSpecUnitParams(params); | |
| 879 | ✗ | print("}\n"); | |
| 880 | then (); | ||
| 881 | end match; | ||
| 882 | end printSpecUnit; | ||
| 883 | |||
| 884 | public function printSpecUnitParams | ||
| 885 | input list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> params; | ||
| 886 | algorithm | ||
| 887 | () := match params | ||
| 888 | local | ||
| 889 | String name; | ||
| 890 | Integer i1,i2,loc; | ||
| 891 | list<tuple<MMath.Rational,UnitAbsyn.TypeParameter>> rest; | ||
| 892 | |||
| 893 | case {} then (); | ||
| 894 | |||
| 895 | case (MMath.RATIONAL(i1,i2),UnitAbsyn.TYPEPARAMETER(name,loc))::rest | ||
| 896 | algorithm | ||
| 897 | ✗ | print("(\""); | |
| 898 | ✗ | print(name); | |
| 899 | ✗ | print("\","); | |
| 900 | ✗ | print(intString(loc)); | |
| 901 | ✗ | print(")^("); | |
| 902 | ✗ | print(intString(i1)); | |
| 903 | ✗ | print("/"); | |
| 904 | ✗ | print(intString(i2)); | |
| 905 | ✗ | print("),"); | |
| 906 | ✗ | printSpecUnitParams(rest); | |
| 907 | then (); | ||
| 908 | end match; | ||
| 909 | end printSpecUnitParams; | ||
| 910 | |||
| 911 | public function testUnitOp "Test unit operations" | ||
| 912 | protected | ||
| 913 | algorithm | ||
| 914 | ✗ | print("test"); | |
| 915 | end testUnitOp; | ||
| 916 | |||
| 917 | public function printResult "Print out the result from the unit check" | ||
| 918 | input UnitAbsyn.UnitCheckResult res; | ||
| 919 | algorithm | ||
| 920 | () := match res | ||
| 921 | local | ||
| 922 | UnitAbsyn.SpecUnit u1,u2; | ||
| 923 | String str1,str2; | ||
| 924 | |||
| 925 | case UnitAbsyn.CONSISTENT() | ||
| 926 | algorithm | ||
| 927 | ✗ | print("\n---\nThe system of units is consistent.\n---\n"); | |
| 928 | then (); | ||
| 929 | |||
| 930 | case UnitAbsyn.INCONSISTENT(u1,u2) | ||
| 931 | algorithm | ||
| 932 | ✗ | print("\n---\nThe system of units is inconsistent. \""); | |
| 933 | ✗ | str1 := UnitAbsynBuilder.unit2str(UnitAbsyn.SPECIFIED(u1)); | |
| 934 | ✗ | print(str1); | |
| 935 | ✗ | print("\" != \""); | |
| 936 | ✗ | str2 := UnitAbsynBuilder.unit2str(UnitAbsyn.SPECIFIED(u2)); | |
| 937 | ✗ | print(str2); | |
| 938 | ✗ | print("\"\n---\n"); | |
| 939 | then (); | ||
| 940 | end match; | ||
| 941 | end printResult; | ||
| 942 | |||
| 943 | annotation(__OpenModelica_Interface="frontend"); | ||
| 944 | end UnitChecker; | ||
| 945 |