OMCompiler/Compiler/Script/ProgramUtil.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 ProgramUtil | ||
| 37 | " file: ProgramUtil.mo | ||
| 38 | package: ProgramUtil | ||
| 39 | description: Absyn program-tree navigation and manipulation helpers, factored | ||
| 40 | out of InteractiveUtil so lower layers (backend/SimCode) can use | ||
| 41 | them without depending on the interactive/scripting layer." | ||
| 42 | |||
| 43 | import Absyn; | ||
| 44 | |||
| 45 | protected | ||
| 46 | import AbsynUtil; | ||
| 47 | import DoubleEnded; | ||
| 48 | import Dump; | ||
| 49 | import Error; | ||
| 50 | import FBuiltin; | ||
| 51 | import List; | ||
| 52 | import Print; | ||
| 53 | import Util; | ||
| 54 | import Testsuite; | ||
| 55 | import System; | ||
| 56 | import Settings; | ||
| 57 | import Autoconf; | ||
| 58 | |||
| 59 | public | ||
| 60 | public function buildWithin | ||
| 61 | " From a fully qualified model name, build a suitable within clause" | ||
| 62 | input Absyn.Path inPath; | ||
| 63 | output Absyn.Within outWithin; | ||
| 64 | algorithm | ||
| 65 | outWithin := match inPath | ||
| 66 | local Absyn.Path w_path,path; | ||
| 67 | case Absyn.IDENT() then Absyn.TOP(); | ||
| 68 | case Absyn.FULLYQUALIFIED(path) // handle fully qual also! | ||
| 69 | 140 | then | |
| 70 | buildWithin(path); | ||
| 71 | case path | ||
| 72 | algorithm | ||
| 73 | 129 | w_path := AbsynUtil.stripLast(path); | |
| 74 | 129 | then | |
| 75 | Absyn.WITHIN(w_path); | ||
| 76 | end match; | ||
| 77 | end buildWithin; | ||
| 78 | public function updateProgram | ||
| 79 | " This function takes an old program (second argument), i.e. the old | ||
| 80 | symboltable, and a new program (first argument), i.e. a new set of | ||
| 81 | classes and updates the old program with the definitions in the new one. | ||
| 82 | It also takes in the current symboltable and returns a new one with any | ||
| 83 | replaced functions cache cleared." | ||
| 84 | input Absyn.Program inNewProgram; | ||
| 85 | input Absyn.Program inOldProgram; | ||
| 86 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 87 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 88 | output Absyn.Program outProgram; | ||
| 89 | protected | ||
| 90 | list<Absyn.Class> cs; | ||
| 91 | Absyn.Within w; | ||
| 92 | algorithm | ||
| 93 | 5153 | Absyn.PROGRAM(classes=cs,within_=w) := inNewProgram; | |
| 94 | 5153 | outProgram := updateProgram2(listReverse(cs),w,inOldProgram, mergeAST, allowFilenameChange); | |
| 95 | end updateProgram; | ||
| 96 | public function updateProgram2 | ||
| 97 | " This function takes an old program (second argument), i.e. the old | ||
| 98 | symboltable, and a new program (first argument), i.e. a new set of | ||
| 99 | classes and updates the old program with the definitions in the new one. | ||
| 100 | It also takes in the current symboltable and returns a new one with any | ||
| 101 | replaced functions cache cleared." | ||
| 102 | input list<Absyn.Class> inNewClasses; | ||
| 103 | input Absyn.Within w; | ||
| 104 | input Absyn.Program inOldProgram; | ||
| 105 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 106 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 107 | output Absyn.Program outProgram; | ||
| 108 | algorithm | ||
| 109 | outProgram := match (inNewClasses,w,inOldProgram) | ||
| 110 | local | ||
| 111 | Absyn.Program prg,newp,p2,newp_1; | ||
| 112 | Absyn.Class c1; | ||
| 113 | String name; | ||
| 114 | list<Absyn.Class> c2,c3; | ||
| 115 | Absyn.Within w2; | ||
| 116 | |||
| 117 | case ({},_,prg) then prg; | ||
| 118 | |||
| 119 | case ((c1 as Absyn.CLASS(name = name)) :: c2,Absyn.TOP(), (p2 as Absyn.PROGRAM(classes = c3,within_ = w2))) | ||
| 120 | algorithm | ||
| 121 |
2/2✓ Branch 1 taken 162 times.
✓ Branch 2 taken 6514 times.
|
6676 | if classInProgram(name, p2) then |
| 122 | 162 | newp := replaceClassInProgram(c1, p2, mergeAST); | |
| 123 | else | ||
| 124 | 6514 | newp := Absyn.PROGRAM((c1 :: c3),w2); | |
| 125 | end if; | ||
| 126 | 6676 | then updateProgram2(c2,w,newp, mergeAST, allowFilenameChange); | |
| 127 | |||
| 128 | case ((c1 :: c2),Absyn.WITHIN(),p2) | ||
| 129 | algorithm | ||
| 130 | 34 | newp := insertClassInProgram(c1, w, p2, mergeAST, allowFilenameChange); | |
| 131 | 34 | newp_1 := updateProgram2(c2,w,newp, mergeAST, allowFilenameChange); | |
| 132 | then newp_1; | ||
| 133 | |||
| 134 | end match; | ||
| 135 | end updateProgram2; | ||
| 136 | public function getClassnamesInParts | ||
| 137 | "Helper function to getClassnamesInClass." | ||
| 138 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 139 | input Boolean inShowProtected; | ||
| 140 | input Boolean includeConstants; | ||
| 141 | output list<String> outStringLst; | ||
| 142 | algorithm | ||
| 143 | outStringLst:= | ||
| 144 | matchcontinue (inAbsynClassPartLst,inShowProtected,includeConstants) | ||
| 145 | local | ||
| 146 | list<String> l1,l2,res; | ||
| 147 | list<Absyn.ElementItem> elts; | ||
| 148 | list<Absyn.ClassPart> rest; | ||
| 149 | Boolean b,c; | ||
| 150 | |||
| 151 | case ({},_,_) then {}; | ||
| 152 | |||
| 153 | case ((Absyn.PUBLIC(contents = elts) :: rest),b,c) | ||
| 154 | algorithm | ||
| 155 | 12 | l1 := getClassnamesInElts(elts,c); | |
| 156 | 12 | l2 := getClassnamesInParts(rest,b,c); | |
| 157 | 12 | res := listAppend(l1, l2); | |
| 158 | then | ||
| 159 | res; | ||
| 160 | |||
| 161 | // adeas31 2012-01-25: Also check the protected sections. | ||
| 162 | case ((Absyn.PROTECTED(contents = elts) :: rest), true, c) | ||
| 163 | algorithm | ||
| 164 | ✗ | l1 := getClassnamesInElts(elts,c); | |
| 165 | ✗ | l2 := getClassnamesInParts(rest,true,c); | |
| 166 | ✗ | res := listAppend(l1, l2); | |
| 167 | then | ||
| 168 | res; | ||
| 169 | |||
| 170 | case ((_ :: rest),b,c) | ||
| 171 | algorithm | ||
| 172 | ✗ | res := getClassnamesInParts(rest,b,c); | |
| 173 | then | ||
| 174 | res; | ||
| 175 | |||
| 176 | end matchcontinue; | ||
| 177 | end getClassnamesInParts; | ||
| 178 | public function getClassnamesInElts | ||
| 179 | "Helper function to getClassnamesInParts." | ||
| 180 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 181 | input Boolean includeConstants; | ||
| 182 | output list<String> outStringLst; | ||
| 183 | protected | ||
| 184 | DoubleEnded.MutableList<String> delst; | ||
| 185 | algorithm | ||
| 186 | 12 | delst := DoubleEnded.fromList({}); | |
| 187 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 12 times.
|
50 | for elt in inAbsynElementItemLst loop |
| 188 | () := match elt | ||
| 189 | local | ||
| 190 | String id; | ||
| 191 | list<Absyn.ComponentItem> lst; | ||
| 192 | |||
| 193 | case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = | ||
| 194 | Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = id))))) | ||
| 195 | algorithm | ||
| 196 | ✗ | DoubleEnded.push_back(delst, id); | |
| 197 | then (); | ||
| 198 | |||
| 199 | case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.CLASSDEF(class_ = | ||
| 200 | Absyn.CLASS(name = id)))) | ||
| 201 | algorithm | ||
| 202 | 32 | DoubleEnded.push_back(delst, id); | |
| 203 | then (); | ||
| 204 | |||
| 205 | case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = Absyn.COMPONENTS(attributes = Absyn.ATTR(variability = Absyn.CONST()), | ||
| 206 | components = lst))) guard includeConstants | ||
| 207 | algorithm | ||
| 208 | 3 | DoubleEnded.push_list_back(delst, getComponentItemsName(lst,false)); | |
| 209 | then (); | ||
| 210 | |||
| 211 | else (); | ||
| 212 | end match; | ||
| 213 | end for; | ||
| 214 | 12 | outStringLst := DoubleEnded.toListAndClear(delst); | |
| 215 | end getClassnamesInElts; | ||
| 216 | public function getComponentItemsName | ||
| 217 | " separated list of all component names." | ||
| 218 | input list<Absyn.ComponentItem> inComponents; | ||
| 219 | input Boolean inQuoteNames "Adds quotes around the component names if true."; | ||
| 220 | output list<String> outStrings = {}; | ||
| 221 | protected | ||
| 222 | String name; | ||
| 223 | algorithm | ||
| 224 |
2/2✓ Branch 1 taken 4 times.
✓ Branch 2 taken 3 times.
|
7 | for comp in listReverse(inComponents) loop |
| 225 | () := match comp | ||
| 226 | case Absyn.COMPONENTITEM(component = Absyn.COMPONENT(name = name)) | ||
| 227 | algorithm | ||
| 228 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | outStrings := (if inQuoteNames then |
| 229 | stringAppendList({"\"", name, "\""}) else | ||
| 230 | stringAppendList({name})) :: outStrings; | ||
| 231 | then | ||
| 232 | (); | ||
| 233 | |||
| 234 | else (); | ||
| 235 | end match; | ||
| 236 | end for; | ||
| 237 | end getComponentItemsName; | ||
| 238 | public function replaceClassInProgram2 | ||
| 239 | input Absyn.Class inClass; | ||
| 240 | input String inClassName; | ||
| 241 | output Boolean outReplace; | ||
| 242 | protected | ||
| 243 | String cls_name; | ||
| 244 | algorithm | ||
| 245 | 512 | Absyn.CLASS(name = cls_name) := inClass; | |
| 246 |
4/4✓ Branch 0 taken 280 times.
✓ Branch 1 taken 232 times.
✓ Branch 3 taken 115 times.
✓ Branch 4 taken 165 times.
|
512 | outReplace := cls_name == inClassName; |
| 247 | end replaceClassInProgram2; | ||
| 248 | public function replaceClassInProgram | ||
| 249 | " This function takes a Class and a Program and replaces the class | ||
| 250 | definition at the top level in the program by the class definition of | ||
| 251 | the Class. It also updates the functionlist for the symboltable if needed." | ||
| 252 | input Absyn.Class inClass; | ||
| 253 | input Absyn.Program inProgram; | ||
| 254 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 255 | output Absyn.Program outProgram; | ||
| 256 | protected | ||
| 257 | String cls_name1; | ||
| 258 | list<Absyn.Class> clst, clsFilter; | ||
| 259 | Absyn.Within w; | ||
| 260 | Boolean replaced; | ||
| 261 | Absyn.Class cls; | ||
| 262 | algorithm | ||
| 263 | 162 | Absyn.CLASS(name = cls_name1) := inClass; | |
| 264 | 162 | Absyn.PROGRAM(classes = clst, within_ = w) := inProgram; | |
| 265 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 159 times.
|
162 | if mergeAST then |
| 266 | 3 | clsFilter := List.filterOnTrue(clst, function replaceClassInProgram2(inClassName = cls_name1)); | |
| 267 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if listEmpty(clsFilter) |
| 268 | then | ||
| 269 | cls := inClass; | ||
| 270 | else | ||
| 271 | 3 | cls::_ := clsFilter; | |
| 272 | 3 | cls := mergeClasses(inClass, cls); | |
| 273 | end if; | ||
| 274 | else | ||
| 275 | cls := inClass; | ||
| 276 | end if; | ||
| 277 | 162 | (clst, replaced) := List.replaceOnTrue(cls, clst, | |
| 278 | function replaceClassInProgram2(inClassName = cls_name1)); | ||
| 279 | |||
| 280 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 162 times.
|
162 | if not replaced then |
| 281 | ✗ | clst := List.appendElt(inClass, clst); | |
| 282 | end if; | ||
| 283 | |||
| 284 | 162 | outProgram := Absyn.PROGRAM(clst, w); | |
| 285 | end replaceClassInProgram; | ||
| 286 | public function insertClassInProgram | ||
| 287 | " This function inserts the class into the Program at the scope given by | ||
| 288 | the within argument. If the class referenced by the within argument is | ||
| 289 | not defined, the function prints an error message and fails." | ||
| 290 | input Absyn.Class inClass; | ||
| 291 | input Absyn.Within inWithin; | ||
| 292 | input Absyn.Program inProgram; | ||
| 293 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 294 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 295 | output Absyn.Program outProgram; | ||
| 296 | algorithm | ||
| 297 | outProgram := matchcontinue (inClass,inWithin,inProgram) | ||
| 298 | local | ||
| 299 | Absyn.Class c2,c3,c1; | ||
| 300 | Absyn.Program pnew,p; | ||
| 301 | Absyn.Within w; | ||
| 302 | String n1,s1,s2,name; | ||
| 303 | list<Absyn.Path> paths; | ||
| 304 | |||
| 305 | case (c1,(w as Absyn.WITHIN(path = Absyn.QUALIFIED(name = n1))),p as Absyn.PROGRAM()) | ||
| 306 | algorithm | ||
| 307 | 7 | c2 := getClassInProgram(n1, p); | |
| 308 | 7 | c3 := insertClassInClass(c1, w, c2, mergeAST, allowFilenameChange); | |
| 309 | 7 | pnew := updateProgram(Absyn.PROGRAM({c3},Absyn.TOP()), p, mergeAST, allowFilenameChange); | |
| 310 | then | ||
| 311 | pnew; | ||
| 312 | |||
| 313 | case (c1,(w as Absyn.WITHIN(path = Absyn.IDENT(name = n1))),p as Absyn.PROGRAM()) | ||
| 314 | algorithm | ||
| 315 | 27 | c2 := getClassInProgram(n1, p); | |
| 316 | 27 | c3 := insertClassInClass(c1, w, c2, mergeAST, allowFilenameChange); | |
| 317 | 27 | pnew := updateProgram(Absyn.PROGRAM({c3},Absyn.TOP()), p, mergeAST, allowFilenameChange); | |
| 318 | then | ||
| 319 | pnew; | ||
| 320 | |||
| 321 | case (_,Absyn.WITHIN(path=Absyn.QUALIFIED(name="OpenModelica")),p) then p; | ||
| 322 | |||
| 323 | case ((Absyn.CLASS(name = name)),w,p) | ||
| 324 | algorithm | ||
| 325 | ✗ | s1 := Dump.unparseWithin(w); | |
| 326 | /* adeas31 2012-01-25: false indicates that the classnamesrecursive doesn't look into protected sections */ | ||
| 327 | /* adeas31 2016-11-29: false indicates that the classnamesrecursive doesn't look for constants */ | ||
| 328 | ✗ | (_, paths) := getClassNamesRecursive(NONE(), p, false, false, {}); | |
| 329 | ✗ | s2 := stringAppendList(List.map1r(list(AbsynUtil.pathString(p) for p in paths),stringAppend,"\n ")); | |
| 330 | ✗ | Error.addMessage(Error.INSERT_CLASS, {name,s1,s2}); | |
| 331 | ✗ | then | |
| 332 | fail(); | ||
| 333 | |||
| 334 | end matchcontinue; | ||
| 335 | end insertClassInProgram; | ||
| 336 | public function insertClassInClass " | ||
| 337 | This function takes a class to update (the first argument) and an inner | ||
| 338 | class (which is either replacing | ||
| 339 | an earlier class or is a new inner definition) and a within statement | ||
| 340 | pointing inside the class (including the class itself in the reference), | ||
| 341 | and updates the class with the inner class. | ||
| 342 | " | ||
| 343 | input Absyn.Class inClass1; | ||
| 344 | input Absyn.Within inWithin2; | ||
| 345 | input Absyn.Class inClass3; | ||
| 346 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 347 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 348 | output Absyn.Class outClass; | ||
| 349 | algorithm | ||
| 350 | outClass := match (inClass1,inWithin2,inClass3) | ||
| 351 | local | ||
| 352 | Absyn.Class cnew,c1,c2,cinner; | ||
| 353 | String name2; | ||
| 354 | Absyn.Path path; | ||
| 355 | |||
| 356 | case (c1,Absyn.WITHIN(path = Absyn.IDENT()),c2) | ||
| 357 | 34 | then replaceInnerClass(c1, c2, mergeAST, allowFilenameChange); | |
| 358 | |||
| 359 | case (c1,Absyn.WITHIN(path = Absyn.QUALIFIED(path = path)),c2) | ||
| 360 | algorithm | ||
| 361 | 7 | name2 := AbsynUtil.pathFirstIdent(path); | |
| 362 | 7 | cinner := getInnerClass(c2, name2); | |
| 363 | 7 | cnew := insertClassInClass(c1, Absyn.WITHIN(path), cinner, mergeAST, allowFilenameChange); | |
| 364 | 7 | then replaceInnerClass(cnew, c2, mergeAST, allowFilenameChange); | |
| 365 | |||
| 366 | end match; | ||
| 367 | end insertClassInClass; | ||
| 368 | public function replaceInnerClass | ||
| 369 | "This function takes two class definitions. The first one is | ||
| 370 | inserted/replaced as a local class inside the second one." | ||
| 371 | input Absyn.Class inClass1; | ||
| 372 | input Absyn.Class inClass2; | ||
| 373 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 374 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 375 | output Absyn.Class outClass; | ||
| 376 | protected | ||
| 377 | String enclosingFileName; | ||
| 378 | algorithm | ||
| 379 | 41 | Absyn.CLASS(info = SOURCEINFO(fileName = enclosingFileName)) := inClass2; | |
| 380 | outClass:= | ||
| 381 | matchcontinue (inClass1,inClass2) | ||
| 382 | local | ||
| 383 | list<Absyn.ElementItem> publst,publst2,prolst,prolst2; | ||
| 384 | list<Absyn.ClassPart> parts2,parts; | ||
| 385 | Absyn.Class c1; | ||
| 386 | String bcname; | ||
| 387 | Option<String> cmt; | ||
| 388 | list<Absyn.ElementArg> modif; | ||
| 389 | list<String> typeVars; | ||
| 390 | list<Absyn.NamedArg> classAttrs; | ||
| 391 | list<Absyn.Annotation> ann; | ||
| 392 | |||
| 393 | // a class with parts - we can find the element in the public list | ||
| 394 | case (c1,outClass as Absyn.CLASS(body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann=ann,comment = cmt))) | ||
| 395 | algorithm | ||
| 396 | 41 | publst := getPublicList(parts); | |
| 397 |
2/2✓ Branch 1 taken 11 times.
✓ Branch 2 taken 30 times.
|
41 | (publst2, true) := replaceClassInElementitemlist(publst, c1, mergeAST, allowFilenameChange, enclosingFileName); |
| 398 | 30 | parts2 := replacePublicList(parts, publst2); | |
| 399 | 60 | outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt); | |
| 400 | then | ||
| 401 | outClass; | ||
| 402 | |||
| 403 | // a class with parts - we can find the element in the protected list | ||
| 404 | case (c1,outClass as Absyn.CLASS( | ||
| 405 | body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann=ann,comment = cmt))) | ||
| 406 | algorithm | ||
| 407 | 11 | prolst := getProtectedList(parts); | |
| 408 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
11 | (prolst2, true) := replaceClassInElementitemlist(prolst, c1, mergeAST, allowFilenameChange, enclosingFileName); |
| 409 | ✗ | parts2 := replaceProtectedList(parts, prolst2); | |
| 410 | ✗ | outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt); | |
| 411 | then | ||
| 412 | outClass; | ||
| 413 | |||
| 414 | // a class with parts - we cannot find the element in the public or protected list, add it to the public list | ||
| 415 | case (c1,outClass as Absyn.CLASS( | ||
| 416 | body = Absyn.PARTS(typeVars = typeVars, classAttrs = classAttrs, classParts = parts,ann=ann,comment = cmt))) | ||
| 417 | algorithm | ||
| 418 | 11 | publst := getPublicList(parts); | |
| 419 | 11 | publst := addClassInElementitemlist(publst, c1); | |
| 420 | 11 | parts2 := replacePublicList(parts, publst); | |
| 421 | 22 | outClass.body := Absyn.PARTS(typeVars,classAttrs,parts2,ann,cmt); | |
| 422 | then | ||
| 423 | outClass; | ||
| 424 | |||
| 425 | // an extended class with parts: model extends M end M; - we can find the element in the public list | ||
| 426 | case (c1,outClass as Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications = modif,parts = parts,ann=ann,comment = cmt))) | ||
| 427 | algorithm | ||
| 428 | ✗ | publst := getPublicList(parts); | |
| 429 | ✗ | (publst2, true) := replaceClassInElementitemlist(publst, c1, mergeAST, allowFilenameChange, enclosingFileName); | |
| 430 | ✗ | parts2 := replacePublicList(parts, publst2); | |
| 431 | ✗ | outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann); | |
| 432 | then | ||
| 433 | outClass; | ||
| 434 | |||
| 435 | // an extended class with parts: model extends M end M; - we can find the element in the protected list | ||
| 436 | case (c1,outClass as Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications = modif,parts = parts,ann=ann,comment = cmt))) | ||
| 437 | algorithm | ||
| 438 | ✗ | prolst := getProtectedList(parts); | |
| 439 | ✗ | (prolst2, true) := replaceClassInElementitemlist(prolst, c1, mergeAST, allowFilenameChange, enclosingFileName); | |
| 440 | ✗ | parts2 := replaceProtectedList(parts, prolst2); | |
| 441 | ✗ | outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann); | |
| 442 | then | ||
| 443 | outClass; | ||
| 444 | |||
| 445 | // an extended class with parts: model extends M end M; - we cannot find the element in the public or protected list, add it to the public list | ||
| 446 | case (c1,outClass as Absyn.CLASS(body = Absyn.CLASS_EXTENDS(baseClassName = bcname,modifications = modif,parts = parts,ann=ann,comment = cmt))) | ||
| 447 | algorithm | ||
| 448 | ✗ | publst := getPublicList(parts); | |
| 449 | ✗ | publst := addClassInElementitemlist(publst, c1); | |
| 450 | ✗ | parts2 := replacePublicList(parts, publst); | |
| 451 | ✗ | outClass.body := Absyn.CLASS_EXTENDS(bcname,modif,cmt,parts2,ann); | |
| 452 | then | ||
| 453 | outClass; | ||
| 454 | |||
| 455 | else | ||
| 456 | algorithm | ||
| 457 | ✗ | Print.printBuf("Failed in replaceInnerClass\n"); | |
| 458 | ✗ | then | |
| 459 | fail(); | ||
| 460 | end matchcontinue; | ||
| 461 | end replaceInnerClass; | ||
| 462 | public function replaceClassInElementitemlist | ||
| 463 | "This function takes an Element list and a Class and returns a modified | ||
| 464 | element list where the class definition of the class is updated or added." | ||
| 465 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 466 | input Absyn.Class inClass; | ||
| 467 | input Boolean mergeAST = false "when true, the new program should be merged with the old program"; | ||
| 468 | input Boolean allowFilenameChange = false "when true, the class is allowed to move to the file it carries; only setSourceFile relocates a class"; | ||
| 469 | input String enclosingFileName = "" "the file the enclosing class is stored in"; | ||
| 470 | output list<Absyn.ElementItem> outAbsynElementItemLst; | ||
| 471 | output Boolean replaced "true signals a replacement, false nothing changed!"; | ||
| 472 | algorithm | ||
| 473 | (outAbsynElementItemLst, replaced) := match (inAbsynElementItemLst,inClass) | ||
| 474 | local | ||
| 475 | list<Absyn.ElementItem> res,xs; | ||
| 476 | Absyn.ElementItem e1; | ||
| 477 | Absyn.Class c, c1, c2; | ||
| 478 | String name1,name,oldFileName; | ||
| 479 | Boolean a,e; | ||
| 480 | Option<Absyn.RedeclareKeywords> b; | ||
| 481 | SourceInfo info; | ||
| 482 | Option<Absyn.ConstrainClass> h; | ||
| 483 | Absyn.InnerOuter io; | ||
| 484 | |||
| 485 | case (((Absyn.ELEMENTITEM(element = Absyn.ELEMENT(finalPrefix = a,redeclareKeywords = b,innerOuter = io,specification = Absyn.CLASSDEF(replaceable_ = e,class_ = c1 as Absyn.CLASS(name = name1)),constrainClass = h))) :: xs),(c2 as Absyn.CLASS(name = name))) | ||
| 486 | guard stringEq(name1, name) | ||
| 487 | algorithm | ||
| 488 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 26 times.
|
30 | c := if mergeAST then mergeClasses(c2, c1) else c2; |
| 489 | // A class stored in the same file as the class enclosing it has to stay | ||
| 490 | // in that file. Letting the replacement bring its own file name along | ||
| 491 | // would make it invisible to listFile on the enclosing class, which | ||
| 492 | // dumps only the elements belonging to that class' file, and the class | ||
| 493 | // would silently disappear on the next listFile/loadString round trip. | ||
| 494 | // A class that already lives in a file of its own (a package stored with | ||
| 495 | // a folder structure) may be relocated, and setSourceFile relocates any | ||
| 496 | // class on purpose. | ||
| 497 | 30 | Absyn.CLASS(info = SOURCEINFO(fileName = oldFileName)) := c1; | |
| 498 |
5/6✓ Branch 0 taken 28 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 22 times.
✓ Branch 3 taken 6 times.
✓ Branch 5 taken 22 times.
✗ Branch 6 not taken.
|
30 | if not allowFilenameChange and stringEq(oldFileName, enclosingFileName) then |
| 499 | 22 | c := AbsynUtil.setClassFilename(c, oldFileName); | |
| 500 | end if; | ||
| 501 | 30 | Absyn.CLASS(info = info) := c; | |
| 502 |
2/4✓ Branch 0 taken 30 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 30 times.
✗ Branch 4 not taken.
|
90 | then |
| 503 | (Absyn.ELEMENTITEM(Absyn.ELEMENT(a,b,io,Absyn.CLASSDEF(e,c),info /* The new CLASS might have update info */,h)) :: xs, true); | ||
| 504 | |||
| 505 | case ((e1 :: xs),c) | ||
| 506 | algorithm | ||
| 507 | 15 | (res, replaced) := replaceClassInElementitemlist(xs, c, mergeAST, allowFilenameChange, enclosingFileName); | |
| 508 | 15 | then | |
| 509 | (e1 :: res, replaced); | ||
| 510 | |||
| 511 | else ({}, false); | ||
| 512 | |||
| 513 | end match; | ||
| 514 | end replaceClassInElementitemlist; | ||
| 515 | public function addClassInElementitemlist | ||
| 516 | "This function takes an Element list and a Class and returns a modified | ||
| 517 | element list where the class definition of the class is updated or added." | ||
| 518 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 519 | input Absyn.Class inClass; | ||
| 520 | output list<Absyn.ElementItem> outAbsynElementItemLst; | ||
| 521 | protected | ||
| 522 | Absyn.Info info; | ||
| 523 | algorithm | ||
| 524 | 11 | Absyn.CLASS(info=info) := inClass; | |
| 525 | 22 | outAbsynElementItemLst := listAppend(inAbsynElementItemLst, | |
| 526 | {Absyn.ELEMENTITEM( | ||
| 527 | Absyn.ELEMENT(false,NONE(),Absyn.NOT_INNER_OUTER(),Absyn.CLASSDEF(false,inClass), | ||
| 528 | info,NONE()))}); | ||
| 529 | end addClassInElementitemlist; | ||
| 530 | public function getInnerClass | ||
| 531 | "This function takes a class name and a class and | ||
| 532 | returns the inner class definition having that name." | ||
| 533 | input Absyn.Class inClass; | ||
| 534 | input Absyn.Ident inIdent; | ||
| 535 | output Absyn.Class outClass; | ||
| 536 | algorithm | ||
| 537 | outClass:= | ||
| 538 | matchcontinue (inClass,inIdent) | ||
| 539 | local | ||
| 540 | list<Absyn.ElementItem> publst,prolst; | ||
| 541 | Absyn.Class c1; | ||
| 542 | list<Absyn.ClassPart> parts; | ||
| 543 | String name; | ||
| 544 | |||
| 545 | // class found in public | ||
| 546 | case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),name) | ||
| 547 | algorithm | ||
| 548 | 7 | publst := getPublicList(parts); | |
| 549 | 7 | c1 := getClassFromElementitemlist(publst, name); | |
| 550 | then | ||
| 551 | c1; | ||
| 552 | |||
| 553 | // class found in protected | ||
| 554 | case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)),name) | ||
| 555 | algorithm | ||
| 556 | ✗ | prolst := getProtectedList(parts); | |
| 557 | ✗ | c1 := getClassFromElementitemlist(prolst, name); | |
| 558 | then | ||
| 559 | c1; | ||
| 560 | |||
| 561 | // class found in public | ||
| 562 | case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),name) | ||
| 563 | algorithm | ||
| 564 | ✗ | publst := getPublicList(parts); | |
| 565 | ✗ | c1 := getClassFromElementitemlist(publst, name); | |
| 566 | then | ||
| 567 | c1; | ||
| 568 | |||
| 569 | // class found in protected | ||
| 570 | case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)),name) | ||
| 571 | algorithm | ||
| 572 | ✗ | prolst := getProtectedList(parts); | |
| 573 | ✗ | c1 := getClassFromElementitemlist(prolst, name); | |
| 574 | then | ||
| 575 | c1; | ||
| 576 | |||
| 577 | /* Does nothing | ||
| 578 | case (c as Absyn.CLASS(),name) | ||
| 579 | algorithm | ||
| 580 | handle = Print.saveAndClearBuf(); | ||
| 581 | Print.printBuf("getInnerClass failed, c:"); | ||
| 582 | Dump.dump(Absyn.PROGRAM({c},Absyn.TOP())); | ||
| 583 | Print.printBuf("name :"); | ||
| 584 | Print.printBuf(name); | ||
| 585 | Print.clear(); // Print.getString(); | ||
| 586 | Print.restoreBuf(handle); | ||
| 587 | then | ||
| 588 | fail(); | ||
| 589 | */ | ||
| 590 | end matchcontinue; | ||
| 591 | end getInnerClass; | ||
| 592 | public function replacePublicList | ||
| 593 | " This function replaces the ElementItem list in | ||
| 594 | the ClassPart list, and returns the updated list. | ||
| 595 | If no public list is available, one is created." | ||
| 596 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 597 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 598 | output list<Absyn.ClassPart> outAbsynClassPartLst; | ||
| 599 | algorithm | ||
| 600 | outAbsynClassPartLst := match (inAbsynClassPartLst,inAbsynElementItemLst) | ||
| 601 | local | ||
| 602 | list<Absyn.ClassPart> rest_1,rest,ys,xs; | ||
| 603 | Absyn.ClassPart x; | ||
| 604 | list<Absyn.ElementItem> newpublst,new,newpublist; | ||
| 605 | |||
| 606 | case (((Absyn.PUBLIC()) :: rest),newpublst) | ||
| 607 | algorithm | ||
| 608 | 2585 | rest_1 := deletePublicList(rest); | |
| 609 | 2585 | then | |
| 610 | (Absyn.PUBLIC(newpublst) :: rest_1); | ||
| 611 | |||
| 612 | case ((x :: xs),new) | ||
| 613 | algorithm | ||
| 614 | ✗ | ys := replacePublicList(xs, new); | |
| 615 | then | ||
| 616 | (x :: ys); | ||
| 617 | |||
| 618 | 8 | case ({},newpublist) then {Absyn.PUBLIC(newpublist)}; | |
| 619 | |||
| 620 | end match; | ||
| 621 | end replacePublicList; | ||
| 622 | public function replaceProtectedList " | ||
| 623 | This function replaces the `ElementItem\' list in the `ClassPart\' list, | ||
| 624 | and returns the updated list. | ||
| 625 | If no protected list is available, one is created. | ||
| 626 | " | ||
| 627 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 628 | input list<Absyn.ElementItem> inAbsynElementItemLst; | ||
| 629 | output list<Absyn.ClassPart> outAbsynClassPartLst; | ||
| 630 | algorithm | ||
| 631 | outAbsynClassPartLst := match (inAbsynClassPartLst,inAbsynElementItemLst) | ||
| 632 | local | ||
| 633 | list<Absyn.ClassPart> rest_1,rest,ys,xs; | ||
| 634 | Absyn.ClassPart x; | ||
| 635 | list<Absyn.ElementItem> newprotlist,new; | ||
| 636 | |||
| 637 | case (((Absyn.PROTECTED()) :: rest),newprotlist) | ||
| 638 | algorithm | ||
| 639 | 2 | rest_1 := deleteProtectedList(rest); | |
| 640 | 2 | then | |
| 641 | (Absyn.PROTECTED(newprotlist) :: rest_1); | ||
| 642 | |||
| 643 | case ((x :: xs),new) | ||
| 644 | algorithm | ||
| 645 | 4 | ys := replaceProtectedList(xs, new); | |
| 646 | then | ||
| 647 | (x :: ys); | ||
| 648 | |||
| 649 | 2 | case ({},newprotlist) then {Absyn.PROTECTED(newprotlist)}; | |
| 650 | |||
| 651 | end match; | ||
| 652 | end replaceProtectedList; | ||
| 653 | public function deletePublicList " | ||
| 654 | Deletes all PULIC classparts from the list. | ||
| 655 | " | ||
| 656 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 657 | output list<Absyn.ClassPart> outAbsynClassPartLst; | ||
| 658 | algorithm | ||
| 659 | outAbsynClassPartLst:= | ||
| 660 | match inAbsynClassPartLst | ||
| 661 | local | ||
| 662 | list<Absyn.ClassPart> res,xs; | ||
| 663 | Absyn.ClassPart x; | ||
| 664 | case {} then {}; | ||
| 665 | case Absyn.PUBLIC() :: xs | ||
| 666 | algorithm | ||
| 667 | 52 | res := deletePublicList(xs); | |
| 668 | then | ||
| 669 | res; | ||
| 670 | case x :: xs | ||
| 671 | algorithm | ||
| 672 | 2192 | res := deletePublicList(xs); | |
| 673 | then | ||
| 674 | (x :: res); | ||
| 675 | end match; | ||
| 676 | end deletePublicList; | ||
| 677 | public function deleteProtectedList " | ||
| 678 | Deletes all PROTECTED classparts from the list. | ||
| 679 | " | ||
| 680 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 681 | output list<Absyn.ClassPart> outAbsynClassPartLst; | ||
| 682 | algorithm | ||
| 683 | outAbsynClassPartLst:= | ||
| 684 | match inAbsynClassPartLst | ||
| 685 | local | ||
| 686 | list<Absyn.ClassPart> res,xs; | ||
| 687 | Absyn.ClassPart x; | ||
| 688 | case {} then {}; | ||
| 689 | case Absyn.PROTECTED() :: xs | ||
| 690 | algorithm | ||
| 691 | ✗ | res := deleteProtectedList(xs); | |
| 692 | then | ||
| 693 | res; | ||
| 694 | case x :: xs | ||
| 695 | algorithm | ||
| 696 | ✗ | res := deleteProtectedList(xs); | |
| 697 | then | ||
| 698 | (x :: res); | ||
| 699 | end match; | ||
| 700 | end deleteProtectedList; | ||
| 701 | public function getPublicList " | ||
| 702 | This function takes a ClassPart List and returns an appended list of | ||
| 703 | all public lists. | ||
| 704 | " | ||
| 705 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 706 | output list<Absyn.ElementItem> outAbsynElementItemLst; | ||
| 707 | algorithm | ||
| 708 | outAbsynElementItemLst:= | ||
| 709 | match inAbsynClassPartLst | ||
| 710 | local | ||
| 711 | list<Absyn.ElementItem> res2,res,res1,ys; | ||
| 712 | list<Absyn.ClassPart> rest,xs; | ||
| 713 | case {} then {}; | ||
| 714 | case Absyn.PUBLIC(contents = res1) :: rest | ||
| 715 | algorithm | ||
| 716 | 5242 | res2 := getPublicList(rest); | |
| 717 | 5242 | res := listAppend(res1, res2); | |
| 718 | then | ||
| 719 | res; | ||
| 720 | case _ :: xs | ||
| 721 | algorithm | ||
| 722 | 4378 | ys := getPublicList(xs); | |
| 723 | then | ||
| 724 | ys; | ||
| 725 | end match; | ||
| 726 | end getPublicList; | ||
| 727 | public function getProtectedList " | ||
| 728 | This function takes a ClassPart List and returns an appended list of | ||
| 729 | all protected lists." | ||
| 730 | input list<Absyn.ClassPart> inAbsynClassPartLst; | ||
| 731 | output list<Absyn.ElementItem> outAbsynElementItemLst; | ||
| 732 | algorithm | ||
| 733 | outAbsynElementItemLst:= | ||
| 734 | match inAbsynClassPartLst | ||
| 735 | local | ||
| 736 | list<Absyn.ElementItem> res2,res,res1,ys; | ||
| 737 | list<Absyn.ClassPart> rest,xs; | ||
| 738 | case {} then {}; | ||
| 739 | case Absyn.PROTECTED(contents = res1) :: rest | ||
| 740 | algorithm | ||
| 741 | 12 | res2 := getProtectedList(rest); | |
| 742 | 12 | res := listAppend(res1, res2); | |
| 743 | then | ||
| 744 | res; | ||
| 745 | case _ :: xs | ||
| 746 | algorithm | ||
| 747 | 40 | ys := getProtectedList(xs); | |
| 748 | then | ||
| 749 | ys; | ||
| 750 | end match; | ||
| 751 | end getProtectedList; | ||
| 752 | public function getClassFromElementitemlist " | ||
| 753 | This function takes an ElementItem list and an Ident and returns the | ||
| 754 | class definition among the element list having that identifier. | ||
| 755 | " | ||
| 756 | input list<Absyn.ElementItem> inElements; | ||
| 757 | input Absyn.Ident inIdent; | ||
| 758 | output Absyn.Class outClass; | ||
| 759 | protected | ||
| 760 | Absyn.ElementItem elem; | ||
| 761 | algorithm | ||
| 762 | 7 | elem := List.getMemberOnTrue(inIdent, inElements, classElementItemIsNamed); | |
| 763 |
3/6✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 6 not taken.
✓ Branch 7 taken 7 times.
|
7 | Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = |
| 764 | Absyn.CLASSDEF(class_ = outClass))) := elem; | ||
| 765 | end getClassFromElementitemlist; | ||
| 766 | public function classInProgram | ||
| 767 | "This function takes a name and a Program and returns | ||
| 768 | true if the name exists as a top class in the program." | ||
| 769 | input String name; | ||
| 770 | input Absyn.Program p; | ||
| 771 | output Boolean b; | ||
| 772 | algorithm | ||
| 773 | b := match p | ||
| 774 | local | ||
| 775 | String str; | ||
| 776 | case Absyn.PROGRAM() | ||
| 777 | algorithm | ||
| 778 |
2/2✓ Branch 0 taken 102249 times.
✓ Branch 1 taken 6514 times.
|
108763 | for cl in p.classes loop |
| 779 | 102249 | Absyn.CLASS(name=str) := cl; | |
| 780 |
4/4✓ Branch 0 taken 7554 times.
✓ Branch 1 taken 94695 times.
✓ Branch 3 taken 162 times.
✓ Branch 4 taken 7392 times.
|
102249 | if str == name then |
| 781 | b := true; | ||
| 782 | 162 | return; | |
| 783 | end if; | ||
| 784 | end for; | ||
| 785 | then false; | ||
| 786 | end match; | ||
| 787 | end classInProgram; | ||
| 788 | public function getPathedClassInProgram | ||
| 789 | "This function takes a Path and a Program and retrieves the | ||
| 790 | class definition referenced by the Path from the Program. | ||
| 791 | If enclOnErr is true and such class doesn't exist return enclosing class." | ||
| 792 | input Absyn.Path inPath; | ||
| 793 | input Absyn.Program inProgram; | ||
| 794 | input Boolean enclOnErr = false; | ||
| 795 | input Boolean showError = false; | ||
| 796 | output Absyn.Class outClass; | ||
| 797 | algorithm | ||
| 798 | outClass := matchcontinue () | ||
| 799 | 36913 | case () then getPathedClassInProgramWork(inPath, inProgram, enclOnErr); | |
| 800 | 2051 | case () then getPathedClassInProgramWork(inPath, FBuiltin.getInitialFunctions(), enclOnErr); | |
| 801 | |||
| 802 | else | ||
| 803 | algorithm | ||
| 804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2044 times.
|
2044 | if showError then |
| 805 | ✗ | Error.addMessage(Error.LOOKUP_ERROR, | |
| 806 | {AbsynUtil.pathString(inPath), "<TOP>"}); | ||
| 807 | end if; | ||
| 808 | 2044 | then | |
| 809 | fail(); | ||
| 810 | |||
| 811 | end matchcontinue; | ||
| 812 | end getPathedClassInProgram; | ||
| 813 | public function getPathedClassInProgramWork | ||
| 814 | "This function takes a Path and a Program and retrieves the class definition | ||
| 815 | referenced by the Path from the Program. | ||
| 816 | If enclOnErr is true and such class doesn't exist return enclosing class." | ||
| 817 | input Absyn.Path inPath; | ||
| 818 | input Absyn.Program inProgram; | ||
| 819 | input Boolean enclOnErr = false; | ||
| 820 | output Absyn.Class outClass; | ||
| 821 | algorithm | ||
| 822 | outClass := match inPath | ||
| 823 | local | ||
| 824 | Absyn.Class c; | ||
| 825 | |||
| 826 | case Absyn.IDENT() | ||
| 827 | 14595 | then getClassInProgram(inPath.name, inProgram); | |
| 828 | |||
| 829 | case Absyn.QUALIFIED() | ||
| 830 | algorithm | ||
| 831 | 24369 | c := getClassInProgram(inPath.name, inProgram); | |
| 832 | 24333 | then | |
| 833 | getPathedClassInClass(inPath.path, c, enclOnErr); | ||
| 834 | |||
| 835 | case Absyn.FULLYQUALIFIED() | ||
| 836 | 141 | then | |
| 837 | getPathedClassInProgramWork(inPath.path, inProgram, enclOnErr); | ||
| 838 | |||
| 839 | end match; | ||
| 840 | end getPathedClassInProgramWork; | ||
| 841 | public function getPathedClassInClass | ||
| 842 | "Retrieves the class definition referenced by the Path in the given class. | ||
| 843 | If such class doesn't exist return the class itself if enclOnError = true, otherwise fail." | ||
| 844 | input Absyn.Path inPath; | ||
| 845 | input Absyn.Class inClass; | ||
| 846 | input Boolean enclOnError; | ||
| 847 | output Absyn.Class outClass; | ||
| 848 | algorithm | ||
| 849 | outClass := matchcontinue inPath | ||
| 850 | local | ||
| 851 | Absyn.Class c; | ||
| 852 | String str; | ||
| 853 | Absyn.Path path; | ||
| 854 | |||
| 855 | case Absyn.IDENT(name = str) | ||
| 856 | 24331 | then | |
| 857 | getClassInClass(str, inClass); | ||
| 858 | |||
| 859 | case Absyn.FULLYQUALIFIED(path) | ||
| 860 | ✗ | then | |
| 861 | getPathedClassInClass(path, inClass, enclOnError); | ||
| 862 | |||
| 863 | case Absyn.QUALIFIED(name = str, path = path) | ||
| 864 | algorithm | ||
| 865 | 55544 | c := getClassInClass(str, inClass); | |
| 866 | 55542 | then | |
| 867 | getPathedClassInClass(path, c, enclOnError); | ||
| 868 | |||
| 869 | case _ guard enclOnError then inClass; | ||
| 870 | end matchcontinue; | ||
| 871 | end getPathedClassInClass; | ||
| 872 | public function getClassInClass | ||
| 873 | "Looks up a named class in the given class. Fails if the class can't be found." | ||
| 874 | input String name; | ||
| 875 | input Absyn.Class inClass; | ||
| 876 | output Absyn.Class outClass; | ||
| 877 | algorithm | ||
| 878 |
2/2✓ Branch 1 taken 80879 times.
✓ Branch 2 taken 4 times.
|
80883 | for part in AbsynUtil.getClassPartsInClass(inClass) loop |
| 879 |
2/2✓ Branch 1 taken 1052060 times.
✓ Branch 2 taken 1008 times.
|
1053068 | for item in AbsynUtil.getElementItemsInClassPart(part) loop |
| 880 |
2/2✓ Branch 1 taken 79871 times.
✓ Branch 2 taken 972189 times.
|
1052060 | if AbsynUtil.isElementItemClassNamed(name, item) then |
| 881 | 79871 | outClass := AbsynUtil.elementItemClass(item); | |
| 882 | 79871 | return; | |
| 883 | end if; | ||
| 884 | end for; | ||
| 885 | end for; | ||
| 886 | |||
| 887 | 4 | fail(); | |
| 888 | end getClassInClass; | ||
| 889 | public function getClassInProgram | ||
| 890 | "Looks up a function with the given name in a program, or fails if the class doesn't exist." | ||
| 891 | input String name; | ||
| 892 | input Absyn.Program program; | ||
| 893 | output Absyn.Class cls; | ||
| 894 | algorithm | ||
| 895 | 47911 | cls := List.find(program.classes, function AbsynUtil.isClassNamed(inName = name)); | |
| 896 | end getClassInProgram; | ||
| 897 | public function getClassnamesInClassList | ||
| 898 | input Absyn.Path inPath; | ||
| 899 | input Absyn.Program inProgram; | ||
| 900 | input Absyn.Class inClass; | ||
| 901 | input Boolean inShowProtected; | ||
| 902 | input Boolean includeConstants; | ||
| 903 | output list<String> outString; | ||
| 904 | algorithm | ||
| 905 | outString:= | ||
| 906 | match (inClass, inShowProtected, includeConstants) | ||
| 907 | local | ||
| 908 | list<String> strlist; | ||
| 909 | list<Absyn.ClassPart> parts; | ||
| 910 | Boolean b,c; | ||
| 911 | |||
| 912 | case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)), b, c) | ||
| 913 | algorithm | ||
| 914 | 3 | strlist := getClassnamesInParts(parts,b,c); | |
| 915 | then | ||
| 916 | strlist; | ||
| 917 | |||
| 918 | case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)), b, c) | ||
| 919 | algorithm | ||
| 920 | ✗ | strlist := getClassnamesInParts(parts,b,c); | |
| 921 | then strlist; | ||
| 922 | |||
| 923 | case (Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH())), _, _) | ||
| 924 | algorithm | ||
| 925 | //(cdef,newpath) = lookupClassdef(path, inmodel, p); | ||
| 926 | //res = getClassnamesInClassList(newpath, p, cdef); | ||
| 927 | then | ||
| 928 | {};//res; | ||
| 929 | |||
| 930 | case (Absyn.CLASS(body = Absyn.OVERLOAD()), _, _) | ||
| 931 | algorithm | ||
| 932 | then {}; | ||
| 933 | |||
| 934 | case (Absyn.CLASS(body = Absyn.ENUMERATION()), _, _) | ||
| 935 | algorithm | ||
| 936 | then {}; | ||
| 937 | |||
| 938 | case (Absyn.CLASS(body = Absyn.PDER()), _, _) | ||
| 939 | algorithm | ||
| 940 | then {}; | ||
| 941 | |||
| 942 | end match; | ||
| 943 | end getClassnamesInClassList; | ||
| 944 | public function getClassNamesRecursive | ||
| 945 | "Returns a string with all the classes for a given path." | ||
| 946 | input Option<Absyn.Path> inPath; | ||
| 947 | input Absyn.Program inProgram; | ||
| 948 | input Boolean inShowProtected; | ||
| 949 | input Boolean includeConstants; | ||
| 950 | input list<Absyn.Path> inAcc; | ||
| 951 | output Option<Absyn.Path> opath; | ||
| 952 | output list<Absyn.Path> paths; | ||
| 953 | algorithm | ||
| 954 | (opath,paths) := matchcontinue (inPath,inProgram,inShowProtected,includeConstants,inAcc) | ||
| 955 | local | ||
| 956 | Absyn.Class cdef; | ||
| 957 | String s1; | ||
| 958 | list<String> strlst; | ||
| 959 | Absyn.Path pp; | ||
| 960 | Absyn.Program p; | ||
| 961 | list<Absyn.Class> classes; | ||
| 962 | list<Option<Absyn.Path>> result_path_lst; | ||
| 963 | list<Absyn.Path> acc; | ||
| 964 | Boolean b,c; | ||
| 965 | |||
| 966 | case (SOME(pp),p,b,c,acc) | ||
| 967 | algorithm | ||
| 968 | 3 | acc := pp::acc; | |
| 969 | 3 | cdef := getPathedClassInProgram(pp, p); | |
| 970 | 3 | strlst := getClassnamesInClassList(pp, p, cdef, b, c); | |
| 971 | 3 | result_path_lst := List.map(List.map1(strlst, joinPaths, pp),Util.makeOption); | |
| 972 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
6 | (_,acc) := List.map3Fold(result_path_lst, getClassNamesRecursive, p, b, c, acc); |
| 973 | 3 | then (inPath,acc); | |
| 974 | case (NONE(),p as Absyn.PROGRAM(classes=classes),b,c,acc) | ||
| 975 | algorithm | ||
| 976 | ✗ | strlst := List.map(classes, AbsynUtil.getClassName); | |
| 977 | ✗ | result_path_lst := List.mapMap(strlst, AbsynUtil.makeIdentPathFromString, Util.makeOption); | |
| 978 | ✗ | (_,acc) := List.map3Fold(result_path_lst, getClassNamesRecursive, p, b, c, acc); | |
| 979 | ✗ | then (inPath,acc); | |
| 980 | case (SOME(pp),_,_,_,_) | ||
| 981 | algorithm | ||
| 982 | ✗ | s1 := AbsynUtil.pathString(pp); | |
| 983 | ✗ | Error.addMessage(Error.LOOKUP_ERROR, {s1,"<TOP>"}); | |
| 984 | then (inPath,{}); | ||
| 985 | end matchcontinue; | ||
| 986 | end getClassNamesRecursive; | ||
| 987 | public function mergeClasses | ||
| 988 | "@author adrpo | ||
| 989 | merge two classes cNew and cOld in the following way: | ||
| 990 | 1. get all the inner class definitions from cOld that were loaded from a different file than itself | ||
| 991 | 2. append all elements from step 1 to class cNew public list!" | ||
| 992 | input Absyn.Class cNew; | ||
| 993 | input Absyn.Class cOld; | ||
| 994 | output Absyn.Class c; | ||
| 995 | algorithm | ||
| 996 | c := matchcontinue(cNew, cOld) | ||
| 997 | local | ||
| 998 | list<Absyn.ClassPart> partsC1, partsC2; | ||
| 999 | list<Absyn.ElementItem> pubElementsC1, pubElementsC2; | ||
| 1000 | String file; | ||
| 1001 | list<String> typeVars1; | ||
| 1002 | list<Absyn.NamedArg> classAttrs1; | ||
| 1003 | list<Absyn.Annotation> ann1; | ||
| 1004 | Option<String> cmt1; | ||
| 1005 | |||
| 1006 | |||
| 1007 | // if cOld has no parts then just return cNew | ||
| 1008 | case (_, Absyn.CLASS(body = Absyn.PARTS(classParts = {}))) then cNew; | ||
| 1009 | case (_, Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = {}))) then cNew; | ||
| 1010 | |||
| 1011 | // if cNew and cOld has parts, get the foreign elements (loaded from other file) from cOld | ||
| 1012 | // and append them to the public list of cNew | ||
| 1013 | case (c as Absyn.CLASS(body=Absyn.PARTS(typeVars1,classAttrs1,partsC1,ann1,cmt1)), | ||
| 1014 | Absyn.CLASS(body = Absyn.PARTS(classParts = partsC2), info = SOURCEINFO(fileName = file))) | ||
| 1015 | algorithm | ||
| 1016 | 2524 | pubElementsC2 := getPublicList(partsC2); | |
| 1017 | 2524 | pubElementsC2 := excludeElementsFromFile(file, pubElementsC2); | |
| 1018 | 2524 | pubElementsC1 := getPublicList(partsC1); | |
| 1019 | 2524 | pubElementsC1 := mergeElements(pubElementsC1, pubElementsC2); | |
| 1020 | 2524 | partsC1 := replacePublicList(partsC1, pubElementsC1); | |
| 1021 | 5048 | c.body := Absyn.PARTS(typeVars1,classAttrs1,partsC1,ann1,cmt1); | |
| 1022 | then c; | ||
| 1023 | |||
| 1024 | // TODO! FIXME! handle also CLASS_EXTENDS! | ||
| 1025 | // if the class cNew or cOld is not containing parts then don't bother, just replace the entire class! | ||
| 1026 | case (_, _) then cNew; | ||
| 1027 | end matchcontinue; | ||
| 1028 | end mergeClasses; | ||
| 1029 | public function mergeElement | ||
| 1030 | "@author adrpo | ||
| 1031 | merge the element given as second argument with the element from the first list with same name. | ||
| 1032 | if no such elements are in the first list, just append it at the end" | ||
| 1033 | input list<Absyn.ElementItem> inEls; | ||
| 1034 | input Absyn.ElementItem inEl; | ||
| 1035 | output list<Absyn.ElementItem> outEls; | ||
| 1036 | algorithm | ||
| 1037 | outEls := matchcontinue(inEls, inEl) | ||
| 1038 | local | ||
| 1039 | String n1,n2; | ||
| 1040 | list<Absyn.ElementItem> rest, filtered; | ||
| 1041 | Absyn.ElementItem e1,e2; | ||
| 1042 | Boolean r; | ||
| 1043 | Boolean f; | ||
| 1044 | Option<Absyn.RedeclareKeywords> redecl; | ||
| 1045 | Absyn.InnerOuter innout ; | ||
| 1046 | String name; | ||
| 1047 | Absyn.Info i; | ||
| 1048 | Option<Absyn.ConstrainClass> cc; | ||
| 1049 | Absyn.Class c1, c2; | ||
| 1050 | case ({}, _) then inEl::{}; | ||
| 1051 | // not found put it at the end | ||
| 1052 | case (Absyn.ELEMENTITEM(Absyn.ELEMENT(f, redecl, innout, Absyn.CLASSDEF(r, c1 as Absyn.CLASS(name = n1)), i, cc)) :: rest, | ||
| 1053 | Absyn.ELEMENTITEM(Absyn.ELEMENT(specification = Absyn.CLASSDEF(_,c2 as Absyn.CLASS(name = n2))))) | ||
| 1054 | algorithm | ||
| 1055 |
4/4✓ Branch 0 taken 3847 times.
✓ Branch 1 taken 11773 times.
✓ Branch 3 taken 2555 times.
✓ Branch 4 taken 1292 times.
|
15620 | true := stringEqual(n1, n2); |
| 1056 | // element found, merge it! | ||
| 1057 | 2555 | c1 := mergeClasses(c1, c2); | |
| 1058 |
2/4✓ Branch 0 taken 2555 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 2555 times.
✗ Branch 4 not taken.
|
7665 | then |
| 1059 | Absyn.ELEMENTITEM(Absyn.ELEMENT(f, redecl, innout, Absyn.CLASSDEF(r, c1), i, cc)) :: rest; | ||
| 1060 | case (e1 :: rest, e2) | ||
| 1061 | algorithm | ||
| 1062 | // try the second from the first list | ||
| 1063 | 15773 | filtered := mergeElement(rest, e2); | |
| 1064 | then | ||
| 1065 | e1::filtered; | ||
| 1066 | end matchcontinue; | ||
| 1067 | end mergeElement; | ||
| 1068 | public function mergeElements | ||
| 1069 | "@author adrpo see merge element" | ||
| 1070 | input list<Absyn.ElementItem> inEls1; | ||
| 1071 | input list<Absyn.ElementItem> inEls2; | ||
| 1072 | output list<Absyn.ElementItem> outEls; | ||
| 1073 | algorithm | ||
| 1074 | outEls := match(inEls1, inEls2) | ||
| 1075 | local | ||
| 1076 | list<Absyn.ElementItem> rest, merged; | ||
| 1077 | Absyn.ElementItem e2; | ||
| 1078 | case ({}, _) then inEls2; | ||
| 1079 | case (_, {}) then inEls1; | ||
| 1080 | case (_, e2::rest) | ||
| 1081 | algorithm | ||
| 1082 | 2563 | merged := mergeElement(inEls1, e2); | |
| 1083 | 2563 | merged := mergeElements(merged, rest); | |
| 1084 | then merged; | ||
| 1085 | end match; | ||
| 1086 | end mergeElements; | ||
| 1087 | public function excludeElementsFromFile | ||
| 1088 | "exclude all elements which are part of the given file" | ||
| 1089 | input String inFile; | ||
| 1090 | input list<Absyn.ElementItem> inEls; | ||
| 1091 | output list<Absyn.ElementItem> outEls; | ||
| 1092 | algorithm | ||
| 1093 | outEls := match (inFile,inEls) | ||
| 1094 | local | ||
| 1095 | Absyn.ElementItem e; | ||
| 1096 | list<Absyn.ElementItem> rest, filtered; | ||
| 1097 | String f,file; | ||
| 1098 | Boolean b = false; | ||
| 1099 | |||
| 1100 | case (_,{}) then {}; | ||
| 1101 | // elements can come from different files | ||
| 1102 | case (file,(e as Absyn.ELEMENTITEM(Absyn.ELEMENT(info = SOURCEINFO(fileName = f))))::rest) | ||
| 1103 | algorithm | ||
| 1104 |
4/4✓ Branch 0 taken 19900 times.
✓ Branch 1 taken 2455 times.
✓ Branch 3 taken 109 times.
✓ Branch 4 taken 19791 times.
|
22355 | b := stringEqual(file, f); // not from this file, use it, else discard! |
| 1105 | 22355 | filtered := excludeElementsFromFile(file, rest); | |
| 1106 |
2/2✓ Branch 0 taken 2564 times.
✓ Branch 1 taken 19791 times.
|
22355 | then if not b then e::filtered else filtered; |
| 1107 | // lexer comments can only be from this file, exclude | ||
| 1108 | case (file,(Absyn.LEXER_COMMENT(_))::rest) | ||
| 1109 | algorithm | ||
| 1110 | 195 | filtered := excludeElementsFromFile(file, rest); | |
| 1111 | then filtered; | ||
| 1112 | end match; | ||
| 1113 | end excludeElementsFromFile; | ||
| 1114 | public function getClassnamesInClass | ||
| 1115 | " This function takes a `Class\' definition and a Path identifying the | ||
| 1116 | class. | ||
| 1117 | It returns a string containing comma separated package names found | ||
| 1118 | in the class definition. | ||
| 1119 | The list also contains proctected classes if inShowProtected is true." | ||
| 1120 | input Absyn.Path inPath; | ||
| 1121 | input Absyn.Program inProgram; | ||
| 1122 | input Absyn.Class inClass; | ||
| 1123 | input Boolean inShowProtected; | ||
| 1124 | input Boolean includeConstants; | ||
| 1125 | output list<Absyn.Path> paths; | ||
| 1126 | algorithm | ||
| 1127 | paths := match (inClass, inShowProtected, includeConstants) | ||
| 1128 | local | ||
| 1129 | list<String> strlist; | ||
| 1130 | list<Absyn.ClassPart> parts; | ||
| 1131 | Boolean b,c; | ||
| 1132 | /* a class with parts */ | ||
| 1133 | case (Absyn.CLASS(body = Absyn.PARTS(classParts = parts)), b, c) | ||
| 1134 | algorithm | ||
| 1135 | 9 | strlist := ProgramUtil.getClassnamesInParts(parts,b,c); | |
| 1136 | 9 | then List.map(strlist,AbsynUtil.makeIdentPathFromString); | |
| 1137 | /* an extended class with parts: model extends M end M; */ | ||
| 1138 | case (Absyn.CLASS(body = Absyn.CLASS_EXTENDS(parts = parts)), b, c) | ||
| 1139 | algorithm | ||
| 1140 | ✗ | strlist := ProgramUtil.getClassnamesInParts(parts,b,c); | |
| 1141 | ✗ | then List.map(strlist,AbsynUtil.makeIdentPathFromString); | |
| 1142 | /* a derived class */ | ||
| 1143 | case (Absyn.CLASS(body = Absyn.DERIVED(typeSpec=Absyn.TPATH(_, _))), _, _) | ||
| 1144 | algorithm | ||
| 1145 | /* adrpo 2009-10-27: we sholdn't dive into derived classes! | ||
| 1146 | (cdef,newpath) = lookupClassdef(path, inmodel, p); | ||
| 1147 | res = getClassnamesInClass(newpath, p, cdef); | ||
| 1148 | */ | ||
| 1149 | then {}; | ||
| 1150 | end match; | ||
| 1151 | end getClassnamesInClass; | ||
| 1152 | public function classElementItemIsNamed | ||
| 1153 | input String inClassName; | ||
| 1154 | input Absyn.ElementItem inElement; | ||
| 1155 | output Boolean outIsNamed; | ||
| 1156 | algorithm | ||
| 1157 | outIsNamed := match inElement | ||
| 1158 | local | ||
| 1159 | String name; | ||
| 1160 | |||
| 1161 | case Absyn.ELEMENTITEM(element = Absyn.ELEMENT(specification = | ||
| 1162 | Absyn.CLASSDEF(class_ = (Absyn.CLASS(name = name))))) | ||
| 1163 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 time.
✗ Branch 3 not taken.
✓ Branch 4 taken 8 times.
|
9 | then inClassName == name; |
| 1164 | |||
| 1165 | else false; | ||
| 1166 | end match; | ||
| 1167 | end classElementItemIsNamed; | ||
| 1168 | public function joinPaths | ||
| 1169 | input String child; | ||
| 1170 | input Absyn.Path parent; | ||
| 1171 | output Absyn.Path outPath; | ||
| 1172 | algorithm | ||
| 1173 | outPath := match (child, parent) | ||
| 1174 | local | ||
| 1175 | Absyn.Path r, res; | ||
| 1176 | String c; | ||
| 1177 | case (c, r) | ||
| 1178 | algorithm | ||
| 1179 | 6 | res := AbsynUtil.joinPaths(r, Absyn.IDENT(c)); | |
| 1180 | then res; | ||
| 1181 | end match; | ||
| 1182 | end joinPaths; | ||
| 1183 | public function getDefaultComponentPrefixesModStr "Extractor function for defaultComponentPrefixes modifier" | ||
| 1184 | input Option<Absyn.Modification> mod; | ||
| 1185 | output String docStr; | ||
| 1186 | algorithm | ||
| 1187 | docStr := matchcontinue mod | ||
| 1188 | local Absyn.Exp e; | ||
| 1189 | case SOME(Absyn.CLASSMOD(eqMod = Absyn.EQMOD(exp=e))) algorithm | ||
| 1190 | 4 | docStr := Dump.printExpStr(e); | |
| 1191 | then docStr; | ||
| 1192 | else ""; | ||
| 1193 | end matchcontinue; | ||
| 1194 | end getDefaultComponentPrefixesModStr; | ||
| 1195 | public function getNamedAnnotationExp | ||
| 1196 | "This function takes a Path and a Program and returns a comma separated | ||
| 1197 | string of values for the Documentation annotation for the class named by the | ||
| 1198 | first argument." | ||
| 1199 | input Absyn.Path inPath; | ||
| 1200 | input Absyn.Program inProgram; | ||
| 1201 | input Absyn.Path id; | ||
| 1202 | input Option<T> default; | ||
| 1203 | input ModFunc f; | ||
| 1204 | partial function ModFunc | ||
| 1205 | input Option<Absyn.Modification> mod; | ||
| 1206 | output T docStr; | ||
| 1207 | end ModFunc; | ||
| 1208 | output T outString; | ||
| 1209 | replaceable type T subtypeof Any; | ||
| 1210 | algorithm | ||
| 1211 | outString := matchcontinue (inPath, inProgram, default) | ||
| 1212 | local | ||
| 1213 | Absyn.Class cdef; | ||
| 1214 | T str; | ||
| 1215 | Absyn.Path modelpath; | ||
| 1216 | Absyn.Program p; | ||
| 1217 | |||
| 1218 | case (modelpath, p, _) | ||
| 1219 | algorithm | ||
| 1220 | 8177 | cdef := getPathedClassInProgram(modelpath, p); | |
| 1221 |
3/4✗ Branch 1 not taken.
✓ Branch 2 taken 8161 times.
✓ Branch 3 taken 7317 times.
✓ Branch 4 taken 844 times.
|
8161 | SOME(str) := AbsynUtil.getNamedAnnotationInClass(cdef,id,f); |
| 1222 | then | ||
| 1223 | str; | ||
| 1224 | |||
| 1225 | case (_, _, SOME(str)) then str; | ||
| 1226 | end matchcontinue; | ||
| 1227 | end getNamedAnnotationExp; | ||
| 1228 | public function getFileDir "author: x02lucpo | ||
| 1229 | returns the dir where class file (.mo) was saved or | ||
| 1230 | $OPENMODELICAHOME/work if the file was not saved yet" | ||
| 1231 | input Absyn.ComponentRef inComponentRef "class"; | ||
| 1232 | input Absyn.Program inProgram; | ||
| 1233 | output String outString; | ||
| 1234 | algorithm | ||
| 1235 | outString:= | ||
| 1236 | matchcontinue (inComponentRef,inProgram) | ||
| 1237 | local | ||
| 1238 | Absyn.Path p_class; | ||
| 1239 | Absyn.Class cdef; | ||
| 1240 | String filename,pd,dir_1,omhome,omhome_1; | ||
| 1241 | String pd_1; | ||
| 1242 | list<String> filename_1,dir; | ||
| 1243 | Absyn.ComponentRef class_; | ||
| 1244 | Absyn.Program p; | ||
| 1245 | case (class_,p) | ||
| 1246 | algorithm | ||
| 1247 | 1257 | p_class := AbsynUtil.crefToPath(class_) "change to the saved files directory" ; | |
| 1248 | 1257 | cdef := getPathedClassInProgram(p_class, p); | |
| 1249 | 1257 | filename := AbsynUtil.classFilename(cdef); | |
| 1250 | pd := Autoconf.pathDelimiter; | ||
| 1251 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1257 times.
|
1257 | pd_1 :: _ := stringListStringChar(pd); |
| 1252 | 1257 | filename_1 := Util.stringSplitAtChar(filename, pd_1); | |
| 1253 | 1257 | dir := List.stripLast(filename_1); | |
| 1254 | 1257 | dir_1 := stringDelimitList(dir, pd); | |
| 1255 | then | ||
| 1256 | dir_1; | ||
| 1257 | case (_,_) | ||
| 1258 | algorithm | ||
| 1259 | ✗ | omhome := Settings.getInstallationDirectoryPath() "model not yet saved! change to $OPENMODELICAHOME/work" ; | |
| 1260 | ✗ | omhome_1 := System.trim(omhome, "\""); | |
| 1261 | pd := Autoconf.pathDelimiter; | ||
| 1262 | ✗ | dir_1 := stringAppendList({"\"",omhome_1,pd,"work","\""}); | |
| 1263 | then | ||
| 1264 | dir_1; | ||
| 1265 | else ""; /* this function should never fail */ | ||
| 1266 | end matchcontinue; | ||
| 1267 | end getFileDir; | ||
| 1268 | public function getFullPathFromUri | ||
| 1269 | input Absyn.Program program; | ||
| 1270 | input String uri; | ||
| 1271 | input Boolean printError; | ||
| 1272 | output String path; | ||
| 1273 | protected | ||
| 1274 | String str1,str2,str3; | ||
| 1275 | algorithm | ||
| 1276 | 1766 | (str1,str2,str3) := System.uriToClassAndPath(uri); | |
| 1277 | 1766 | path := getBasePathFromUri(str1,str2,program,Settings.getModelicaPath(Testsuite.isRunning()),printError) + str3; | |
| 1278 | end getFullPathFromUri; | ||
| 1279 | public function getBasePathFromUri "Handle modelica:// URIs" | ||
| 1280 | input String scheme; | ||
| 1281 | input String iname; | ||
| 1282 | input Absyn.Program program; | ||
| 1283 | input String modelicaPath; | ||
| 1284 | input Boolean printError; | ||
| 1285 | output String basePath; | ||
| 1286 | algorithm | ||
| 1287 | basePath := matchcontinue (scheme, iname, modelicaPath, printError) | ||
| 1288 | local | ||
| 1289 | Boolean isDir; | ||
| 1290 | list<String> mps,names; | ||
| 1291 | String gd,mp,bp,str,name,fileName; | ||
| 1292 | case ("modelica://", name, _, _) | ||
| 1293 | algorithm | ||
| 1294 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1766 times.
|
1766 | name::names := System.strtok(name,"."); |
| 1295 | 1766 | Absyn.CLASS(info=SOURCEINFO(fileName=fileName)) := getPathedClassInProgram(Absyn.IDENT(name),program); | |
| 1296 | 1712 | mp := System.dirname(fileName); | |
| 1297 | 1712 | bp := findModelicaPath2(mp,names,"",true); | |
| 1298 | then bp; | ||
| 1299 | case ("modelica://", name, mp, _) | ||
| 1300 | algorithm | ||
| 1301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 54 times.
|
54 | name::names := System.strtok(name,"."); |
| 1302 |
2/2✓ Branch 0 taken 54 times.
✓ Branch 1 taken 54 times.
|
108 | failure(getPathedClassInProgram(Absyn.IDENT(name),program)); |
| 1303 | gd := Autoconf.groupDelimiter; | ||
| 1304 | 54 | mps := System.strtok(mp, gd); | |
| 1305 | 54 | (mp,name,isDir) := System.getLoadModelPath(name, {"default"}, mps); | |
| 1306 | ✗ | mp := if isDir then mp + name else mp; | |
| 1307 | ✗ | bp := findModelicaPath2(mp,names,"",true); | |
| 1308 | then bp; | ||
| 1309 | case ("file://", _, _, _) then ""; | ||
| 1310 | case ("modelica://", name, mp, true) | ||
| 1311 | algorithm | ||
| 1312 | ✗ | name::_ := System.strtok(name,"."); | |
| 1313 | ✗ | str := "Could not resolve modelica://" + name + " with OPENMODELICALIBRARY (MODELICAPATH in the language specification): " + mp; | |
| 1314 | ✗ | Error.addMessage(Error.COMPILER_ERROR,{str}); | |
| 1315 | ✗ | then fail(); | |
| 1316 | end matchcontinue; | ||
| 1317 | end getBasePathFromUri; | ||
| 1318 | public function findModelicaPath "Handle modelica:// URIs" | ||
| 1319 | input list<String> imps; | ||
| 1320 | input list<String> names; | ||
| 1321 | input String version; | ||
| 1322 | output String basePath; | ||
| 1323 | algorithm | ||
| 1324 | basePath := matchcontinue imps | ||
| 1325 | local | ||
| 1326 | String mp; | ||
| 1327 | list<String> mps; | ||
| 1328 | |||
| 1329 | case mp::_ | ||
| 1330 | ✗ | then findModelicaPath2(mp,names,version,false); | |
| 1331 | case _::mps | ||
| 1332 | ✗ | then findModelicaPath(mps,names,version); | |
| 1333 | end matchcontinue; | ||
| 1334 | end findModelicaPath; | ||
| 1335 | public function findModelicaPath2 "Handle modelica:// URIs" | ||
| 1336 | input String mp; | ||
| 1337 | input list<String> inames; | ||
| 1338 | input String version; | ||
| 1339 | input Boolean b; | ||
| 1340 | output String basePath; | ||
| 1341 | algorithm | ||
| 1342 | basePath := matchcontinue (inames, b) | ||
| 1343 | local | ||
| 1344 | list<String> names; | ||
| 1345 | String name,file; | ||
| 1346 | |||
| 1347 | case (name::names, _) | ||
| 1348 | algorithm | ||
| 1349 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
|
4 | false := stringEq(version,""); |
| 1350 | ✗ | file := mp + "/" + name + " " + version; | |
| 1351 | ✗ | true := System.directoryExists(file); | |
| 1352 | // print("Found file 1: " + file + "\n"); | ||
| 1353 | ✗ | then findModelicaPath2(file,names,"",true); | |
| 1354 | case (name::_, _) | ||
| 1355 | algorithm | ||
| 1356 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
|
4 | false := stringEq(version,""); |
| 1357 | ✗ | file := mp + "/" + name + " " + version + ".mo"; | |
| 1358 | ✗ | true := System.regularFileExists(file); | |
| 1359 | // print("Found file 2: " + file + "\n"); | ||
| 1360 | then mp; | ||
| 1361 | |||
| 1362 | case (name::names, _) | ||
| 1363 | algorithm | ||
| 1364 | 4 | file := mp + "/" + name; | |
| 1365 |
2/2✓ Branch 1 taken 1 time.
✓ Branch 2 taken 3 times.
|
4 | true := System.directoryExists(file); |
| 1366 | // print("Found file 3: " + file + "\n"); | ||
| 1367 | 3 | then findModelicaPath2(file,names,"",true); | |
| 1368 | case (name::_, _) | ||
| 1369 | algorithm | ||
| 1370 | 1 | file := mp + "/" + name + ".mo"; | |
| 1371 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 time.
|
1 | true := System.regularFileExists(file); |
| 1372 | // print("Found file 4: " + file + "\n"); | ||
| 1373 | then mp; | ||
| 1374 | |||
| 1375 | // This class is part of the current package.mo, or whatever... | ||
| 1376 | case (_, true) | ||
| 1377 | algorithm | ||
| 1378 | // print("Did not find file 5: " + mp + " - " + name + "\n"); | ||
| 1379 | then mp; | ||
| 1380 | end matchcontinue; | ||
| 1381 | end findModelicaPath2; | ||
| 1382 | annotation(__OpenModelica_Interface="program_util"); | ||
| 1383 | end ProgramUtil; | ||
| 1384 |