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 |