OMCompiler/Compiler/FrontEnd/InstFunction.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 InstFunction | ||
| 37 | " file: InstFunction.mo | ||
| 38 | package: InstFunction | ||
| 39 | description: Function instantiation | ||
| 40 | |||
| 41 | |||
| 42 | This module is responsible for instantiation of Modelica functions. | ||
| 43 | |||
| 44 | " | ||
| 45 | |||
| 46 | public import Absyn; | ||
| 47 | public import AbsynUtil; | ||
| 48 | public import ClassInf; | ||
| 49 | public import DAE.Connect; | ||
| 50 | public import ConnectionGraph; | ||
| 51 | public import DAE; | ||
| 52 | public import FCore; | ||
| 53 | public import InnerOuter; | ||
| 54 | public import InstTypes; | ||
| 55 | public import Mod; | ||
| 56 | public import SCode; | ||
| 57 | public import UnitAbsyn; | ||
| 58 | |||
| 59 | protected import Lookup; | ||
| 60 | protected import Inst; | ||
| 61 | protected import InstBasics; | ||
| 62 | protected import InstUtil; | ||
| 63 | protected import UnitAbsynBuilder; | ||
| 64 | protected import ElementSource; | ||
| 65 | protected import List; | ||
| 66 | protected import Types; | ||
| 67 | protected import Flags; | ||
| 68 | protected import FGraph; | ||
| 69 | protected import FNode; | ||
| 70 | protected import Debug; | ||
| 71 | protected import SCodeDump; | ||
| 72 | import SCodeUtil; | ||
| 73 | protected import Util; | ||
| 74 | protected import Config; | ||
| 75 | protected import DAEUtil; | ||
| 76 | protected import PrefixUtil; | ||
| 77 | protected import Error; | ||
| 78 | |||
| 79 | protected type Ident = DAE.Ident "an identifier"; | ||
| 80 | protected type InstanceHierarchy = InnerOuter.InstHierarchy "an instance hierarchy"; | ||
| 81 | protected type InstDims = list<list<DAE.Dimension>>; | ||
| 82 | |||
| 83 | public function instantiateExternalObject | ||
| 84 | "instantiate an external object. | ||
| 85 | This is done by instantiating the destructor and constructor | ||
| 86 | functions and create a DAE element containing these two." | ||
| 87 | input FCore.Cache inCache; | ||
| 88 | input FCore.Graph inEnv "environment"; | ||
| 89 | input InnerOuter.InstHierarchy inIH; | ||
| 90 | input list<SCode.Element> els "elements"; | ||
| 91 | input DAE.Mod inMod; | ||
| 92 | input Boolean impl; | ||
| 93 | input SCode.Comment comment; | ||
| 94 | input SourceInfo info; | ||
| 95 | output FCore.Cache outCache; | ||
| 96 | output FCore.Graph outEnv; | ||
| 97 | output InnerOuter.InstHierarchy outIH; | ||
| 98 | output DAE.DAElist dae "resulting dae"; | ||
| 99 | output ClassInf.State ciState; | ||
| 100 | algorithm | ||
| 101 | (outCache,outEnv,outIH,dae,ciState) := matchcontinue(inCache, inEnv, inIH, impl) | ||
| 102 | local | ||
| 103 | SCode.Element destr,constr; | ||
| 104 | FCore.Cache cache; | ||
| 105 | Ident className; | ||
| 106 | Absyn.Path classNameFQ; | ||
| 107 | DAE.Type functp; | ||
| 108 | FCore.Graph env; | ||
| 109 | FCore.Ref r; | ||
| 110 | InstanceHierarchy ih; | ||
| 111 | DAE.ElementSource source "the origin of the element"; | ||
| 112 | // Explicit instantiation, generate constructor and destructor and the function type. | ||
| 113 | case (cache, env, ih, false) | ||
| 114 | algorithm | ||
| 115 | 63 | className := FNode.refName(FGraph.lastScopeRef(env)); // The external object classname is in top frame of environment. | |
| 116 | 63 | checkExternalObjectMod(inMod, className); | |
| 117 | 62 | destr := SCodeUtil.getExternalObjectDestructor(els); | |
| 118 | 62 | constr := SCodeUtil.getExternalObjectConstructor(els); | |
| 119 | 62 | env := FGraph.mkClassNode(env, destr, DAE.NOPRE(), inMod); | |
| 120 | 62 | env := FGraph.mkClassNode(env, constr, DAE.NOPRE(), inMod); | |
| 121 | 62 | (cache,ih) := instantiateExternalObjectDestructor(cache,env,ih,destr); | |
| 122 | 62 | (cache,ih,functp) := instantiateExternalObjectConstructor(cache,env,ih,constr); | |
| 123 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 62 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 62 times.
|
62 | SOME(classNameFQ):= FGraph.getScopePath(env); // Fully qualified classname |
| 124 | // Extend the frame with the type, one frame up at the same place as the class. | ||
| 125 | 62 | (env, r) := FGraph.stripLastScopeRef(env); | |
| 126 | 62 | env := FGraph.mkTypeNode(env,className,functp); | |
| 127 | 62 | env := FGraph.pushScopeRef(env, r); | |
| 128 | |||
| 129 | // set the of this element | ||
| 130 | 62 | source := ElementSource.addElementSourcePartOfOpt(DAE.emptyElementSource, FGraph.getScopePath(env)); | |
| 131 | 62 | source := ElementSource.addCommentToSource(source, SOME(comment)); | |
| 132 | 62 | source := ElementSource.addElementSourceFileInfo(source, info); | |
| 133 | 124 | then | |
| 134 | (cache,env,ih,DAE.DAE({DAE.EXTOBJECTCLASS(classNameFQ,source)}),ClassInf.EXTERNAL_OBJ(classNameFQ)); | ||
| 135 | |||
| 136 | // Implicit, do not instantiate constructor and destructor. | ||
| 137 | case (cache, _, ih, true) | ||
| 138 | algorithm | ||
| 139 |
2/4✗ Branch 1 not taken.
✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 28 times.
|
28 | SOME(classNameFQ):= FGraph.getScopePath(inEnv); // Fully qualified classname |
| 140 | 28 | then | |
| 141 | (cache,inEnv,ih,DAE.emptyDae,ClassInf.EXTERNAL_OBJ(classNameFQ)); | ||
| 142 | |||
| 143 | // failed | ||
| 144 | else | ||
| 145 | algorithm | ||
| 146 |
1/2✓ Branch 1 taken 1 time.
✗ Branch 2 not taken.
|
1 | true := Flags.isSet(Flags.FAILTRACE); |
| 147 | ✗ | Debug.trace("- InstFunction.instantiateExternalObject failed.\n"); | |
| 148 | ✗ | then fail(); | |
| 149 | end matchcontinue; | ||
| 150 | end instantiateExternalObject; | ||
| 151 | |||
| 152 | protected function checkExternalObjectMod | ||
| 153 | "Checks that an external object instance does not have any modifiers. This is | ||
| 154 | done because an external object may only have two elements, a constructor and | ||
| 155 | a destructor, and there's no point in modifying these." | ||
| 156 | input DAE.Mod inMod; | ||
| 157 | input String inClassName; | ||
| 158 | algorithm | ||
| 159 | () := match inMod | ||
| 160 | local | ||
| 161 | DAE.Ident id; | ||
| 162 | DAE.Mod mod; | ||
| 163 | SourceInfo info; | ||
| 164 | |||
| 165 | case DAE.NOMOD() then (); | ||
| 166 | case DAE.MOD(subModLst = {}) then (); | ||
| 167 | |||
| 168 | // The modifier contains a list of submods. Print an error for the first one | ||
| 169 | // to make it look like a normal modifier error. | ||
| 170 | case DAE.MOD(subModLst = DAE.NAMEMOD(ident = id, mod = mod) :: _) | ||
| 171 | algorithm | ||
| 172 | 1 | info := Mod.getModInfo(mod); | |
| 173 | 1 | Error.addSourceMessage(Error.MISSING_MODIFIED_ELEMENT, | |
| 174 | {id, inClassName}, info); | ||
| 175 | 1 | then | |
| 176 | fail(); | ||
| 177 | |||
| 178 | end match; | ||
| 179 | end checkExternalObjectMod; | ||
| 180 | |||
| 181 | protected function instantiateExternalObjectDestructor | ||
| 182 | "instantiates the destructor function of an external object" | ||
| 183 | input FCore.Cache inCache; | ||
| 184 | input FCore.Graph env; | ||
| 185 | input InnerOuter.InstHierarchy inIH; | ||
| 186 | input SCode.Element cl; | ||
| 187 | output FCore.Cache outCache; | ||
| 188 | output InnerOuter.InstHierarchy outIH; | ||
| 189 | algorithm | ||
| 190 | (outCache,outIH) := matchcontinue (inCache, inIH) | ||
| 191 | local | ||
| 192 | FCore.Cache cache; | ||
| 193 | InstanceHierarchy ih; | ||
| 194 | |||
| 195 | case (cache, ih) | ||
| 196 | algorithm | ||
| 197 | 62 | (cache,_,ih) := implicitFunctionInstantiation(cache,env,ih,DAE.NOMOD(),DAE.NOPRE(),cl,{}); | |
| 198 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | then |
| 199 | (cache,ih); | ||
| 200 | else | ||
| 201 | algorithm | ||
| 202 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 203 | ✗ | Debug.trace("- InstFunction.instantiateExternalObjectDestructor failed.\n"); | |
| 204 | ✗ | then fail(); | |
| 205 | end matchcontinue; | ||
| 206 | end instantiateExternalObjectDestructor; | ||
| 207 | |||
| 208 | protected function instantiateExternalObjectConstructor | ||
| 209 | "instantiates the constructor function of an external object" | ||
| 210 | input FCore.Cache inCache; | ||
| 211 | input FCore.Graph env; | ||
| 212 | input InnerOuter.InstHierarchy inIH; | ||
| 213 | input SCode.Element cl; | ||
| 214 | output FCore.Cache outCache; | ||
| 215 | output InnerOuter.InstHierarchy outIH; | ||
| 216 | output DAE.Type outType; | ||
| 217 | algorithm | ||
| 218 | (outCache,outIH,outType) := matchcontinue (inCache, inIH) | ||
| 219 | local | ||
| 220 | FCore.Cache cache; | ||
| 221 | FCore.Graph env1; | ||
| 222 | DAE.Type ty; | ||
| 223 | InstanceHierarchy ih; | ||
| 224 | |||
| 225 | case (cache, ih) | ||
| 226 | algorithm | ||
| 227 | 62 | (cache,env1,ih) := implicitFunctionInstantiation(cache,env,ih, DAE.NOMOD(), DAE.NOPRE(), cl, {}); | |
| 228 | 62 | (cache,ty,_) := Lookup.lookupType(cache,env1,Absyn.IDENT("constructor"),NONE()); | |
| 229 |
1/2✓ Branch 0 taken 62 times.
✗ Branch 1 not taken.
|
62 | then |
| 230 | (cache,ih,ty); | ||
| 231 | else | ||
| 232 | algorithm | ||
| 233 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 234 | ✗ | Debug.trace("- InstFunction.instantiateExternalObjectConstructor failed.\n"); | |
| 235 | ✗ | then fail(); | |
| 236 | end matchcontinue; | ||
| 237 | end instantiateExternalObjectConstructor; | ||
| 238 | |||
| 239 | public function implicitFunctionInstantiation | ||
| 240 | "This function instantiates a function, which is performed *implicitly* | ||
| 241 | since the variables of a function should not be instantiated as for an | ||
| 242 | ordinary class." | ||
| 243 | input FCore.Cache inCache; | ||
| 244 | input FCore.Graph inEnv; | ||
| 245 | input InnerOuter.InstHierarchy inIH; | ||
| 246 | input DAE.Mod inMod; | ||
| 247 | input DAE.Prefix inPrefix; | ||
| 248 | input SCode.Element inClass; | ||
| 249 | input list<list<DAE.Dimension>> inInstDims; | ||
| 250 | output FCore.Cache outCache; | ||
| 251 | output FCore.Graph outEnv; | ||
| 252 | output InnerOuter.InstHierarchy outIH; | ||
| 253 | algorithm | ||
| 254 | (outCache,outEnv,outIH):= match (inCache,inEnv,inIH,inMod,inPrefix,inClass,inInstDims) | ||
| 255 | local | ||
| 256 | DAE.Type ty1; | ||
| 257 | FCore.Graph env,cenv; | ||
| 258 | Absyn.Path fpath; | ||
| 259 | DAE.Mod mod; | ||
| 260 | DAE.Prefix pre; | ||
| 261 | SCode.Element c; | ||
| 262 | String n; | ||
| 263 | InstDims inst_dims; | ||
| 264 | FCore.Cache cache; | ||
| 265 | InstanceHierarchy ih; | ||
| 266 | DAE.ElementSource source "the origin of the element"; | ||
| 267 | list<DAE.Function> funs; | ||
| 268 | DAE.Function fun; | ||
| 269 | SCode.Restriction r; | ||
| 270 | SCode.Partial pPrefix; | ||
| 271 | |||
| 272 | case (cache,env,ih,mod,pre,(c as SCode.CLASS(name = n,restriction = SCode.R_RECORD(_), partialPrefix = pPrefix)),inst_dims) | ||
| 273 | algorithm | ||
| 274 | ✗ | (cache,c,cenv) := Lookup.lookupRecordConstructorClass(cache,env,Absyn.IDENT(n)); | |
| 275 | ✗ | (cache,env,ih,{DAE.FUNCTION(path = fpath, type_ = ty1, source = source)}) := implicitFunctionInstantiation2(cache,cenv,ih,mod,pre,c,inst_dims,true); | |
| 276 | // fpath = AbsynUtil.makeFullyQualified(fpath); | ||
| 277 | ✗ | fun := DAE.RECORD_CONSTRUCTOR(fpath,ty1,source); | |
| 278 | ✗ | cache := InstUtil.addFunctionsToDAE(cache, {fun}, pPrefix); | |
| 279 | ✗ | then (cache,env,ih); | |
| 280 | |||
| 281 | case (cache,env,ih,mod,pre,(c as SCode.CLASS(restriction = r,partialPrefix = pPrefix)),inst_dims) | ||
| 282 | algorithm | ||
| 283 |
2/4✓ Branch 0 taken 6727 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6727 times.
✗ Branch 3 not taken.
|
6727 | failure(SCode.R_RECORD(_) := r); |
| 284 | 6727 | (cache,env,ih,funs) := implicitFunctionInstantiation2(cache,env,ih,mod,pre,c,inst_dims,false); | |
| 285 | 6672 | cache := InstUtil.addFunctionsToDAE(cache, funs, pPrefix); | |
| 286 | 6672 | then (cache,env,ih); | |
| 287 | |||
| 288 | // handle failure | ||
| 289 | case (_,env,_,_,_,SCode.CLASS(name=n),_) | ||
| 290 | algorithm | ||
| 291 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 292 | ✗ | Debug.traceln("- Inst.implicitFunctionInstantiation failed " + n); | |
| 293 | ✗ | Debug.traceln(" Scope: " + FGraph.printGraphPathStr(env)); | |
| 294 | ✗ | then fail(); | |
| 295 | end match; | ||
| 296 | end implicitFunctionInstantiation; | ||
| 297 | |||
| 298 | protected function implicitFunctionInstantiation2 | ||
| 299 | "This function instantiates a function, which is performed *implicitly* | ||
| 300 | since the variables of a function should not be instantiated as for an | ||
| 301 | ordinary class." | ||
| 302 | input FCore.Cache inCache; | ||
| 303 | input FCore.Graph inEnv; | ||
| 304 | input InnerOuter.InstHierarchy inIH; | ||
| 305 | input DAE.Mod inMod; | ||
| 306 | input DAE.Prefix inPrefix; | ||
| 307 | input SCode.Element inClass; | ||
| 308 | input list<list<DAE.Dimension>> inInstDims; | ||
| 309 | input Boolean instFunctionTypeOnly "if true, do no additional checking of the function"; | ||
| 310 | output FCore.Cache outCache; | ||
| 311 | output FCore.Graph outEnv; | ||
| 312 | output InnerOuter.InstHierarchy outIH; | ||
| 313 | output list<DAE.Function> funcs; | ||
| 314 | algorithm | ||
| 315 | (outCache,outEnv,outIH,funcs):= matchcontinue (inCache, inEnv, inIH, inMod, inPrefix, inClass, inInstDims) | ||
| 316 | local | ||
| 317 | DAE.Type ty,ty1; | ||
| 318 | FCore.Graph env_1,env,tempenv,cenv; | ||
| 319 | Absyn.Path fpath; | ||
| 320 | DAE.Mod mod; | ||
| 321 | DAE.Prefix pre; | ||
| 322 | SCode.Element c; | ||
| 323 | String n; | ||
| 324 | InstDims inst_dims; | ||
| 325 | SCode.Visibility vis; | ||
| 326 | SCode.Partial partialPrefix; | ||
| 327 | SCode.Encapsulated encapsulatedPrefix; | ||
| 328 | SCode.ExternalDecl scExtdecl; | ||
| 329 | DAE.ExternalDecl extdecl; | ||
| 330 | SCode.Restriction restr; | ||
| 331 | SCode.ClassDef parts; | ||
| 332 | list<Absyn.Path> funcnames; | ||
| 333 | FCore.Cache cache; | ||
| 334 | InstanceHierarchy ih; | ||
| 335 | DAE.ElementSource source "the origin of the element"; | ||
| 336 | list<DAE.Element> daeElts; | ||
| 337 | list<DAE.Function> resfns; | ||
| 338 | list<DAE.FunctionDefinition> derFuncs; | ||
| 339 | SourceInfo info; | ||
| 340 | DAE.InlineType inlineType; | ||
| 341 | SCode.ClassDef cd; | ||
| 342 | Boolean partialPrefixBool, isImpure; | ||
| 343 | SCode.Comment cmt; | ||
| 344 | SCode.FunctionRestriction funcRest; | ||
| 345 | InstTypes.CallingScope cs; | ||
| 346 | SCode.Visibility visibility; | ||
| 347 | Absyn.FunctionPurity purity; | ||
| 348 | |||
| 349 | // normal functions | ||
| 350 | case (cache, env, ih, mod, pre, SCode.CLASS(classDef=cd, prefixes=SCode.PREFIXES(visibility=visibility), partialPrefix = partialPrefix, name = n,restriction = SCode.R_FUNCTION(funcRest),info = info), inst_dims) | ||
| 351 | algorithm | ||
| 352 |
2/2✓ Branch 1 taken 64853 times.
✓ Branch 2 taken 28614 times.
|
93467 | false := SCodeUtil.isExternalFunctionRestriction(funcRest); |
| 353 | 28614 | isImpure := SCodeUtil.isImpureFunctionRestriction(funcRest); | |
| 354 | |||
| 355 | // if we're not MetaModelica set it to non-partial | ||
| 356 |
2/2✓ Branch 1 taken 16356 times.
✓ Branch 2 taken 12258 times.
|
28614 | c := if Config.acceptMetaModelicaGrammar() then inClass else SCodeUtil.setClassPartialPrefix(SCode.NOT_PARTIAL(), inClass); |
| 357 |
2/2✓ Branch 0 taken 7118 times.
✓ Branch 1 taken 21496 times.
|
28614 | cs := if instFunctionTypeOnly then InstTypes.TYPE_CALL() else InstTypes.INNER_CALL(); |
| 358 | //print("1 Prefix: " + PrefixUtil.printPrefixStr(pre) + " path: " + n + "\n"); | ||
| 359 | 28614 | (cache,cenv,ih,_,DAE.DAE(daeElts),_,ty,_,_,_) := | |
| 360 | Inst.instClass(cache, env, ih, UnitAbsynBuilder.emptyInstStore(), mod, pre, | ||
| 361 | c, inst_dims, true, cs, ConnectionGraph.EMPTY, Connect.emptySet); | ||
| 362 | 22066 | List.map2_0(daeElts,InstUtil.checkFunctionElement,false,info); | |
| 363 | // do not add the stripped class to the env, is already there, not stripped! | ||
| 364 | 22066 | env_1 := env; // Env.extendFrameC(env,c); | |
| 365 | 22066 | (cache,fpath) := Inst.makeFullyQualifiedIdent(cache, env_1, n); | |
| 366 | //print("2 Prefix: " + PrefixUtil.printPrefixStr(pre) + " path: " + AbsynUtil.pathString(fpath) + "\n"); | ||
| 367 | 22066 | cmt := InstUtil.extractComment(daeElts); | |
| 368 | 22066 | derFuncs := InstUtil.getDeriveAnnotation(cd, cmt,fpath,cache,cenv,ih,pre,info); | |
| 369 | |||
| 370 | 22066 | cache := instantiateDerivativeFuncs(cache,env,ih,derFuncs,fpath,info); | |
| 371 | |||
| 372 | 22066 | ty1 := InstUtil.setFullyQualifiedTypename(ty,fpath); | |
| 373 | 22066 | checkExtObjOutput(ty1,info); | |
| 374 | // Mark functions whose body always fails as no-return before adding the | ||
| 375 | // type to the environment, so that calls to them get an isNoReturn call | ||
| 376 | // attribute and the def-use analysis treats those calls as terminating. | ||
| 377 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 22049 times.
|
22059 | if InstUtil.functionAlwaysFails(daeElts) then |
| 378 | 10 | ty1 := Types.setFunctionNoReturn(ty1); | |
| 379 | end if; | ||
| 380 | 22059 | env_1 := FGraph.mkTypeNode(env_1, n, ty1); | |
| 381 | |||
| 382 | // set the source of this element | ||
| 383 | 22059 | source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre); | |
| 384 | 22059 | inlineType := InstBasics.commentIsInlineFunc(cmt); | |
| 385 | 22059 | partialPrefixBool := SCodeUtil.partialBool(partialPrefix); | |
| 386 | |||
| 387 | 22059 | daeElts := InstUtil.optimizeFunctionCheckForLocals(fpath,daeElts,NONE(),{},{},{}); | |
| 388 | 22059 | InstUtil.checkFunctionDefUse(daeElts, info); | |
| 389 | /* Not working 100% yet... Also, a lot of code has unused inputs :( */ | ||
| 390 | if false and Config.acceptMetaModelicaGrammar() and not instFunctionTypeOnly then | ||
| 391 | InstUtil.checkFunctionInputUsed(daeElts,NONE(),AbsynUtil.pathString(fpath)); | ||
| 392 | end if; | ||
| 393 |
10/10✓ Branch 1 taken 13617 times.
✓ Branch 2 taken 85556 times.
✓ Branch 3 taken 99173 times.
✓ Branch 4 taken 22059 times.
✓ Branch 5 taken 85556 times.
✓ Branch 6 taken 22059 times.
✓ Branch 9 taken 22048 times.
✓ Branch 10 taken 11 times.
✓ Branch 11 taken 21948 times.
✓ Branch 12 taken 111 times.
|
209346 | then |
| 394 | (cache,env_1,ih,{DAE.FUNCTION(fpath,DAE.FUNCTION_DEF(list(e for e guard not DAEUtil.isComment(e) in daeElts))::derFuncs,ty1,visibility,partialPrefixBool,isImpure,inlineType,{},source,SOME(cmt))}); | ||
| 395 | |||
| 396 | // External functions should also have their type in env, but no dae. | ||
| 397 | case (cache, env, ih, mod, pre, (c as SCode.CLASS(partialPrefix=partialPrefix, prefixes=SCode.PREFIXES(visibility=visibility), name = n,restriction = (restr as SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(purity))), | ||
| 398 | classDef = cd as (parts as SCode.PARTS(externalDecl=SOME(scExtdecl))), info=info, encapsulatedPrefix = encapsulatedPrefix)), inst_dims) | ||
| 399 | algorithm | ||
| 400 | 64853 | (cache,cenv,ih,_,DAE.DAE(daeElts),_,ty,_,_,_) := | |
| 401 | Inst.instClass(cache,env,ih, UnitAbsynBuilder.emptyInstStore(),mod, pre, | ||
| 402 | c, inst_dims, true, InstTypes.INNER_CALL(), ConnectionGraph.EMPTY, Connect.emptySet); | ||
| 403 | 46667 | List.map2_0(daeElts,InstUtil.checkFunctionElement,true,info); | |
| 404 | //env_11 = FGraph.mkClassNode(cenv,pre,mod,c); | ||
| 405 | // Only created to be able to get FQ path. | ||
| 406 | 46667 | (cache,fpath) := Inst.makeFullyQualifiedIdent(cache,env,n); | |
| 407 | |||
| 408 | 46667 | cmt := InstUtil.extractComment(daeElts); | |
| 409 | 46667 | derFuncs := InstUtil.getDeriveAnnotation(cd,cmt,fpath,cache,env,ih,pre,info); | |
| 410 | |||
| 411 | 46667 | cache := instantiateDerivativeFuncs(cache,env,ih,derFuncs,fpath,info); | |
| 412 | |||
| 413 | 46667 | ty1 := InstUtil.setFullyQualifiedTypename(ty,fpath); | |
| 414 | 46667 | checkExtObjOutput(ty1,info); | |
| 415 | // (ty1,_) = Types.traverseType(ty1, -1, Types.makeExpDimensionsUnknown); | ||
| 416 | 46667 | env_1 := FGraph.mkTypeNode(cenv, n, ty1); | |
| 417 | vis := SCode.PUBLIC(); | ||
| 418 | 46667 | isImpure := AbsynUtil.isImpure(purity); | |
| 419 |
2/2✓ Branch 0 taken 36846 times.
✓ Branch 1 taken 9821 times.
|
83513 | (cache,tempenv,ih,_,_,_,_,_,_,_,_,_) := |
| 420 | Inst.instClassdef(cache, env_1, ih, UnitAbsyn.noStore, mod, pre, | ||
| 421 | ClassInf.FUNCTION(fpath, isImpure), n,parts, restr, vis, partialPrefix, | ||
| 422 | encapsulatedPrefix, inst_dims, true, InstTypes.INNER_CALL(), | ||
| 423 | ConnectionGraph.EMPTY, Connect.emptySet, NONE(), cmt, info) "how to get this? impl" ; | ||
| 424 | 46667 | (cache,ih,extdecl) := instExtDecl(cache, tempenv, ih, n, scExtdecl, daeElts, ty1, true, pre,info) "impl" ; | |
| 425 | |||
| 426 | // set the source of this element | ||
| 427 | 46653 | source := ElementSource.createElementSource(info, FGraph.getScopePath(env), pre); | |
| 428 | 46653 | partialPrefixBool := SCodeUtil.partialBool(partialPrefix); | |
| 429 | 46653 | InstUtil.checkExternalFunction(daeElts,extdecl,AbsynUtil.pathString(fpath)); | |
| 430 |
1/2✓ Branch 1 taken 46653 times.
✗ Branch 2 not taken.
|
186612 | then |
| 431 | (cache,env_1,ih,{DAE.FUNCTION(fpath,DAE.FUNCTION_EXT(daeElts,extdecl)::derFuncs,ty1,visibility,partialPrefixBool,isImpure,DAE.NO_INLINE(),{},source,SOME(cmt))}); | ||
| 432 | |||
| 433 | // Instantiate overloaded functions | ||
| 434 | case (cache, env, ih, _, pre, (SCode.CLASS(name = n, prefixes=SCode.PREFIXES(visibility=visibility), restriction = (SCode.R_FUNCTION(SCode.FR_NORMAL_FUNCTION(purity))), | ||
| 435 | classDef = SCode.OVERLOAD(pathLst = funcnames),cmt=cmt)), _) | ||
| 436 | algorithm | ||
| 437 | 6459 | (cache,env,ih,resfns) := instOverloadedFunctions(cache,env,ih,pre,funcnames,inClass.info) "Overloaded functions" ; | |
| 438 | 6459 | (cache,fpath) := Inst.makeFullyQualifiedIdent(cache,env,n); | |
| 439 | 6459 | isImpure := AbsynUtil.isImpure(purity); | |
| 440 |
1/2✓ Branch 0 taken 6459 times.
✗ Branch 1 not taken.
|
12918 | resfns := DAE.FUNCTION(fpath,{DAE.FUNCTION_DEF({})},DAE.T_UNKNOWN_DEFAULT,visibility,true,isImpure,DAE.NO_INLINE(),{},DAE.emptyElementSource,SOME(cmt))::resfns; |
| 441 | 6459 | then | |
| 442 | (cache,env,ih,resfns); | ||
| 443 | |||
| 444 | // handle failure | ||
| 445 | case (_, env, _, _, _, SCode.CLASS(name=n), _) | ||
| 446 | algorithm | ||
| 447 |
2/2✓ Branch 1 taken 18282 times.
✓ Branch 2 taken 14 times.
|
18296 | true := Flags.isSet(Flags.FAILTRACE); |
| 448 | 14 | Debug.traceln("- Inst.implicitFunctionInstantiation2 failed " + n); | |
| 449 | 14 | Debug.traceln(" Scope: " + FGraph.printGraphPathStr(env)); | |
| 450 | 14 | then fail(); | |
| 451 | end matchcontinue; | ||
| 452 | end implicitFunctionInstantiation2; | ||
| 453 | |||
| 454 | protected function instantiateDerivativeFuncs "instantiates all functions found in derivative annotations so they are also added to the | ||
| 455 | dae and can be generated code for in case they are required" | ||
| 456 | input FCore.Cache cache; | ||
| 457 | input FCore.Graph env; | ||
| 458 | input InnerOuter.InstHierarchy ih; | ||
| 459 | input list<DAE.FunctionDefinition> funcs; | ||
| 460 | input Absyn.Path path "the function name itself, must be added to derivative functions mapping to be able to search upwards"; | ||
| 461 | input SourceInfo info; | ||
| 462 | output FCore.Cache outCache; | ||
| 463 | algorithm | ||
| 464 | // print("instantiate deriative functions for "+AbsynUtil.pathString(path)+"\n"); | ||
| 465 | 68733 | outCache := instantiateDerivativeFuncs2(cache,env,ih,DAEUtil.getDerivativePaths(funcs),path,info); | |
| 466 | // print("instantiated derivative functions for "+AbsynUtil.pathString(path)+"\n"); | ||
| 467 | end instantiateDerivativeFuncs; | ||
| 468 | |||
| 469 | protected function instantiateDerivativeFuncs2 "help function" | ||
| 470 | input FCore.Cache inCache; | ||
| 471 | input FCore.Graph inEnv; | ||
| 472 | input InnerOuter.InstHierarchy inIH; | ||
| 473 | input list<Absyn.Path> inPaths; | ||
| 474 | input Absyn.Path path "the function name itself, must be added to derivative functions mapping to be able to search upwards"; | ||
| 475 | input SourceInfo info; | ||
| 476 | output FCore.Cache outCache; | ||
| 477 | algorithm | ||
| 478 | outCache := matchcontinue(inCache, inEnv, inIH, inPaths) | ||
| 479 | local | ||
| 480 | list<DAE.Function> funcs; | ||
| 481 | Absyn.Path p; | ||
| 482 | FCore.Cache cache; | ||
| 483 | FCore.Graph cenv,env; | ||
| 484 | InstanceHierarchy ih; | ||
| 485 | SCode.Element cdef; | ||
| 486 | list<Absyn.Path> paths; | ||
| 487 | String fun,scope; | ||
| 488 | |||
| 489 | case(cache, _, _, {}) then (cache); | ||
| 490 | |||
| 491 | case(cache, env, ih, p::paths) | ||
| 492 | algorithm | ||
| 493 | 960 | (cache,cdef,cenv) := Lookup.lookupClass(cache,env,p,SOME(info)); | |
| 494 | 960 | (cache,p) := Inst.makeFullyQualified(cache,cenv,p); | |
| 495 | () := matchcontinue() | ||
| 496 | case () // Skipped recursive calls (by looking in cache) | ||
| 497 | algorithm | ||
| 498 | 960 | FCore.checkCachedInstFuncGuard(cache,p); | |
| 499 | then (); | ||
| 500 | else // add to cache before instantiating, to break recursion for recursive definitions. | ||
| 501 | algorithm | ||
| 502 | 283 | cache := FCore.addCachedInstFuncGuard(cache,p); | |
| 503 | 283 | (cache,_,ih,funcs) := | |
| 504 | implicitFunctionInstantiation2(cache,cenv,ih,DAE.NOMOD(),DAE.NOPRE(),cdef,{},false); | ||
| 505 | |||
| 506 | 283 | funcs := InstUtil.addNameToDerivativeMapping(funcs,path); | |
| 507 | 283 | cache := FCore.addDaeFunction(cache, funcs); | |
| 508 | then (); | ||
| 509 | end matchcontinue; | ||
| 510 | 960 | then | |
| 511 | instantiateDerivativeFuncs2(cache,env,ih,paths,path,info); | ||
| 512 | |||
| 513 | else | ||
| 514 | algorithm | ||
| 515 | ✗ | p :: _ := inPaths; | |
| 516 | ✗ | fun := AbsynUtil.pathString(p); | |
| 517 | ✗ | scope := FGraph.printGraphPathStr(inEnv); | |
| 518 | ✗ | Error.addSourceMessage(Error.LOOKUP_FUNCTION_ERROR,{fun,scope},info); | |
| 519 | ✗ | then fail(); | |
| 520 | |||
| 521 | end matchcontinue; | ||
| 522 | end instantiateDerivativeFuncs2; | ||
| 523 | |||
| 524 | public function implicitFunctionTypeInstantiation | ||
| 525 | "author: PA | ||
| 526 | When looking up a function type it is sufficient to only instantiate the input and output arguments of the function. | ||
| 527 | The implicitFunctionInstantiation function will instantiate the function body, resulting in a DAE for the body. | ||
| 528 | This function does not do that. Therefore this function is the only solution available for recursive functions, | ||
| 529 | where the function body contain a call to the function itself. | ||
| 530 | |||
| 531 | Extended 2007-06-29, BZ | ||
| 532 | Now this function also handles Derived function." | ||
| 533 | input FCore.Cache inCache; | ||
| 534 | input FCore.Graph inEnv; | ||
| 535 | input InnerOuter.InstHierarchy inIH; | ||
| 536 | input SCode.Element inClass; | ||
| 537 | output FCore.Cache outCache; | ||
| 538 | output FCore.Graph outEnv; | ||
| 539 | output InnerOuter.InstHierarchy outIH; | ||
| 540 | algorithm | ||
| 541 | (outCache,outEnv,outIH) := matchcontinue (inCache,inEnv,inIH,inClass) | ||
| 542 | local | ||
| 543 | SCode.Element stripped_class; | ||
| 544 | FCore.Graph env_1,env; | ||
| 545 | String id; | ||
| 546 | SCode.Partial p; | ||
| 547 | SCode.Encapsulated e; | ||
| 548 | SCode.Restriction r; | ||
| 549 | Option<SCode.ExternalDecl> extDecl; | ||
| 550 | list<SCode.Element> elts; | ||
| 551 | FCore.Cache cache; | ||
| 552 | InstanceHierarchy ih; | ||
| 553 | SourceInfo info; | ||
| 554 | list<DAE.Function> funs; | ||
| 555 | Absyn.Path cn,fpath; | ||
| 556 | SCode.Mod mod1; | ||
| 557 | DAE.Mod mod2; | ||
| 558 | FCore.Graph cenv; | ||
| 559 | SCode.Element c; | ||
| 560 | DAE.Type ty1,ty; | ||
| 561 | SCode.Prefixes prefixes; | ||
| 562 | SCode.Comment cmt; | ||
| 563 | |||
| 564 | // For external functions, include everything essential | ||
| 565 | case (cache,env,ih,SCode.CLASS( | ||
| 566 | restriction = SCode.R_FUNCTION(SCode.FR_EXTERNAL_FUNCTION(_)), | ||
| 567 | classDef = SCode.PARTS())) | ||
| 568 | algorithm | ||
| 569 | // stripped_class = SCode.CLASS(id,prefixes,e,p,r,SCode.PARTS(elts,{},{},{},{},{},{},extDecl),cmt,info); | ||
| 570 | 42943 | (cache,env_1,ih,funs) := implicitFunctionInstantiation2(cache, env, ih, DAE.NOMOD(), DAE.NOPRE(), inClass, {}, true); | |
| 571 | // Only external functions are valid without an algorithm section... | ||
| 572 | 33843 | cache := FCore.addDaeExtFunction(cache, funs); | |
| 573 | 33843 | then | |
| 574 | (cache,env_1,ih); | ||
| 575 | |||
| 576 | // The function type can be determined without the body. Annotations, restrictions and external decls need | ||
| 577 | // to be preserved though (e.g parallel external functions have restrictions parallel_function not external function) | ||
| 578 | // Maybe we need one more restriction type for those. | ||
| 579 | case (cache,env,ih,SCode.CLASS(name = id,prefixes = prefixes, | ||
| 580 | encapsulatedPrefix = e,partialPrefix = p, restriction=r, | ||
| 581 | classDef = SCode.PARTS(elementLst = elts, externalDecl = extDecl),cmt=cmt, info = info)) | ||
| 582 | algorithm | ||
| 583 | 24137 | elts := List.select(elts,isElementImportantForFunction); | |
| 584 | 24137 | stripped_class := SCode.CLASS(id,prefixes,e,p,r,SCode.PARTS(elts,{},{},{},{},{},{},extDecl),cmt,info); | |
| 585 | 24137 | (cache,env_1,ih,_) := implicitFunctionInstantiation2(cache, env, ih, DAE.NOMOD(), DAE.NOPRE(), stripped_class, {}, true); | |
| 586 | // Only external functions are valid without an algorithm section... | ||
| 587 | // cache = FCore.addDaeExtFunction(cache, funs); | ||
| 588 | 14996 | then | |
| 589 | (cache,env_1,ih); | ||
| 590 | |||
| 591 | // Short class definitions. | ||
| 592 | case (cache,env,ih,SCode.CLASS(name = id, | ||
| 593 | classDef = SCode.DERIVED(typeSpec = Absyn.TPATH(path = cn), | ||
| 594 | modifications = mod1),info = info)) | ||
| 595 | algorithm | ||
| 596 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
|
108 | (cache,(c as SCode.CLASS()),cenv) := Lookup.lookupClass(cache, env, cn); // Makes MultiBody gravityacceleration hacks shit itself |
| 597 | 108 | (cache,mod2) := Mod.elabMod(cache, env, ih, DAE.NOPRE(), mod1, false, Mod.DERIVED(cn), info); | |
| 598 | |||
| 599 | 108 | (cache,_,ih,_,_,_,ty,_,_,_) := | |
| 600 | Inst.instClass(cache,cenv,ih,UnitAbsynBuilder.emptyInstStore(), mod2, | ||
| 601 | DAE.NOPRE(), c, {}, true, InstTypes.INNER_CALL(), ConnectionGraph.EMPTY, Connect.emptySet); | ||
| 602 | |||
| 603 | 108 | env_1 := env; // why would you want to do this: FGraph.mkClassNode(env,c); ????? | |
| 604 | 108 | (cache,fpath) := Inst.makeFullyQualifiedIdent(cache,env_1,id); | |
| 605 | 108 | ty1 := InstUtil.setFullyQualifiedTypename(ty,fpath); | |
| 606 | 108 | env_1 := FGraph.mkTypeNode(env_1, id, ty1); | |
| 607 | // (cache,env_1,ih,_) = implicitFunctionInstantiation2(cache, env, ih, DAE.NOMOD(), DAE.NOPRE(), inClass, {}, true); | ||
| 608 | 108 | then | |
| 609 | (cache,env_1,ih); | ||
| 610 | |||
| 611 | case (cache,env,ih,SCode.CLASS( | ||
| 612 | classDef = SCode.OVERLOAD())) | ||
| 613 | algorithm | ||
| 614 | 6459 | (cache,env,ih,_) := implicitFunctionInstantiation2(cache, env, ih, DAE.NOMOD(), DAE.NOPRE(), inClass, {}, true); | |
| 615 | 6459 | then | |
| 616 | (cache,env,ih); | ||
| 617 | |||
| 618 | case (_,_,_,SCode.CLASS(name=id)) | ||
| 619 | algorithm | ||
| 620 |
2/2✓ Branch 1 taken 9134 times.
✓ Branch 2 taken 7 times.
|
9141 | true := Flags.isSet(Flags.FAILTRACE); |
| 621 | 7 | Debug.traceln("- Inst.implicitFunctionTypeInstantiation failed " + id + "\nenv: " + FGraph.getGraphNameStr(inEnv) + "\nelelement: " + SCodeDump.unparseElementStr(inClass,SCodeDump.defaultOptions)); | |
| 622 | 7 | then fail(); | |
| 623 | end matchcontinue; | ||
| 624 | end implicitFunctionTypeInstantiation; | ||
| 625 | |||
| 626 | protected function instOverloadedFunctions | ||
| 627 | "This function instantiates the functions in the overload list of a | ||
| 628 | overloading function definition and register the function types using | ||
| 629 | the overloaded name. It also creates dae elements for the functions." | ||
| 630 | input FCore.Cache inCache; | ||
| 631 | input FCore.Graph inEnv; | ||
| 632 | input InnerOuter.InstHierarchy inIH; | ||
| 633 | input DAE.Prefix pre; | ||
| 634 | input list<Absyn.Path> inAbsynPathLst; | ||
| 635 | input SourceInfo inInfo; | ||
| 636 | output FCore.Cache outCache; | ||
| 637 | output FCore.Graph outEnv; | ||
| 638 | output InnerOuter.InstHierarchy outIH; | ||
| 639 | output list<DAE.Function> outFns; | ||
| 640 | algorithm | ||
| 641 | (outCache,outEnv,outIH,outFns) := matchcontinue (inCache, inEnv, inIH, inAbsynPathLst) | ||
| 642 | local | ||
| 643 | FCore.Graph env,cenv; | ||
| 644 | SCode.Element c; | ||
| 645 | Absyn.Path fn; | ||
| 646 | list<Absyn.Path> fns; | ||
| 647 | FCore.Cache cache; | ||
| 648 | InstanceHierarchy ih; | ||
| 649 | list<DAE.Function> resfns1,resfns2; | ||
| 650 | SCode.Restriction rest; | ||
| 651 | |||
| 652 | case (cache, _, ih, {}) then (cache,inEnv,ih,{}); | ||
| 653 | |||
| 654 | // Instantiate each function, add its FQ name to the type, needed when deoverloading | ||
| 655 | case (cache, env, ih, (fn :: fns)) | ||
| 656 | algorithm | ||
| 657 | // print("instOvl: " + AbsynUtil.pathString(fn) + "\n"); | ||
| 658 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12918 times.
|
12918 | (cache,(c as SCode.CLASS(restriction=rest)),cenv) := |
| 659 | Lookup.lookupClass(cache, env, fn, SOME(inInfo)); | ||
| 660 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 12918 times.
|
12918 | true := SCodeUtil.isFunctionRestriction(rest); |
| 661 | |||
| 662 | 12918 | (cache,env,ih,resfns1) := implicitFunctionInstantiation2(inCache, cenv, inIH, DAE.NOMOD(), pre, c, {}, false); | |
| 663 | 12918 | (cache,env,ih,resfns2) := instOverloadedFunctions(cache,env,ih,pre,fns, inInfo); | |
| 664 | 12918 | then (cache,env,ih,listAppend(resfns1,resfns2)); | |
| 665 | |||
| 666 | // failure | ||
| 667 | case (_, _, _, (fn :: _)) | ||
| 668 | algorithm | ||
| 669 | ✗ | true := Flags.isSet(Flags.FAILTRACE); | |
| 670 | ✗ | Debug.traceln("- Inst.instOverloaded_functions failed " + AbsynUtil.pathString(fn)); | |
| 671 | ✗ | then | |
| 672 | fail(); | ||
| 673 | end matchcontinue; | ||
| 674 | end instOverloadedFunctions; | ||
| 675 | |||
| 676 | protected function instExtDecl | ||
| 677 | "author: LS | ||
| 678 | This function handles the external declaration. If there is an explicit | ||
| 679 | call of the external function, the component references are looked up and | ||
| 680 | inserted in the argument list, otherwise the input and output parameters | ||
| 681 | are inserted in the argument list with their order. The return type is | ||
| 682 | determined according to the specification; if there is a explicit call | ||
| 683 | and a lhs, which must be an output parameter, the type of the function is | ||
| 684 | that type. If no explicit call and only one output parameter exists, then | ||
| 685 | this will be the return type of the function, otherwise the return type | ||
| 686 | will be void." | ||
| 687 | input output FCore.Cache cache; | ||
| 688 | input FCore.Graph env; | ||
| 689 | input output InnerOuter.InstHierarchy iH; | ||
| 690 | input String name; | ||
| 691 | input SCode.ExternalDecl inScExtDecl; | ||
| 692 | input list<DAE.Element> inElements; | ||
| 693 | input DAE.Type funcType; | ||
| 694 | input Boolean impl; | ||
| 695 | input DAE.Prefix pre; | ||
| 696 | input SourceInfo info; | ||
| 697 | output DAE.ExternalDecl daeextdecl; | ||
| 698 | protected | ||
| 699 | String fname,lang; | ||
| 700 | list<DAE.ExtArg> fargs; | ||
| 701 | DAE.ExtArg rettype; | ||
| 702 | Option<SCode.Annotation> ann; | ||
| 703 | SCode.ExternalDecl extdecl=inScExtDecl; | ||
| 704 | algorithm | ||
| 705 | 46667 | ann := InstUtil.instExtGetAnnotation(extdecl); | |
| 706 | 46667 | lang := InstUtil.instExtGetLang(extdecl); | |
| 707 | 46667 | fname := InstUtil.instExtGetFname(extdecl, name); | |
| 708 |
2/2✓ Branch 1 taken 28683 times.
✓ Branch 2 taken 17984 times.
|
46667 | if not InstUtil.isExtExplicitCall(extdecl) then |
| 709 | 28683 | (fargs,rettype) := instExtMakeDefaultExternalCall(inElements, funcType, lang, info); | |
| 710 | else | ||
| 711 | 17984 | (cache,fargs) := InstUtil.instExtGetFargs(cache,env,extdecl,impl,pre,info); | |
| 712 | 17984 | (cache,rettype) := InstUtil.instExtGetRettype(cache,env,extdecl,impl,pre,info); | |
| 713 | end if; | ||
| 714 | 46653 | daeextdecl := DAE.EXTERNALDECL(fname,fargs,rettype,lang,ann); | |
| 715 | end instExtDecl; | ||
| 716 | |||
| 717 | protected function instExtMakeDefaultExternalCall | ||
| 718 | " This function generates a default explicit function call, | ||
| 719 | when it is omitted. If only one output variable exists, | ||
| 720 | the implicit call is equivalent to: | ||
| 721 | external \"C\" output_var=func(input_var1, input_var2,...) | ||
| 722 | with the input_vars in their declaration order. If several output | ||
| 723 | variables exists, the implicit call is equivalent to: | ||
| 724 | external \"C\" func(var1, var2, ...) | ||
| 725 | where each var can be input or output." | ||
| 726 | input list<DAE.Element> elements; | ||
| 727 | input DAE.Type funcType; | ||
| 728 | input String lang; | ||
| 729 | input SourceInfo info; | ||
| 730 | output list<DAE.ExtArg> fargs; | ||
| 731 | output DAE.ExtArg rettype; | ||
| 732 | protected | ||
| 733 | DAE.Type ty; | ||
| 734 | Boolean singleOutput; | ||
| 735 | algorithm | ||
| 736 | fargs := {}; | ||
| 737 |
3/4✓ Branch 0 taken 28660 times.
✓ Branch 1 taken 23 times.
✓ Branch 3 taken 28660 times.
✗ Branch 4 not taken.
|
28683 | if lang=="builtin" then |
| 738 | rettype := DAE.NOEXTARG(); | ||
| 739 | 28660 | return; | |
| 740 | end if; | ||
| 741 | (rettype,singleOutput) := match funcType | ||
| 742 | case DAE.T_FUNCTION(funcResultType=DAE.T_ARRAY()) | ||
| 743 | algorithm | ||
| 744 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
|
17 | if lang<>"builtin" then |
| 745 | 17 | Error.addSourceMessage(Error.EXT_FN_SINGLE_RETURN_ARRAY, {lang}, info); | |
| 746 | end if; | ||
| 747 | then (DAE.NOEXTARG(),false); | ||
| 748 | case DAE.T_FUNCTION(funcResultType=DAE.T_TUPLE()) | ||
| 749 | then (DAE.NOEXTARG(),false); | ||
| 750 | case DAE.T_FUNCTION(funcResultType=DAE.T_NORETCALL()) | ||
| 751 | then (DAE.NOEXTARG(),false); | ||
| 752 | case DAE.T_FUNCTION(funcResultType=ty) | ||
| 753 | 5 | then (DAE.EXTARG(DAEUtil.varCref(List.find(elements, DAEUtil.isOutputVar)), Absyn.OUTPUT(), ty), true); | |
| 754 | else | ||
| 755 | algorithm | ||
| 756 | ✗ | Error.addInternalError("instExtMakeDefaultExternalCall failed for " + TypesDump.unparseType(funcType), info); | |
| 757 | ✗ | then fail(); | |
| 758 | end match; | ||
| 759 |
2/2✓ Branch 0 taken 46 times.
✓ Branch 1 taken 23 times.
|
69 | for elt in elements loop |
| 760 | fargs := match elt | ||
| 761 | case DAE.VAR(direction=DAE.OUTPUT()) guard not singleOutput | ||
| 762 | 17 | then addExtVarToCall(elt.componentRef, Absyn.OUTPUT(), elt.dims, fargs); | |
| 763 | case DAE.VAR(direction=DAE.INPUT()) | ||
| 764 | 24 | then addExtVarToCall(elt.componentRef, Absyn.INPUT(), elt.dims, fargs); | |
| 765 | case DAE.VAR(direction=DAE.BIDIR()) | ||
| 766 | ✗ | then addExtVarToCall(elt.componentRef, Absyn.OUTPUT(), elt.dims, fargs); | |
| 767 | else fargs; | ||
| 768 | end match; | ||
| 769 | end for; | ||
| 770 | 23 | fargs := listReverse(fargs); | |
| 771 | end instExtMakeDefaultExternalCall; | ||
| 772 | |||
| 773 | protected function addExtVarToCall | ||
| 774 | input DAE.ComponentRef cr; | ||
| 775 | input Absyn.Direction dir; | ||
| 776 | input DAE.Dimensions dims; | ||
| 777 | input output list<DAE.ExtArg> fargs; | ||
| 778 | algorithm | ||
| 779 | 41 | fargs := DAE.EXTARG(cr, dir, ComponentReference.crefTypeFull(cr))::fargs; | |
| 780 |
2/2✓ Branch 1 taken 6 times.
✓ Branch 2 taken 35 times.
|
111 | for dim in 1:listLength(dims) loop |
| 781 | 70 | fargs := DAE.EXTARGSIZE(cr, ComponentReference.crefTypeFull(cr), DAE.ICONST(dim))::fargs; | |
| 782 | end for; | ||
| 783 | end addExtVarToCall; | ||
| 784 | |||
| 785 | public function getRecordConstructorFunction | ||
| 786 | input FCore.Cache inCache; | ||
| 787 | input FCore.Graph inEnv; | ||
| 788 | input Absyn.Path inPath; | ||
| 789 | output FCore.Cache outCache; | ||
| 790 | output DAE.Function outFunc; | ||
| 791 | algorithm | ||
| 792 | (outCache,outFunc) := matchcontinue inPath | ||
| 793 | local | ||
| 794 | Absyn.Path path; | ||
| 795 | SCode.Element recordCl; | ||
| 796 | FCore.Graph recordEnv; | ||
| 797 | DAE.Function func; | ||
| 798 | FCore.Cache cache; | ||
| 799 | DAE.Type recType,fixedTy,funcTy; | ||
| 800 | list<DAE.Var> vars, inputs, locals; | ||
| 801 | list<DAE.FuncArg> fargs; | ||
| 802 | DAE.EqualityConstraint eqCo; | ||
| 803 | String name, newName; | ||
| 804 | Boolean extConvert; | ||
| 805 | |||
| 806 | |||
| 807 | case _ | ||
| 808 | algorithm | ||
| 809 | 93280 | path := AbsynUtil.makeFullyQualified(inPath); | |
| 810 | 93280 | func := FCore.getCachedInstFunc(inCache,path); | |
| 811 | then | ||
| 812 | (inCache,func); | ||
| 813 | |||
| 814 | case _ | ||
| 815 | algorithm | ||
| 816 | 59793 | (_,recordCl,recordEnv) := Lookup.lookupClass(inCache, inEnv, inPath); | |
| 817 |
2/2✓ Branch 1 taken 52491 times.
✓ Branch 2 taken 3514 times.
|
56005 | true := SCodeUtil.isRecord(recordCl); |
| 818 | |||
| 819 | 3514 | name := SCodeUtil.getElementName(recordCl); | |
| 820 | 3514 | newName := FGraph.getInstanceOriginalName(recordEnv, name); | |
| 821 | 3514 | recordCl := SCodeUtil.setClassName(newName, recordCl); | |
| 822 | |||
| 823 | 3514 | (cache,_,_,_,_,_,recType,_,_,_) := Inst.instClass(inCache,recordEnv, InnerOuter.emptyInstHierarchy, | |
| 824 | UnitAbsynBuilder.emptyInstStore(), DAE.NOMOD(), DAE.NOPRE(), recordCl, | ||
| 825 | {}, true, InstTypes.INNER_CALL(), ConnectionGraph.EMPTY, Connect.emptySet); | ||
| 826 | |||
| 827 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 3514 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3514 times.
|
3514 | DAE.T_COMPLEX(ClassInf.RECORD(path), vars, eqCo, extConvert) := recType; |
| 828 | |||
| 829 | 3514 | vars := Types.filterRecordComponents(vars, SCodeUtil.elementInfo(recordCl)); | |
| 830 | 3514 | (inputs,locals) := List.extractOnTrue(vars, Types.isModifiableTypesVar); | |
| 831 | 3514 | inputs := List.map(inputs,Types.setVarDefaultInput); | |
| 832 | 3514 | locals := List.map(locals,Types.setVarProtected); | |
| 833 | 3514 | vars := listAppend(inputs,locals); | |
| 834 | |||
| 835 | 3514 | path := AbsynUtil.makeFullyQualified(path); | |
| 836 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3514 times.
|
3514 | fixedTy := DAE.T_COMPLEX(ClassInf.RECORD(path), vars, eqCo, extConvert); |
| 837 | 3514 | fargs := Types.makeFargsList(inputs); | |
| 838 | 3514 | funcTy := DAE.T_FUNCTION(fargs, fixedTy, DAE.FUNCTION_ATTRIBUTES_DEFAULT, path); | |
| 839 | 3514 | func := DAE.RECORD_CONSTRUCTOR(path,funcTy,DAE.emptyElementSource); | |
| 840 | |||
| 841 | 3514 | cache := InstUtil.addFunctionsToDAE(cache, {func}, SCode.NOT_PARTIAL()); | |
| 842 | |||
| 843 | // add the instance record constructor too! | ||
| 844 | 3514 | path := AbsynUtil.pathSetLastIdent(path, name); | |
| 845 | 3514 | fixedTy := DAE.T_COMPLEX(ClassInf.RECORD(path), vars, eqCo, extConvert); | |
| 846 | 3514 | fargs := Types.makeFargsList(inputs); | |
| 847 | 3514 | funcTy := DAE.T_FUNCTION(fargs, fixedTy, DAE.FUNCTION_ATTRIBUTES_DEFAULT, path); | |
| 848 | 3514 | func := DAE.RECORD_CONSTRUCTOR(path,funcTy,DAE.emptyElementSource); | |
| 849 | |||
| 850 | 3514 | cache := InstUtil.addFunctionsToDAE(cache, {func}, SCode.NOT_PARTIAL()); | |
| 851 | |||
| 852 | then | ||
| 853 | (cache,func); | ||
| 854 | |||
| 855 | else | ||
| 856 | algorithm | ||
| 857 |
2/2✓ Branch 1 taken 56274 times.
✓ Branch 2 taken 5 times.
|
56279 | true := Flags.isSet(Flags.FAILTRACE); |
| 858 | 5 | Debug.traceln("InstFunction.getRecordConstructorFunction failed for " + AbsynUtil.pathString(inPath)); | |
| 859 | 5 | then | |
| 860 | fail(); | ||
| 861 | |||
| 862 | end matchcontinue; | ||
| 863 | |||
| 864 | end getRecordConstructorFunction; | ||
| 865 | |||
| 866 | public function addRecordConstructorFunction "Add record constructor whenever we instantiate a variable. Needed so we can cast to this constructor freely." | ||
| 867 | input FCore.Cache inCache; | ||
| 868 | input FCore.Graph inEnv; | ||
| 869 | input DAE.Type inType; | ||
| 870 | input SourceInfo inInfo; | ||
| 871 | output FCore.Cache outCache; | ||
| 872 | algorithm | ||
| 873 | outCache := matchcontinue (inCache, inType) | ||
| 874 | local | ||
| 875 | list<DAE.Var> vars, inputs, locals; | ||
| 876 | DAE.Type fixedTy,funcTy; | ||
| 877 | DAE.EqualityConstraint eqCo; | ||
| 878 | FCore.Cache cache; | ||
| 879 | Absyn.Path path; | ||
| 880 | DAE.Function func; | ||
| 881 | list<DAE.FuncArg> fargs; | ||
| 882 | Boolean extConvert; | ||
| 883 | |||
| 884 | // try to instantiate class | ||
| 885 | case (cache, DAE.T_COMPLEX(complexClassType=ClassInf.RECORD(path))) | ||
| 886 | algorithm | ||
| 887 | 13762 | path := AbsynUtil.makeFullyQualified(path); | |
| 888 | 13762 | (cache, _) := getRecordConstructorFunction(cache, inEnv, path); | |
| 889 | then | ||
| 890 | cache; | ||
| 891 | |||
| 892 | // if previous stuff didn't work, try to use the ty directly | ||
| 893 | case (cache, DAE.T_COMPLEX(ClassInf.RECORD(path), vars, eqCo, extConvert)) | ||
| 894 | algorithm | ||
| 895 | ✗ | path := AbsynUtil.makeFullyQualified(path); | |
| 896 | |||
| 897 | ✗ | vars := Types.filterRecordComponents(vars, inInfo); | |
| 898 | ✗ | (inputs,locals) := List.extractOnTrue(vars, Types.isModifiableTypesVar); | |
| 899 | ✗ | inputs := List.map(inputs,Types.setVarDefaultInput); | |
| 900 | ✗ | locals := List.map(locals,Types.setVarProtected); | |
| 901 | ✗ | vars := listAppend(inputs,locals); | |
| 902 | |||
| 903 | ✗ | fixedTy := DAE.T_COMPLEX(ClassInf.RECORD(path), vars, eqCo, extConvert); | |
| 904 | ✗ | fargs := Types.makeFargsList(inputs); | |
| 905 | ✗ | funcTy := DAE.T_FUNCTION(fargs, fixedTy, DAE.FUNCTION_ATTRIBUTES_DEFAULT, path); | |
| 906 | ✗ | func := DAE.RECORD_CONSTRUCTOR(path,funcTy,DAE.emptyElementSource); | |
| 907 | |||
| 908 | ✗ | cache := InstUtil.addFunctionsToDAE(cache, {func}, SCode.NOT_PARTIAL()); | |
| 909 | then | ||
| 910 | (cache); | ||
| 911 | |||
| 912 | else inCache; | ||
| 913 | |||
| 914 | end matchcontinue; | ||
| 915 | end addRecordConstructorFunction; | ||
| 916 | |||
| 917 | protected function isElementImportantForFunction | ||
| 918 | input SCode.Element elt; | ||
| 919 | output Boolean b; | ||
| 920 | algorithm | ||
| 921 | b := match elt | ||
| 922 | case SCode.COMPONENT(prefixes=SCode.PREFIXES(visibility=SCode.PROTECTED()), | ||
| 923 | attributes=SCode.ATTR(direction=Absyn.BIDIR(),variability=SCode.VAR())) | ||
| 924 | then false; | ||
| 925 | else true; | ||
| 926 | end match; | ||
| 927 | end isElementImportantForFunction; | ||
| 928 | |||
| 929 | protected function checkExtObjOutput | ||
| 930 | input DAE.Type inType; | ||
| 931 | input SourceInfo info; | ||
| 932 | algorithm | ||
| 933 | () := match inType | ||
| 934 | local | ||
| 935 | Absyn.Path path; | ||
| 936 | DAE.Type ty; | ||
| 937 | case DAE.T_FUNCTION(funcResultType=ty,path=path) | ||
| 938 | algorithm | ||
| 939 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 68726 times.
|
68733 | (_,(_,_,true)) := Types.traverseType(ty,(path,info,true),checkExtObjOutputWork); |
| 940 | then (); | ||
| 941 | end match; | ||
| 942 | end checkExtObjOutput; | ||
| 943 | |||
| 944 | protected function checkExtObjOutputWork | ||
| 945 | input DAE.Type ty; | ||
| 946 | input tuple<Absyn.Path,SourceInfo,Boolean> inTpl; | ||
| 947 | output DAE.Type oty = ty; | ||
| 948 | output tuple<Absyn.Path,SourceInfo,Boolean> outTpl; | ||
| 949 | algorithm | ||
| 950 | outTpl := match (ty,inTpl) | ||
| 951 | local | ||
| 952 | Absyn.Path path1,path2; | ||
| 953 | SourceInfo info; | ||
| 954 | String str1,str2; | ||
| 955 | Boolean b; | ||
| 956 | case (DAE.T_COMPLEX(complexClassType=ClassInf.EXTERNAL_OBJ(path1)),(path2,info,true)) | ||
| 957 | algorithm | ||
| 958 | 69 | path1 := AbsynUtil.joinPaths(path1,Absyn.IDENT("constructor")); | |
| 959 | 69 | str1 := AbsynUtil.pathStringNoQual(path2); | |
| 960 | 69 | str2 := AbsynUtil.pathStringNoQual(path1); | |
| 961 | 69 | b := AbsynUtil.pathEqual(path1,path2); | |
| 962 | 69 | Error.assertionOrAddSourceMessage(b, Error.FUNCTION_RETURN_EXT_OBJ, {str1,str2}, info); | |
| 963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 62 times.
|
62 | outTpl := if b then inTpl else (path2,info,false); |
| 964 | then outTpl; | ||
| 965 | else inTpl; | ||
| 966 | end match; | ||
| 967 | end checkExtObjOutputWork; | ||
| 968 | |||
| 969 | annotation(__OpenModelica_Interface="frontend"); | ||
| 970 | end InstFunction; | ||
| 971 |